mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Merge sanja.is.com.ua:/home/bell/mysql/mysql-4.1
into sanja.is.com.ua:/home/bell/mysql/work-in-4.1
This commit is contained in:
@ -99,6 +99,17 @@ select * from t3 where not exists (select * from t2 where t2.b=t3.a);
|
|||||||
a
|
a
|
||||||
6
|
6
|
||||||
3
|
3
|
||||||
|
select * from t3 where a in (select b from t2);
|
||||||
|
a
|
||||||
|
7
|
||||||
|
select * from t3 where a not in (select b from t2);
|
||||||
|
a
|
||||||
|
6
|
||||||
|
3
|
||||||
|
select * from t3 where a in (select a,b from t2);
|
||||||
|
Subselect returns more than 1 field
|
||||||
|
select * from t3 where a in (select * from t2);
|
||||||
|
Subselect returns more than 1 field
|
||||||
insert into t4 values (12,7),(1,7),(10,9),(9,6),(7,6),(3,9);
|
insert into t4 values (12,7),(1,7),(10,9),(9,6),(7,6),(3,9);
|
||||||
select b,max(a) as ma from t4 group by b having b < (select max(t2.a)
|
select b,max(a) as ma from t4 group by b having b < (select max(t2.a)
|
||||||
from t2 where t2.b=t4.b);
|
from t2 where t2.b=t4.b);
|
||||||
|
@ -34,6 +34,12 @@ select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2
|
|||||||
explain select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) from t4;
|
explain select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) from t4;
|
||||||
select * from t3 where exists (select * from t2 where t2.b=t3.a);
|
select * from t3 where exists (select * from t2 where t2.b=t3.a);
|
||||||
select * from t3 where not exists (select * from t2 where t2.b=t3.a);
|
select * from t3 where not exists (select * from t2 where t2.b=t3.a);
|
||||||
|
select * from t3 where a in (select b from t2);
|
||||||
|
select * from t3 where a not in (select b from t2);
|
||||||
|
-- error 1239
|
||||||
|
select * from t3 where a in (select a,b from t2);
|
||||||
|
-- error 1239
|
||||||
|
select * from t3 where a in (select * from t2);
|
||||||
insert into t4 values (12,7),(1,7),(10,9),(9,6),(7,6),(3,9);
|
insert into t4 values (12,7),(1,7),(10,9),(9,6),(7,6),(3,9);
|
||||||
select b,max(a) as ma from t4 group by b having b < (select max(t2.a)
|
select b,max(a) as ma from t4 group by b having b < (select max(t2.a)
|
||||||
from t2 where t2.b=t4.b);
|
from t2 where t2.b=t4.b);
|
||||||
|
47
sql/item.cc
47
sql/item.cc
@ -424,6 +424,53 @@ bool Item::fix_fields(THD *thd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Item_outer_select_context_saver::fix_fields(THD *thd,
|
||||||
|
struct st_table_list *list,
|
||||||
|
Item ** ref)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("Item_outer_select_context_saver::fix_fields");
|
||||||
|
bool res= item->fix_fields(thd,
|
||||||
|
0, // do not show current subselect fields
|
||||||
|
&item);
|
||||||
|
*ref= item;
|
||||||
|
DBUG_RETURN(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Item_asterisk_remover::fix_fields(THD *thd,
|
||||||
|
struct st_table_list *list,
|
||||||
|
Item ** ref)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("Item_asterisk_remover::fix_fields");
|
||||||
|
|
||||||
|
bool res;
|
||||||
|
if (item)
|
||||||
|
if (item->type() == Item::FIELD_ITEM &&
|
||||||
|
((Item_field*) item)->field_name[0] == '*')
|
||||||
|
{
|
||||||
|
List<Item> fields;
|
||||||
|
fields.push_back(item);
|
||||||
|
List_iterator<Item> it(fields);
|
||||||
|
it++;
|
||||||
|
uint elem=fields.elements;
|
||||||
|
if (insert_fields(thd, list, ((Item_field*) item)->db_name,
|
||||||
|
((Item_field*) item)->table_name, &it))
|
||||||
|
res= -1;
|
||||||
|
else
|
||||||
|
if (fields.elements > 1)
|
||||||
|
{
|
||||||
|
my_message(ER_SUBSELECT_NO_1_COL, ER(ER_SUBSELECT_NO_1_COL), MYF(0));
|
||||||
|
res= -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
res= item->fix_fields(thd, list, &item);
|
||||||
|
else
|
||||||
|
res= -1;
|
||||||
|
*ref= item;
|
||||||
|
DBUG_RETURN(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||||
{
|
{
|
||||||
if (!field) // If field is not checked
|
if (!field) // If field is not checked
|
||||||
|
49
sql/item.h
49
sql/item.h
@ -90,6 +90,55 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Wrapper base class
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Item_wrapper :public Item
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
Item *item;
|
||||||
|
public:
|
||||||
|
/*
|
||||||
|
Following methods should not be used, because fix_fields exclude this
|
||||||
|
item (it assign '*ref' with field 'item' in derived classes)
|
||||||
|
*/
|
||||||
|
enum Type type() const { return item->type(); }
|
||||||
|
double val() { return item->val(); }
|
||||||
|
longlong val_int() { return item->val_int(); }
|
||||||
|
String* val_str(String* s) { return item->val_str(s); }
|
||||||
|
void make_field(Send_field* f) { item->make_field(f); }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Save context of name resolution for Item, used in subselect transformer.
|
||||||
|
*/
|
||||||
|
class Item_outer_select_context_saver :public Item_wrapper
|
||||||
|
{
|
||||||
|
Item *item;
|
||||||
|
public:
|
||||||
|
Item_outer_select_context_saver(Item *i):
|
||||||
|
item(i)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
bool fix_fields(THD *, struct st_table_list *, Item ** ref);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
To resolve '*' field moved to condition
|
||||||
|
*/
|
||||||
|
class Item_asterisk_remover :public Item_wrapper
|
||||||
|
{
|
||||||
|
Item *item;
|
||||||
|
public:
|
||||||
|
Item_asterisk_remover(Item *i):
|
||||||
|
item(i)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
bool fix_fields(THD *, struct st_table_list *, Item ** ref);
|
||||||
|
};
|
||||||
|
|
||||||
class st_select_lex;
|
class st_select_lex;
|
||||||
class Item_ident :public Item
|
class Item_ident :public Item
|
||||||
{
|
{
|
||||||
|
@ -44,12 +44,13 @@ Item_subselect::Item_subselect():
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Item_subselect::init(THD *thd, st_select_lex *select_lex,
|
void Item_subselect::init(THD *thd, st_select_lex *select_lex,
|
||||||
select_subselect *result)
|
select_subselect *result, Item *left_expr)
|
||||||
{
|
{
|
||||||
|
|
||||||
DBUG_ENTER("Item_subselect::init");
|
DBUG_ENTER("Item_subselect::init");
|
||||||
DBUG_PRINT("subs", ("select_lex 0x%xl", (long) select_lex));
|
DBUG_PRINT("subs", ("select_lex 0x%xl", (ulong) select_lex));
|
||||||
|
|
||||||
|
select_transformer(select_lex, left_expr);
|
||||||
if (select_lex->next_select())
|
if (select_lex->next_select())
|
||||||
engine= new subselect_union_engine(thd, select_lex->master_unit(), result,
|
engine= new subselect_union_engine(thd, select_lex->master_unit(), result,
|
||||||
this);
|
this);
|
||||||
@ -65,6 +66,14 @@ Item_subselect::~Item_subselect()
|
|||||||
delete engine;
|
delete engine;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Item_subselect::select_transformer(st_select_lex *select_lex,
|
||||||
|
Item *left_expr)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("Item_subselect::select_transformer");
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Item_subselect::make_field (Send_field *tmp_field)
|
void Item_subselect::make_field (Send_field *tmp_field)
|
||||||
{
|
{
|
||||||
if (null_value)
|
if (null_value)
|
||||||
@ -109,9 +118,11 @@ Item_singleval_subselect::Item_singleval_subselect(THD *thd,
|
|||||||
st_select_lex *select_lex):
|
st_select_lex *select_lex):
|
||||||
Item_subselect()
|
Item_subselect()
|
||||||
{
|
{
|
||||||
init(thd, select_lex, new select_singleval_subselect(this));
|
DBUG_ENTER("Item_singleval_subselect::Item_singleval_subselect");
|
||||||
|
init(thd, select_lex, new select_singleval_subselect(this), 0);
|
||||||
max_columns= 1;
|
max_columns= 1;
|
||||||
maybe_null= 1;
|
maybe_null= 1;
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Item_singleval_subselect::fix_length_and_dec()
|
void Item_singleval_subselect::fix_length_and_dec()
|
||||||
@ -156,17 +167,37 @@ String *Item_singleval_subselect::val_str (String *str)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Item_exists_subselect::Item_exists_subselect(THD *thd,
|
Item_exists_subselect::Item_exists_subselect(THD *thd,
|
||||||
st_select_lex *select_lex):
|
st_select_lex *select_lex,
|
||||||
|
Item *left_expr):
|
||||||
Item_subselect()
|
Item_subselect()
|
||||||
{
|
{
|
||||||
init(thd, select_lex, new select_exists_subselect(this));
|
DBUG_ENTER("Item_exists_subselect::Item_exists_subselect");
|
||||||
|
init(thd, select_lex, new select_exists_subselect(this), left_expr);
|
||||||
max_columns= UINT_MAX;
|
max_columns= UINT_MAX;
|
||||||
null_value= 0; //can't be NULL
|
null_value= 0; //can't be NULL
|
||||||
maybe_null= 0; //can't be NULL
|
maybe_null= 0; //can't be NULL
|
||||||
value= 0;
|
value= 0;
|
||||||
select_lex->select_limit= 1; // we need only 1 row to determinate existence
|
// We need only 1 row to determinate existence
|
||||||
|
select_lex->master_unit()->global_parameters->select_limit= 1;
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Item_in_subselect::Item_in_subselect(THD *thd, Item * left_expr,
|
||||||
|
st_select_lex *select_lex):
|
||||||
|
Item_exists_subselect()
|
||||||
|
{
|
||||||
|
DBUG_ENTER("Item_in_subselect::Item_in_subselect");
|
||||||
|
init(thd, select_lex, new select_exists_subselect(this), left_expr);
|
||||||
|
max_columns= UINT_MAX;
|
||||||
|
null_value= 0; //can't be NULL
|
||||||
|
maybe_null= 0; //can't be NULL
|
||||||
|
value= 0;
|
||||||
|
// We need only 1 row to determinate existence
|
||||||
|
select_lex->master_unit()->global_parameters->select_limit= 1;
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Item_exists_subselect::fix_length_and_dec()
|
void Item_exists_subselect::fix_length_and_dec()
|
||||||
{
|
{
|
||||||
max_length= 1;
|
max_length= 1;
|
||||||
@ -204,6 +235,37 @@ String *Item_exists_subselect::val_str(String *str)
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Item_in_subselect::Item_in_subselect(Item_in_subselect *item):
|
||||||
|
Item_exists_subselect(item)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Item_in_subselect::select_transformer(st_select_lex *select_lex,
|
||||||
|
Item *left_expr)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("Item_in_subselect::select_transformer");
|
||||||
|
for(SELECT_LEX * sl= select_lex; sl; sl= sl->next_select())
|
||||||
|
{
|
||||||
|
Item *item;
|
||||||
|
if (sl->item_list.elements > 1)
|
||||||
|
{
|
||||||
|
my_message(ER_SUBSELECT_NO_1_COL, ER(ER_SUBSELECT_NO_1_COL), MYF(0));
|
||||||
|
item= 0; // Item_asterisk_remover mast fail
|
||||||
|
}
|
||||||
|
else
|
||||||
|
item= (Item*) sl->item_list.pop();
|
||||||
|
sl->item_list.empty();
|
||||||
|
sl->item_list.push_back(new Item_int(1));
|
||||||
|
left_expr= new Item_outer_select_context_saver(left_expr);
|
||||||
|
item= new Item_asterisk_remover(item);
|
||||||
|
if (sl->where)
|
||||||
|
sl->where= new Item_cond_and(sl->where,
|
||||||
|
new Item_func_eq(item, left_expr));
|
||||||
|
else
|
||||||
|
sl->where= new Item_func_eq(item, left_expr);
|
||||||
|
}
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
subselect_single_select_engine::subselect_single_select_engine(THD *thd,
|
subselect_single_select_engine::subselect_single_select_engine(THD *thd,
|
||||||
st_select_lex *select,
|
st_select_lex *select,
|
||||||
|
@ -55,13 +55,16 @@ public:
|
|||||||
pointer in constructor initialization list, but we need pass pointer
|
pointer in constructor initialization list, but we need pass pointer
|
||||||
to subselect Item class to select_subselect classes constructor.
|
to subselect Item class to select_subselect classes constructor.
|
||||||
*/
|
*/
|
||||||
void init (THD *thd, st_select_lex *select_lex, select_subselect *result);
|
virtual void init (THD *thd, st_select_lex *select_lex,
|
||||||
|
select_subselect *result,
|
||||||
|
Item *left_expr= 0);
|
||||||
|
|
||||||
~Item_subselect();
|
~Item_subselect();
|
||||||
virtual void assign_null()
|
virtual void assign_null()
|
||||||
{
|
{
|
||||||
null_value= 1;
|
null_value= 1;
|
||||||
}
|
}
|
||||||
|
virtual void select_transformer(st_select_lex *select_lex, Item *left_expr);
|
||||||
bool assigned() { return value_assigned; }
|
bool assigned() { return value_assigned; }
|
||||||
void assigned(bool a) { value_assigned= a; }
|
void assigned(bool a) { value_assigned= a; }
|
||||||
enum Type type() const;
|
enum Type type() const;
|
||||||
@ -74,7 +77,6 @@ public:
|
|||||||
friend class select_subselect;
|
friend class select_subselect;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* single value subselect */
|
/* single value subselect */
|
||||||
|
|
||||||
class Item_singleval_subselect :public Item_subselect
|
class Item_singleval_subselect :public Item_subselect
|
||||||
@ -127,12 +129,15 @@ protected:
|
|||||||
longlong value; /* value of this item (boolean: exists/not-exists) */
|
longlong value; /* value of this item (boolean: exists/not-exists) */
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Item_exists_subselect(THD *thd, st_select_lex *select_lex);
|
Item_exists_subselect(THD *thd, st_select_lex *select_lex,
|
||||||
|
Item *left_expr= 0);
|
||||||
Item_exists_subselect(Item_exists_subselect *item):
|
Item_exists_subselect(Item_exists_subselect *item):
|
||||||
Item_subselect(item)
|
Item_subselect(item)
|
||||||
{
|
{
|
||||||
value= item->value;
|
value= item->value;
|
||||||
}
|
}
|
||||||
|
Item_exists_subselect(): Item_subselect() {}
|
||||||
|
|
||||||
virtual void assign_null()
|
virtual void assign_null()
|
||||||
{
|
{
|
||||||
value= 0;
|
value= 0;
|
||||||
@ -147,6 +152,16 @@ public:
|
|||||||
friend class select_exists_subselect;
|
friend class select_exists_subselect;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* IN subselect */
|
||||||
|
|
||||||
|
class Item_in_subselect :public Item_exists_subselect
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Item_in_subselect(THD *thd, Item * left_expr, st_select_lex *select_lex);
|
||||||
|
Item_in_subselect(Item_in_subselect *item);
|
||||||
|
virtual void select_transformer(st_select_lex *select_lex, Item *left_exp);
|
||||||
|
};
|
||||||
|
|
||||||
class subselect_engine
|
class subselect_engine
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
@ -70,6 +70,7 @@ inline Item *or_or_concat(Item* A, Item* B)
|
|||||||
enum Item_udftype udf_type;
|
enum Item_udftype udf_type;
|
||||||
CHARSET_INFO *charset;
|
CHARSET_INFO *charset;
|
||||||
interval_type interval;
|
interval_type interval;
|
||||||
|
st_select_lex *select_lex;
|
||||||
}
|
}
|
||||||
|
|
||||||
%{
|
%{
|
||||||
@ -530,7 +531,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
|
|||||||
|
|
||||||
%type <lex_str>
|
%type <lex_str>
|
||||||
IDENT TEXT_STRING REAL_NUM FLOAT_NUM NUM LONG_NUM HEX_NUM LEX_HOSTNAME
|
IDENT TEXT_STRING REAL_NUM FLOAT_NUM NUM LONG_NUM HEX_NUM LEX_HOSTNAME
|
||||||
ULONGLONG_NUM field_ident select_alias ident ident_or_text UNDERSCORE_CHARSET
|
ULONGLONG_NUM field_ident select_alias ident ident_or_text
|
||||||
|
UNDERSCORE_CHARSET
|
||||||
|
|
||||||
%type <lex_str_ptr>
|
%type <lex_str_ptr>
|
||||||
opt_table_alias
|
opt_table_alias
|
||||||
@ -612,6 +614,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
|
|||||||
|
|
||||||
%type <variable> internal_variable_name
|
%type <variable> internal_variable_name
|
||||||
|
|
||||||
|
%type <select_lex> in_subselect in_subselect_init
|
||||||
|
|
||||||
%type <NONE>
|
%type <NONE>
|
||||||
query verb_clause create change select do drop insert replace insert2
|
query verb_clause create change select do drop insert replace insert2
|
||||||
insert_values update delete truncate rename
|
insert_values update delete truncate rename
|
||||||
@ -1719,10 +1723,16 @@ expr: expr_expr { $$= $1; }
|
|||||||
|
|
||||||
/* expressions that begin with 'expr' */
|
/* expressions that begin with 'expr' */
|
||||||
expr_expr:
|
expr_expr:
|
||||||
expr IN_SYM '(' expr_list ')'
|
expr IN_SYM '(' expr_list ')'
|
||||||
{ $$= new Item_func_in($1,*$4); }
|
{ $$= new Item_func_in($1,*$4); }
|
||||||
| expr NOT IN_SYM '(' expr_list ')'
|
| expr NOT IN_SYM '(' expr_list ')'
|
||||||
{ $$= new Item_func_not(new Item_func_in($1,*$5)); }
|
{ $$= new Item_func_not(new Item_func_in($1,*$5)); }
|
||||||
|
| expr IN_SYM in_subselect
|
||||||
|
{ $$= new Item_in_subselect(current_thd, $1, $3); }
|
||||||
|
| expr NOT IN_SYM in_subselect
|
||||||
|
{
|
||||||
|
$$= new Item_func_not(new Item_in_subselect(current_thd, $1, $4));
|
||||||
|
}
|
||||||
| expr BETWEEN_SYM no_and_expr AND expr
|
| expr BETWEEN_SYM no_and_expr AND expr
|
||||||
{ $$= new Item_func_between($1,$3,$5); }
|
{ $$= new Item_func_between($1,$3,$5); }
|
||||||
| expr NOT BETWEEN_SYM no_and_expr AND expr
|
| expr NOT BETWEEN_SYM no_and_expr AND expr
|
||||||
@ -1802,10 +1812,16 @@ no_in_expr:
|
|||||||
|
|
||||||
/* expressions that begin with 'expr' that does NOT follow AND */
|
/* expressions that begin with 'expr' that does NOT follow AND */
|
||||||
no_and_expr:
|
no_and_expr:
|
||||||
no_and_expr IN_SYM '(' expr_list ')'
|
no_and_expr IN_SYM '(' expr_list ')'
|
||||||
{ $$= new Item_func_in($1,*$4); }
|
{ $$= new Item_func_in($1,*$4); }
|
||||||
| no_and_expr NOT IN_SYM '(' expr_list ')'
|
| no_and_expr NOT IN_SYM '(' expr_list ')'
|
||||||
{ $$= new Item_func_not(new Item_func_in($1,*$5)); }
|
{ $$= new Item_func_not(new Item_func_in($1,*$5)); }
|
||||||
|
| no_and_expr IN_SYM in_subselect
|
||||||
|
{ $$= new Item_in_subselect(current_thd, $1, $3); }
|
||||||
|
| no_and_expr NOT IN_SYM in_subselect
|
||||||
|
{
|
||||||
|
$$= new Item_func_not(new Item_in_subselect(current_thd, $1, $4));
|
||||||
|
}
|
||||||
| no_and_expr BETWEEN_SYM no_and_expr AND expr
|
| no_and_expr BETWEEN_SYM no_and_expr AND expr
|
||||||
{ $$= new Item_func_between($1,$3,$5); }
|
{ $$= new Item_func_between($1,$3,$5); }
|
||||||
| no_and_expr NOT BETWEEN_SYM no_and_expr AND expr
|
| no_and_expr NOT BETWEEN_SYM no_and_expr AND expr
|
||||||
@ -4193,6 +4209,19 @@ exists_subselect_init:
|
|||||||
Lex->select->master_unit()->first_select());
|
Lex->select->master_unit()->first_select());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
in_subselect:
|
||||||
|
subselect_start in_subselect_init
|
||||||
|
subselect_end
|
||||||
|
{
|
||||||
|
$$= $2;
|
||||||
|
};
|
||||||
|
|
||||||
|
in_subselect_init:
|
||||||
|
select_init
|
||||||
|
{
|
||||||
|
$$= Lex->select->master_unit()->first_select();
|
||||||
|
};
|
||||||
|
|
||||||
subselect_start:
|
subselect_start:
|
||||||
'('
|
'('
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user