From e5b841e392d80dcc8162443fb0a27d7f11b14be3 Mon Sep 17 00:00:00 2001 From: "Sinisa@sinisa.nasamreza.org" <> Date: Wed, 20 Aug 2003 20:16:37 +0300 Subject: [PATCH] sql_union.cc: Merge fix --- sql/sql_union.cc | 52 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 81a4806ab65..fe13261b454 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -31,9 +31,10 @@ int mysql_union(THD *thd, LEX *lex,select_result *result) ORDER *order; List item_list; TABLE *table; - int describe=(lex->select_lex.options & SELECT_DESCRIBE) ? 1 : 0; - int res, add_rows=0; - bool found_rows_for_union= lex->select_lex.options & OPTION_FOUND_ROWS; + int res; + ulonglong add_rows= 0; + ulong found_rows_for_union= lex->select_lex.options & OPTION_FOUND_ROWS; + ulong describe= lex->select_lex.options & SELECT_DESCRIBE; TABLE_LIST result_table_list; TABLE_LIST *first_table=(TABLE_LIST *)lex->select_lex.table_list.first; TMP_TABLE_PARAM tmp_table_param; @@ -135,19 +136,29 @@ int mysql_union(THD *thd, LEX *lex,select_result *result) union_result->tmp_table_param=&tmp_table_param; for (sl= &lex->select_lex; sl; sl=sl->next) { - unsigned int rows; + ha_rows records_at_start; lex->select=sl; - thd->offset_limit=sl->offset_limit; + /* Don't use offset for the last union if there is no braces */ + thd->offset_limit= sl != lex_sl ? sl->offset_limit : 0; thd->select_limit=sl->select_limit+sl->offset_limit; if (thd->select_limit < sl->select_limit) thd->select_limit= HA_POS_ERROR; // no limit + /* + When using braces, SQL_CALC_FOUND_ROWS affects the whole query. + We don't calculate found_rows() per union part + */ if (thd->select_limit == HA_POS_ERROR || sl->braces) sl->options&= ~OPTION_FOUND_ROWS; - else if (found_rows_for_union) + else { - rows= thd->select_limit; - sl->options|= OPTION_FOUND_ROWS; + /* + We are doing an union without braces. In this case + SQL_CALC_FOUND_ROWS should be done on all sub parts + */ + sl->options|= found_rows_for_union; } + + records_at_start= table->file->records; res=mysql_select(thd, (describe && sl->linkage==NOT_A_SELECT) ? first_table : (TABLE_LIST*) sl->table_list.first, @@ -159,12 +170,23 @@ int mysql_union(THD *thd, LEX *lex,select_result *result) sl->having, (ORDER*) NULL, sl->options | thd->options | SELECT_NO_UNLOCK | - ((describe) ? SELECT_DESCRIBE : 0), + describe, union_result); - if (found_rows_for_union && !sl->braces && sl->options & OPTION_FOUND_ROWS) - add_rows+= (thd->limit_found_rows > rows) ? thd->limit_found_rows - rows : 0; if (res) goto exit; + /* Needed for the following test and for records_at_start in next loop */ + table->file->info(HA_STATUS_VARIABLE); + if (found_rows_for_union & sl->options) + { + /* + This is a union without braces. Remember the number of rows that could + also have been part of the result set. + We get this from the difference of between total number of possible + rows and actual rows added to the temporary table. + */ + add_rows+= (ulonglong) (thd->limit_found_rows - (table->file->records - + records_at_start)); + } } if (union_result->flush()) { @@ -217,12 +239,8 @@ int mysql_union(THD *thd, LEX *lex,select_result *result) item_list, NULL, (describe) ? 0 : order, (ORDER*) NULL, NULL, (ORDER*) NULL, thd->options, result); - if (found_rows_for_union && !res) - { - thd->limit_found_rows= table->file->records; - if (!last_sl->braces) - thd->limit_found_rows+= add_rows; - } + if (!res) + thd->limit_found_rows = (ulonglong)table->file->records + add_rows; } }