mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 12:02:42 +01:00
support of subselect without FROM reducing (SCRUM)
fixed bug of calling setup_fields without correct lex->current_select pointer in mysql_derived more correct creation of reference in Item_field::fix_field mysql-test/r/subselect.result: new explain with subselect reduced mysql-test/t/subselect.test: new explain with subselect reduced sql/item.cc: support of subselect without FROM reducing more correct creation of reference in Item_field::fix_field sql/item.h: support of subselect without FROM reducing sql/item_cmpfunc.cc: support of subselect without FROM reducing sql/item_cmpfunc.h: support of subselect without FROM reducing sql/item_func.cc: support of subselect without FROM reducing sql/item_func.h: support of subselect without FROM reducing sql/item_row.cc: support of subselect without FROM reducing sql/item_row.h: support of subselect without FROM reducing sql/item_strfunc.h: fixed layout support of subselect without FROM reducing sql/item_subselect.cc: support of subselect without FROM reducing sql/item_subselect.h: support of subselect without FROM reducing sql/mysql_priv.h: reference in Item_field::fix_field related changes sql/sql_base.cc: reference in Item_field::fix_field related changes sql/sql_derived.cc: fixed bug of calling setup_fields without correct lex->current_select pointer
This commit is contained in:
parent
da4d8e1b62
commit
1dfa625f7b
16 changed files with 223 additions and 34 deletions
|
@ -1,13 +1,32 @@
|
||||||
select (select 2);
|
select (select 2);
|
||||||
(select 2)
|
(select 2)
|
||||||
2
|
2
|
||||||
|
explain select (select 2);
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
|
Warnings:
|
||||||
|
Note 1247 Select 2 was reduced during optimisation
|
||||||
SELECT (SELECT 1) UNION SELECT (SELECT 2);
|
SELECT (SELECT 1) UNION SELECT (SELECT 2);
|
||||||
(SELECT 1)
|
(SELECT 1)
|
||||||
1
|
1
|
||||||
2
|
2
|
||||||
|
explain SELECT (SELECT 1) UNION SELECT (SELECT 2);
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
|
3 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
|
Warnings:
|
||||||
|
Note 1247 Select 2 was reduced during optimisation
|
||||||
|
Note 1247 Select 4 was reduced during optimisation
|
||||||
SELECT (SELECT (SELECT 0 UNION SELECT 0));
|
SELECT (SELECT (SELECT 0 UNION SELECT 0));
|
||||||
(SELECT (SELECT 0 UNION SELECT 0))
|
(SELECT (SELECT 0 UNION SELECT 0))
|
||||||
0
|
0
|
||||||
|
explain SELECT (SELECT (SELECT 0 UNION SELECT 0));
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
|
3 SUBSELECT NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
|
4 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
|
Warnings:
|
||||||
|
Note 1247 Select 2 was reduced during optimisation
|
||||||
SELECT (SELECT 1 FROM (SELECT 1) as b HAVING a=1) as a;
|
SELECT (SELECT 1 FROM (SELECT 1) as b HAVING a=1) as a;
|
||||||
Reference 'a' not supported (forward reference in item list)
|
Reference 'a' not supported (forward reference in item list)
|
||||||
SELECT (SELECT 1 FROM (SELECT 1) as b HAVING b=1) as a,(SELECT 1 FROM (SELECT 1) as c HAVING a=1) as b;
|
SELECT (SELECT 1 FROM (SELECT 1) as b HAVING b=1) as a,(SELECT 1 FROM (SELECT 1) as c HAVING a=1) as b;
|
||||||
|
@ -20,8 +39,9 @@ Reference 'a' not supported (forward reference in item list)
|
||||||
EXPLAIN SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1;
|
EXPLAIN SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1;
|
||||||
id select_type table type possible_keys key key_len ref rows Extra
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
1 PRIMARY <derived2> system NULL NULL NULL NULL 1
|
1 PRIMARY <derived2> system NULL NULL NULL NULL 1
|
||||||
3 DEPENDENT SUBSELECT NULL NULL NULL NULL NULL NULL NULL No tables used
|
|
||||||
2 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
|
2 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
|
Warnings:
|
||||||
|
Note 1247 Select 3 was reduced during optimisation
|
||||||
SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1;
|
SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1;
|
||||||
1
|
1
|
||||||
1
|
1
|
||||||
|
@ -629,6 +649,7 @@ 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
|
1 PRIMARY t ref id id 5 const 1 Using where; Using index
|
||||||
3 SUBSELECT NULL NULL NULL NULL NULL NULL NULL No tables used
|
3 SUBSELECT NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
Warnings:
|
Warnings:
|
||||||
|
Note 1247 Select 3 was reduced during optimisation
|
||||||
Note 1247 Select 2 was reduced during optimisation
|
Note 1247 Select 2 was reduced during optimisation
|
||||||
EXPLAIN SELECT * FROM t WHERE id IN (SELECT 1 UNION SELECT 3);
|
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
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
@ -752,6 +773,16 @@ NULL
|
||||||
select 10.5 > ANY (SELECT * from t);
|
select 10.5 > ANY (SELECT * from t);
|
||||||
10.5 > ANY (SELECT * from t)
|
10.5 > ANY (SELECT * from t)
|
||||||
1
|
1
|
||||||
|
explain select (select a+1) from t;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t ALL NULL NULL NULL NULL 3
|
||||||
|
Warnings:
|
||||||
|
Note 1247 Select 2 was reduced during optimisation
|
||||||
|
select (select a+1) from t;
|
||||||
|
(select a+1)
|
||||||
|
2.5
|
||||||
|
NULL
|
||||||
|
4.5
|
||||||
drop table t;
|
drop table t;
|
||||||
create table t (a float);
|
create table t (a float);
|
||||||
select 10.5 IN (SELECT * from t LIMIT 1);
|
select 10.5 IN (SELECT * from t LIMIT 1);
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
select (select 2);
|
select (select 2);
|
||||||
|
explain select (select 2);
|
||||||
SELECT (SELECT 1) UNION SELECT (SELECT 2);
|
SELECT (SELECT 1) UNION SELECT (SELECT 2);
|
||||||
|
explain SELECT (SELECT 1) UNION SELECT (SELECT 2);
|
||||||
SELECT (SELECT (SELECT 0 UNION SELECT 0));
|
SELECT (SELECT (SELECT 0 UNION SELECT 0));
|
||||||
|
explain SELECT (SELECT (SELECT 0 UNION SELECT 0));
|
||||||
-- error 1245
|
-- error 1245
|
||||||
SELECT (SELECT 1 FROM (SELECT 1) as b HAVING a=1) as a;
|
SELECT (SELECT 1 FROM (SELECT 1) as b HAVING a=1) as a;
|
||||||
-- error 1245
|
-- error 1245
|
||||||
|
@ -424,6 +427,8 @@ select 1.5 > ALL (SELECT * from t);
|
||||||
select 10.5 > ALL (SELECT * from t);
|
select 10.5 > ALL (SELECT * from t);
|
||||||
select 1.5 > ANY (SELECT * from t);
|
select 1.5 > ANY (SELECT * from t);
|
||||||
select 10.5 > ANY (SELECT * from t);
|
select 10.5 > ANY (SELECT * from t);
|
||||||
|
explain select (select a+1) from t;
|
||||||
|
select (select a+1) from t;
|
||||||
drop table t;
|
drop table t;
|
||||||
|
|
||||||
#LIMIT is not supported now
|
#LIMIT is not supported now
|
||||||
|
@ -433,6 +438,7 @@ select 10.5 IN (SELECT * from t LIMIT 1);
|
||||||
-- error 1235
|
-- error 1235
|
||||||
select 10.5 IN (SELECT * from t LIMIT 1 UNION SELECT 1.5);
|
select 10.5 IN (SELECT * from t LIMIT 1 UNION SELECT 1.5);
|
||||||
drop table t;
|
drop table t;
|
||||||
|
|
||||||
create table t1 (a int, b int, c varchar(10));
|
create table t1 (a int, b int, c varchar(10));
|
||||||
create table t2 (a int);
|
create table t2 (a int);
|
||||||
insert into t1 values (1,2,'a'),(2,3,'b'),(3,4,'c');
|
insert into t1 values (1,2,'a'),(2,3,'b'),(3,4,'c');
|
||||||
|
|
42
sql/item.cc
42
sql/item.cc
|
@ -546,8 +546,11 @@ 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
|
||||||
{
|
{
|
||||||
Field *tmp;
|
TABLE_LIST *where= 0;
|
||||||
if ((tmp= find_field_in_tables(thd, this, tables, 0)) == not_found_field)
|
Field *tmp= (Field *)not_found_field;
|
||||||
|
if (outer_resolving ||
|
||||||
|
(tmp= find_field_in_tables(thd, this, tables, &where, 0)) ==
|
||||||
|
not_found_field)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
We can't find table field in table list of current select,
|
We can't find table field in table list of current select,
|
||||||
|
@ -565,12 +568,12 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||||
SELECT_LEX *cursel=(SELECT_LEX *) thd->lex.current_select;
|
SELECT_LEX *cursel=(SELECT_LEX *) thd->lex.current_select;
|
||||||
if (cursel->master_unit()->first_select()->linkage !=
|
if (cursel->master_unit()->first_select()->linkage !=
|
||||||
DERIVED_TABLE_TYPE)
|
DERIVED_TABLE_TYPE)
|
||||||
for (SELECT_LEX *sl=cursel->outer_select();
|
for (SELECT_LEX *sl=(outer_resolving?cursel:cursel->outer_select());
|
||||||
sl;
|
sl;
|
||||||
sl= sl->outer_select())
|
sl= sl->outer_select())
|
||||||
{
|
{
|
||||||
if ((tmp= find_field_in_tables(thd, this,
|
if ((tmp= find_field_in_tables(thd, this,
|
||||||
(last= sl)->get_table_list(),
|
(last= sl)->get_table_list(), &where,
|
||||||
0)) != not_found_field)
|
0)) != not_found_field)
|
||||||
break;
|
break;
|
||||||
if ((refer= find_item_in_list(this, sl->item_list,
|
if ((refer= find_item_in_list(this, sl->item_list,
|
||||||
|
@ -588,7 +591,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||||
else if (tmp == not_found_field && refer == (Item **)not_found_item)
|
else if (tmp == not_found_field && refer == (Item **)not_found_item)
|
||||||
{
|
{
|
||||||
// call to return error code
|
// call to return error code
|
||||||
find_field_in_tables(thd, this, tables, 1);
|
find_field_in_tables(thd, this, tables, &where, 1);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else if (refer != (Item **)not_found_item)
|
else if (refer != (Item **)not_found_item)
|
||||||
|
@ -614,6 +617,17 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||||
found table as depended (of select where was found table)
|
found table as depended (of select where was found table)
|
||||||
*/
|
*/
|
||||||
thd->lex.current_select->mark_as_dependent(last);
|
thd->lex.current_select->mark_as_dependent(last);
|
||||||
|
if (depended_from->having_fix_field)
|
||||||
|
{
|
||||||
|
Item_ref *rf;
|
||||||
|
*ref= rf= new Item_ref((where->db[0]?where->db:0),
|
||||||
|
(char *)where->alias,
|
||||||
|
(char *)field_name);
|
||||||
|
if (!rf)
|
||||||
|
return 1;
|
||||||
|
(rf)->outer_resolving= outer_resolving;
|
||||||
|
return rf->check_cols(1) || rf->fix_fields(thd, tables, ref);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!tmp)
|
else if (!tmp)
|
||||||
|
@ -629,14 +643,6 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||||
table->used_fields++;
|
table->used_fields++;
|
||||||
table->used_keys&=field->part_of_key;
|
table->used_keys&=field->part_of_key;
|
||||||
}
|
}
|
||||||
if (depended_from != 0 && depended_from->having_fix_field)
|
|
||||||
{
|
|
||||||
*ref= new Item_ref((char *)db_name, (char *)table_name,
|
|
||||||
(char *)field_name);
|
|
||||||
if (!*ref)
|
|
||||||
return 1;
|
|
||||||
return (*ref)->check_cols(1) || (*ref)->fix_fields(thd, tables, ref);
|
|
||||||
}
|
|
||||||
fixed= 1;
|
fixed= 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1007,13 +1013,17 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
|
||||||
{
|
{
|
||||||
if (!ref)
|
if (!ref)
|
||||||
{
|
{
|
||||||
SELECT_LEX *sl= thd->lex.current_select->outer_select();
|
TABLE_LIST *where= 0;
|
||||||
|
SELECT_LEX *sl= (outer_resolving?
|
||||||
|
thd->lex.current_select->select_lex():
|
||||||
|
thd->lex.current_select->outer_select());
|
||||||
/*
|
/*
|
||||||
Finding only in current select will be performed for selects that have
|
Finding only in current select will be performed for selects that have
|
||||||
not outer one and for derived tables (which not support using outer
|
not outer one and for derived tables (which not support using outer
|
||||||
fields for now)
|
fields for now)
|
||||||
*/
|
*/
|
||||||
if ((ref= find_item_in_list(this,
|
if (outer_resolving ||
|
||||||
|
(ref= find_item_in_list(this,
|
||||||
*(thd->lex.current_select->get_item_list()),
|
*(thd->lex.current_select->get_item_list()),
|
||||||
((sl &&
|
((sl &&
|
||||||
thd->lex.current_select->master_unit()->
|
thd->lex.current_select->master_unit()->
|
||||||
|
@ -1041,7 +1051,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
|
||||||
(Item **)not_found_item)
|
(Item **)not_found_item)
|
||||||
break;
|
break;
|
||||||
if ((tmp= find_field_in_tables(thd, this,
|
if ((tmp= find_field_in_tables(thd, this,
|
||||||
sl->get_table_list(),
|
sl->get_table_list(), &where,
|
||||||
0)) != not_found_field);
|
0)) != not_found_field);
|
||||||
if (sl->master_unit()->first_select()->linkage ==
|
if (sl->master_unit()->first_select()->linkage ==
|
||||||
DERIVED_TABLE_TYPE)
|
DERIVED_TABLE_TYPE)
|
||||||
|
|
|
@ -96,6 +96,7 @@ public:
|
||||||
CHARSET_INFO *thd_charset() const;
|
CHARSET_INFO *thd_charset() const;
|
||||||
CHARSET_INFO *charset() const { return str_value.charset(); };
|
CHARSET_INFO *charset() const { return str_value.charset(); };
|
||||||
void set_charset(CHARSET_INFO *cs) { str_value.set_charset(cs); }
|
void set_charset(CHARSET_INFO *cs) { str_value.set_charset(cs); }
|
||||||
|
virtual void set_outer_resolving() {}
|
||||||
|
|
||||||
// Row emulation
|
// Row emulation
|
||||||
virtual uint cols() { return 1; }
|
virtual uint cols() { return 1; }
|
||||||
|
@ -117,12 +118,14 @@ public:
|
||||||
const char *table_name;
|
const char *table_name;
|
||||||
const char *field_name;
|
const char *field_name;
|
||||||
st_select_lex *depended_from;
|
st_select_lex *depended_from;
|
||||||
|
bool outer_resolving; /* used for items from reduced subselect */
|
||||||
Item_ident(const char *db_name_par,const char *table_name_par,
|
Item_ident(const char *db_name_par,const char *table_name_par,
|
||||||
const char *field_name_par)
|
const char *field_name_par)
|
||||||
:db_name(db_name_par),table_name(table_name_par),
|
:db_name(db_name_par), table_name(table_name_par),
|
||||||
field_name(field_name_par), depended_from(0)
|
field_name(field_name_par), depended_from(0), outer_resolving(0)
|
||||||
{ name = (char*) field_name_par; }
|
{ name = (char*) field_name_par; }
|
||||||
const char *full_name() const;
|
const char *full_name() const;
|
||||||
|
void set_outer_resolving() { outer_resolving= 1; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -946,6 +946,13 @@ Item_func_case::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Item_func_case::set_outer_resolving()
|
||||||
|
{
|
||||||
|
first_expr->set_outer_resolving();
|
||||||
|
else_expr->set_outer_resolving();
|
||||||
|
Item_func::set_outer_resolving();
|
||||||
|
}
|
||||||
|
|
||||||
bool Item_func_case::check_loop(uint id)
|
bool Item_func_case::check_loop(uint id)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("Item_func_case::check_loop");
|
DBUG_ENTER("Item_func_case::check_loop");
|
||||||
|
@ -1523,6 +1530,15 @@ bool Item_cond::check_loop(uint id)
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Item_cond::set_outer_resolving()
|
||||||
|
{
|
||||||
|
Item_func::set_outer_resolving();
|
||||||
|
List_iterator<Item> li(list);
|
||||||
|
Item *item;
|
||||||
|
while ((item= li++))
|
||||||
|
item->set_outer_resolving();
|
||||||
|
}
|
||||||
|
|
||||||
void Item_cond::split_sum_func(List<Item> &fields)
|
void Item_cond::split_sum_func(List<Item> &fields)
|
||||||
{
|
{
|
||||||
List_iterator<Item> li(list);
|
List_iterator<Item> li(list);
|
||||||
|
|
|
@ -277,6 +277,11 @@ public:
|
||||||
const char *func_name() const { return "interval"; }
|
const char *func_name() const { return "interval"; }
|
||||||
void update_used_tables();
|
void update_used_tables();
|
||||||
bool check_loop(uint id);
|
bool check_loop(uint id);
|
||||||
|
void set_outer_resolving()
|
||||||
|
{
|
||||||
|
item->set_outer_resolving();
|
||||||
|
Item_func::set_outer_resolving();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -359,6 +364,7 @@ public:
|
||||||
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
|
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
|
||||||
Item *find_item(String *str);
|
Item *find_item(String *str);
|
||||||
bool check_loop(uint id);
|
bool check_loop(uint id);
|
||||||
|
void set_outer_resolving();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -643,6 +649,11 @@ class Item_func_in :public Item_int_func
|
||||||
DBUG_RETURN(item->check_loop(id));
|
DBUG_RETURN(item->check_loop(id));
|
||||||
}
|
}
|
||||||
bool nulls_in_row();
|
bool nulls_in_row();
|
||||||
|
void set_outer_resolving()
|
||||||
|
{
|
||||||
|
item->set_outer_resolving();
|
||||||
|
Item_int_func::set_outer_resolving();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Functions used by where clause */
|
/* Functions used by where clause */
|
||||||
|
@ -784,6 +795,7 @@ public:
|
||||||
friend int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds);
|
friend int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds);
|
||||||
bool check_loop(uint id);
|
bool check_loop(uint id);
|
||||||
void top_level_item() { abort_on_null=1; }
|
void top_level_item() { abort_on_null=1; }
|
||||||
|
void set_outer_resolving();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -146,6 +146,16 @@ bool Item_func::check_loop(uint id)
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Item_func::set_outer_resolving()
|
||||||
|
{
|
||||||
|
if (arg_count)
|
||||||
|
{
|
||||||
|
Item **arg,**arg_end;
|
||||||
|
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
|
||||||
|
(*arg)->set_outer_resolving();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Item_func::split_sum_func(List<Item> &fields)
|
void Item_func::split_sum_func(List<Item> &fields)
|
||||||
{
|
{
|
||||||
Item **arg,**arg_end;
|
Item **arg,**arg_end;
|
||||||
|
@ -2356,6 +2366,15 @@ bool Item_func_match::check_loop(uint id)
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Item_func_match::set_outer_resolving()
|
||||||
|
{
|
||||||
|
Item_real_func::set_outer_resolving();
|
||||||
|
List_iterator<Item> li(fields);
|
||||||
|
Item *item;
|
||||||
|
while ((item= li++))
|
||||||
|
item->set_outer_resolving();
|
||||||
|
}
|
||||||
|
|
||||||
bool Item_func_match::fix_index()
|
bool Item_func_match::fix_index()
|
||||||
{
|
{
|
||||||
List_iterator_fast<Item> li(fields);
|
List_iterator_fast<Item> li(fields);
|
||||||
|
|
|
@ -133,6 +133,7 @@ public:
|
||||||
friend class udf_handler;
|
friend class udf_handler;
|
||||||
Field *tmp_table_field(TABLE *t_arg);
|
Field *tmp_table_field(TABLE *t_arg);
|
||||||
bool check_loop(uint id);
|
bool check_loop(uint id);
|
||||||
|
void set_outer_resolving();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -632,6 +633,11 @@ public:
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
DBUG_RETURN(item->check_loop(id));
|
DBUG_RETURN(item->check_loop(id));
|
||||||
}
|
}
|
||||||
|
void set_outer_resolving()
|
||||||
|
{
|
||||||
|
item->set_outer_resolving();
|
||||||
|
Item_int_func::set_outer_resolving();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1006,6 +1012,7 @@ public:
|
||||||
bool fix_index();
|
bool fix_index();
|
||||||
void init_search(bool no_order);
|
void init_search(bool no_order);
|
||||||
bool check_loop(uint id);
|
bool check_loop(uint id);
|
||||||
|
void set_outer_resolving();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -105,5 +105,20 @@ void Item_row::bring_value()
|
||||||
{
|
{
|
||||||
for (uint i= 0; i < arg_count; i++)
|
for (uint i= 0; i < arg_count; i++)
|
||||||
items[i]->bring_value();
|
items[i]->bring_value();
|
||||||
return;
|
}
|
||||||
|
|
||||||
|
void Item_row::set_outer_resolving()
|
||||||
|
{
|
||||||
|
for (uint i= 0; i < arg_count; i++)
|
||||||
|
items[i]->set_outer_resolving();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Item_row::check_loop(uint id)
|
||||||
|
{
|
||||||
|
if (Item::check_loop(id))
|
||||||
|
return 1;
|
||||||
|
for (uint i= 0; i < arg_count; i++)
|
||||||
|
if (items[i]->check_loop(id))
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,8 @@ public:
|
||||||
bool const_item() const { return const_item_cache; };
|
bool const_item() const { return const_item_cache; };
|
||||||
enum Item_result result_type() const { return ROW_RESULT; }
|
enum Item_result result_type() const { return ROW_RESULT; }
|
||||||
void update_used_tables();
|
void update_used_tables();
|
||||||
|
bool check_loop(uint id);
|
||||||
|
void set_outer_resolving();
|
||||||
|
|
||||||
uint cols() { return arg_count; }
|
uint cols() { return arg_count; }
|
||||||
Item* el(uint i) { return items[i]; }
|
Item* el(uint i) { return items[i]; }
|
||||||
|
|
|
@ -108,14 +108,19 @@ public:
|
||||||
separator->fix_fields(thd, tlist, &separator) ||
|
separator->fix_fields(thd, tlist, &separator) ||
|
||||||
Item_func::fix_fields(thd, tlist, ref));
|
Item_func::fix_fields(thd, tlist, ref));
|
||||||
}
|
}
|
||||||
const char *func_name() const { return "concat_ws"; }
|
const char *func_name() const { return "concat_ws"; }
|
||||||
bool check_loop(uint id)
|
bool check_loop(uint id)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("Item_func_concat_ws::check_loop");
|
DBUG_ENTER("Item_func_concat_ws::check_loop");
|
||||||
if (Item_str_func::check_loop(id))
|
if (Item_str_func::check_loop(id))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
DBUG_RETURN(separator->check_loop(id));
|
DBUG_RETURN(separator->check_loop(id));
|
||||||
}
|
}
|
||||||
|
void set_outer_resolving()
|
||||||
|
{
|
||||||
|
separator->set_outer_resolving();
|
||||||
|
Item_func::set_outer_resolving();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Item_func_reverse :public Item_str_func
|
class Item_func_reverse :public Item_str_func
|
||||||
|
@ -393,6 +398,11 @@ public:
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
DBUG_RETURN(item->check_loop(id));
|
DBUG_RETURN(item->check_loop(id));
|
||||||
}
|
}
|
||||||
|
void set_outer_resolving()
|
||||||
|
{
|
||||||
|
item->set_outer_resolving();
|
||||||
|
Item_str_func::set_outer_resolving();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -421,6 +431,11 @@ public:
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
DBUG_RETURN(item->check_loop(id));
|
DBUG_RETURN(item->check_loop(id));
|
||||||
}
|
}
|
||||||
|
void set_outer_resolving()
|
||||||
|
{
|
||||||
|
item->set_outer_resolving();
|
||||||
|
Item_str_func::set_outer_resolving();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -146,6 +146,54 @@ void Item_singlerow_subselect::reset()
|
||||||
value->null_value= 1;
|
value->null_value= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Item_singlerow_subselect::select_transformer(st_select_lex_unit *unit)
|
||||||
|
{
|
||||||
|
SELECT_LEX *select_lex= unit->first_select();
|
||||||
|
|
||||||
|
if (!select_lex->next_select() && !select_lex->table_list.elements &&
|
||||||
|
select_lex->item_list.elements == 1)
|
||||||
|
{
|
||||||
|
|
||||||
|
have_to_be_excluded= 1;
|
||||||
|
THD *thd= current_thd;
|
||||||
|
if (thd->lex.describe)
|
||||||
|
{
|
||||||
|
char warn_buff[MYSQL_ERRMSG_SIZE];
|
||||||
|
sprintf(warn_buff, ER(ER_SELECT_REDUCED), select_lex->select_number);
|
||||||
|
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||||
|
ER_SELECT_REDUCED, warn_buff);
|
||||||
|
}
|
||||||
|
substitution= select_lex->item_list.head();
|
||||||
|
substitution->set_outer_resolving();
|
||||||
|
if (substitution->type() == FIELD_ITEM ||
|
||||||
|
substitution->type() == REF_ITEM)
|
||||||
|
name= substitution->name; // Save name for correct resolving
|
||||||
|
|
||||||
|
if (select_lex->where || select_lex->having)
|
||||||
|
{
|
||||||
|
Item *cond;
|
||||||
|
if (!select_lex->having)
|
||||||
|
cond= select_lex->where;
|
||||||
|
else if (!select_lex->where)
|
||||||
|
cond= select_lex->having;
|
||||||
|
else
|
||||||
|
if (!(cond= new Item_cond_and(select_lex->having, select_lex->where)))
|
||||||
|
{
|
||||||
|
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
|
||||||
|
thd->fatal_error= 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!(substitution= new Item_func_if(cond, substitution,
|
||||||
|
new Item_null())))
|
||||||
|
{
|
||||||
|
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
|
||||||
|
thd->fatal_error= 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Item_singlerow_subselect::store(uint i, Item *item)
|
void Item_singlerow_subselect::store(uint i, Item *item)
|
||||||
{
|
{
|
||||||
row[i]->store(item);
|
row[i]->store(item);
|
||||||
|
|
|
@ -106,6 +106,7 @@ public:
|
||||||
decimals= item->decimals;
|
decimals= item->decimals;
|
||||||
}
|
}
|
||||||
void reset();
|
void reset();
|
||||||
|
void select_transformer(st_select_lex_unit *unit);
|
||||||
void store(uint i, Item* item);
|
void store(uint i, Item* item);
|
||||||
double val();
|
double val();
|
||||||
longlong val_int ();
|
longlong val_int ();
|
||||||
|
|
|
@ -463,7 +463,7 @@ bool drop_locked_tables(THD *thd,const char *db, const char *table_name);
|
||||||
void abort_locked_tables(THD *thd,const char *db, const char *table_name);
|
void abort_locked_tables(THD *thd,const char *db, const char *table_name);
|
||||||
extern const Field *not_found_field;
|
extern const Field *not_found_field;
|
||||||
Field *find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
|
Field *find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
|
||||||
bool report_error);
|
TABLE_LIST **where, bool report_error);
|
||||||
Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
|
Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
|
||||||
bool check_grant,bool allow_rowid);
|
bool check_grant,bool allow_rowid);
|
||||||
#ifdef HAVE_OPENSSL
|
#ifdef HAVE_OPENSSL
|
||||||
|
|
|
@ -1654,6 +1654,7 @@ const Field *not_found_field= (Field*) 0x1;
|
||||||
thd - pointer to current thread structure
|
thd - pointer to current thread structure
|
||||||
item - field item that should be found
|
item - field item that should be found
|
||||||
tables - tables for scaning
|
tables - tables for scaning
|
||||||
|
where - table where field found will be returned via this parameter
|
||||||
report_error - if FALSE then do not report error if item not found and
|
report_error - if FALSE then do not report error if item not found and
|
||||||
return not_found_field;
|
return not_found_field;
|
||||||
|
|
||||||
|
@ -1667,7 +1668,7 @@ const Field *not_found_field= (Field*) 0x1;
|
||||||
|
|
||||||
Field *
|
Field *
|
||||||
find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
|
find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
|
||||||
bool report_error)
|
TABLE_LIST **where, bool report_error)
|
||||||
{
|
{
|
||||||
Field *found=0;
|
Field *found=0;
|
||||||
const char *db=item->db_name;
|
const char *db=item->db_name;
|
||||||
|
@ -1688,6 +1689,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
|
||||||
grant_option && !thd->master_access,1);
|
grant_option && !thd->master_access,1);
|
||||||
if (find)
|
if (find)
|
||||||
{
|
{
|
||||||
|
(*where)= tables;
|
||||||
if (find == WRONG_GRANT)
|
if (find == WRONG_GRANT)
|
||||||
return (Field*) 0;
|
return (Field*) 0;
|
||||||
if (db || !thd->where)
|
if (db || !thd->where)
|
||||||
|
@ -1742,6 +1744,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
|
||||||
{
|
{
|
||||||
if (field == WRONG_GRANT)
|
if (field == WRONG_GRANT)
|
||||||
return (Field*) 0;
|
return (Field*) 0;
|
||||||
|
(*where)= tables;
|
||||||
if (found)
|
if (found)
|
||||||
{
|
{
|
||||||
if (!thd->where) // Returns first found
|
if (!thd->where) // Returns first found
|
||||||
|
|
|
@ -63,6 +63,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
|
||||||
TMP_TABLE_PARAM tmp_table_param;
|
TMP_TABLE_PARAM tmp_table_param;
|
||||||
bool is_union=sl->next_select() && sl->next_select()->linkage == UNION_TYPE;
|
bool is_union=sl->next_select() && sl->next_select()->linkage == UNION_TYPE;
|
||||||
DBUG_ENTER("mysql_derived");
|
DBUG_ENTER("mysql_derived");
|
||||||
|
SELECT_LEX_NODE *save_current_select= lex->current_select;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -111,6 +112,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lex->current_select= sl;
|
||||||
if (setup_fields(thd,tables,item_list,0,0,1))
|
if (setup_fields(thd,tables,item_list,0,0,1))
|
||||||
{
|
{
|
||||||
res=-1;
|
res=-1;
|
||||||
|
@ -119,7 +121,8 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
|
||||||
bzero((char*) &tmp_table_param,sizeof(tmp_table_param));
|
bzero((char*) &tmp_table_param,sizeof(tmp_table_param));
|
||||||
tmp_table_param.field_count=item_list.elements;
|
tmp_table_param.field_count=item_list.elements;
|
||||||
if (!(table=create_tmp_table(thd, &tmp_table_param, item_list,
|
if (!(table=create_tmp_table(thd, &tmp_table_param, item_list,
|
||||||
(ORDER*) 0, is_union && !unit->union_option, 1,
|
(ORDER*) 0,
|
||||||
|
is_union && !unit->union_option, 1,
|
||||||
(sl->options | thd->options |
|
(sl->options | thd->options |
|
||||||
TMP_TABLE_ALL_COLUMNS),
|
TMP_TABLE_ALL_COLUMNS),
|
||||||
HA_POS_ERROR)))
|
HA_POS_ERROR)))
|
||||||
|
@ -138,8 +141,6 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
|
||||||
if (unit->select_limit_cnt == HA_POS_ERROR)
|
if (unit->select_limit_cnt == HA_POS_ERROR)
|
||||||
sl->options&= ~OPTION_FOUND_ROWS;
|
sl->options&= ~OPTION_FOUND_ROWS;
|
||||||
|
|
||||||
SELECT_LEX_NODE *save_current_select= lex->current_select;
|
|
||||||
lex->current_select= sl;
|
|
||||||
if (is_union)
|
if (is_union)
|
||||||
res=mysql_union(thd,lex,derived_result,unit);
|
res=mysql_union(thd,lex,derived_result,unit);
|
||||||
else
|
else
|
||||||
|
@ -149,7 +150,6 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
|
||||||
sl->having, (ORDER*) NULL,
|
sl->having, (ORDER*) NULL,
|
||||||
sl->options | thd->options | SELECT_NO_UNLOCK,
|
sl->options | thd->options | SELECT_NO_UNLOCK,
|
||||||
derived_result, unit, sl, 0);
|
derived_result, unit, sl, 0);
|
||||||
lex->current_select= save_current_select;
|
|
||||||
|
|
||||||
if (!res)
|
if (!res)
|
||||||
{
|
{
|
||||||
|
@ -184,6 +184,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
|
||||||
if (res)
|
if (res)
|
||||||
free_tmp_table(thd,table);
|
free_tmp_table(thd,table);
|
||||||
exit:
|
exit:
|
||||||
|
lex->current_select= save_current_select;
|
||||||
close_thread_tables(thd);
|
close_thread_tables(thd);
|
||||||
}
|
}
|
||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
|
|
Loading…
Reference in a new issue