MDEV-15703: Crash in EXECUTE IMMEDIATE 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)' USING DEFAULT

This patch fixes the issue with passing the DEFAULT or IGNORE values to
positional parameters for some kind of SQL statements to be executed
as prepared statements.

The main idea of the patch is to associate an actual value being passed
by the USING clause with the positional parameter represented by
the Item_param class. Such association must be performed on execution of
UPDATE statement in PS/SP mode. Other corner cases that results in
server crash is on handling CREATE TABLE when positional parameter
placed after the DEFAULT clause or CALL statement and passing either
the value DEFAULT or IGNORE as an actual value for the positional parameter.
This case is fixed by checking whether an error is set in diagnostics
area at the function pack_vcols() on return from the function pack_expression()
This commit is contained in:
Dmitry Shulga 2024-02-08 12:17:02 +07:00 committed by Oleksandr Byelkin
parent 6b2cd78695
commit e48bd474a2
16 changed files with 418 additions and 17 deletions

View file

@ -5815,5 +5815,123 @@ GROUP_CONCAT(@x)
0
DROP TABLE t;
#
# MDEV-15703: Crash in EXECUTE IMMEDIATE 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)' USING DEFAULT
#
PREPARE stmt FROM 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)';
EXECUTE stmt USING DEFAULT;
ERROR HY000: Default/ignore value is not supported for such parameter usage
DEALLOCATE PREPARE stmt;
PREPARE stmt FROM 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)';
EXECUTE stmt USING IGNORE;
ERROR HY000: Default/ignore value is not supported for such parameter usage
DEALLOCATE PREPARE stmt;
EXECUTE IMMEDIATE 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)' USING DEFAULT;
ERROR HY000: Default/ignore value is not supported for such parameter usage
EXECUTE IMMEDIATE 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)' USING IGNORE;
ERROR HY000: Default/ignore value is not supported for such parameter usage
EXECUTE IMMEDIATE 'BEGIN NOT ATOMIC DECLARE a INT DEFAULT ?; END' USING DEFAULT;
ERROR HY000: Default/ignore value is not supported for such parameter usage
EXECUTE IMMEDIATE 'BEGIN NOT ATOMIC DECLARE a INT DEFAULT ?; END' USING IGNORE;
ERROR HY000: Default/ignore value is not supported for such parameter usage
CREATE PROCEDURE p1(a INT) SELECT 1;
EXECUTE IMMEDIATE 'CALL p1(?)' USING DEFAULT;
ERROR HY000: Default/ignore value is not supported for such parameter usage
EXECUTE IMMEDIATE 'CALL p1(?)' USING IGNORE;
ERROR HY000: Default/ignore value is not supported for such parameter usage
DROP PROCEDURE p1;
EXECUTE IMMEDIATE 'SELECT ? UNION SELECT 1' USING DEFAULT;
ERROR HY000: Default/ignore value is not supported for such parameter usage
EXECUTE IMMEDIATE 'SELECT ? UNION SELECT 1' USING IGNORE;
ERROR HY000: Default/ignore value is not supported for such parameter usage
EXECUTE IMMEDIATE 'SELECT * FROM (SELECT ? UNION ALL SELECT 1) AS derived' USING DEFAULT;
ERROR HY000: Default/ignore value is not supported for such parameter usage
EXECUTE IMMEDIATE 'SELECT * FROM (SELECT ? UNION ALL SELECT 1) AS derived' USING IGNORE;
ERROR HY000: Default/ignore value is not supported for such parameter usage
EXECUTE IMMEDIATE 'SELECT * FROM (SELECT ? UNION DISTINCT SELECT 1) AS derived' USING DEFAULT;
ERROR HY000: Default/ignore value is not supported for such parameter usage
EXECUTE IMMEDIATE 'SELECT * FROM (SELECT ? UNION DISTINCT SELECT 1) AS derived' USING IGNORE;
ERROR HY000: Default/ignore value is not supported for such parameter usage
# multi-update and DEFAULT
CREATE TABLE t1 (a INT, b INT DEFAULT a);
INSERT into t1 VALUES (1,2),(2,3);
CREATE TABLE t2 (a INT, b INT DEFAULT a);
INSERT INTO t2 VALUES (1,10),(2,30);
UPDATE t1,t2 SET t1.b = DEFAULT, t2.b = DEFAULT WHERE t1.a=t2.a;
SELECT * FROM t1;
a b
1 1
2 2
SELECT * FROM t2;
a b
1 1
2 2
# re-check the case for Prepared Statement with parameters
TRUNCATE TABLE t1;
TRUNCATE TABLE t2;
INSERT INTO t1 VALUES (1,2),(2,3);
INSERT INTO t2 VALUES (1,10),(2,30);
EXECUTE IMMEDIATE 'UPDATE t1,t2 SET t1.b = ?, t2.b = ? WHERE t1.a=t2.a' USING DEFAULT, DEFAULT;
SELECT * FROM t1;
a b
1 1
2 2
SELECT * FROM t2;
a b
1 1
2 2
DROP TABLE t1, t2;
# multi-update and IGNORE
CREATE TABLE t1 (a INT, b INT default a);
INSERT INTO t1 VALUES (1,2),(2,3);
CREATE TABLE t2 (a INT, b INT default a);
INSERT INTO t2 VALUES (1,10),(2,30);
UPDATE t1,t2 SET t1.b = IGNORE, t2.b = IGNORE WHERE t1.a=t2.a;
SELECT * FROM t1;
a b
1 2
2 3
SELECT * FROM t2;
a b
1 NULL
2 NULL
# re-check the case for Prepared Statement with parameters
TRUNCATE TABLE t1;
TRUNCATE TABLE t2;
INSERT INTO t1 VALUES (1,2),(2,3);
INSERT INTO t2 VALUES (1,10),(2,30);
EXECUTE IMMEDIATE 'UPDATE t1,t2 SET t1.b = ?, t2.b = ? WHERE t1.a=t2.a' USING IGNORE, IGNORE;
SELECT * FROM t1;
a b
1 2
2 3
SELECT * FROM t2;
a b
1 10
2 30
DROP TABLE t1, t2;
# multi-update and DEFAULT parameter (no default)
CREATE TABLE t1 (a INT, b INT NOT NULL);
INSERT INTO t1 VALUES (1,2),(2,3);
CREATE TABLE t2 (a INT, b INT NOT NULL);
INSERT INTO t2 VALUES (1,10),(2,30);
EXECUTE IMMEDIATE 'UPDATE t1,t2 SET t1.b = ?, t2.b = ? WHERE t1.a=t2.a' USING DEFAULT, DEFAULT;
ERROR HY000: Field 'b' doesn't have a default value
DROP TABLE t1, t2;
# multi-update and IGNORE parameter (no default)
CREATE TABLE t1 (a INT, b INT NOT NULL);
INSERT INTO t1 VALUES (1,2),(2,3);
CREATE TABLE t2 (a INT, b INT NOT NULL);
INSERT INTO t2 VALUES (1,10),(2,30);
EXECUTE IMMEDIATE 'UPDATE t1,t2 SET t1.b = ?, t2.b = ? WHERE t1.a=t2.a' USING IGNORE, IGNORE;
SELECT * FROM t1;
a b
1 2
2 3
SELECT * FROM t2;
a b
1 10
2 30
DROP TABLE t1, t2;
#
# End of 10.4 tests
#

View file

@ -5243,6 +5243,125 @@ EXECUTE IMMEDIATE 'SELECT GROUP_CONCAT(@x) FROM t GROUP BY @x := f';
DROP TABLE t;
--echo #
--echo # MDEV-15703: Crash in EXECUTE IMMEDIATE 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)' USING DEFAULT
--echo #
PREPARE stmt FROM 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)';
--error ER_INVALID_DEFAULT_PARAM
EXECUTE stmt USING DEFAULT;
DEALLOCATE PREPARE stmt;
PREPARE stmt FROM 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)';
--error ER_INVALID_DEFAULT_PARAM
EXECUTE stmt USING IGNORE;
DEALLOCATE PREPARE stmt;
--error ER_INVALID_DEFAULT_PARAM
EXECUTE IMMEDIATE 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)' USING DEFAULT;
--error ER_INVALID_DEFAULT_PARAM
EXECUTE IMMEDIATE 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)' USING IGNORE;
--error ER_INVALID_DEFAULT_PARAM
EXECUTE IMMEDIATE 'BEGIN NOT ATOMIC DECLARE a INT DEFAULT ?; END' USING DEFAULT;
--error ER_INVALID_DEFAULT_PARAM
EXECUTE IMMEDIATE 'BEGIN NOT ATOMIC DECLARE a INT DEFAULT ?; END' USING IGNORE;
CREATE PROCEDURE p1(a INT) SELECT 1;
--error ER_INVALID_DEFAULT_PARAM
EXECUTE IMMEDIATE 'CALL p1(?)' USING DEFAULT;
--error ER_INVALID_DEFAULT_PARAM
EXECUTE IMMEDIATE 'CALL p1(?)' USING IGNORE;
DROP PROCEDURE p1;
--error ER_INVALID_DEFAULT_PARAM
EXECUTE IMMEDIATE 'SELECT ? UNION SELECT 1' USING DEFAULT;
--error ER_INVALID_DEFAULT_PARAM
EXECUTE IMMEDIATE 'SELECT ? UNION SELECT 1' USING IGNORE;
--error ER_INVALID_DEFAULT_PARAM
EXECUTE IMMEDIATE 'SELECT * FROM (SELECT ? UNION ALL SELECT 1) AS derived' USING DEFAULT;
--error ER_INVALID_DEFAULT_PARAM
EXECUTE IMMEDIATE 'SELECT * FROM (SELECT ? UNION ALL SELECT 1) AS derived' USING IGNORE;
--error ER_INVALID_DEFAULT_PARAM
EXECUTE IMMEDIATE 'SELECT * FROM (SELECT ? UNION DISTINCT SELECT 1) AS derived' USING DEFAULT;
--error ER_INVALID_DEFAULT_PARAM
EXECUTE IMMEDIATE 'SELECT * FROM (SELECT ? UNION DISTINCT SELECT 1) AS derived' USING IGNORE;
--echo # multi-update and DEFAULT
CREATE TABLE t1 (a INT, b INT DEFAULT a);
INSERT into t1 VALUES (1,2),(2,3);
CREATE TABLE t2 (a INT, b INT DEFAULT a);
INSERT INTO t2 VALUES (1,10),(2,30);
UPDATE t1,t2 SET t1.b = DEFAULT, t2.b = DEFAULT WHERE t1.a=t2.a;
SELECT * FROM t1;
SELECT * FROM t2;
--echo # re-check the case for Prepared Statement with parameters
TRUNCATE TABLE t1;
TRUNCATE TABLE t2;
INSERT INTO t1 VALUES (1,2),(2,3);
INSERT INTO t2 VALUES (1,10),(2,30);
EXECUTE IMMEDIATE 'UPDATE t1,t2 SET t1.b = ?, t2.b = ? WHERE t1.a=t2.a' USING DEFAULT, DEFAULT;
SELECT * FROM t1;
SELECT * FROM t2;
# Cleanup
DROP TABLE t1, t2;
--echo # multi-update and IGNORE
CREATE TABLE t1 (a INT, b INT default a);
INSERT INTO t1 VALUES (1,2),(2,3);
CREATE TABLE t2 (a INT, b INT default a);
INSERT INTO t2 VALUES (1,10),(2,30);
UPDATE t1,t2 SET t1.b = IGNORE, t2.b = IGNORE WHERE t1.a=t2.a;
SELECT * FROM t1;
SELECT * FROM t2;
--echo # re-check the case for Prepared Statement with parameters
TRUNCATE TABLE t1;
TRUNCATE TABLE t2;
INSERT INTO t1 VALUES (1,2),(2,3);
INSERT INTO t2 VALUES (1,10),(2,30);
EXECUTE IMMEDIATE 'UPDATE t1,t2 SET t1.b = ?, t2.b = ? WHERE t1.a=t2.a' USING IGNORE, IGNORE;
SELECT * FROM t1;
SELECT * FROM t2;
# Cleanup
DROP TABLE t1, t2;
--echo # multi-update and DEFAULT parameter (no default)
CREATE TABLE t1 (a INT, b INT NOT NULL);
INSERT INTO t1 VALUES (1,2),(2,3);
CREATE TABLE t2 (a INT, b INT NOT NULL);
INSERT INTO t2 VALUES (1,10),(2,30);
--error ER_NO_DEFAULT_FOR_FIELD
EXECUTE IMMEDIATE 'UPDATE t1,t2 SET t1.b = ?, t2.b = ? WHERE t1.a=t2.a' USING DEFAULT, DEFAULT;
# Cleanup
DROP TABLE t1, t2;
--echo # multi-update and IGNORE parameter (no default)
CREATE TABLE t1 (a INT, b INT NOT NULL);
INSERT INTO t1 VALUES (1,2),(2,3);
CREATE TABLE t2 (a INT, b INT NOT NULL);
INSERT INTO t2 VALUES (1,10),(2,30);
EXECUTE IMMEDIATE 'UPDATE t1,t2 SET t1.b = ?, t2.b = ? WHERE t1.a=t2.a' USING IGNORE, IGNORE;
SELECT * FROM t1;
SELECT * FROM t2;
# Cleanup
DROP TABLE t1, t2;
--echo #
--echo # End of 10.4 tests
--echo #

View file

@ -2594,9 +2594,9 @@ ERROR HY000: 'ignore' is not allowed in this context
VALUES (DEFAULT);
ERROR HY000: 'default' is not allowed in this context
EXECUTE IMMEDIATE 'VALUES (?)' USING IGNORE;
ERROR HY000: 'ignore' is not allowed in this context
ERROR HY000: Default/ignore value is not supported for such parameter usage
EXECUTE IMMEDIATE 'VALUES (?)' USING DEFAULT;
ERROR HY000: 'default' is not allowed in this context
ERROR HY000: Default/ignore value is not supported for such parameter usage
#
# MDEV-24675: TVC using subqueries
#

View file

@ -1349,9 +1349,9 @@ DELIMITER ;$$
VALUES (IGNORE);
--error ER_UNKNOWN_ERROR
VALUES (DEFAULT);
--error ER_UNKNOWN_ERROR
--error ER_INVALID_DEFAULT_PARAM
EXECUTE IMMEDIATE 'VALUES (?)' USING IGNORE;
--error ER_UNKNOWN_ERROR
--error ER_INVALID_DEFAULT_PARAM
EXECUTE IMMEDIATE 'VALUES (?)' USING DEFAULT;
--echo #

View file

@ -1353,6 +1353,9 @@ bool Field::sp_prepare_and_store_item(THD *thd, Item **value)
if (!(expr_item= thd->sp_prepare_func_item(value, 1)))
goto error;
if (expr_item->check_is_evaluable_expression_or_error())
goto error;
/*
expr_item is now fixed, it's safe to call cmp_type()
*/
@ -11424,6 +11427,30 @@ bool Field::validate_value_in_record_with_warn(THD *thd, const uchar *record)
}
/**
Find which reaction should be for IGNORE value.
*/
ignore_value_reaction find_ignore_reaction(THD *thd)
{
enum_sql_command com= thd->lex->sql_command;
// All insert-like commands
if (com == SQLCOM_INSERT || com == SQLCOM_REPLACE ||
com == SQLCOM_INSERT_SELECT || com == SQLCOM_REPLACE_SELECT ||
com == SQLCOM_LOAD)
{
return IGNORE_MEANS_DEFAULT;
}
// Update commands
if (com == SQLCOM_UPDATE || com == SQLCOM_UPDATE_MULTI)
{
return IGNORE_MEANS_FIELD_VALUE;
}
return IGNORE_MEANS_ERROR;
}
bool Field::save_in_field_default_value(bool view_error_processing)
{
THD *thd= table->in_use;

View file

@ -60,6 +60,15 @@ enum enum_check_fields
CHECK_FIELD_ERROR_FOR_NULL,
};
enum ignore_value_reaction
{
IGNORE_MEANS_ERROR,
IGNORE_MEANS_DEFAULT,
IGNORE_MEANS_FIELD_VALUE
};
ignore_value_reaction find_ignore_reaction(THD *thd);
/*
Common declarations for Field and Item
*/

View file

@ -3991,7 +3991,9 @@ Item_param::Item_param(THD *thd, const LEX_CSTRING *name_arg,
as an actual parameter. See Item_param::set_from_item().
*/
m_is_settable_routine_parameter(true),
m_clones(thd->mem_root)
m_clones(thd->mem_root),
m_associated_field(nullptr),
m_default_field(nullptr)
{
name= *name_arg;
/*
@ -4398,10 +4400,29 @@ int Item_param::save_in_field(Field *field, bool no_conversions)
case NULL_VALUE:
return set_field_to_null_with_conversions(field, no_conversions);
case DEFAULT_VALUE:
if (m_associated_field)
return assign_default(field);
return field->save_in_field_default_value(field->table->pos_in_table_list->
top_table() !=
field->table->pos_in_table_list);
case IGNORE_VALUE:
if (m_associated_field)
{
switch (find_ignore_reaction(field->table->in_use))
{
case IGNORE_MEANS_DEFAULT:
DBUG_ASSERT(0); // impossible now, but fully working code if needed
return assign_default(field);
case IGNORE_MEANS_FIELD_VALUE:
m_associated_field->save_val(field);
return false;
default:
; // fall through to error
}
DBUG_ASSERT(0); //impossible
my_error(ER_INVALID_DEFAULT_PARAM, MYF(0));
return true;
}
return field->save_in_field_ignore_value(field->table->pos_in_table_list->
top_table() !=
field->table->pos_in_table_list);
@ -5007,6 +5028,44 @@ static Field *make_default_field(THD *thd, Field *field_arg)
}
/**
Assign a default value of a table column to the positional parameter that
is performed on execution of a prepared statement with the clause
'USING DEFAULT'
@param field a field that should be assigned an actual value of positional
parameter passed via the clause 'USING DEFAULT'
@return false on success, true on failure
*/
bool Item_param::assign_default(Field *field)
{
DBUG_ASSERT(m_associated_field);
if (m_associated_field->field->flags & NO_DEFAULT_VALUE_FLAG)
{
my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0),
m_associated_field->field->field_name.str);
return true;
}
if (!m_default_field)
{
m_default_field= make_default_field(field->table->in_use,
m_associated_field->field);
if (!m_default_field)
return true;
}
if (m_default_field->default_value)
m_default_field->set_default();
return field_conv(field, m_default_field);
}
/****************************************************************************
Item_copy_string
****************************************************************************/
@ -9675,6 +9734,15 @@ Item *Item_default_value::transform(THD *thd, Item_transformer transformer,
}
bool Item_default_value::associate_with_target_field(THD *thd,
Item_field *field)
{
m_associated= true;
arg= field;
return tie_field(thd);
}
/**
Call fix_fields for an item representing the default value, create
an instance of Field for representing the default value and assign it

View file

@ -834,7 +834,7 @@ protected:
const Tmp_field_param *param,
bool is_explicit_null);
void raise_error_not_evaluable();
virtual void raise_error_not_evaluable();
void push_note_converted_to_negative_complement(THD *thd);
void push_note_converted_to_positive_complement(THD *thd);
@ -2453,6 +2453,18 @@ public:
Checks if this item consists in the left part of arg IN subquery predicate
*/
bool pushable_equality_checker_for_subquery(uchar *arg);
/**
This method is to set relationship between a positional parameter
represented by the '?' and an actual argument value passed to the
call of PS/SP by the USING clause. The method is overridden in classes
Item_param and Item_default_value.
*/
virtual bool associate_with_target_field(THD *, Item_field *)
{
DBUG_ASSERT(is_fixed());
return false;
}
};
MEM_ROOT *get_thd_memroot(THD *thd);
@ -4192,6 +4204,10 @@ public:
void sync_clones();
bool register_clone(Item_param *i) { return m_clones.push_back(i); }
virtual void raise_error_not_evaluable()
{
invalid_default_param();
}
private:
void invalid_default_param() const;
@ -4206,6 +4222,17 @@ public:
virtual void make_send_field(THD *thd, Send_field *field);
/**
See comments on @see Item::associate_with_target_field for method
description
*/
virtual bool associate_with_target_field(THD *, Item_field *field)
{
m_associated_field= field;
return false;
}
bool assign_default(Field *field);
private:
Send_field *m_out_param_info;
bool m_is_settable_routine_parameter;
@ -4215,6 +4242,8 @@ private:
synchronize the actual value of the parameter with the values of the clones.
*/
Mem_root_array<Item_param *, true> m_clones;
Item_field *m_associated_field;
Field *m_default_field;
};
@ -6512,6 +6541,8 @@ public:
class Item_default_value : public Item_field
{
bool vcol_assignment_ok;
bool m_associated;
void calculate();
public:
Item *arg;
@ -6519,6 +6550,7 @@ public:
bool vcol_assignment_arg)
:Item_field(thd, context_arg, (const char *)NULL, (const char *)NULL,
&null_clex_str), vcol_assignment_ok(vcol_assignment_arg),
m_associated(false),
arg(a) {}
enum Type type() const { return DEFAULT_VALUE_ITEM; }
bool eq(const Item *item, bool binary_cmp) const;
@ -6581,6 +6613,12 @@ public:
Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src,
const Tmp_field_param *param);
/**
See comments on @see Item::associate_with_target_field for method
description
*/
virtual bool associate_with_target_field(THD *thd, Item_field *field);
private:
bool tie_field(THD *thd);
};

View file

@ -8870,6 +8870,9 @@ fill_record_n_invoke_before_triggers(THD *thd, TABLE *table,
@param values values to fill with
@param ignore_errors TRUE if we should ignore errors
@param use_value forces usage of value of the items instead of result
@param check_for_computability whether to check for ability to invoke val_*()
methods (val_int () etc) against supplied
values
@details
fill_record() may set table->auto_increment_field_not_null and a
@ -8883,7 +8886,7 @@ fill_record_n_invoke_before_triggers(THD *thd, TABLE *table,
bool
fill_record(THD *thd, TABLE *table, Field **ptr, List<Item> &values,
bool ignore_errors, bool use_value)
bool ignore_errors, bool use_value, bool check_for_computability)
{
List_iterator_fast<Item> v(values);
List<TABLE> tbl_list;
@ -8921,6 +8924,10 @@ fill_record(THD *thd, TABLE *table, Field **ptr, List<Item> &values,
else
value=v++;
if (check_for_computability &&
value->check_is_evaluable_expression_or_error())
goto err;
bool vers_sys_field= table->versioned() && field->vers_sys_field();
if (field->field_index == autoinc_index)
@ -8995,7 +9002,7 @@ fill_record_n_invoke_before_triggers(THD *thd, TABLE *table, Field **ptr,
bool result;
Table_triggers_list *triggers= table->triggers;
result= fill_record(thd, table, ptr, values, ignore_errors, FALSE);
result= fill_record(thd, table, ptr, values, ignore_errors, false, false);
if (!result && triggers && *ptr)
result= triggers->process_triggers(thd, event, TRG_ACTION_BEFORE, TRUE) ||

View file

@ -184,7 +184,8 @@ void unfix_fields(List<Item> &items);
bool fill_record(THD * thd, TABLE *table_arg, List<Item> &fields,
List<Item> &values, bool ignore_errors, bool update);
bool fill_record(THD *thd, TABLE *table, Field **field, List<Item> &values,
bool ignore_errors, bool use_value);
bool ignore_errors, bool use_value,
bool check_for_evaluability);
Field *
find_field_in_tables(THD *thd, Item_ident *item,

View file

@ -271,7 +271,8 @@ my_bool Expression_cache_tmptable::put_value(Item *value)
}
*(items.head_ref())= value;
fill_record(table_thd, cache_table, cache_table->field, items, TRUE, TRUE);
fill_record(table_thd, cache_table, cache_table->field, items, true, true,
true);
if (unlikely(table_thd->is_error()))
goto err;;

View file

@ -12732,7 +12732,8 @@ end_sj_materialize(JOIN *join, JOIN_TAB *join_tab, bool end_of_records)
if (item->is_null())
DBUG_RETURN(NESTED_LOOP_OK);
}
fill_record(thd, table, table->field, sjm->sjm_table_cols, TRUE, FALSE);
fill_record(thd, table, table->field, sjm->sjm_table_cols, true, false,
true);
if (unlikely(thd->is_error()))
DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */
if (unlikely((error= table->file->ha_write_tmp_row(table->record[0]))))

View file

@ -3066,7 +3066,7 @@ int select_result_explain_buffer::send_data(List<Item> &items)
memory.
*/
set_current_thd(thd);
fill_record(thd, dst_table, dst_table->field, items, TRUE, FALSE);
fill_record(thd, dst_table, dst_table->field, items, true, false, false);
res= dst_table->file->ha_write_tmp_row(dst_table->record[0]);
set_current_thd(cur_thd);
DBUG_RETURN(MY_TEST(res));

View file

@ -122,11 +122,11 @@ int select_unit::send_data(List<Item> &values)
table->null_catch_flags= CHECK_ROW_FOR_NULLS_TO_REJECT;
if (intersect_mark)
{
fill_record(thd, table, table->field + 1, values, TRUE, FALSE);
fill_record(thd, table, table->field + 1, values, true, false, true);
table->field[0]->store((ulonglong) curr_step, 1);
}
else
fill_record(thd, table, table->field, values, TRUE, FALSE);
fill_record(thd, table, table->field, values, true, false, true);
if (unlikely(thd->is_error()))
{
rc= 1;
@ -562,7 +562,7 @@ int select_union_direct::send_data(List<Item> &items)
send_records++;
}
fill_record(thd, table, table->field, items, true, false);
fill_record(thd, table, table->field, items, true, false, true);
if (unlikely(thd->is_error()))
return true; /* purecov: inspected */

View file

@ -2160,6 +2160,10 @@ int multi_update::prepare(List<Item> &not_used_values,
{
Item *value= value_it++;
uint offset= item->field->table->pos_in_table_list->shared;
if (value->associate_with_target_field(thd, item))
DBUG_RETURN(1);
fields_for_table[offset]->push_back(item, thd->mem_root);
values_for_table[offset]->push_back(value, thd->mem_root);
}
@ -2658,7 +2662,7 @@ int multi_update::send_data(List<Item> &not_used_values)
tmp_table_param[offset].func_count);
fill_record(thd, tmp_table,
tmp_table->field + 1 + unupdated_check_opt_tables.elements,
*values_for_table[offset], TRUE, FALSE);
*values_for_table[offset], true, false, false);
/* Write row, ignoring duplicated updates to a row */
error= tmp_table->file->ha_write_tmp_row(tmp_table->record[0]);

View file

@ -649,7 +649,15 @@ static bool pack_vcols(THD *thd, String *buf, List<Create_field> &create_fields,
? VCOL_GENERATED_STORED : VCOL_GENERATED_VIRTUAL))
return 1;
if (field->has_default_expression() && !field->has_default_now_unireg_check())
if (pack_expression(buf, field->default_value, field_nr, VCOL_DEFAULT))
if (pack_expression(buf, field->default_value, field_nr, VCOL_DEFAULT) ||
/*
field->has_default_expression() can return error (e.g. because
the method Item_param::basic_const_item invokes
invalid_default_param()
in case either DEFAULT_VALUE or IGNORE_VALUE is handled).
Take this fact into account and return error in this case.
*/
thd->is_error())
return 1;
if (field->check_constraint)
if (pack_expression(buf, field->check_constraint, field_nr,