summaryrefslogtreecommitdiff
path: root/sql/sql_union.cc
diff options
context:
space:
mode:
authorbell@sanja.is.com.ua <>2002-05-08 23:14:40 +0300
committerbell@sanja.is.com.ua <>2002-05-08 23:14:40 +0300
commitead6f225a426c43b181e3dee2dfebad40df4f163 (patch)
tree23c58e5b8137b1a19b2371ec5ab4dadf69329e50 /sql/sql_union.cc
parent494184ff5fe9b614d843d622bc1a0230c970fe3f (diff)
downloadmariadb-git-ead6f225a426c43b181e3dee2dfebad40df4f163.tar.gz
new SELECT_LEX structures used for storing global ORDER BY, global LIMIT & limit counters
Diffstat (limited to 'sql/sql_union.cc')
-rw-r--r--sql/sql_union.cc102
1 files changed, 40 insertions, 62 deletions
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 7178b857bbc..2eae37a70eb 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -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,
- (ORDER*) 0, !describe & !lex->union_option,
- 1, 0,
- (lex->select_lex.options | thd->options |
- TMP_TABLE_ALL_COLUMNS))))
+ 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),
+ 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)
- thd->options&= ~OPTION_FOUND_ROWS;
- }
- else
- {
- thd->offset_limit= 0;
- thd->select_limit= thd->default_select_limit;
- }
+ 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;
if (describe)
- thd->select_limit= HA_POS_ERROR; // no limit
- res=mysql_select(thd,&result_table_list,
- item_list, NULL, (describe) ? 0 : order,
- (ORDER*) NULL, NULL, (ORDER*) NULL,
- thd->options, result);
+ 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, 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);