Commit 236015ed authored by unknown's avatar unknown

three bug fixes and major code cleanup

parent 6f5ea702
......@@ -230,3 +230,7 @@ id_master id text1 text2
1 3 NULL bar3
1 4 foo4 bar4
drop table if exists t1,t2;
(SELECT 1,3) UNION (SELECT 2,1) ORDER BY (SELECT 2);
1 3
1 3
2 1
......@@ -124,3 +124,4 @@ INSERT INTO t2 (id, id_master, text1, text2) VALUES("4", "1",
SELECT 1 AS id_master, 1 AS id, NULL AS text1, 'ABCDE' AS text2 UNION SELECT id_master, t2.id, text1, text2 FROM t1 LEFT JOIN t2 ON t1.id = t2.id_master;
SELECT 1 AS id_master, 1 AS id, 'ABCDE' AS text1, 'ABCDE' AS text2 UNION SELECT id_master, t2.id, text1, text2 FROM t1 LEFT JOIN t2 ON t1.id = t2.id_master;
drop table if exists t1,t2;
(SELECT 1,3) UNION (SELECT 2,1) ORDER BY (SELECT 2);
......@@ -684,7 +684,7 @@ int subselect_single_select_engine::prepare()
(ORDER*) select_lex->group_list.first,
select_lex->having,
(ORDER*) 0, select_lex,
select_lex->master_unit(), 0, 0))
select_lex->master_unit(), 0))
return 1;
thd->lex.current_select= save_select;
return 0;
......
......@@ -405,8 +405,7 @@ int mysql_select(THD *thd, Item ***rref_pointer_array,
COND *conds, uint og_num, ORDER *order, ORDER *group,
Item *having, ORDER *proc_param, ulong select_type,
select_result *result, SELECT_LEX_UNIT *unit,
SELECT_LEX *select_lex, bool fake_select_lex,
bool tables_and_fields_initied);
SELECT_LEX *select_lex, bool tables_and_fields_initied);
void free_underlaid_joins(THD *thd, SELECT_LEX *select);
void fix_tables_pointers(SELECT_LEX *select_lex);
void fix_tables_pointers(SELECT_LEX_UNIT *select_lex);
......
......@@ -172,7 +172,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
(ORDER *) select_cursor->group_list.first,
select_cursor->having, (ORDER*) NULL,
select_cursor->options | thd->options | SELECT_NO_UNLOCK,
derived_result, unit, select_cursor, 0, 1);
derived_result, unit, select_cursor, 1);
if (!res)
{
......
......@@ -311,6 +311,11 @@ class st_select_lex_unit: public st_select_lex_node {
st_select_lex_unit* master_unit();
st_select_lex* outer_select();
st_select_lex* first_select() { return (st_select_lex*) slave; }
st_select_lex* first_select_in_union()
{
return (slave && slave->linkage == GLOBAL_OPTIONS_TYPE) ?
(st_select_lex*) slave->next : (st_select_lex*) slave;
}
st_select_lex_unit* next_unit() { return (st_select_lex_unit*) next; }
void exclude_level();
......@@ -404,6 +409,13 @@ class st_select_lex: public st_select_lex_node
}
friend void mysql_init_query(THD *thd);
void make_empty_select(st_select_lex *last_select)
{
select_number=INT_MAX;
init_query();
init_select();
include_neighbour(last_select);
}
};
typedef class st_select_lex SELECT_LEX;
......
......@@ -2433,7 +2433,7 @@ mysql_execute_command(THD *thd)
(ORDER *)NULL,
select_lex->options | thd->options |
SELECT_NO_JOIN_CACHE,
result, unit, select_lex, 0, 0);
result, unit, select_lex, 0);
if (thd->net.report_error)
res= -1;
delete result;
......
......@@ -567,7 +567,7 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables,
if (join->prepare(&select_lex->ref_pointer_array, tables,
wild_num, conds, og_num, order, group, having, proc,
select_lex, unit, 0, 0))
select_lex, unit, 0))
DBUG_RETURN(1);
/*
......
......@@ -182,7 +182,7 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
select_lex->having,
(ORDER*) lex->proc_list.first,
select_lex->options | thd->options,
result, &(lex->unit), &(lex->select_lex), 0, 0);
result, &(lex->unit), &(lex->select_lex), 0);
if (res && result)
result->abort();
......@@ -268,7 +268,7 @@ JOIN::prepare(Item ***rref_pointer_array,
Item *having_init,
ORDER *proc_param_init, SELECT_LEX *select,
SELECT_LEX_UNIT *unit,
bool fake_select_lex, bool tables_and_fields_initied)
bool tables_and_fields_initied)
{
DBUG_ENTER("JOIN::prepare");
......@@ -279,8 +279,7 @@ JOIN::prepare(Item ***rref_pointer_array,
proc_param= proc_param_init;
tables_list= tables_init;
select_lex= select;
if (!fake_select_lex)
select_lex->join= this;
select_lex->join= this;
union_part= (unit->first_select()->next_select() != 0);
/* Check that all tables, fields, conds and order are ok */
......@@ -1261,7 +1260,6 @@ int
JOIN::cleanup(THD *thd)
{
DBUG_ENTER("JOIN::cleanup");
select_lex->join= 0;
if (tmp_join)
......@@ -1292,15 +1290,14 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
COND *conds, uint og_num, ORDER *order, ORDER *group,
Item *having, ORDER *proc_param, ulong select_options,
select_result *result, SELECT_LEX_UNIT *unit,
SELECT_LEX *select_lex, bool fake_select_lex,
bool tables_and_fields_initied)
SELECT_LEX *select_lex, bool tables_and_fields_initied)
{
int err;
bool free_join= 1;
DBUG_ENTER("mysql_select");
JOIN *join;
if (!fake_select_lex && select_lex->join != 0)
if (select_lex->join != 0)
{
//here is EXPLAIN of subselect or derived table
join= select_lex->join;
......@@ -1320,8 +1317,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
if (join->prepare(rref_pointer_array, tables, wild_num,
conds, og_num, order, group, having, proc_param,
select_lex, unit, fake_select_lex,
tables_and_fields_initied))
select_lex, unit, tables_and_fields_initied))
{
DBUG_RETURN(-1);
}
......@@ -1350,7 +1346,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
thd->limit_found_rows= curr_join->send_records;
thd->examined_row_count= curr_join->examined_rows;
thd->proc_info="end";
err= (fake_select_lex ? curr_join->error : join->cleanup(thd));
err= join->cleanup(thd);
if (thd->net.report_error)
err= -1;
delete join;
......@@ -7086,15 +7082,16 @@ find_order_in_list(THD *thd, Item **ref_pointer_array,
TABLE_LIST *tables,ORDER *order, List<Item> &fields,
List<Item> &all_fields)
{
if ((*order->item)->type() == Item::INT_ITEM)
Item *itemptr=*order->item;
if (itemptr->type() == Item::INT_ITEM)
{ /* Order by position */
Item *item=0;
uint count= (uint) ((Item_int*) (*order->item))->value;
uint count= (uint) ((Item_int*)itemptr)->value;
if (count > fields.elements)
{
my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),
MYF(0),(*order->item)->full_name(),
MYF(0),itemptr->full_name(),
thd->where);
return 1;
}
......@@ -7103,8 +7100,7 @@ find_order_in_list(THD *thd, Item **ref_pointer_array,
return 0;
}
uint counter;
Item **item= find_item_in_list(*order->item, fields, &counter,
IGNORE_ERRORS);
Item **item= find_item_in_list(itemptr, fields, &counter, IGNORE_ERRORS);
if (item)
{
order->item= ref_pointer_array + counter;
......@@ -8103,7 +8099,7 @@ int mysql_explain_select(THD *thd, SELECT_LEX *select_lex, char const *type,
select_lex->having,
(ORDER*) thd->lex.proc_list.first,
select_lex->options | thd->options | SELECT_DESCRIBE,
result, unit, select_lex, 0, 0);
result, unit, select_lex, 0);
DBUG_RETURN(res);
}
......
......@@ -256,8 +256,7 @@ class JOIN :public Sql_alloc
int prepare(Item ***rref_pointer_array, TABLE_LIST *tables, uint wind_num,
COND *conds, uint og_num, ORDER *order, ORDER *group,
Item *having, ORDER *proc_param, SELECT_LEX *select,
SELECT_LEX_UNIT *unit, bool fake_select_lex,
bool tables_and_fields_initied);
SELECT_LEX_UNIT *unit, bool tables_and_fields_initied);
int optimize();
int reinit();
void exec();
......
......@@ -122,9 +122,9 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result,
this->result= result;
t_and_f= tables_and_fields_initied;
SELECT_LEX_NODE *lex_select_save= thd->lex.current_select;
SELECT_LEX *sl;
SELECT_LEX *select_cursor;
thd->lex.current_select= sl= first_select();
thd->lex.current_select= select_cursor= first_select_in_union();
/* Global option */
if (((void*)(global_parameters)) == ((void*)this))
{
......@@ -136,26 +136,27 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result,
if (t_and_f)
{
// Item list and tables will be initialized by mysql_derived
item_list= sl->item_list;
item_list= select_cursor->item_list;
}
else
{
item_list.empty();
TABLE_LIST *first_table= (TABLE_LIST*) first_select()->table_list.first;
TABLE_LIST *first_table= (TABLE_LIST*) select_cursor->table_list.first;
if (setup_tables(first_table) ||
setup_wild(thd, first_table, sl->item_list, 0, sl->with_wild))
setup_wild(thd, first_table, select_cursor->item_list, 0, select_cursor->with_wild))
goto err;
List_iterator<Item> it(sl->item_list);
List_iterator<Item> it(select_cursor->item_list);
Item *item;
while((item=it++))
item->maybe_null=1;
item_list= sl->item_list;
sl->with_wild= 0;
if (setup_ref_array(thd, &sl->ref_pointer_array,
(item_list.elements + sl->with_sum_func +
sl->order_list.elements + sl->group_list.elements)) ||
setup_fields(thd, sl->ref_pointer_array, first_table, item_list,
item_list= select_cursor->item_list;
select_cursor->with_wild= 0;
if (setup_ref_array(thd, &select_cursor->ref_pointer_array,
(item_list.elements + select_cursor->with_sum_func +
select_cursor->order_list.elements +
select_cursor->group_list.elements)) ||
setup_fields(thd, select_cursor->ref_pointer_array, first_table, item_list,
0, 0, 1))
goto err;
t_and_f= 1;
......@@ -165,7 +166,7 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result,
tmp_table_param.field_count=item_list.elements;
if (!(table= create_tmp_table(thd, &tmp_table_param, item_list,
(ORDER*) 0, !union_option,
1, (first_select()->options | thd->options |
1, (select_cursor->options | thd->options |
TMP_TABLE_ALL_COLUMNS),
HA_POS_ERROR)))
goto err;
......@@ -181,9 +182,16 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result,
union_result->not_describe=1;
union_result->tmp_table_param=&tmp_table_param;
/*
the following piece of code is placed here solely for the purpose of
getting correct results with EXPLAIN when UNION is withing a sub-select
or derived table ...
*/
if (thd->lex.describe)
{
for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
for (SELECT_LEX *sl= select_cursor; sl; sl= sl->next_select())
{
JOIN *join= new JOIN(thd, sl->item_list,
sl->options | thd->options | SELECT_NO_UNLOCK,
......@@ -206,16 +214,17 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result,
(ORDER*) sl->group_list.first,
sl->having,
(ORDER*) NULL,
sl, this, 0, t_and_f);
sl, this, t_and_f);
t_and_f= 0;
if (res | thd->is_fatal_error)
goto err;
}
}
item_list.empty();
thd->lex.current_select= lex_select_save;
{
List_iterator<Item> it(first_select()->item_list);
List_iterator<Item> it(select_cursor->item_list);
Field **field;
for (field= table->field; *field; field++)
......@@ -236,7 +245,8 @@ int st_select_lex_unit::exec()
{
DBUG_ENTER("st_select_lex_unit::exec");
SELECT_LEX_NODE *lex_select_save= thd->lex.current_select;
SELECT_LEX *select_cursor=first_select_in_union(), *last_select;
if (executed && !(dependent || uncacheable))
DBUG_RETURN(0);
executed= 1;
......@@ -249,8 +259,9 @@ int st_select_lex_unit::exec()
item->reset();
table->file->delete_all_rows();
}
for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
for (SELECT_LEX *sl= select_cursor; sl; sl= sl->next_select())
{
last_select=sl;
if (optimized)
res= sl->join->reinit();
else
......@@ -276,7 +287,7 @@ int st_select_lex_unit::exec()
(ORDER*) sl->group_list.first,
sl->having,
(ORDER*) NULL,
sl, this, 0, t_and_f);
sl, this, t_and_f);
t_and_f=0;
if (res | thd->is_fatal_error)
{
......@@ -307,7 +318,7 @@ int st_select_lex_unit::exec()
/* Send result to 'result' */
// to correct ORDER BY reference resolving
thd->lex.current_select = first_select();
thd->lex.current_select = select_cursor;
res =-1;
{
#if 0
......@@ -321,9 +332,10 @@ int st_select_lex_unit::exec()
if (!thd->is_fatal_error) // Check if EOM
{
SELECT_LEX *sl=thd->lex.current_select->master_unit()->first_select();
offset_limit_cnt= (sl->braces) ? global_parameters->offset_limit : 0;
select_limit_cnt= (sl->braces) ? global_parameters->select_limit+
SELECT_LEX *fake_select = new SELECT_LEX();
fake_select->make_empty_select(last_select);
offset_limit_cnt= (select_cursor->braces) ? global_parameters->offset_limit : 0;
select_limit_cnt= (select_cursor->braces) ? global_parameters->select_limit+
global_parameters->offset_limit : HA_POS_ERROR;
if (select_limit_cnt < global_parameters->select_limit)
select_limit_cnt= HA_POS_ERROR; // no limit
......@@ -334,9 +346,11 @@ int st_select_lex_unit::exec()
global_parameters->order_list.elements,
(ORDER*)global_parameters->order_list.first,
(ORDER*) NULL, NULL, (ORDER*) NULL,
thd->options, result, this, first_select(), 1, 0);
thd->options, result, this, fake_select, 0);
if (found_rows_for_union && !res)
thd->limit_found_rows = (ulonglong)table->file->records;
fake_select->exclude();
delete fake_select;
}
}
thd->lex.select_lex.ftfunc_list= &thd->lex.select_lex.ftfunc_list_alloc;
......@@ -357,7 +371,7 @@ int st_select_lex_unit::cleanup()
free_tmp_table(thd, table);
table= 0; // Safety
}
for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
for (SELECT_LEX *sl= first_select_in_union(); sl; sl= sl->next_select())
{
JOIN *join;
if ((join= sl->join))
......
......@@ -428,7 +428,7 @@ int mysql_multi_update(THD *thd,
conds, 0, (ORDER *) NULL, (ORDER *)NULL, (Item *) NULL,
(ORDER *)NULL,
options | SELECT_NO_JOIN_CACHE,
result, unit, select_lex, 0, 0);
result, unit, select_lex, 0);
delete result;
DBUG_RETURN(res);
}
......
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