Commit 6ff06df2 authored by unknown's avatar unknown

new SELECT_LEX structures used for storing global ORDER BY, global LIMIT & limit counters


mysql-test/r/union.result:
  correct result of union explain command
parent 2c62a868
......@@ -88,7 +88,6 @@ explain (select a,b from t1 limit 2) union all (select a,b from t2 order by a l
table type possible_keys key key_len ref rows Extra
t1 ALL NULL NULL NULL NULL 4
t2 ALL NULL NULL NULL NULL 4 Using filesort
t1 ALL NULL NULL NULL NULL 4
(select sql_calc_found_rows a,b from t1 limit 2) union all (select a,b from t2 order by a) limit 2;
a b
1 a
......
......@@ -940,6 +940,7 @@ bool Item_sum_count_distinct::fix_fields(THD *thd,TABLE_LIST *tables)
bool Item_sum_count_distinct::setup(THD *thd)
{
List<Item> list;
SELECT_LEX *select_lex= current_lex->select;
/* Create a table with an unique key over all parameters */
for (uint i=0; i < arg_count ; i++)
{
......@@ -961,9 +962,10 @@ bool Item_sum_count_distinct::setup(THD *thd)
free_tmp_table(thd, table);
tmp_table_param->cleanup();
}
if (!(table=create_tmp_table(thd, tmp_table_param, list, (ORDER*) 0, 1,
if (!(table= create_tmp_table(thd, tmp_table_param, list, (ORDER*) 0, 1,
0, 0,
current_lex->select->options | thd->options)))
select_lex->options | thd->options,
(SELECT_LEX_UNIT*) select_lex->master)))
return 1;
table->file->extra(HA_EXTRA_NO_ROWS); // Don't update rows
table->no_rows=1;
......
......@@ -359,7 +359,8 @@ int setup_order(THD *thd,TABLE_LIST *tables, List<Item> &fields,
int handle_select(THD *thd, LEX *lex, select_result *result);
int mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &list,COND *conds,
ORDER *order, ORDER *group,Item *having,ORDER *proc_param,
ulong select_type,select_result *result);
ulong select_type,select_result *result,
SELECT_LEX_UNIT *unit);
int mysql_union(THD *thd, LEX *lex,select_result *result);
int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t);
Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
......
......@@ -389,9 +389,9 @@ bool select_send::send_data(List<Item> &items)
String *packet= &thd->packet;
DBUG_ENTER("send_data");
if (thd->offset_limit)
if (unit->offset_limit_cnt)
{ // using limit offset,count
thd->offset_limit--;
unit->offset_limit_cnt--;
DBUG_RETURN(0);
}
packet->length(0); // Reset packet
......@@ -439,11 +439,12 @@ select_export::~select_export()
}
int
select_export::prepare(List<Item> &list)
select_export::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
{
char path[FN_REFLEN];
uint option=4;
bool blob_flag=0;
unit= u;
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
option|=1; // Force use of db directory
#endif
......@@ -510,9 +511,9 @@ bool select_export::send_data(List<Item> &items)
String tmp(buff,sizeof(buff)),*res;
tmp.length(0);
if (thd->offset_limit)
if (unit->offset_limit_cnt)
{ // using limit offset,count
thd->offset_limit--;
unit->offset_limit_cnt--;
DBUG_RETURN(0);
}
row_count++;
......@@ -678,9 +679,11 @@ select_dump::~select_dump()
}
int
select_dump::prepare(List<Item> &list __attribute__((unused)))
select_dump::prepare(List<Item> &list __attribute__((unused)),
SELECT_LEX_UNIT *u)
{
uint option=4;
unit= u;
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
option|=1; // Force use of db directory
#endif
......@@ -719,9 +722,9 @@ bool select_dump::send_data(List<Item> &items)
Item *item;
DBUG_ENTER("send_data");
if (thd->offset_limit)
if (unit->offset_limit_cnt)
{ // using limit offset,count
thd->offset_limit--;
unit->offset_limit_cnt--;
DBUG_RETURN(0);
}
if (row_count++ > 1)
......
......@@ -382,7 +382,7 @@ class THD :public ilink {
#endif
ulonglong next_insert_id,last_insert_id,current_insert_id,
limit_found_rows;
ha_rows select_limit,offset_limit,default_select_limit,cuted_fields,
ha_rows default_select_limit,cuted_fields,
max_join_size, sent_row_count, examined_row_count;
table_map used_tables;
UC *user_connect;
......@@ -551,10 +551,15 @@ void send_error(NET *net,uint sql_errno=0, const char *err=0);
class select_result :public Sql_alloc {
protected:
THD *thd;
SELECT_LEX_UNIT *unit;
public:
select_result();
virtual ~select_result() {};
virtual int prepare(List<Item> &list) { return 0; }
virtual int prepare(List<Item> &list, SELECT_LEX_UNIT *u)
{
unit= u;
return 0;
}
virtual bool send_fields(List<Item> &list,uint flag)=0;
virtual bool send_data(List<Item> &items)=0;
virtual void initialize_tables (JOIN *join=0) {}
......@@ -587,7 +592,7 @@ class select_export :public select_result {
public:
select_export(sql_exchange *ex) :exchange(ex),file(-1),row_count(0L) {}
~select_export();
int prepare(List<Item> &list);
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_fields(List<Item> &list,
uint flag) { return 0; }
bool send_data(List<Item> &items);
......@@ -606,7 +611,7 @@ class select_dump :public select_result {
select_dump(sql_exchange *ex) :exchange(ex),file(-1),row_count(0L)
{ path[0]=0; }
~select_dump();
int prepare(List<Item> &list);
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_fields(List<Item> &list,
uint flag) { return 0; }
bool send_data(List<Item> &items);
......@@ -629,7 +634,7 @@ class select_insert :public select_result {
info.handle_duplicates=duplic;
}
~select_insert();
int prepare(List<Item> &list);
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_fields(List<Item> &list, uint flag)
{ return 0; }
bool send_data(List<Item> &items);
......@@ -658,7 +663,7 @@ class select_create: public select_insert {
create_info(create_info_par),
lock(0)
{}
int prepare(List<Item> &list);
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_data(List<Item> &values);
bool send_eof();
void abort();
......@@ -672,7 +677,7 @@ class select_union :public select_result {
select_union(TABLE *table_par);
~select_union();
int prepare(List<Item> &list);
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_fields(List<Item> &list, uint flag)
{ return 0; }
bool send_data(List<Item> &items);
......@@ -787,7 +792,7 @@ class Unique :public Sql_alloc
multi_delete(THD *thd, TABLE_LIST *dt, thr_lock_type lock_option_arg,
uint num_of_tables);
~multi_delete();
int prepare(List<Item> &list);
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_fields(List<Item> &list,
uint flag) { return 0; }
bool send_data(List<Item> &items);
......@@ -816,7 +821,7 @@ class Unique :public Sql_alloc
enum enum_duplicates handle_duplicates,
thr_lock_type lock_option_arg, uint num);
~multi_update();
int prepare(List<Item> &list);
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_fields(List<Item> &list,
uint flag) { return 0; }
bool send_data(List<Item> &items);
......
......@@ -232,9 +232,10 @@ multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt,
int
multi_delete::prepare(List<Item> &values)
multi_delete::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
{
DBUG_ENTER("multi_delete::prepare");
unit= u;
do_delete = true;
thd->proc_info="deleting from main table";
......
......@@ -28,13 +28,13 @@
static const char *any_db="*any*"; // Special symbol for check_access
int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t)
int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
{
/*
TODO: make derived tables with union inside (now only 1 SELECT may be
procesed)
*/
SELECT_LEX *sl= (SELECT_LEX*)s->slave;
SELECT_LEX *sl= (SELECT_LEX*)unit->slave;
List<Item> item_list;
TABLE *table;
int res;
......@@ -75,9 +75,11 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t)
}
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, sl->item_list,
if (!(table= create_tmp_table(thd, &tmp_table_param, sl->item_list,
(ORDER*) 0, 0, 1, 0,
(sl->options | thd->options | TMP_TABLE_ALL_COLUMNS))))
(sl->options | thd->options |
TMP_TABLE_ALL_COLUMNS),
unit)))
{
res=-1;
goto exit;
......@@ -85,11 +87,11 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t)
if ((derived_result=new select_union(table)))
{
thd->offset_limit=sl->offset_limit;
thd->select_limit=sl->select_limit+sl->offset_limit;
if (thd->select_limit < sl->select_limit)
thd->select_limit= HA_POS_ERROR;
if (thd->select_limit == HA_POS_ERROR)
unit->offset_limit_cnt= sl->offset_limit;
unit->select_limit_cnt= sl->select_limit+sl->offset_limit;
if (unit->select_limit_cnt < sl->select_limit)
unit->select_limit_cnt= HA_POS_ERROR;
if (unit->select_limit_cnt == HA_POS_ERROR)
sl->options&= ~OPTION_FOUND_ROWS;
res=mysql_select(thd, tables, sl->item_list,
......@@ -97,7 +99,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t)
(ORDER*) sl->group_list.first,
sl->having, (ORDER*) NULL,
sl->options | thd->options | SELECT_NO_UNLOCK,
derived_result);
derived_result, unit);
if (!res)
{
// Here we entirely fix both TABLE_LIST and list of SELECT's as there were no derived tables
......
......@@ -1266,10 +1266,11 @@ bool delayed_insert::handle_inserts(void)
***************************************************************************/
int
select_insert::prepare(List<Item> &values)
select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
{
DBUG_ENTER("select_insert::prepare");
unit= u;
save_time_stamp=table->time_stamp;
if (check_insert_fields(thd,table,*fields,values,1))
DBUG_RETURN(1);
......@@ -1302,9 +1303,9 @@ select_insert::~select_insert()
bool select_insert::send_data(List<Item> &values)
{
if (thd->offset_limit)
if (unit->offset_limit_cnt)
{ // using limit offset,count
thd->offset_limit--;
unit->offset_limit_cnt--;
return 0;
}
if (fields->elements)
......@@ -1380,10 +1381,11 @@ bool select_insert::send_eof()
***************************************************************************/
int
select_create::prepare(List<Item> &values)
select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
{
DBUG_ENTER("select_create::prepare");
unit= u;
table=create_table_from_items(thd, create_info, db, name,
extra_fields, keys, &values, &lock);
if (!table)
......@@ -1413,9 +1415,9 @@ select_create::prepare(List<Item> &values)
bool select_create::send_data(List<Item> &values)
{
if (thd->offset_limit)
if (unit->offset_limit_cnt)
{ // using limit offset,count
thd->offset_limit--;
unit->offset_limit_cnt--;
return 0;
}
fill_record(field,values);
......
......@@ -895,14 +895,16 @@ void st_select_lex_node::init_select()
order_list.elements= 0;
order_list.first= 0;
order_list.next= (byte**) &order_list.first;
select_limit= offset_limit= 0;
select_limit= HA_POS_ERROR;
offset_limit= 0;
}
void st_select_lex_unit::init_query()
{
st_select_lex_node::init_query();
global_parameters= this;
select_limit_cnt= offset_limit_cnt= 0;
select_limit_cnt= HA_POS_ERROR;
offset_limit_cnt= 0;
}
void st_select_lex::init_query()
......
......@@ -1203,11 +1203,12 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
void
mysql_execute_command(void)
{
int res=0;
THD *thd=current_thd;
int res= 0;
THD *thd= current_thd;
LEX *lex= &thd->lex;
TABLE_LIST *tables=(TABLE_LIST*) lex->select_lex.table_list.first;
SELECT_LEX *select_lex = lex->select;
TABLE_LIST *tables= (TABLE_LIST*) lex->select_lex.table_list.first;
SELECT_LEX *select_lex= lex->select;
SELECT_LEX_UNIT *unit= &lex->unit;
DBUG_ENTER("mysql_execute_command");
if (thd->slave_thread)
......@@ -1274,11 +1275,11 @@ mysql_execute_command(void)
break; // Error message is given
}
thd->offset_limit=select_lex->offset_limit;
thd->select_limit=select_lex->select_limit+select_lex->offset_limit;
if (thd->select_limit < select_lex->select_limit)
thd->select_limit= HA_POS_ERROR; // no limit
if (thd->select_limit == HA_POS_ERROR)
unit->offset_limit_cnt =select_lex->offset_limit;
unit->select_limit_cnt =select_lex->select_limit+select_lex->offset_limit;
if (unit->select_limit_cnt < select_lex->select_limit)
unit->select_limit_cnt= HA_POS_ERROR; // no limit
if (unit->select_limit_cnt == HA_POS_ERROR)
select_lex->options&= ~OPTION_FOUND_ROWS;
if (lex->exchange)
......@@ -1503,10 +1504,11 @@ mysql_execute_command(void)
for (table = tables->next ; table ; table=table->next)
table->lock_type= lex->lock_option;
}
thd->offset_limit=select_lex->offset_limit;
thd->select_limit=select_lex->select_limit+select_lex->offset_limit;
if (thd->select_limit < select_lex->select_limit)
thd->select_limit= HA_POS_ERROR; // No limit
unit->offset_limit_cnt= select_lex->offset_limit;
unit->select_limit_cnt= select_lex->select_limit+
select_lex->offset_limit;
if (unit->select_limit_cnt < select_lex->select_limit)
unit->select_limit_cnt= HA_POS_ERROR; // No limit
/* Skip first table, which is the table we are creating */
lex->select_lex.table_list.first=
......@@ -1788,13 +1790,13 @@ mysql_execute_command(void)
while ((item=value_list++))
total_list.push_back(item);
res=mysql_select(thd,tables,total_list,
res= mysql_select(thd, tables, total_list,
select_lex->where,
(ORDER *)NULL,(ORDER *)NULL,(Item *)NULL,
(ORDER *)NULL, (ORDER *)NULL, (Item *)NULL,
(ORDER *)NULL,
select_lex->options | thd->options |
SELECT_NO_JOIN_CACHE,
result);
result, unit);
delete result;
}
else
......@@ -1844,10 +1846,10 @@ mysql_execute_command(void)
}
select_result *result;
thd->offset_limit=select_lex->offset_limit;
thd->select_limit=select_lex->select_limit+select_lex->offset_limit;
if (thd->select_limit < select_lex->select_limit)
thd->select_limit= HA_POS_ERROR; // No limit
unit->offset_limit_cnt= select_lex->offset_limit;
unit->select_limit_cnt= select_lex->select_limit+select_lex->offset_limit;
if (unit->select_limit_cnt < select_lex->select_limit)
unit->select_limit_cnt= HA_POS_ERROR; // No limit
if (check_dup(tables->db, tables->real_name, tables->next))
{
......@@ -1963,7 +1965,7 @@ mysql_execute_command(void)
(ORDER *)NULL,
select_lex->options | thd->options |
SELECT_NO_JOIN_CACHE,
result);
result, unit);
delete result;
}
else
......@@ -2667,8 +2669,10 @@ mysql_init_query(THD *thd)
{
DBUG_ENTER("mysql_init_query");
thd->lex.unit.init_query();
thd->lex.unit.init_select();
thd->lex.select_lex.init_query();
thd->lex.unit.slave= &thd->lex.select_lex;
thd->lex.unit.select_limit= thd->default_select_limit; //Global limit
thd->lex.select_lex.master= &thd->lex.unit;
thd->lex.select_lex.prev= &thd->lex.unit.slave;
thd->lex.value_list.empty();
......@@ -2716,6 +2720,7 @@ mysql_new_select(LEX *lex, bool move_down)
else
select_lex->include_neighbour(lex->select);
((SELECT_LEX_UNIT*)select_lex->master)->global_parameters= select_lex;
select_lex->include_global(&lex->select->link_next);
lex->select= select_lex;
return 0;
......
......@@ -65,7 +65,8 @@ static ORDER *remove_const(JOIN *join,ORDER *first_order,COND *cond,
static int return_zero_rows(select_result *res,TABLE_LIST *tables,
List<Item> &fields, bool send_row,
uint select_options, const char *info,
Item *having, Procedure *proc);
Item *having, Procedure *proc,
SELECT_LEX_UNIT *unit);
static COND *optimize_cond(COND *conds,Item::cond_result *cond_value);
static COND *remove_eq_conds(COND *cond,Item::cond_result *cond_value);
static bool const_expression_in_where(COND *conds,Item *item, Item **comp_item);
......@@ -166,7 +167,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);
result, &(lex->unit));
if (res && result)
result->abort();
delete result;
......@@ -182,7 +183,8 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
int
mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
ORDER *order, ORDER *group,Item *having,ORDER *proc_param,
ulong select_options,select_result *result)
ulong select_options,select_result *result,
SELECT_LEX_UNIT *unit)
{
TABLE *tmp_table;
int error, tmp_error;
......@@ -195,8 +197,8 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
Procedure *procedure;
List<Item> all_fields(fields);
bool select_distinct;
SELECT_LEX *select_lex = &(thd->lex.select_lex);
SELECT_LEX *cur_sel = thd->lex.select;
SELECT_LEX *select_lex= &(thd->lex.select_lex);
SELECT_LEX *cur_sel= thd->lex.select;
DBUG_ENTER("mysql_select");
/* Check that all tables, fields, conds and order are ok */
......@@ -312,7 +314,8 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
join.do_send_rows = 1;
join.group= group != 0;
join.row_limit= ((select_distinct || order || group) ? HA_POS_ERROR :
thd->select_limit);
unit->select_limit_cnt);
join.unit= unit;
#ifdef RESTRICTED_GROUP
if (join.sum_func_count && !group && (join.func_count || join.field_count))
......@@ -322,7 +325,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
DBUG_RETURN(-1);
}
#endif
if (!procedure && result->prepare(fields))
if (!procedure && result->prepare(fields, unit))
{ /* purecov: inspected */
DBUG_RETURN(-1); /* purecov: inspected */
}
......@@ -351,7 +354,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
delete procedure;
DBUG_RETURN(0);
}
if (cond_value == Item::COND_FALSE || !thd->select_limit)
if (cond_value == Item::COND_FALSE || !unit->select_limit_cnt)
{ /* Impossible cond */
if (select_options & SELECT_DESCRIBE && select_lex->next)
select_describe(&join,false,false,false,"Impossible WHERE");
......@@ -359,7 +362,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
error=return_zero_rows(result, tables, fields,
join.tmp_table_param.sum_func_count != 0 && !group,
select_options,"Impossible WHERE",having,
procedure);
procedure, unit);
delete procedure;
DBUG_RETURN(error);
}
......@@ -376,8 +379,8 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
select_describe(&join,false,false,false,"No matching min/max row");
else
error=return_zero_rows(result, tables, fields, !group,
select_options,"No matching min/max row",
having,procedure);
select_options, "No matching min/max row",
having, procedure, unit);
delete procedure;
DBUG_RETURN(error);
}
......@@ -435,9 +438,9 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
if (join.const_table_map != join.found_const_table_map &&
!(select_options & SELECT_DESCRIBE))
{
error=return_zero_rows(result,tables,fields,
error= return_zero_rows(result, tables, fields,
join.tmp_table_param.sum_func_count != 0 &&
!group,0,"",having,procedure);
!group, 0, "", having, procedure, unit);
goto err;
}
if (!(thd->options & OPTION_BIG_SELECTS) &&
......@@ -483,11 +486,12 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
if (select_options & SELECT_DESCRIBE && select_lex->next)
select_describe(&join,false,false,false,"Impossible WHERE noticed after reading const tables");
else
error=return_zero_rows(result,tables,fields,
join.tmp_table_param.sum_func_count != 0 && !group,
error= return_zero_rows(result,tables,fields,
join.tmp_table_param.sum_func_count != 0 &&
!group,
select_options,
"Impossible WHERE noticed after reading const tables",
having,procedure);
having, procedure, unit);
goto err;
}
......@@ -501,12 +505,12 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
select_distinct=0;
}
else if (select_distinct && join.tables - join.const_tables == 1 &&
(thd->select_limit == HA_POS_ERROR ||
(unit->select_limit_cnt == HA_POS_ERROR ||
(join.select_options & OPTION_FOUND_ROWS) ||
order &&
!(skip_sort_order=
test_if_skip_sort_order(&join.join_tab[join.const_tables],
order, thd->select_limit,1))))
order, unit->select_limit_cnt,1))))
{
if ((group=create_distinct_group(order,fields)))
{
......@@ -593,7 +597,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
((group && join.const_tables != join.tables &&
(!simple_group ||
!test_if_skip_sort_order(&join.join_tab[join.const_tables], group,
thd->select_limit,0))) ||
unit->select_limit_cnt, 0))) ||
select_distinct) &&
join.tmp_table_param.quick_group && !procedure)
{
......@@ -610,7 +614,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
test_if_skip_sort_order(&join.join_tab[join.const_tables], order,
(join.const_tables != join.tables - 1 ||
(join.select_options & OPTION_FOUND_ROWS)) ?
HA_POS_ERROR : thd->select_limit,0))))
HA_POS_ERROR : unit->select_limit_cnt, 0))))
order=0;
select_describe(&join,need_tmp,
order != 0 && !skip_sort_order,
......@@ -637,7 +641,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
group && simple_group,
(order == 0 || skip_sort_order) &&
!(join.select_options & OPTION_FOUND_ROWS),
join.select_options)))
join.select_options, unit)))
goto err; /* purecov: inspected */
if (having && (join.sort_and_group || (tmp_table->distinct && !group)))
......@@ -690,7 +694,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
if (order && skip_sort_order)
{
(void) test_if_skip_sort_order(&join.join_tab[join.const_tables],
order, thd->select_limit,0);
order, unit->select_limit_cnt, 0);
order=0;
}
}
......@@ -760,7 +764,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
(ORDER*) 0,
select_distinct && !group,
1, 0,
join.select_options)))
join.select_options, unit)))
goto err; /* purecov: inspected */
if (group)
{
......@@ -817,9 +821,9 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
if (procedure)
{
if (procedure->change_columns(fields) ||
result->prepare(fields))
result->prepare(fields, unit))
goto err;
count_field_types(&join.tmp_table_param,all_fields,0);
count_field_types(&join.tmp_table_param, all_fields, 0);
}
if (join.group || join.tmp_table_param.sum_func_count ||
(procedure && (procedure->flags & PROC_GROUP)))
......@@ -864,7 +868,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
(having || group ||
join.const_tables != join.tables - 1 ||
(join.select_options & OPTION_FOUND_ROWS)) ?
HA_POS_ERROR : thd->select_limit))
HA_POS_ERROR : unit->select_limit_cnt))
goto err; /* purecov: inspected */
}
join.having=having; // Actually a parameter
......@@ -2480,7 +2484,8 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
if ((tab->keys & ~ tab->const_keys && i > 0) ||
(tab->const_keys && i == join->const_tables &&
join->thd->select_limit < join->best_positions[i].records_read &&
join->unit->select_limit_cnt <
join->best_positions[i].records_read &&
!(join->select_options & OPTION_FOUND_ROWS)))
{
/* Join with outer join condition */
......@@ -2491,7 +2496,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
(join->select_options &
OPTION_FOUND_ROWS ?
HA_POS_ERROR :
join->thd->select_limit)) < 0)
join->unit->select_limit_cnt)) < 0)
DBUG_RETURN(1); // Impossible range
sel->cond=orig_cond;
}
......@@ -2929,7 +2934,7 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond, bool *simple_order)
static int
return_zero_rows(select_result *result,TABLE_LIST *tables,List<Item> &fields,
bool send_row, uint select_options,const char *info,
Item *having, Procedure *procedure)
Item *having, Procedure *procedure, SELECT_LEX_UNIT *unit)
{
DBUG_ENTER("return_zero_rows");
......@@ -2940,7 +2945,7 @@ return_zero_rows(select_result *result,TABLE_LIST *tables,List<Item> &fields,
}
if (procedure)
{
if (result->prepare(fields)) // This hasn't been done yet
if (result->prepare(fields, unit)) // This hasn't been done yet
DBUG_RETURN(-1);
}
if (send_row)
......@@ -3475,7 +3480,8 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
TABLE *
create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
ORDER *group, bool distinct, bool save_sum_fields,
bool allow_distinct_limit, ulong select_options)
bool allow_distinct_limit, ulong select_options,
SELECT_LEX_UNIT *unit)
{
TABLE *table;
uint i,field_count,reclength,null_count,null_pack_length,
......@@ -3846,8 +3852,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
test(null_pack_length));
if (allow_distinct_limit)
{
set_if_smaller(table->max_rows,thd->select_limit);
param->end_write_records=thd->select_limit;
set_if_smaller(table->max_rows, unit->select_limit_cnt);
param->end_write_records= unit->select_limit_cnt;
}
else
param->end_write_records= HA_POS_ERROR;
......@@ -4892,7 +4898,8 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
error=join->result->send_data(*join->fields);
if (error)
DBUG_RETURN(-1); /* purecov: inspected */
if (++join->send_records >= join->thd->select_limit && join->do_send_rows)
if (++join->send_records >= join->unit->select_limit_cnt &&
join->do_send_rows)
{
if (join->select_options & OPTION_FOUND_ROWS)
{
......@@ -4907,8 +4914,8 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
}
else
{
join->do_send_rows=0;
join->thd->select_limit = HA_POS_ERROR;
join->do_send_rows= 0;
join->unit->select_limit= HA_POS_ERROR;
DBUG_RETURN(0);
}
}
......@@ -4969,13 +4976,13 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
DBUG_RETURN(-1); /* purecov: inspected */
if (end_of_records)
DBUG_RETURN(0);
if (!error && ++join->send_records >= join->thd->select_limit &&
if (!error && ++join->send_records >= join->unit->select_limit_cnt &&
join->do_send_rows)
{
if (!(join->select_options & OPTION_FOUND_ROWS))
DBUG_RETURN(-3); // Abort nicely
join->do_send_rows=0;
join->thd->select_limit = HA_POS_ERROR;
join->unit->select_limit_cnt = HA_POS_ERROR;
}
}
}
......@@ -5056,7 +5063,7 @@ end_write(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
if (!(join->select_options & OPTION_FOUND_ROWS))
DBUG_RETURN(-3);
join->do_send_rows=0;
join->thd->select_limit = HA_POS_ERROR;
join->unit->select_limit_cnt = HA_POS_ERROR;
DBUG_RETURN(0);
}
}
......@@ -5755,7 +5762,7 @@ remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields, Item *having)
if (!field_count)
{ // only const items
join->thd->select_limit=1; // Only send first row
join->unit->select_limit_cnt= 1; // Only send first row
DBUG_RETURN(0);
}
Field **first_field=entry->field+entry->fields - field_count;
......
......@@ -173,6 +173,8 @@ class JOIN {
select_result *result;
TMP_TABLE_PARAM tmp_table_param;
MYSQL_LOCK *lock;
// unit structure (with global parameters) for this select
SELECT_LEX_UNIT *unit;
};
......@@ -187,7 +189,8 @@ void TEST_join(JOIN *join);
bool store_val_in_field(Field *field,Item *val);
TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
ORDER *group, bool distinct, bool save_sum_fields,
bool allow_distinct_limit, ulong select_options);
bool allow_distinct_limit, ulong select_options,
SELECT_LEX_UNIT *unit);
void free_tmp_table(THD *thd, TABLE *entry);
void count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields,
bool reset_with_sum_func);
......
......@@ -27,8 +27,8 @@
int mysql_union(THD *thd, LEX *lex,select_result *result)
{
SELECT_LEX *sl, *last_sl, *lex_sl;
ORDER *order;
SELECT_LEX *sl;
SELECT_LEX_UNIT *unit= &(lex->unit);
List<Item> item_list;
TABLE *table;
int describe=(lex->select_lex.options & SELECT_DESCRIBE) ? 1 : 0;
......@@ -39,12 +39,12 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
TMP_TABLE_PARAM tmp_table_param;
select_union *union_result;
DBUG_ENTER("mysql_union");
st_select_lex_node * global;
/* Fix tables 'to-be-unioned-from' list to point at opened tables */
last_sl= &lex->select_lex;
for (sl= last_sl;
sl && sl->linkage != GLOBAL_OPTIONS_TYPE;
last_sl= sl, sl= (SELECT_LEX *) sl->next)
for (sl= &lex->select_lex;
sl;
sl= (SELECT_LEX *) sl->next)
{
for (TABLE_LIST *cursor= (TABLE_LIST *)sl->table_list.first;
cursor;
......@@ -52,31 +52,13 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
cursor->table= ((TABLE_LIST*) cursor->table)->table;
}
/* last_sel now points at the last select where the ORDER BY is stored */
if (sl)
/* Global option */
if (((void*)(global= unit->global_parameters)) == ((void*)unit))
{
/*
The found SL is an extra SELECT_LEX argument that contains
the ORDER BY and LIMIT parameter for the whole UNION
*/
lex_sl= sl;
order= (ORDER *) lex_sl->order_list.first;
found_rows_for_union = lex->select_lex.options & OPTION_FOUND_ROWS && !describe && sl->select_limit;
found_rows_for_union = lex->select_lex.options & OPTION_FOUND_ROWS &&
!describe && global->select_limit;
if (found_rows_for_union)
lex->select_lex.options ^= OPTION_FOUND_ROWS;
// This is done to eliminate unnecessary slowing down of the first query
if (!order || !describe)
last_sl->next=0; // Remove this extra element
}
else if (!last_sl->braces)
{
lex_sl= last_sl; // ORDER BY is here
order= (ORDER *) lex_sl->order_list.first;
}
else
{
lex_sl=0;
order=0;
}
if (describe)
......@@ -113,11 +95,12 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
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,
if (!(table= create_tmp_table(thd, &tmp_table_param, item_list,
(ORDER*) 0, !describe & !lex->union_option,
1, 0,
(lex->select_lex.options | thd->options |
TMP_TABLE_ALL_COLUMNS))))
TMP_TABLE_ALL_COLUMNS),
unit)))
DBUG_RETURN(-1);
table->file->extra(HA_EXTRA_WRITE_CACHE);
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
......@@ -136,11 +119,11 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
for (sl= &lex->select_lex; sl; sl= (SELECT_LEX*) sl->next)
{
lex->select=sl;
thd->offset_limit=sl->offset_limit;
thd->select_limit=sl->select_limit+sl->offset_limit;
if (thd->select_limit < sl->select_limit)
thd->select_limit= HA_POS_ERROR; // no limit
if (thd->select_limit == HA_POS_ERROR)
unit->offset_limit_cnt= sl->offset_limit;
unit->select_limit_cnt= sl->select_limit+sl->offset_limit;
if (unit->select_limit_cnt < sl->select_limit)
unit->select_limit_cnt= HA_POS_ERROR; // no limit
if (unit->select_limit_cnt == HA_POS_ERROR)
sl->options&= ~OPTION_FOUND_ROWS;
res= mysql_select(thd,
......@@ -155,7 +138,7 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
(ORDER*) NULL,
sl->options | thd->options |
SELECT_NO_UNLOCK | ((describe) ? SELECT_DESCRIBE : 0),
union_result);
union_result, unit);
if (res)
goto exit;
}
......@@ -187,26 +170,20 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
}
if (!thd->fatal_error) // Check if EOM
{
if (lex_sl)
{
thd->offset_limit=lex_sl->offset_limit;
thd->select_limit=lex_sl->select_limit+lex_sl->offset_limit;
if (thd->select_limit < lex_sl->select_limit)
thd->select_limit= HA_POS_ERROR; // no limit
if (thd->select_limit == HA_POS_ERROR)
st_select_lex_node * global= unit->global_parameters;
unit->offset_limit_cnt= global->offset_limit;
unit->select_limit_cnt= global->select_limit+global->offset_limit;
if (unit->select_limit_cnt < global->select_limit)
unit->select_limit_cnt= HA_POS_ERROR; // no limit
if (unit->select_limit_cnt == HA_POS_ERROR)
thd->options&= ~OPTION_FOUND_ROWS;
}
else
{
thd->offset_limit= 0;
thd->select_limit= thd->default_select_limit;
}
if (describe)
thd->select_limit= HA_POS_ERROR; // no limit
res=mysql_select(thd,&result_table_list,
item_list, NULL, (describe) ? 0 : order,
unit->select_limit_cnt= HA_POS_ERROR; // no limit
res= mysql_select(thd,&result_table_list,
item_list, NULL,
(describe) ? 0 : (ORDER*)global->order_list.first,
(ORDER*) NULL, NULL, (ORDER*) NULL,
thd->options, result);
thd->options, result, unit);
if (found_rows_for_union && !res)
thd->limit_found_rows = (ulonglong)table->file->records;
}
......@@ -230,7 +207,7 @@ select_union::select_union(TABLE *table_par)
We can always use DUP_IGNORE because the temporary table will only
contain a unique key if we are using not using UNION ALL
*/
info.handle_duplicates=DUP_IGNORE;
info.handle_duplicates= DUP_IGNORE;
}
select_union::~select_union()
......@@ -238,8 +215,9 @@ select_union::~select_union()
}
int select_union::prepare(List<Item> &list)
int select_union::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
{
unit= u;
if (save_time_stamp && list.elements != table->fields)
{
my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
......@@ -251,9 +229,9 @@ int select_union::prepare(List<Item> &list)
bool select_union::send_data(List<Item> &values)
{
if (thd->offset_limit)
if (unit->offset_limit_cnt)
{ // using limit offset,count
thd->offset_limit--;
unit->offset_limit_cnt--;
return 0;
}
fill_record(table->field,values);
......
......@@ -379,9 +379,10 @@ multi_update::multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> &fs,
}
int
multi_update::prepare(List<Item> &values)
multi_update::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
{
DBUG_ENTER("multi_update::prepare");
unit= u;
do_update = true;
thd->count_cuted_fields=1;
thd->cuted_fields=0L;
......@@ -466,15 +467,19 @@ multi_update::prepare(List<Item> &values)
}
if (counter)
{
Field_string offset(table_ref->table->file->ref_length,false,"offset",table_ref->table,true);
Field_string offset(table_ref->table->file->ref_length, false,
"offset", table_ref->table, true);
temp_fields->push_front(new Item_field(((Field *)&offset)));
// Here I make tmp tables
int cnt=counter-1;
TMP_TABLE_PARAM tmp_table_param;
bzero((char*) &tmp_table_param,sizeof(tmp_table_param));
tmp_table_param.field_count=temp_fields->elements;
if (!(tmp_tables[cnt]=create_tmp_table(thd, &tmp_table_param, *temp_fields,
(ORDER*) 0, 1, 0, 0, TMP_TABLE_ALL_COLUMNS)))
if (!(tmp_tables[cnt]=create_tmp_table(thd, &tmp_table_param,
*temp_fields,
(ORDER*) 0, 1, 0, 0,
TMP_TABLE_ALL_COLUMNS,
unit)))
{
error = 1; // A proper error message is due here
DBUG_RETURN(1);
......
......@@ -1449,7 +1449,14 @@ select:
select_init:
SELECT_SYM select_part2 { Select->braces=false; } union
|
'(' SELECT_SYM select_part2 ')' { Select->braces=true;} union_opt
'(' SELECT_SYM select_part2 ')'
{
SELECT_LEX * sel=Select;
sel->braces=true;
/* select in braces, can't contain global parameters */
((SELECT_LEX_UNIT*)sel->master)->global_parameters=
sel->master;
} union_opt
select_part2:
......@@ -3826,10 +3833,15 @@ optional_order_or_limit:
|
{
LEX *lex=Lex;
if (!lex->select->braces || mysql_new_select(lex, 0))
if (!lex->select->braces)
YYABORT;
mysql_init_select(lex);
lex->select->linkage= GLOBAL_OPTIONS_TYPE;
((SELECT_LEX_UNIT*)lex->select->master)->global_parameters=
lex->select->master;
/*
Following type conversion looks like hack, but all that need SELECT_LEX
fields always check linkage type.
*/
lex->select= (SELECT_LEX*)lex->select->master;
lex->select->select_limit=lex->thd->default_select_limit;
}
opt_order_clause limit_clause
......
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