1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

Merge 10.5 into 10.6

This commit is contained in:
Marko Mäkelä
2021-03-05 16:05:47 +02:00
40 changed files with 1656 additions and 1165 deletions

View File

@ -3262,6 +3262,146 @@ bool Sql_cmd_call::execute(THD *thd)
}
/**
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.
@ -3548,127 +3688,13 @@ mysql_execute_command(THD *thd)
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);
/* 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() ||
(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;