1
0
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:
bell@sanja.is.com.ua
2003-01-26 21:30:35 +02:00
parent 44d8a8cdab
commit 760e22f0bb
16 changed files with 141 additions and 94 deletions

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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()

View File

@ -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);
};

View File

@ -17,8 +17,6 @@
/* compare and test functions */
#include "assert.h"
#ifdef __GNUC__
#pragma interface /* gcc class implementation */
#endif

View File

@ -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=

View File

@ -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

View File

@ -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,

View File

@ -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();
}
}
};
/*

View File

@ -71,6 +71,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
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_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,16 +92,31 @@ 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;
@ -131,7 +147,9 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
if (is_union)
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;

View File

@ -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))
{

View File

@ -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;

View File

@ -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);

View File

@ -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,

View File

@ -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)