diff --git a/mysql-test/main/ps.result b/mysql-test/main/ps.result index 32560ab2b2c..4ed0e71a29a 100644 --- a/mysql-test/main/ps.result +++ b/mysql-test/main/ps.result @@ -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 # diff --git a/mysql-test/main/ps.test b/mysql-test/main/ps.test index 70213e05391..e710050cb48 100644 --- a/mysql-test/main/ps.test +++ b/mysql-test/main/ps.test @@ -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 # diff --git a/mysql-test/main/table_value_constr.result b/mysql-test/main/table_value_constr.result index bd0aac5edce..d5eb8a599e5 100644 --- a/mysql-test/main/table_value_constr.result +++ b/mysql-test/main/table_value_constr.result @@ -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 # diff --git a/mysql-test/main/table_value_constr.test b/mysql-test/main/table_value_constr.test index 1d58cd0819d..21e066dec41 100644 --- a/mysql-test/main/table_value_constr.test +++ b/mysql-test/main/table_value_constr.test @@ -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 # diff --git a/sql/field.cc b/sql/field.cc index e37b4801f6b..185aed9cdb9 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -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; diff --git a/sql/field.h b/sql/field.h index 8d23a05e720..2bf9407feb1 100644 --- a/sql/field.h +++ b/sql/field.h @@ -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 */ diff --git a/sql/item.cc b/sql/item.cc index 8a52a0ec7c5..383c9e4b68e 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -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 diff --git a/sql/item.h b/sql/item.h index db4de2c035e..9fc5cc4068f 100644 --- a/sql/item.h +++ b/sql/item.h @@ -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 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); }; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 4e8598a8d65..e6a7110d45b 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -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 &values, - bool ignore_errors, bool use_value) + bool ignore_errors, bool use_value, bool check_for_computability) { List_iterator_fast v(values); List tbl_list; @@ -8921,6 +8924,10 @@ fill_record(THD *thd, TABLE *table, Field **ptr, List &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) || diff --git a/sql/sql_base.h b/sql/sql_base.h index 56c6c82907a..d6c6fd943ab 100644 --- a/sql/sql_base.h +++ b/sql/sql_base.h @@ -184,7 +184,8 @@ void unfix_fields(List &items); bool fill_record(THD * thd, TABLE *table_arg, List &fields, List &values, bool ignore_errors, bool update); bool fill_record(THD *thd, TABLE *table, Field **field, List &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, diff --git a/sql/sql_expression_cache.cc b/sql/sql_expression_cache.cc index bc44ecd79fa..75197bbfce6 100644 --- a/sql/sql_expression_cache.cc +++ b/sql/sql_expression_cache.cc @@ -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;; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index a871faec99e..dfbc3b6a70e 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -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])))) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index d93dea50972..3c854ec0eb9 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -3066,7 +3066,7 @@ int select_result_explain_buffer::send_data(List &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)); diff --git a/sql/sql_union.cc b/sql/sql_union.cc index bc33f827084..c536c859b98 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -122,11 +122,11 @@ int select_unit::send_data(List &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 &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 */ diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 233ad49576e..a1789445ef0 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -2160,6 +2160,10 @@ int multi_update::prepare(List ¬_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 ¬_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]); diff --git a/sql/unireg.cc b/sql/unireg.cc index f2d57e7549f..9b0f29963c7 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -649,7 +649,15 @@ static bool pack_vcols(THD *thd, String *buf, List &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,