diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/sql_lex.h | 8 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 18 | ||||
-rw-r--r-- | sql/sql_union.cc | 77 |
3 files changed, 77 insertions, 26 deletions
diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 78bf3bdd5f5..aa3e81fd9c9 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -332,7 +332,10 @@ public: Item_subselect *item; /* thread handler */ THD *thd; - /* fake SELECT_LEX for union processing */ + /* + SELECT_LEX for hidden SELECT in onion which process global + ORDER BY and LIMIT + */ st_select_lex *fake_select_lex; st_select_lex *union_distinct; /* pointer to the last UNION DISTINCT */ @@ -366,7 +369,8 @@ public: bool check_updateable(char *db, char *table); void print(String *str); - + + ulong init_prepare_fake_select_lex(THD *thd); friend void mysql_init_query(THD *thd); friend int subselect_union_engine::exec(); diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 951f92011ca..61e5b778b64 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1555,18 +1555,20 @@ set_params_data_err: /* - Reset a prepared statement, in case there was an error in send_longdata. - Note: we don't send any reply to that command. + Reset a prepared statement in case there was a recoverable error. SYNOPSIS mysql_stmt_reset() thd Thread handle packet Packet with stmt id DESCRIPTION - This function is useful when one gets an error after calling - mysql_stmt_getlongdata() and wants to reset the handle - so that one can call execute again. - See also bug #1664 + This function resets statement to the state it was right after prepare. + It can be used to: + - clear an error happened during mysql_stmt_send_long_data + - cancel long data stream for all placeholders without + having to call mysql_stmt_execute. + Sends 'OK' packet in case of success (statement was reset) + or 'ERROR' packet (unrecoverable error/statement not found/etc). */ void mysql_stmt_reset(THD *thd, char *packet) @@ -1577,7 +1579,7 @@ void mysql_stmt_reset(THD *thd, char *packet) DBUG_ENTER("mysql_stmt_reset"); - if (!(stmt= find_prepared_statement(thd, stmt_id, "reset", DONT_SEND_ERROR))) + if (!(stmt= find_prepared_statement(thd, stmt_id, "reset", SEND_ERROR))) DBUG_VOID_RETURN; stmt->get_longdata_error= 0; @@ -1587,6 +1589,8 @@ void mysql_stmt_reset(THD *thd, char *packet) mysql_stmt_send_long_data() call. */ reset_stmt_params(stmt); + + send_ok(thd); DBUG_VOID_RETURN; } diff --git a/sql/sql_union.cc b/sql/sql_union.cc index e5649192fe5..63638b618d9 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -106,6 +106,41 @@ bool select_union::flush() } +/* + initialization procedures before fake_select_lex preparation() + + SYNOPSIS + st_select_lex_unit::init_prepare_fake_select_lex() + thd - thread handler + + RETURN + options of SELECT +*/ + +ulong +st_select_lex_unit::init_prepare_fake_select_lex(THD *thd) +{ + ulong options_tmp= thd->options; + thd->lex->current_select= fake_select_lex; + 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) + options_tmp&= ~OPTION_FOUND_ROWS; + else if (found_rows_for_union && !thd->lex->describe) + options_tmp|= OPTION_FOUND_ROWS; + fake_select_lex->ftfunc_list_alloc.empty(); + fake_select_lex->ftfunc_list= &fake_select_lex->ftfunc_list_alloc; + fake_select_lex->table_list.link_in_list((byte *)&result_table_list, + (byte **) + &result_table_list.next); + return options_tmp; +} + + int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, ulong additional_options) { @@ -207,7 +242,6 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, } } - item_list.empty(); // it is not single select if (first_select->next_select()) { @@ -229,6 +263,7 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, union_result->set_table(table); thd_arg->lex->current_select= lex_select_save; + if (!item_list.elements) { Statement *stmt= thd->current_statement; Statement backup; @@ -246,7 +281,30 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, } } if (stmt) + { thd->restore_backup_item_arena(stmt, &backup); + + /* prepare fake select to initialize it correctly */ + ulong options_tmp= init_prepare_fake_select_lex(thd); + if (!(fake_select_lex->join= new JOIN(thd, item_list, thd->options, + result))) + { + fake_select_lex->table_list.empty(); + DBUG_RETURN(-1); + } + fake_select_lex->item_list= item_list; + + thd_arg->lex->current_select= fake_select_lex; + res= fake_select_lex->join-> + prepare(&fake_select_lex->ref_pointer_array, + (TABLE_LIST*) fake_select_lex->table_list.first, + 0, 0, + fake_select_lex->order_list.elements, + (ORDER*) fake_select_lex->order_list.first, + (ORDER*) NULL, NULL, (ORDER*) NULL, + fake_select_lex, this); + fake_select_lex->table_list.empty(); + } } } else @@ -373,22 +431,7 @@ int st_select_lex_unit::exec() if (!thd->is_fatal_error) // Check if EOM { - ulong options_tmp= thd->options; - thd->lex->current_select= fake_select_lex; - 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) - options_tmp&= ~OPTION_FOUND_ROWS; - else if (found_rows_for_union && !thd->lex->describe) - options_tmp|= OPTION_FOUND_ROWS; - fake_select_lex->ftfunc_list= &empty_list; - fake_select_lex->table_list.link_in_list((byte *)&result_table_list, - (byte **) - &result_table_list.next); + ulong options_tmp= init_prepare_fake_select_lex(thd); JOIN *join= fake_select_lex->join; if (!join) { |