summaryrefslogtreecommitdiff
path: root/sql/sql_parse.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_parse.cc')
-rw-r--r--sql/sql_parse.cc323
1 files changed, 179 insertions, 144 deletions
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 83100e743ad..573df24cb33 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2034,7 +2034,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
locks.
*/
trans_rollback_implicit(thd);
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
}
thd->cleanup_after_query();
@@ -2099,7 +2099,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
ulonglong options= (ulonglong) (uchar) packet[0];
if (trans_commit_implicit(thd))
break;
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
if (check_global_access(thd,RELOAD_ACL))
break;
general_log_print(thd, command, NullS);
@@ -2132,7 +2132,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (trans_commit_implicit(thd))
break;
close_thread_tables(thd);
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
my_ok(thd);
break;
}
@@ -2179,6 +2179,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break;
general_log_print(thd, command, NullS);
status_var_increment(thd->status_var.com_stat[SQLCOM_SHOW_STATUS]);
+ *current_global_status_var= global_status_var;
calc_sum_of_all_status(current_global_status_var);
if (!(uptime= (ulong) (thd->start_time - server_start_time)))
queries_per_second1000= 0;
@@ -2934,7 +2935,7 @@ err:
/* Close tables and release metadata locks. */
close_thread_tables(thd);
DBUG_ASSERT(!thd->locked_tables_mode);
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
return TRUE;
}
@@ -2994,6 +2995,146 @@ static bool do_execute_sp(THD *thd, sp_head *sp)
/**
+ Check whether the SQL statement being processed is prepended by
+ SET STATEMENT clause and handle variables assignment if it is.
+
+ @param thd thread handle
+ @param lex current lex
+
+ @return false in case of success, true in case of error.
+*/
+
+bool run_set_statement_if_requested(THD *thd, LEX *lex)
+{
+ if (!lex->stmt_var_list.is_empty() && !thd->slave_thread)
+ {
+ Query_arena backup;
+ DBUG_PRINT("info", ("SET STATEMENT %d vars", lex->stmt_var_list.elements));
+
+ lex->old_var_list.empty();
+ List_iterator_fast<set_var_base> it(lex->stmt_var_list);
+ set_var_base *var;
+
+ if (lex->set_arena_for_set_stmt(&backup))
+ return true;
+
+ MEM_ROOT *mem_root= thd->mem_root;
+ while ((var= it++))
+ {
+ DBUG_ASSERT(var->is_system());
+ set_var *o= NULL, *v= (set_var*)var;
+ if (!v->var->is_set_stmt_ok())
+ {
+ my_error(ER_SET_STATEMENT_NOT_SUPPORTED, MYF(0), v->var->name.str);
+ lex->reset_arena_for_set_stmt(&backup);
+ lex->old_var_list.empty();
+ lex->free_arena_for_set_stmt();
+ return true;
+ }
+ if (v->var->session_is_default(thd))
+ o= new set_var(thd,v->type, v->var, &v->base, NULL);
+ else
+ {
+ switch (v->var->option.var_type & GET_TYPE_MASK)
+ {
+ case GET_BOOL:
+ case GET_INT:
+ case GET_LONG:
+ case GET_LL:
+ {
+ bool null_value;
+ longlong val= v->var->val_int(&null_value, thd, v->type, &v->base);
+ o= new set_var(thd, v->type, v->var, &v->base,
+ (null_value ?
+ (Item *) new (mem_root) Item_null(thd) :
+ (Item *) new (mem_root) Item_int(thd, val)));
+ }
+ break;
+ case GET_UINT:
+ case GET_ULONG:
+ case GET_ULL:
+ {
+ bool null_value;
+ ulonglong val= v->var->val_int(&null_value, thd, v->type, &v->base);
+ o= new set_var(thd, v->type, v->var, &v->base,
+ (null_value ?
+ (Item *) new (mem_root) Item_null(thd) :
+ (Item *) new (mem_root) Item_uint(thd, val)));
+ }
+ break;
+ case GET_DOUBLE:
+ {
+ bool null_value;
+ double val= v->var->val_real(&null_value, thd, v->type, &v->base);
+ o= new set_var(thd, v->type, v->var, &v->base,
+ (null_value ?
+ (Item *) new (mem_root) Item_null(thd) :
+ (Item *) new (mem_root) Item_float(thd, val, 1)));
+ }
+ break;
+ default:
+ case GET_NO_ARG:
+ case GET_DISABLED:
+ DBUG_ASSERT(0);
+ /* fall through */
+ case 0:
+ case GET_FLAGSET:
+ case GET_ENUM:
+ case GET_SET:
+ case GET_STR:
+ case GET_STR_ALLOC:
+ {
+ char buff[STRING_BUFFER_USUAL_SIZE];
+ String tmp(buff, sizeof(buff), v->var->charset(thd)),*val;
+ val= v->var->val_str(&tmp, thd, v->type, &v->base);
+ if (val)
+ {
+ Item_string *str=
+ new (mem_root) Item_string(thd, v->var->charset(thd),
+ val->ptr(), val->length());
+ o= new set_var(thd, v->type, v->var, &v->base, str);
+ }
+ else
+ o= new set_var(thd, v->type, v->var, &v->base,
+ new (mem_root) Item_null(thd));
+ }
+ break;
+ }
+ }
+ DBUG_ASSERT(o);
+ lex->old_var_list.push_back(o, thd->mem_root);
+ }
+ lex->reset_arena_for_set_stmt(&backup);
+
+ if (lex->old_var_list.is_empty())
+ lex->free_arena_for_set_stmt();
+
+ if (thd->is_error() ||
+ sql_set_variables(thd, &lex->stmt_var_list, false))
+ {
+ if (!thd->is_error())
+ my_error(ER_WRONG_ARGUMENTS, MYF(0), "SET");
+ lex->restore_set_statement_var();
+ return true;
+ }
+ /*
+ The value of last_insert_id is remembered in THD to be written to binlog
+ when it's used *the first time* in the statement. But SET STATEMENT
+ must read the old value of last_insert_id to be able to restore it at
+ the end. This should not count at "reading of last_insert_id" and
+ should not remember last_insert_id for binlog. That is, it should clear
+ stmt_depends_on_first_successful_insert_id_in_prev_stmt flag.
+ */
+ if (!thd->in_sub_stmt)
+ {
+ thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0;
+ }
+ }
+ return false;
+}
+
+
+/**
Execute command saved in thd and lex->sql_command.
@param thd Thread handle
@@ -3195,6 +3336,11 @@ mysql_execute_command(THD *thd)
#ifdef HAVE_REPLICATION
} /* endif unlikely slave */
#endif
+ /* store old value of binlog format */
+ enum_binlog_format orig_binlog_format,orig_current_stmt_binlog_format;
+
+ thd->get_binlog_format(&orig_binlog_format,
+ &orig_current_stmt_binlog_format);
#ifdef WITH_WSREP
if (wsrep && WSREP(thd))
{
@@ -3246,132 +3392,13 @@ mysql_execute_command(THD *thd)
DBUG_ASSERT(thd->transaction.stmt.modified_non_trans_table == FALSE);
- /* store old value of binlog format */
- enum_binlog_format orig_binlog_format,orig_current_stmt_binlog_format;
-
- thd->get_binlog_format(&orig_binlog_format,
- &orig_current_stmt_binlog_format);
-
- if (!lex->stmt_var_list.is_empty() && !thd->slave_thread)
- {
- Query_arena backup;
- DBUG_PRINT("info", ("SET STATEMENT %d vars", lex->stmt_var_list.elements));
-
- lex->old_var_list.empty();
- List_iterator_fast<set_var_base> it(lex->stmt_var_list);
- set_var_base *var;
-
- if (lex->set_arena_for_set_stmt(&backup))
- goto error;
-
- MEM_ROOT *mem_root= thd->mem_root;
- while ((var= it++))
- {
- DBUG_ASSERT(var->is_system());
- set_var *o= NULL, *v= (set_var*)var;
- if (!v->var->is_set_stmt_ok())
- {
- my_error(ER_SET_STATEMENT_NOT_SUPPORTED, MYF(0), v->var->name.str);
- lex->reset_arena_for_set_stmt(&backup);
- lex->old_var_list.empty();
- lex->free_arena_for_set_stmt();
- goto error;
- }
- if (v->var->session_is_default(thd))
- o= new set_var(thd,v->type, v->var, &v->base, NULL);
- else
- {
- switch (v->var->option.var_type & GET_TYPE_MASK)
- {
- case GET_BOOL:
- case GET_INT:
- case GET_LONG:
- case GET_LL:
- {
- bool null_value;
- longlong val= v->var->val_int(&null_value, thd, v->type, &v->base);
- o= new set_var(thd, v->type, v->var, &v->base,
- (null_value ?
- (Item *) new (mem_root) Item_null(thd) :
- (Item *) new (mem_root) Item_int(thd, val)));
- }
- break;
- case GET_UINT:
- case GET_ULONG:
- case GET_ULL:
- {
- bool null_value;
- ulonglong val= v->var->val_int(&null_value, thd, v->type, &v->base);
- o= new set_var(thd, v->type, v->var, &v->base,
- (null_value ?
- (Item *) new (mem_root) Item_null(thd) :
- (Item *) new (mem_root) Item_uint(thd, val)));
- }
- break;
- case GET_DOUBLE:
- {
- bool null_value;
- double val= v->var->val_real(&null_value, thd, v->type, &v->base);
- o= new set_var(thd, v->type, v->var, &v->base,
- (null_value ?
- (Item *) new (mem_root) Item_null(thd) :
- (Item *) new (mem_root) Item_float(thd, val, 1)));
- }
- break;
- default:
- case GET_NO_ARG:
- case GET_DISABLED:
- DBUG_ASSERT(0);
- case 0:
- case GET_FLAGSET:
- case GET_ENUM:
- case GET_SET:
- case GET_STR:
- case GET_STR_ALLOC:
- {
- char buff[STRING_BUFFER_USUAL_SIZE];
- String tmp(buff, sizeof(buff), v->var->charset(thd)),*val;
- val= v->var->val_str(&tmp, thd, v->type, &v->base);
- if (val)
- {
- Item_string *str= new (mem_root) Item_string(thd, v->var->charset(thd),
- val->ptr(), val->length());
- o= new set_var(thd, v->type, v->var, &v->base, str);
- }
- else
- o= new set_var(thd, v->type, v->var, &v->base,
- new (mem_root) Item_null(thd));
- }
- break;
- }
- }
- DBUG_ASSERT(o);
- lex->old_var_list.push_back(o, thd->mem_root);
- }
- lex->reset_arena_for_set_stmt(&backup);
- if (lex->old_var_list.is_empty())
- lex->free_arena_for_set_stmt();
- if (thd->is_error() ||
- (res= sql_set_variables(thd, &lex->stmt_var_list, false)))
- {
- if (!thd->is_error())
- my_error(ER_WRONG_ARGUMENTS, MYF(0), "SET");
- lex->restore_set_statement_var();
- goto error;
- }
- /*
- The value of last_insert_id is remembered in THD to be written to binlog
- when it's used *the first time* in the statement. But SET STATEMENT
- must read the old value of last_insert_id to be able to restore it at
- the end. This should not count at "reading of last_insert_id" and
- should not remember last_insert_id for binlog. That is, it should clear
- stmt_depends_on_first_successful_insert_id_in_prev_stmt flag.
- */
- if (!thd->in_sub_stmt)
- {
- thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0;
- }
- }
+ /*
+ Assign system variables with values specified by the clause
+ SET STATEMENT var1=value1 [, var2=value2, ...] FOR <statement>
+ if they are any.
+ */
+ if (run_set_statement_if_requested(thd, lex))
+ goto error;
if (thd->lex->mi.connection_name.str == NULL)
thd->lex->mi.connection_name= thd->variables.default_master_connection;
@@ -3406,7 +3433,7 @@ mysql_execute_command(THD *thd)
/* Commit the normal transaction if one is active. */
bool commit_failed= trans_commit_implicit(thd);
/* Release metadata locks acquired in this transaction. */
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
if (commit_failed)
{
WSREP_DEBUG("implicit commit failed, MDL released: %lld",
@@ -4645,7 +4672,7 @@ mysql_execute_command(THD *thd)
{
res= trans_commit_implicit(thd);
thd->locked_tables_list.unlock_locked_tables(thd);
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
thd->variables.option_bits&= ~(OPTION_TABLE_LOCK);
}
if (thd->global_read_lock.is_acquired())
@@ -4659,7 +4686,7 @@ mysql_execute_command(THD *thd)
res= trans_commit_implicit(thd);
thd->locked_tables_list.unlock_locked_tables(thd);
/* Release transactional metadata locks. */
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
if (res)
goto error;
@@ -5313,7 +5340,7 @@ mysql_execute_command(THD *thd)
DBUG_PRINT("info", ("Executing SQLCOM_BEGIN thd: %p", thd));
if (trans_begin(thd, lex->start_transaction_opt))
{
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
WSREP_DEBUG("BEGIN failed, MDL released: %lld",
(longlong) thd->thread_id);
goto error;
@@ -5331,7 +5358,7 @@ mysql_execute_command(THD *thd)
(thd->variables.completion_type == 2 &&
lex->tx_release != TVL_NO));
bool commit_failed= trans_commit(thd);
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
if (commit_failed)
{
WSREP_DEBUG("COMMIT failed, MDL released: %lld",
@@ -5382,7 +5409,7 @@ mysql_execute_command(THD *thd)
(thd->variables.completion_type == 2 &&
lex->tx_release != TVL_NO));
bool rollback_failed= trans_rollback(thd);
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
if (rollback_failed)
{
@@ -5859,7 +5886,6 @@ mysql_execute_command(THD *thd)
case SQLCOM_XA_COMMIT:
{
bool commit_failed= trans_xa_commit(thd);
- thd->mdl_context.release_transactional_locks();
if (commit_failed)
{
WSREP_DEBUG("XA commit failed, MDL released: %lld",
@@ -5877,7 +5903,6 @@ mysql_execute_command(THD *thd)
case SQLCOM_XA_ROLLBACK:
{
bool rollback_failed= trans_xa_rollback(thd);
- thd->mdl_context.release_transactional_locks();
if (rollback_failed)
{
WSREP_DEBUG("XA rollback failed, MDL released: %lld",
@@ -6095,7 +6120,7 @@ finish:
all storage engines including binary log.
*/
trans_rollback_implicit(thd);
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
}
else if (stmt_causes_implicit_commit(thd, CF_IMPLICIT_COMMIT_END))
{
@@ -6108,7 +6133,7 @@ finish:
/* Commit the normal transaction if one is active. */
trans_commit_implicit(thd);
thd->get_stmt_da()->set_overwrite_status(false);
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
}
}
else if (! thd->in_sub_stmt && ! thd->in_multi_stmt_transaction_mode())
@@ -6123,7 +6148,7 @@ finish:
- If in autocommit mode, or outside a transactional context,
automatically release metadata locks of the current statement.
*/
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
}
else if (! thd->in_sub_stmt)
{
@@ -6145,7 +6170,7 @@ finish:
{
WSREP_DEBUG("Forcing release of transactional locks for thd: %lld",
(longlong) thd->thread_id);
- thd->mdl_context.release_transactional_locks();
+ thd->release_transactional_locks();
}
#endif /* WITH_WSREP */
@@ -6641,6 +6666,9 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
bool check_single_table_access(THD *thd, ulong privilege, TABLE_LIST *tables,
bool no_errors)
{
+ if (tables->derived)
+ return 0;
+
Switch_to_definer_security_ctx backup_sctx(thd, tables);
const char *db_name;
@@ -7332,8 +7360,13 @@ void THD::reset_for_next_command(bool do_clear_error)
thd->save_prep_leaf_list= false;
- DBUG_PRINT("debug",
- ("is_current_stmt_binlog_format_row(): %d",
+#ifdef WITH_WSREP
+#if !defined(DBUG_OFF)
+ if (mysql_bin_log.is_open())
+#endif
+#endif
+ DBUG_PRINT("debug",
+ ("is_current_stmt_binlog_format_row(): %d",
thd->is_current_stmt_binlog_format_row()));
DBUG_VOID_RETURN;
@@ -8745,6 +8778,8 @@ push_new_name_resolution_context(THD *thd,
left_op->first_leaf_for_name_resolution();
on_context->last_name_resolution_table=
right_op->last_leaf_for_name_resolution();
+ on_context->select_lex = thd->lex->current_select;
+ on_context->outer_context = thd->lex->current_context()->outer_context;
return thd->lex->push_context(on_context, thd->mem_root);
}