Commit b8b7d0b0 authored by bell@sanja.is.com.ua's avatar bell@sanja.is.com.ua

fixed * without tables in IN bug

fixed sunction-test select in IN bug
fixed unions in subselect bug
parent d2e5a5dd
......@@ -262,4 +262,5 @@
#define ER_CYCLIC_REFERENCE 1243
#define ER_AUTO_CONVERT 1244
#define ER_ILLEGAL_REFERENCE 1245
#define ER_ERROR_MESSAGES 246
#define ER_SELECT_REDUCED 1246
#define ER_ERROR_MESSAGES 247
......@@ -513,3 +513,30 @@ x y
4 2
2 1
drop table t1, t2;
SELECT * FROM (SELECT 1) WHERE 1 IN (SELECT *);
No tables used
drop table if exists t;
CREATE TABLE t (id int(11) default NULL, KEY id (id)) TYPE=MyISAM CHARSET=latin1;
INSERT INTO t VALUES (1),(2);
SELECT * FROM t WHERE id IN (SELECT 1);
id
1
EXPLAIN SELECT * FROM t WHERE id IN (SELECT 1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t ref id id 5 const 1 Using where; Using index
Warnings:
Note 1246 Select 2 was reduced during optimisation
SELECT * FROM t WHERE id IN (SELECT 1 UNION SELECT 3);
id
1
EXPLAIN SELECT * FROM t WHERE id IN (SELECT 1 UNION SELECT 3);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t index NULL id 5 NULL 2 Using where; Using index
2 DEPENDENT SUBSELECT No tables used
3 UNION No tables used
SELECT * FROM t WHERE id IN (SELECT 5 UNION SELECT 3);
id
SELECT * FROM t WHERE id IN (SELECT 5 UNION SELECT 2);
id
2
drop table if exists t;
......@@ -306,3 +306,17 @@ select * from t1;
replace LOW_PRIORITY into t1 (x, y) VALUES ((SELECT a+1 FROM t2), (SELECT a FROM t2));
select * from t1;
drop table t1, t2;
-- error 1096
SELECT * FROM (SELECT 1) WHERE 1 IN (SELECT *);
drop table if exists t;
CREATE TABLE t (id int(11) default NULL, KEY id (id)) TYPE=MyISAM CHARSET=latin1;
INSERT INTO t VALUES (1),(2);
SELECT * FROM t WHERE id IN (SELECT 1);
EXPLAIN SELECT * FROM t WHERE id IN (SELECT 1);
SELECT * FROM t WHERE id IN (SELECT 1 UNION SELECT 3);
EXPLAIN SELECT * FROM t WHERE id IN (SELECT 1 UNION SELECT 3);
SELECT * FROM t WHERE id IN (SELECT 5 UNION SELECT 3);
SELECT * FROM t WHERE id IN (SELECT 5 UNION SELECT 2);
drop table if exists t;
......@@ -463,6 +463,7 @@ bool Item_asterisk_remover::fix_fields(THD *thd,
((Item_field*) item)->field_name[0] == '*')
{
Item_field *fitem= (Item_field*) item;
if (list)
if (!list->next || fitem->db_name || fitem->table_name)
{
TABLE_LIST *table= find_table_in_list(list,
......@@ -489,15 +490,14 @@ bool Item_asterisk_remover::fix_fields(THD *thd,
my_message(ER_SUBSELECT_NO_1_COL, ER(ER_SUBSELECT_NO_1_COL),
MYF(0));
}
else
if (!fitem->table_name)
my_error(ER_NO_TABLES_USED, MYF(0));
else
my_error(ER_BAD_TABLE_ERROR, MYF(0), fitem->table_name);
}
else
my_message(ER_SUBSELECT_NO_1_COL, ER(ER_SUBSELECT_NO_1_COL),
MYF(0));
else
my_error(ER_NO_TABLES_USED, MYF(0));
}
else
res= item->fix_fields(thd, list, &item);
......
......@@ -33,7 +33,7 @@ SUBSELECT TODO:
#include "sql_select.h"
Item_subselect::Item_subselect():
Item_result_field(), engine_owner(1), value_assigned(0)
Item_result_field(), engine_owner(1), value_assigned(0), substitution(0)
{
assign_null();
/*
......@@ -89,6 +89,13 @@ void Item_subselect::make_field (Send_field *tmp_field)
bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
if (substitution)
{
(*ref)= substitution;
engine->exclude();
return substitution->fix_fields(thd, tables, ref);
}
char const *save_where= thd->where;
int res= engine->prepare();
if (!res)
......@@ -291,12 +298,12 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
else
item= (Item*) sl->item_list.pop();
left_expr= new Item_outer_select_context_saver(left_expr);
Item *expr= new Item_outer_select_context_saver(left_expr);
if (sl->having || sl->with_sum_func || sl->group_list.first)
{
sl->item_list.push_back(item);
item= (*func)(left_expr, new Item_ref(sl->item_list.head_ref(),
item= (*func)(expr, new Item_ref(sl->item_list.head_ref(),
0, "<result>"));
if (sl->having)
sl->having= new Item_cond_and(sl->having, item);
......@@ -307,12 +314,43 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
{
sl->item_list.empty();
sl->item_list.push_back(new Item_int(1));
item= (*func)(left_expr, new Item_asterisk_remover(item));
if (sl->table_list.elements)
{
item= (*func)(expr, new Item_asterisk_remover(item));
if (sl->where)
sl->where= new Item_cond_and(sl->where, item);
else
sl->where= item;
}
else
{
if (item->type() == Item::FIELD_ITEM &&
((Item_field*) item)->field_name[0] == '*')
{
my_error(ER_NO_TABLES_USED, MYF(0));
DBUG_VOID_RETURN;
}
if (select_lex->next_select())
{
// it is in union => we should perform it
sl->having= (*func)(expr, item);
}
else
{
// it is single select without tables => possible optimization
item= (*func)(left_expr, item);
substitution= item;
THD *thd= current_thd;
if (thd->lex.describe)
{
char warn_buff[MYSQL_ERRMSG_SIZE];
sprintf(warn_buff, ER(ER_SELECT_REDUCED), sl->select_number);
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_SELECT_REDUCED, warn_buff);
}
}
}
}
}
DBUG_VOID_RETURN;
}
......@@ -502,3 +540,17 @@ bool subselect_union_engine::check_loop(uint id)
DBUG_RETURN(1);
DBUG_RETURN(0);
}
void subselect_single_select_engine::exclude()
{
select_lex->master_unit()->exclude_level();
//if (current_thd->lex->describe)
}
void subselect_union_engine::exclude()
{
unit->exclude_level();
// for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select())
// if (sl->join && sl->join->check_loop(id))
// DBUG_RETURN(1);
}
......@@ -36,6 +36,8 @@ class Item_subselect :public Item_result_field
my_bool engine_owner; /* Is this item owner of engine */
my_bool value_assigned; /* value already assigned to subselect */
protected:
/* substitution instead of subselect in case of optimization */
Item *substitution;
/* engine that perform execution of subselect (single select or union) */
subselect_engine *engine;
/* allowed number of columns (1 for single value subqueries) */
......@@ -45,6 +47,7 @@ public:
Item_subselect();
Item_subselect(Item_subselect *item)
{
substitution= item->substitution;
null_value= item->null_value;
decimals= item->decimals;
max_columns= item->max_columns;
......@@ -213,6 +216,7 @@ public:
virtual bool depended()= 0; /* depended from outer select */
enum Item_result type() { return res_type; }
virtual bool check_loop(uint id)= 0;
virtual void exclude()= 0;
};
class subselect_single_select_engine: public subselect_engine
......@@ -232,6 +236,7 @@ public:
uint cols();
bool depended();
bool check_loop(uint id);
void exclude();
};
class subselect_union_engine: public subselect_engine
......@@ -248,4 +253,5 @@ public:
uint cols();
bool depended();
bool check_loop(uint id);
void exclude();
};
......@@ -256,3 +256,4 @@
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
"Select %u was reduced during optimisation",
......@@ -250,3 +250,4 @@
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
"Select %u was reduced during optimisation",
......@@ -258,3 +258,4 @@
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
"Select %u was reduced during optimisation",
......@@ -247,3 +247,4 @@
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
"Select %u was reduced during optimisation",
......@@ -252,3 +252,4 @@
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
"Select %u was reduced during optimisation",
......@@ -247,3 +247,4 @@
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
"Select %u was reduced during optimisation",
......@@ -250,3 +250,4 @@
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
"Select %u was reduced during optimisation",
......@@ -247,3 +247,4 @@
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
"Select %u was reduced during optimisation",
......@@ -249,3 +249,4 @@
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
"Select %u was reduced during optimisation",
......@@ -247,3 +247,4 @@
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
"Select %u was reduced during optimisation",
......@@ -249,3 +249,4 @@
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
"Select %u was reduced during optimisation",
......@@ -247,3 +247,4 @@
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
"Select %u was reduced during optimisation",
......@@ -249,3 +249,4 @@
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
"Select %u was reduced during optimisation",
......@@ -249,3 +249,4 @@
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
"Select %u was reduced during optimisation",
......@@ -251,3 +251,4 @@
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
"Select %u was reduced during optimisation",
......@@ -247,3 +247,4 @@
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
"Select %u was reduced during optimisation",
......@@ -251,3 +251,4 @@
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s"
"Reference '%-.64s' not supported (%s)",
"Select %u was reduced during optimisation",
......@@ -250,3 +250,4 @@
" ",
" '%s' %s %s",
" '%-.64s' (%s)",
"Select %u ",
......@@ -243,3 +243,4 @@
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
"Select %u was reduced during optimisation",
......@@ -255,3 +255,4 @@
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
"Select %u was reduced during optimisation",
......@@ -248,3 +248,4 @@
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
"Reference '%-.64s' not supported (%s)",
"Select %u was reduced during optimisation",
......@@ -247,3 +247,4 @@
"Syklisk referens i subselect",
"Konvertar kolumn '%s' från %s till %s",
"Reference '%-.64s' not supported (%s)",
"Select %u was reduced during optimisation",
......@@ -252,3 +252,4 @@
"i i",
" '%s' %s %s",
" '%-.64s' i (%s)",
"Select %u was iii",
......@@ -2082,7 +2082,7 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields,
while ((item=it++))
{
if (item->type() == Item::FIELD_ITEM &&
if (item->type() == Item::FIELD_ITEM && ((Item_field*) item)->field_name &&
((Item_field*) item)->field_name[0] == '*')
{
uint elem= fields.elements;
......
......@@ -1058,6 +1058,31 @@ void st_select_lex_node::exclude()
*/
}
void st_select_lex_unit::exclude_level()
{
SELECT_LEX_UNIT *units= 0, **units_last= &units;
for(SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
{
if (sl->link_prev && (*sl->link_prev= sl->link_next))
sl->link_next->link_prev= sl->link_prev;
SELECT_LEX_UNIT **last= 0;
for (SELECT_LEX_UNIT *u= sl->first_inner_unit(); u; u= u->next_unit())
last= (SELECT_LEX_UNIT**)&(u->next);
if (last)
{
(*units_last)= sl->first_inner_unit();
units_last= last;
}
}
if (units)
{
(*prev)= units;
(*units_last)= (SELECT_LEX_UNIT*)next;
}
else
(*prev)= next;
}
st_select_lex* st_select_lex_node::select_lex()
{
DBUG_ENTER("st_select_lex_node::select_lex (never should be called)");
......
......@@ -242,6 +242,8 @@ public:
List<String> *ignore_index= 0);
virtual void set_lock_for_tables(thr_lock_type lock_type) {}
void mark_as_dependent(st_select_lex *last);
friend class st_select_lex_unit;
private:
void fast_exclude();
};
......@@ -288,6 +290,7 @@ public:
st_select_lex* outer_select();
st_select_lex* first_select() { return (st_select_lex*) slave; }
st_select_lex_unit* next_unit() { return (st_select_lex_unit*) next; }
void st_select_lex_unit::exclude_level();
/* UNION methods */
int prepare(THD *thd, select_result *result);
......
......@@ -1329,7 +1329,6 @@ mysql_execute_command(THD *thd)
*/
thd->old_total_warn_count= thd->total_warn_count;
thd->net.report_error= 0;
if (thd->slave_thread)
{
/*
......@@ -2957,6 +2956,8 @@ mysql_parse(THD *thd, char *inBuf, uint length)
mysql_init_query(thd);
thd->query_length = length;
thd->net.report_error= 0;
if (query_cache_send_result_to_client(thd, inBuf, length) <= 0)
{
LEX *lex=lex_start(thd, (uchar*) inBuf, length);
......@@ -2968,11 +2969,16 @@ mysql_parse(THD *thd, char *inBuf, uint length)
thd->net.error = 0;
}
else
{
if (thd->net.report_error)
send_error(thd, 0, NullS);
else
{
mysql_execute_command(thd);
query_cache_end_of_result(&thd->net);
}
}
}
else
{
DBUG_PRINT("info",("Command aborted. Fatal_error: %d",
......
......@@ -214,7 +214,11 @@ int st_select_lex_unit::exec()
if (dependent || !item || !item->assigned())
{
if (optimized && item && item->assigned())
{
item->assigned(0); // We will reinit & rexecute unit
item->assign_null();
table->file->delete_all_rows();
}
for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
{
thd->lex.current_select= sl;
......
......@@ -3323,11 +3323,10 @@ describe:
YYABORT;
}
opt_describe_column
| describe_command select
| describe_command { Lex->describe=1; } select
{
LEX *lex=Lex;
lex->select_lex.options|= SELECT_DESCRIBE;
lex->describe=1;
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment