diff options
author | unknown <bell@sanja.is.com.ua> | 2002-09-03 09:50:36 +0300 |
---|---|---|
committer | unknown <bell@sanja.is.com.ua> | 2002-09-03 09:50:36 +0300 |
commit | 3fbcafea9c5e85dc6315f0b89872ac5e273195c8 (patch) | |
tree | 80af274b045962ab1f5805301ffc1dfa15a21b96 /sql/sql_union.cc | |
parent | 1648e47889f6c981847ab300bf6e71d08c9f0667 (diff) | |
download | mariadb-git-3fbcafea9c5e85dc6315f0b89872ac5e273195c8.tar.gz |
subselect with union
new error handling
Item_ref bug fixed
include/mysql_com.h:
new error handling
query cache pointer description
mysql-test/r/distinct.result:
new result's after Monty's bug fixing
mysql-test/r/subselect.result:
subselect with union test
mysql-test/t/subselect.test:
subselect with union test
sql/item.cc:
subselect with union
Item_ref bug fixed
sql/item_cmpfunc.cc:
Monty's bug fixing
sql/item_subselect.cc:
TODO changing
subselect with union
sql/item_subselect.h:
subselect with union
sql/mysql_priv.h:
Item_ref bug fixed
sql/mysqld.cc:
new error handling
sql/net_pkg.cc:
new error handling
sql/net_serv.cc:
new error handling
sql/sql_base.cc:
Item_ref bug fixed
sql/sql_class.cc:
new error handling
sql/sql_class.h:
new error handling
sql/sql_derived.cc:
subselect with union
sql/sql_insert.cc:
new error handling (only with mysql_select now)
sql/sql_lex.cc:
subselect with union
sql/sql_lex.h:
subselect with union
sql/sql_parse.cc:
new error handling
sql/sql_select.cc:
new error handling
subselect with union
removed thd->where=0 hack
sql/sql_select.h:
subselect with union
sql/sql_union.cc:
subselect with union
sql/sql_update.cc:
new error handling (only with mysql_select now)
sql/sql_yacc.yy:
subselect with union
Diffstat (limited to 'sql/sql_union.cc')
-rw-r--r-- | sql/sql_union.cc | 312 |
1 files changed, 188 insertions, 124 deletions
diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 0eea10e068a..e8ee3582135 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -24,31 +24,103 @@ #include "mysql_priv.h" #include "sql_select.h" +int mysql_union(THD *thd, LEX *lex, select_result *result) +{ + DBUG_ENTER("mysql_union"); + SELECT_LEX_UNIT *unit= &lex->unit; + int res= 0; + if (!(res= unit->prepare(thd, result))) + res= unit->exec(); + res|= unit->cleanup(); + DBUG_RETURN(res); +} + + +/*************************************************************************** +** store records in temporary table for UNION +***************************************************************************/ + +select_union::select_union(TABLE *table_par) + :table(table_par) +{ + bzero((char*) &info,sizeof(info)); + /* + 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; +} + +select_union::~select_union() +{ +} + + +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, + ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT),MYF(0)); + return -1; + } + return 0; +} + +bool select_union::send_data(List<Item> &values) +{ + if (unit->offset_limit_cnt) + { // using limit offset,count + unit->offset_limit_cnt--; + return 0; + } + fill_record(table->field,values); + if ((write_record(table,&info))) + { + if (create_myisam_from_heap(table, tmp_table_param, info.errorno, 0)) + return 1; + } + return 0; +} + +bool select_union::send_eof() +{ + return 0; +} -int mysql_union(THD *thd, LEX *lex,select_result *result) +bool select_union::flush() { - 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; - int res; - bool found_rows_for_union=false; - TABLE_LIST result_table_list; + int error; + if ((error=table->file->extra(HA_EXTRA_NO_CACHE))) + { + table->file->print_error(error,MYF(0)); + ::send_error(&thd->net); + return 1; + } + return 0; +} + +typedef JOIN * JOIN_P; +int st_select_lex_unit::prepare(THD *thd, select_result *result) +{ + describe=(first_select()->options & SELECT_DESCRIBE) ? 1 : 0; + res= 0; + found_rows_for_union= false; TMP_TABLE_PARAM tmp_table_param; - select_union *union_result; - DBUG_ENTER("mysql_union"); - st_select_lex_node * global; + DBUG_ENTER("st_select_lex_unit::prepare"); + this->thd= thd; + this->result= result; /* Global option */ - if (((void*)(global= unit->global_parameters)) == ((void*)unit)) + if (((void*)(global_parameters)) == ((void*)this)) { - found_rows_for_union = lex->select_lex.options & OPTION_FOUND_ROWS && - !describe && global->select_limit; + found_rows_for_union = first_select()->options & OPTION_FOUND_ROWS && + !describe && global_parameters->select_limit; if (found_rows_for_union) - lex->select_lex.options ^= OPTION_FOUND_ROWS; + first_select()->options ^= OPTION_FOUND_ROWS; } - + item_list.empty(); if (describe) { Item *item; @@ -70,8 +142,8 @@ int mysql_union(THD *thd, LEX *lex,select_result *result) else { Item *item; - List_iterator<Item> it(lex->select_lex.item_list); - TABLE_LIST *first_table= (TABLE_LIST*) lex->select_lex.table_list.first; + List_iterator<Item> it(first_select()->item_list); + TABLE_LIST *first_table= (TABLE_LIST*) first_select()->table_list.first; /* Create a list of items that will be in the result set */ while ((item= it++)) @@ -84,11 +156,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, + (ORDER*) 0, !describe & + !thd->lex.union_option, 1, 0, - (lex->select_lex.options | thd->options | + (first_select()->options | thd->options | TMP_TABLE_ALL_COLUMNS), - unit))) + this))) DBUG_RETURN(-1); table->file->extra(HA_EXTRA_WRITE_CACHE); table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); @@ -98,46 +171,82 @@ int mysql_union(THD *thd, LEX *lex,select_result *result) result_table_list.table=table; if (!(union_result=new select_union(table))) - { - res= -1; - goto exit; - } + DBUG_RETURN(-1); + union_result->save_time_stamp=!describe; union_result->tmp_table_param=&tmp_table_param; - for (sl= &lex->select_lex; sl; sl= sl->next_select()) + + // prepare selects + joins.empty(); + for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select()) { - lex->select=sl; - 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) + JOIN *join= new JOIN(thd, sl->item_list, + sl->options | thd->options | SELECT_NO_UNLOCK | + ((describe) ? SELECT_DESCRIBE : 0), + union_result); + joins.push_back(new JOIN_P(join)); + thd->lex.select=sl; + offset_limit_cnt= sl->offset_limit; + select_limit_cnt= sl->select_limit+sl->offset_limit; + if (select_limit_cnt < sl->select_limit) + select_limit_cnt= HA_POS_ERROR; // no limit + if (select_limit_cnt == HA_POS_ERROR) sl->options&= ~OPTION_FOUND_ROWS; - res= mysql_select(thd, - (TABLE_LIST*) sl->table_list.first, - sl->item_list, - sl->where, - (sl->braces) ? - (ORDER *)sl->order_list.first : (ORDER *) 0, - (ORDER*) sl->group_list.first, - sl->having, - (ORDER*) NULL, - sl->options | thd->options | - SELECT_NO_UNLOCK | ((describe) ? SELECT_DESCRIBE : 0), - union_result, unit); - if (res) - goto exit; + res= join->prepare((TABLE_LIST*) sl->table_list.first, + sl->where, + (sl->braces) ? + (ORDER *)sl->order_list.first : (ORDER *) 0, + (ORDER*) sl->group_list.first, + sl->having, + (ORDER*) NULL, + sl, this, 0); + if (res | thd->fatal_error) + DBUG_RETURN(res | thd->fatal_error); } + DBUG_RETURN(res | thd->fatal_error); +} + +int st_select_lex_unit::exec() +{ + DBUG_ENTER("st_select_lex_unit::exec"); + if(depended || !item || !item->assigned()) + { + if (optimized && item && item->assigned()) + item->assigned(0); // We will reinit & rexecute unit + + for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select()) + { + thd->lex.select=sl; + offset_limit_cnt= sl->offset_limit; + select_limit_cnt= sl->select_limit+sl->offset_limit; + if (select_limit_cnt < sl->select_limit) + select_limit_cnt= HA_POS_ERROR; // no limit + if (select_limit_cnt == HA_POS_ERROR) + sl->options&= ~OPTION_FOUND_ROWS; + + if (!optimized) + sl->join->optimize(); + else + sl->join->reinit(); + + sl->join->exec(); + res= sl->join->error; + + if (res) + DBUG_RETURN(res); + } + optimized= 1; + } + if (union_result->flush()) { res= 1; // Error is already sent - goto exit; + DBUG_RETURN(res); } - delete union_result; /* Send result to 'result' */ - lex->select = &lex->select_lex; + thd->lex.select = first_select(); res =-1; { /* Create a list of fields in the temporary table */ @@ -147,7 +256,9 @@ int mysql_union(THD *thd, LEX *lex,select_result *result) List<Item_func_match> ftfunc_list; ftfunc_list.empty(); #else - thd->lex.select_lex.ftfunc_list.empty(); + List<Item_func_match> empty_list; + empty_list.empty(); + thd->lex.select_lex.ftfunc_list= &empty_list; #endif for (field=table->field ; *field ; field++) @@ -157,92 +268,45 @@ int mysql_union(THD *thd, LEX *lex,select_result *result) } if (!thd->fatal_error) // Check if EOM { - 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) + offset_limit_cnt= global_parameters->offset_limit; + select_limit_cnt= global_parameters->select_limit+ + global_parameters->offset_limit; + if (select_limit_cnt < global_parameters->select_limit) + select_limit_cnt= HA_POS_ERROR; // no limit + if (select_limit_cnt == HA_POS_ERROR) thd->options&= ~OPTION_FOUND_ROWS; if (describe) - unit->select_limit_cnt= HA_POS_ERROR; // no limit + 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, + (describe) ? + 0: + (ORDER*)global_parameters->order_list.first, (ORDER*) NULL, NULL, (ORDER*) NULL, - thd->options, result, unit); + thd->options, result, this, 1); if (found_rows_for_union && !res) thd->limit_found_rows = (ulonglong)table->file->records; } } - -exit: - free_tmp_table(thd,table); + thd->lex.select_lex.ftfunc_list= &thd->lex.select_lex.ftfunc_list_alloc; DBUG_RETURN(res); } - -/*************************************************************************** -** store records in temporary table for UNION -***************************************************************************/ - -select_union::select_union(TABLE *table_par) - :table(table_par) +int st_select_lex_unit::cleanup() { - bzero((char*) &info,sizeof(info)); - /* - 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; -} - -select_union::~select_union() -{ -} - - -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, - ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT),MYF(0)); - return -1; - } - return 0; -} - -bool select_union::send_data(List<Item> &values) -{ - if (unit->offset_limit_cnt) - { // using limit offset,count - unit->offset_limit_cnt--; - return 0; - } - fill_record(table->field,values); - if ((write_record(table,&info))) - { - if (create_myisam_from_heap(table, tmp_table_param, info.errorno, 0)) - return 1; - } - return 0; -} - -bool select_union::send_eof() -{ - return 0; -} - -bool select_union::flush() -{ - int error; - if ((error=table->file->extra(HA_EXTRA_NO_CACHE))) + DBUG_ENTER("st_select_lex_unit::cleanup"); + delete union_result; + free_tmp_table(thd,table); + table= 0; // Safety + + List_iterator<JOIN*> j(joins); + JOIN** join; + while ((join= j++)) { - table->file->print_error(error,MYF(0)); - ::send_error(&thd->net); - return 1; + (*join)->cleanup(thd); + delete *join; + delete join; } - return 0; + joins.empty(); + DBUG_RETURN(0); } |