summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/sql_lex.h8
-rw-r--r--sql/sql_prepare.cc18
-rw-r--r--sql/sql_union.cc77
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)
{