mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
after merge fix of 577 task (SCRUM, pre commit to be able to merge with static tables optimization fix)
fixed derived tables with subselect inside
This commit is contained in:
@ -95,7 +95,17 @@ id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 8
|
||||
2 DERIVED t1 ALL NULL NULL NULL NULL 4
|
||||
3 UNION t1 ALL NULL NULL NULL NULL 4
|
||||
drop table if exists t1;
|
||||
CREATE TABLE t2 (a int not null);
|
||||
insert into t2 values(1);
|
||||
select * from (select * from t1 where t1.a=(select a from t2 where t2.a=t1.a)) a;
|
||||
a b
|
||||
1 a
|
||||
select * from (select * from t1 where t1.a=(select t2.a from t2 where t2.a=t1.a) union select t1.a, t1.b from t1) a;
|
||||
a b
|
||||
1 a
|
||||
2 b
|
||||
3 c
|
||||
drop table t1, t2;
|
||||
create table t1(a int not null, t char(8), index(a));
|
||||
SELECT * FROM (SELECT * FROM t1) as b ORDER BY a ASC LIMIT 0,20;
|
||||
a t
|
||||
|
@ -37,7 +37,11 @@ select * from (select * from t1 union select * from t1) a;
|
||||
select * from (select * from t1 union all select * from t1) a;
|
||||
explain select * from (select * from t1 union select * from t1) a;
|
||||
explain select * from (select * from t1 union all select * from t1) a;
|
||||
drop table if exists t1;
|
||||
CREATE TABLE t2 (a int not null);
|
||||
insert into t2 values(1);
|
||||
select * from (select * from t1 where t1.a=(select a from t2 where t2.a=t1.a)) a;
|
||||
select * from (select * from t1 where t1.a=(select t2.a from t2 where t2.a=t1.a) union select t1.a, t1.b from t1) a;
|
||||
drop table t1, t2;
|
||||
create table t1(a int not null, t char(8), index(a));
|
||||
disable_query_log;
|
||||
let $1 = 10000;
|
||||
|
@ -206,19 +206,22 @@ SELECT numeropost,maxnumrep FROM t1 WHERE exists (SELECT 1 FROM t2 WHERE (mot='j
|
||||
SELECT (SELECT 1) as a FROM (SELECT 1 FROM t1 HAVING a=1) b;
|
||||
-- error 1054
|
||||
SELECT 1 IN (SELECT 1 FROM t2 HAVING a);
|
||||
SELECT * from t2 where topic IN (SELECT topic FROM t2 GROUP BY date);
|
||||
SELECT * from t2 where topic IN (SELECT topic FROM t2 GROUP BY date HAVING topic < 4100);
|
||||
|
||||
SELECT * from t2 where topic IN (SELECT topic FROM t2 GROUP BY topic);
|
||||
SELECT * from t2 where topic IN (SELECT topic FROM t2 GROUP BY topic HAVING topic < 4100);
|
||||
SELECT * from t2 where topic IN (SELECT SUM(topic) FROM t1);
|
||||
SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY date);
|
||||
SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY date HAVING topic < 4100);
|
||||
SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY topic);
|
||||
SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY topic HAVING topic < 4100);
|
||||
SELECT * from t2 where topic = any (SELECT SUM(topic) FROM t1);
|
||||
SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY date);
|
||||
SELECT topic FROM t2 GROUP BY date;
|
||||
SELECT topic FROM t2 GROUP BY date HAVING topic < 4100;
|
||||
SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY date HAVING topic < 4100);
|
||||
SELECT *, date as fff from t2 where not (SELECT date FROM t2 GROUP BY date HAVING topic < 4100 and fff!=date);
|
||||
SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY topic);
|
||||
SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY topic HAVING topic < 4100);
|
||||
SELECT topic FROM t2 GROUP BY topic HAVING topic < 4100;
|
||||
SELECT *, topic = all (SELECT topic FROM t2 GROUP BY topic HAVING topic < 4100) from t2;
|
||||
SELECT * from t2 where topic = all (SELECT SUM(topic) FROM t2);
|
||||
SELECT * from t2 where topic <> any (SELECT SUM(topic) FROM t2);
|
||||
delete from t2 where topic=40143;
|
||||
SELECT *, topic = all (SELECT topic FROM t2 GROUP BY topic HAVING topic < 4100) from t2;
|
||||
SELECT *, topic as fff, exists (SELECT topic FROM t2 GROUP BY topic HAVING topic < 4100 and fff = topic) from t2;
|
||||
drop table t1,t2;
|
||||
|
||||
#forumconthardwarefr7
|
||||
|
12
sql/item.cc
12
sql/item.cc
@ -573,20 +573,14 @@ bool Item_ref_on_list_position::fix_fields(THD *thd,
|
||||
struct st_table_list *tables,
|
||||
Item ** reference)
|
||||
{
|
||||
List_iterator<Item> li(list);
|
||||
Item *item;
|
||||
for (uint i= 0; (item= li++) && i < pos; i++);
|
||||
if (item)
|
||||
{
|
||||
ref= li.ref();
|
||||
return Item_ref_null_helper::fix_fields(thd, tables, reference);
|
||||
}
|
||||
else
|
||||
if (select_lex->item_list.elements <= pos)
|
||||
{
|
||||
ref= 0;
|
||||
my_error(ER_CARDINALITY_COL, MYF(0), pos);
|
||||
return 1;
|
||||
}
|
||||
ref= select_lex->ref_pointer_array + pos;
|
||||
return Item_ref_null_helper::fix_fields(thd, tables, reference);
|
||||
}
|
||||
|
||||
double Item_ref_null_helper::val()
|
||||
|
@ -548,14 +548,14 @@ public:
|
||||
class Item_ref_on_list_position: public Item_ref_null_helper
|
||||
{
|
||||
protected:
|
||||
List<Item> &list;
|
||||
st_select_lex *select_lex;
|
||||
uint pos;
|
||||
public:
|
||||
Item_ref_on_list_position(Item_in_subselect* master,
|
||||
List<Item> &li, uint num,
|
||||
st_select_lex *sl, uint num,
|
||||
char *table_name, char *field_name):
|
||||
Item_ref_null_helper(master, 0, table_name, field_name),
|
||||
list(li), pos(num) {}
|
||||
select_lex(sl), pos(num) {}
|
||||
bool fix_fields(THD *, struct st_table_list *, Item ** ref);
|
||||
};
|
||||
|
||||
|
@ -17,8 +17,6 @@
|
||||
|
||||
/* compare and test functions */
|
||||
|
||||
#include "assert.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma interface /* gcc class implementation */
|
||||
#endif
|
||||
|
@ -439,7 +439,6 @@ void Item_in_subselect::single_value_transformer(THD *thd,
|
||||
compare_func_creator func)
|
||||
{
|
||||
DBUG_ENTER("Item_in_subselect::single_value_transformer");
|
||||
THD *thd= current_thd;
|
||||
|
||||
if (unit->global_parameters->select_limit != HA_POS_ERROR)
|
||||
{
|
||||
@ -488,9 +487,8 @@ void Item_in_subselect::single_value_transformer(THD *thd,
|
||||
{
|
||||
sl->item_list.push_back(item);
|
||||
setup_ref_array(thd, &sl->ref_pointer_array,
|
||||
1+ select_lex->with_sum_func +
|
||||
select_lex->order_list.elements +
|
||||
select_lex->group_list.elements);
|
||||
1 + sl->with_sum_func +
|
||||
sl->order_list.elements + sl->group_list.elements);
|
||||
item= (*func)(expr, new Item_ref_null_helper(this,
|
||||
sl->ref_pointer_array,
|
||||
(char *)"<no matter>",
|
||||
@ -597,7 +595,7 @@ void Item_in_subselect::row_value_transformer(THD *thd,
|
||||
for (uint i= 0; i < n; i++)
|
||||
{
|
||||
Item *func=
|
||||
new Item_ref_on_list_position(this, sl->item_list, i,
|
||||
new Item_ref_on_list_position(this, sl, i,
|
||||
(char *) "<no matter>",
|
||||
(char *) "<list ref>");
|
||||
func=
|
||||
|
@ -332,6 +332,22 @@ public:
|
||||
Item_std_field(Item_sum_std *item);
|
||||
enum Type type() const { return FIELD_STD_ITEM; }
|
||||
double val();
|
||||
};
|
||||
|
||||
/*
|
||||
standard_deviation(a) = sqrt(variance(a))
|
||||
*/
|
||||
|
||||
class Item_sum_std :public Item_sum_variance
|
||||
{
|
||||
public:
|
||||
Item_sum_std(Item *item_par) :Item_sum_variance(item_par){}
|
||||
enum Sumfunctype sum_func () const { return STD_FUNC; }
|
||||
double val();
|
||||
Item *result_item(Field *field)
|
||||
{ return new Item_std_field(this); }
|
||||
const char *func_name() const { return "std"; }
|
||||
};
|
||||
|
||||
// This class is a string or number function depending on num_func
|
||||
|
||||
|
@ -406,6 +406,7 @@ int mysql_select(THD *thd, Item ***rref_pointer_array,
|
||||
SELECT_LEX *select_lex, bool fake_select_lex);
|
||||
void free_ulderlayed_joins(THD *thd, SELECT_LEX *select);
|
||||
void fix_tables_pointers(SELECT_LEX *select_lex);
|
||||
void fix_tables_pointers(SELECT_LEX_UNIT *select_lex);
|
||||
int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit,
|
||||
select_result *result);
|
||||
int mysql_explain_select(THD *thd, SELECT_LEX *sl, char const *type,
|
||||
|
@ -663,17 +663,6 @@ public:
|
||||
#endif
|
||||
|
||||
void add_possible_loop(Item *);
|
||||
void free_tmp_tables()
|
||||
{
|
||||
if (temporary_tables_should_be_free.elements)
|
||||
{
|
||||
List_iterator_fast<TABLE> lt(temporary_tables_should_be_free);
|
||||
TABLE *table;
|
||||
while ((table= lt++))
|
||||
free_tmp_table(this,table);
|
||||
temporary_tables_should_be_free.empty();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -70,7 +70,8 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
|
||||
select_union *derived_result;
|
||||
TABLE_LIST *tables= (TABLE_LIST *)sl->table_list.first;
|
||||
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;
|
||||
bool is_subsel= sl->first_inner_unit();
|
||||
SELECT_LEX_NODE *save_current_select= lex->current_select;
|
||||
DBUG_ENTER("mysql_derived");
|
||||
|
||||
@ -81,7 +82,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
|
||||
recognize better when this function is called from derived tables
|
||||
and when from other functions.
|
||||
*/
|
||||
if (is_union && unit->create_total_list(thd, lex, &tables))
|
||||
if ((is_union || is_subsel) && unit->create_total_list(thd, lex, &tables, 1))
|
||||
DBUG_RETURN(-1);
|
||||
|
||||
if (tables)
|
||||
@ -91,23 +92,38 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
|
||||
if (res)
|
||||
DBUG_RETURN(-1);
|
||||
|
||||
if (!(res=open_and_lock_tables(thd,tables)))
|
||||
{
|
||||
if (is_union || is_subsel)
|
||||
{
|
||||
/*
|
||||
The following code is a re-do of fix_tables_pointers() found
|
||||
in sql_select.cc for UNION's within derived tables. The only
|
||||
difference is in navigation, as in derived tables we care for
|
||||
this level only.
|
||||
|
||||
*/
|
||||
fix_tables_pointers(unit);
|
||||
}
|
||||
|
||||
Item *item;
|
||||
List_iterator<Item> it(sl->item_list);
|
||||
|
||||
while ((item= it++))
|
||||
item_list.push_back(item);
|
||||
|
||||
if (!(res=open_and_lock_tables(thd,tables)))
|
||||
{
|
||||
if (setup_wild(thd, tables, item_list, 0, sl->with_wild) ||
|
||||
setup_fields(thd, 0, tables, item_list, 0, 0, 1))
|
||||
|
||||
lex->current_select= sl;
|
||||
TABLE_LIST *first_table= (TABLE_LIST*) sl->table_list.first;
|
||||
if (setup_wild(thd, first_table, item_list, 0, sl->with_wild) ||
|
||||
setup_fields(thd, 0, first_table, item_list, 0, 0, 1))
|
||||
{
|
||||
res= -1;
|
||||
goto exit;
|
||||
}
|
||||
bzero((char*) &tmp_table_param,sizeof(tmp_table_param));
|
||||
tmp_table_param.field_count=item_list.elements;
|
||||
if (!(table=create_tmp_table(thd, &tmp_table_param, item_list,
|
||||
tmp_table_param.field_count= item_list.elements;
|
||||
if (!(table= create_tmp_table(thd, &tmp_table_param, item_list,
|
||||
(ORDER*) 0,
|
||||
is_union && !unit->union_option, 1,
|
||||
(sl->options | thd->options |
|
||||
@ -129,9 +145,11 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
|
||||
sl->options&= ~OPTION_FOUND_ROWS;
|
||||
|
||||
if (is_union)
|
||||
res= mysql_union(thd,lex,derived_result,unit);
|
||||
res= mysql_union(thd, lex, derived_result, unit);
|
||||
else
|
||||
res= mysql_select(thd, &sl->ref_pointer_array, tables, sl->with_wild,
|
||||
res= mysql_select(thd, &sl->ref_pointer_array,
|
||||
(TABLE_LIST*) sl->table_list.first,
|
||||
sl->with_wild,
|
||||
sl->item_list, sl->where,
|
||||
sl->order_list.elements+sl->group_list.elements,
|
||||
(ORDER *) sl->order_list.first,
|
||||
@ -170,11 +188,12 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
|
||||
delete derived_result;
|
||||
}
|
||||
if (res)
|
||||
mp_table(thd, table);
|
||||
|
||||
|
||||
>next= thd->derived_tables
|
||||
erived_tables= table;
|
||||
free_tmp_table(thd, table);
|
||||
else
|
||||
{
|
||||
table->next= thd->derived_tables;
|
||||
thd->derived_tables= table;
|
||||
}
|
||||
|
||||
exit:
|
||||
lex->current_select= save_current_select;
|
||||
|
@ -1245,15 +1245,17 @@ ulong st_select_lex_node::get_table_join_options() { return 0; }
|
||||
|
||||
// interface
|
||||
bool st_select_lex_unit::create_total_list(THD *thd, st_lex *lex,
|
||||
TABLE_LIST **result)
|
||||
TABLE_LIST **result,
|
||||
bool check_derived)
|
||||
{
|
||||
*result= 0;
|
||||
return create_total_list_n_last_return(thd, lex, &result);
|
||||
return create_total_list_n_last_return(thd, lex, &result, check_derived);
|
||||
}
|
||||
|
||||
// list creator
|
||||
bool st_select_lex_unit::create_total_list_n_last_return(THD *thd, st_lex *lex,
|
||||
TABLE_LIST ***result)
|
||||
TABLE_LIST ***result,
|
||||
bool check_derived)
|
||||
{
|
||||
TABLE_LIST *slave_list_first=0, **slave_list_last= &slave_list_first;
|
||||
TABLE_LIST **new_table_list= *result, *aux;
|
||||
@ -1266,13 +1268,13 @@ bool st_select_lex_unit::create_total_list_n_last_return(THD *thd, st_lex *lex,
|
||||
net_printf(thd,ER_WRONG_USAGE,"UNION","ORDER BY");
|
||||
return 1;
|
||||
}
|
||||
if (sl->linkage == DERIVED_TABLE_TYPE && !sl->next_select())
|
||||
if (sl->linkage == DERIVED_TABLE_TYPE && !check_derived)
|
||||
continue;
|
||||
for (SELECT_LEX_UNIT *inner= sl->first_inner_unit();
|
||||
inner;
|
||||
inner= inner->next_unit())
|
||||
if (inner->create_total_list_n_last_return(thd, lex,
|
||||
&slave_list_last))
|
||||
&slave_list_last, 0))
|
||||
return 1;
|
||||
if ((aux= (TABLE_LIST*) sl->table_list.first))
|
||||
{
|
||||
|
@ -302,7 +302,8 @@ public:
|
||||
uint union_option;
|
||||
|
||||
void init_query();
|
||||
bool create_total_list(THD *thd, st_lex *lex, TABLE_LIST **result);
|
||||
bool create_total_list(THD *thd, st_lex *lex, TABLE_LIST **result,
|
||||
bool check_current_derived);
|
||||
st_select_lex_unit* master_unit();
|
||||
st_select_lex* outer_select();
|
||||
st_select_lex* first_select() { return (st_select_lex*) slave; }
|
||||
@ -318,7 +319,8 @@ public:
|
||||
friend int subselect_union_engine::exec();
|
||||
private:
|
||||
bool create_total_list_n_last_return(THD *thd, st_lex *lex,
|
||||
TABLE_LIST ***result);
|
||||
TABLE_LIST ***result,
|
||||
bool check_current_derived);
|
||||
};
|
||||
typedef class st_select_lex_unit SELECT_LEX_UNIT;
|
||||
|
||||
|
@ -1599,7 +1599,7 @@ mysql_execute_command(THD *thd)
|
||||
}
|
||||
}
|
||||
if ((&lex->select_lex != lex->all_selects_list &&
|
||||
lex->unit.create_total_list(thd, lex, &tables))
|
||||
lex->unit.create_total_list(thd, lex, &tables, 0))
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
||
|
||||
(table_rules_on && tables && thd->slave_thread &&
|
||||
@ -2887,7 +2887,6 @@ mysql_execute_command(THD *thd)
|
||||
send_ok(thd);
|
||||
break;
|
||||
}
|
||||
thd->free_tmp_tables();
|
||||
thd->proc_info="query end"; // QQ
|
||||
if (res < 0)
|
||||
send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0);
|
||||
|
@ -532,8 +532,9 @@ static bool mysql_test_upd_fields(PREP_STMT *stmt, TABLE_LIST *table_list,
|
||||
And send column list fields info back to client.
|
||||
*/
|
||||
static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables,
|
||||
uint wild_num,
|
||||
List<Item> &fields, COND *conds,
|
||||
ORDER *order, ORDER *group,
|
||||
uint og_num, ORDER *order, ORDER *group,
|
||||
Item *having, ORDER *proc,
|
||||
ulong select_options,
|
||||
SELECT_LEX_UNIT *unit,
|
||||
@ -545,7 +546,7 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables,
|
||||
DBUG_ENTER("mysql_test_select_fields");
|
||||
|
||||
if ((&lex->select_lex != lex->all_selects_list &&
|
||||
lex->unit.create_total_list(thd, lex, &tables)))
|
||||
lex->unit.create_total_list(thd, lex, &tables, 0)))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
if (open_and_lock_tables(thd, tables))
|
||||
@ -564,7 +565,8 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables,
|
||||
JOIN *join= new JOIN(thd, fields, select_options, result);
|
||||
thd->used_tables= 0; // Updated by setup_fields
|
||||
|
||||
if (join->prepare(tables, conds, order, group, having, proc,
|
||||
if (join->prepare(&select_lex->ref_pointer_array, tables,
|
||||
wild_num, conds, og_num, order, group, having, proc,
|
||||
select_lex, unit, 0))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
@ -623,9 +625,11 @@ static bool send_prepare_results(PREP_STMT *stmt)
|
||||
break;
|
||||
|
||||
case SQLCOM_SELECT:
|
||||
if (mysql_test_select_fields(stmt, tables,
|
||||
if (mysql_test_select_fields(stmt, tables, select_lex->with_wild,
|
||||
select_lex->item_list,
|
||||
select_lex->where,
|
||||
select_lex->order_list.elements +
|
||||
select_lex->group_list.elements,
|
||||
(ORDER*) select_lex->order_list.first,
|
||||
(ORDER*) select_lex->group_list.first,
|
||||
select_lex->having,
|
||||
|
@ -217,6 +217,16 @@ void fix_tables_pointers(SELECT_LEX *select_lex)
|
||||
}
|
||||
}
|
||||
|
||||
void fix_tables_pointers(SELECT_LEX_UNIT *unit)
|
||||
{
|
||||
for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select())
|
||||
{
|
||||
relink_tables(sl);
|
||||
for(SELECT_LEX_UNIT *un= sl->first_inner_unit(); un; un= un->next_unit())
|
||||
fix_tables_pointers(un);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Function to setup clauses without sum functions
|
||||
@ -721,7 +731,16 @@ JOIN::optimize()
|
||||
HA_POS_ERROR)))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
//thd->temporary_tables_should_be_free.push_front(exec_tmp_table1);
|
||||
/*
|
||||
We don't have to store rows in temp table that doesn't match HAVING if:
|
||||
- we are sorting the table and writing complete group rows to the
|
||||
temp table.
|
||||
- We are using DISTINCT without resolving the distinct as a GROUP BY
|
||||
on all columns.
|
||||
|
||||
If having is not handled here, it will be checked before the row
|
||||
is sent to the client.
|
||||
*/
|
||||
if (having &&
|
||||
(sort_and_group || (exec_tmp_table1->distinct && !group_list)))
|
||||
having= tmp_having;
|
||||
@ -938,17 +957,7 @@ JOIN::exec()
|
||||
if (tmp_join)
|
||||
curr_join= tmp_join;
|
||||
curr_tmp_table= exec_tmp_table1;
|
||||
/*
|
||||
TODO: move this comment on its place
|
||||
We don't have to store rows in temp table that doesn't match HAVING if:
|
||||
- we are sorting the table and writing complete group rows to the
|
||||
temp table.
|
||||
- We are using DISTINCT without resolving the distinct as a GROUP BY
|
||||
on all columns.
|
||||
|
||||
If having is not handled here, it will be checked before the row
|
||||
is sent to the client.
|
||||
*/
|
||||
/* Copy data to the temporary table */
|
||||
thd->proc_info= "Copying to tmp table";
|
||||
|
||||
@ -1058,7 +1067,6 @@ JOIN::exec()
|
||||
1, curr_join->select_options,
|
||||
HA_POS_ERROR)))
|
||||
DBUG_VOID_RETURN;
|
||||
//thd->temporary_tables_should_be_free.push_front(exec_tmp_table2);
|
||||
curr_join->exec_tmp_table2= exec_tmp_table2;
|
||||
}
|
||||
if (group_list)
|
||||
|
Reference in New Issue
Block a user