summaryrefslogtreecommitdiff
path: root/sql/sql_prepare.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_prepare.cc')
-rw-r--r--sql/sql_prepare.cc113
1 files changed, 69 insertions, 44 deletions
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 220a2a16db6..120cfc3e350 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -106,6 +106,7 @@ When one supplies long data for a placeholder:
#include "sp_head.h"
#include "sp.h"
#include "sp_cache.h"
+#include "sql_handler.h" // mysql_ha_rm_tables
#include "probes_mysql.h"
#ifdef EMBEDDED_LIBRARY
/* include MYSQL_BIND headers */
@@ -343,7 +344,7 @@ static bool send_prep_stmt(Prepared_statement *stmt, uint columns)
int2store(buff+5, columns);
int2store(buff+7, stmt->param_count);
buff[9]= 0; // Guard against a 4.1 client
- tmp= min(stmt->thd->warning_info->statement_warn_count(), 65535);
+ tmp= MY_MIN(stmt->thd->get_stmt_da()->current_statement_warn_count(), 65535);
int2store(buff+10, tmp);
/*
@@ -360,7 +361,7 @@ static bool send_prep_stmt(Prepared_statement *stmt, uint columns)
if (!error)
/* Flag that a response has already been sent */
- thd->stmt_da->disable_status();
+ thd->get_stmt_da()->disable_status();
DBUG_RETURN(error);
}
@@ -373,7 +374,7 @@ static bool send_prep_stmt(Prepared_statement *stmt,
thd->client_stmt_id= stmt->id;
thd->client_param_count= stmt->param_count;
thd->clear_error();
- thd->stmt_da->disable_status();
+ thd->get_stmt_da()->disable_status();
return 0;
}
@@ -1253,6 +1254,17 @@ static bool mysql_test_insert(Prepared_statement *stmt,
List_item *values;
DBUG_ENTER("mysql_test_insert");
+ /*
+ Since INSERT DELAYED doesn't support temporary tables, we could
+ not pre-open temporary tables for SQLCOM_INSERT / SQLCOM_REPLACE.
+ Open them here instead.
+ */
+ if (table_list->lock_type != TL_WRITE_DELAYED)
+ {
+ if (open_temporary_tables(thd, table_list))
+ goto error;
+ }
+
if (insert_precheck(thd, table_list))
goto error;
@@ -1820,6 +1832,13 @@ static bool mysql_test_create_view(Prepared_statement *stmt)
if (create_view_precheck(thd, tables, view, lex->create_view_mode))
goto err;
+ /*
+ Since we can't pre-open temporary tables for SQLCOM_CREATE_VIEW,
+ (see mysql_create_view) we have to do it here instead.
+ */
+ if (open_temporary_tables(thd, tables))
+ goto err;
+
if (open_normal_and_derived_tables(thd, tables, MYSQL_OPEN_FORCE_SHARED_MDL,
DT_PREPARE))
goto err;
@@ -2055,7 +2074,20 @@ static bool check_prepared_statement(Prepared_statement *stmt)
/* Reset warning count for each query that uses tables */
if (tables)
- thd->warning_info->opt_clear_warning_info(thd->query_id);
+ thd->get_stmt_da()->opt_clear_warning_info(thd->query_id);
+
+ if (sql_command_flags[sql_command] & CF_HA_CLOSE)
+ mysql_ha_rm_tables(thd, tables);
+
+ /*
+ Open temporary tables that are known now. Temporary tables added by
+ prelocking will be opened afterwards (during open_tables()).
+ */
+ if (sql_command_flags[sql_command] & CF_PREOPEN_TMP_TABLES)
+ {
+ if (open_temporary_tables(thd, tables))
+ goto error;
+ }
switch (sql_command) {
case SQLCOM_REPLACE:
@@ -2859,7 +2891,7 @@ void mysqld_stmt_close(THD *thd, char *packet)
Prepared_statement *stmt;
DBUG_ENTER("mysqld_stmt_close");
- thd->stmt_da->disable_status();
+ thd->get_stmt_da()->disable_status();
if (!(stmt= find_prepared_statement(thd, stmt_id)))
DBUG_VOID_RETURN;
@@ -2935,7 +2967,7 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
status_var_increment(thd->status_var.com_stmt_send_long_data);
- thd->stmt_da->disable_status();
+ thd->get_stmt_da()->disable_status();
#ifndef EMBEDDED_LIBRARY
/* Minimal size of long data packet is 6 bytes */
if (packet_length < MYSQL_LONG_DATA_HEADER)
@@ -2964,26 +2996,23 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
param= stmt->param_array[param_number];
- Diagnostics_area new_stmt_da, *save_stmt_da= thd->stmt_da;
- Warning_info new_warnning_info(thd->query_id, false);
- Warning_info *save_warinig_info= thd->warning_info;
+ Diagnostics_area new_stmt_da(thd->query_id, false, true);
+ Diagnostics_area *save_stmt_da= thd->get_stmt_da();
- thd->stmt_da= &new_stmt_da;
- thd->warning_info= &new_warnning_info;
+ thd->set_stmt_da(&new_stmt_da);
#ifndef EMBEDDED_LIBRARY
param->set_longdata(packet, (ulong) (packet_end - packet));
#else
param->set_longdata(thd->extra_data, thd->extra_length);
#endif
- if (thd->stmt_da->is_error())
+ if (thd->get_stmt_da()->is_error())
{
stmt->state= Query_arena::STMT_ERROR;
- stmt->last_errno= thd->stmt_da->sql_errno();
- strncpy(stmt->last_error, thd->stmt_da->message(), MYSQL_ERRMSG_SIZE);
+ stmt->last_errno= thd->get_stmt_da()->sql_errno();
+ strncpy(stmt->last_error, thd->get_stmt_da()->message(), MYSQL_ERRMSG_SIZE);
}
- thd->stmt_da= save_stmt_da;
- thd->warning_info= save_warinig_info;
+ thd->set_stmt_da(save_stmt_da);
general_log_print(thd, thd->get_command(), NullS);
@@ -3059,8 +3088,7 @@ Reprepare_observer::report_error(THD *thd)
that this thread execution stops and returns to the caller,
backtracking all the way to Prepared_statement::execute_loop().
*/
- thd->stmt_da->set_error_status(thd, ER_NEED_REPREPARE,
- ER(ER_NEED_REPREPARE), "HY000");
+ thd->get_stmt_da()->set_error_status(ER_NEED_REPREPARE);
m_invalidated= TRUE;
return TRUE;
@@ -3526,7 +3554,6 @@ Prepared_statement::execute_loop(String *expanded_query,
Reprepare_observer reprepare_observer;
bool error;
int reprepare_attempt= 0;
- bool need_set_parameters= true;
/* Check if we got an error when sending long data */
if (state == Query_arena::STMT_ERROR)
@@ -3535,20 +3562,19 @@ Prepared_statement::execute_loop(String *expanded_query,
return TRUE;
}
-reexecute:
- if (need_set_parameters &&
- set_parameters(expanded_query, packet, packet_end))
+ if (set_parameters(expanded_query, packet, packet_end))
return TRUE;
- /*
- if set_parameters() has generated warnings,
- we need to repeat it when reexecuting, to recreate these
- warnings.
- */
- need_set_parameters= thd->warning_info->statement_warn_count();
-
- reprepare_observer.reset_reprepare_observer();
+#ifdef NOT_YET_FROM_MYSQL_5_6
+ if (unlikely(thd->security_ctx->password_expired &&
+ !lex->is_change_password))
+ {
+ my_error(ER_MUST_CHANGE_PASSWORD, MYF(0));
+ return true;
+ }
+#endif
+reexecute:
/*
If the free_list is not empty, we'll wrongly free some externally
allocated items when cleaning up after validation of the prepared
@@ -3562,22 +3588,24 @@ reexecute:
the observer method will be invoked to push an error into
the error stack.
*/
- if (sql_command_flags[lex->sql_command] &
- CF_REEXECUTION_FRAGILE)
+
+ if (sql_command_flags[lex->sql_command] & CF_REEXECUTION_FRAGILE)
{
+ reprepare_observer.reset_reprepare_observer();
DBUG_ASSERT(thd->m_reprepare_observer == NULL);
- thd->m_reprepare_observer = &reprepare_observer;
+ thd->m_reprepare_observer= &reprepare_observer;
}
error= execute(expanded_query, open_cursor) || thd->is_error();
thd->m_reprepare_observer= NULL;
- if (error && !thd->is_fatal_error && !thd->killed &&
+ if ((sql_command_flags[lex->sql_command] & CF_REEXECUTION_FRAGILE) &&
+ error && !thd->is_fatal_error && !thd->killed &&
reprepare_observer.is_invalidated() &&
reprepare_attempt++ < MAX_REPREPARE_ATTEMPTS)
{
- DBUG_ASSERT(thd->stmt_da->sql_errno() == ER_NEED_REPREPARE);
+ DBUG_ASSERT(thd->get_stmt_da()->sql_errno() == ER_NEED_REPREPARE);
thd->clear_error();
error= reprepare();
@@ -3679,7 +3707,7 @@ Prepared_statement::reprepare()
Sic: we can't simply silence warnings during reprepare, because if
it's failed, we need to return all the warnings to the user.
*/
- thd->warning_info->clear_warning_info(thd->query_id);
+ thd->get_stmt_da()->clear_warning_info(thd->query_id);
}
return error;
}
@@ -4041,7 +4069,7 @@ Ed_result_set::Ed_result_set(List<Ed_row> *rows_arg,
*/
Ed_connection::Ed_connection(THD *thd)
- :m_warning_info(thd->query_id, false, true),
+ :m_diagnostics_area(thd->query_id, false, true),
m_thd(thd),
m_rsets(0),
m_current_rset(0)
@@ -4067,7 +4095,7 @@ Ed_connection::free_old_result()
}
m_current_rset= m_rsets;
m_diagnostics_area.reset_diagnostics_area();
- m_warning_info.clear_warning_info(m_thd->query_id);
+ m_diagnostics_area.clear_warning_info(m_thd->query_id);
}
@@ -4104,23 +4132,20 @@ bool Ed_connection::execute_direct(Server_runnable *server_runnable)
Protocol_local protocol_local(m_thd, this);
Prepared_statement stmt(m_thd);
Protocol *save_protocol= m_thd->protocol;
- Diagnostics_area *save_diagnostics_area= m_thd->stmt_da;
- Warning_info *save_warning_info= m_thd->warning_info;
+ Diagnostics_area *save_diagnostics_area= m_thd->get_stmt_da();
DBUG_ENTER("Ed_connection::execute_direct");
free_old_result(); /* Delete all data from previous execution, if any */
m_thd->protocol= &protocol_local;
- m_thd->stmt_da= &m_diagnostics_area;
- m_thd->warning_info= &m_warning_info;
+ m_thd->set_stmt_da(&m_diagnostics_area);
rc= stmt.execute_server_runnable(server_runnable);
m_thd->protocol->end_statement();
m_thd->protocol= save_protocol;
- m_thd->stmt_da= save_diagnostics_area;
- m_thd->warning_info= save_warning_info;
+ m_thd->set_stmt_da(save_diagnostics_area);
/*
Protocol_local makes use of m_current_rset to keep
track of the last result set, while adding result sets to the end.