Commit a72ebebf authored by unknown's avatar unknown

after merge fix of 577 task (SCRUM, pre commit to be able to merge with static...

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


mysql-test/r/derived.result:
  test of subselects inside derived tables
mysql-test/t/derived.test:
  test of subselects inside derived tables
mysql-test/t/subselect.test:
  subselect test (not finished)
sql/item.cc:
  after merge fix
sql/item.h:
  after merge fix
sql/item_cmpfunc.h:
  after merge fix
sql/item_subselect.cc:
  after merge fix
sql/item_sum.h:
  after merge fix
sql/mysql_priv.h:
  fixed derived tables with subselect inside
sql/sql_class.h:
  after merge fix
sql/sql_derived.cc:
  fixed derived tables with subselect inside
sql/sql_lex.cc:
  fixed derived tables with subselect inside
sql/sql_lex.h:
  fixed derived tables with subselect inside
sql/sql_parse.cc:
  fixed derived tables with subselect inside
  after merge fix
sql/sql_prepare.cc:
  after merge fix
sql/sql_select.cc:
  after merge fix
  fixed derived tables with subselect inside
parent fbd882fc
......@@ -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
......
......@@ -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 @@ class Item_ref_null_helper: public Item_ref
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 @@ class Item_std_field :public Item_variance_field
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 @@ class THD :public ilink {
#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 @@ class st_select_lex_unit: public st_select_lex_node {
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 @@ class st_select_lex_unit: public st_select_lex_node {
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)
......
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