diff --git a/mysql-test/r/default.result b/mysql-test/r/default.result index 8335b553a8e..369734ae92a 100644 --- a/mysql-test/r/default.result +++ b/mysql-test/r/default.result @@ -3089,8 +3089,8 @@ DROP TABLE t1; # # Collations # -CREATE TABLE t1 (a VARCHAR(20) CHARACTER SET latin1 DEFAULT CONCAT('ö')) CHARACTER SET koi8r COLLATE koi8r_bin; -ERROR 22007: Encountered illegal value 'ö' when converting to koi8r +CREATE TABLE t1 (a VARCHAR(20) CHARACTER SET latin1 DEFAULT CONCAT('�')) CHARACTER SET koi8r COLLATE koi8r_bin; +ERROR 22007: Encountered illegal value '�' when converting to koi8r CREATE OR REPLACE TABLE t1 (a char(2) default concat('A') COLLATE utf8mb4_unicode_ci); SHOW CREATE TABLE t1; Table Create Table diff --git a/mysql-test/suite/gcol/inc/gcol_ins_upd.inc b/mysql-test/suite/gcol/inc/gcol_ins_upd.inc index 4cfcf371fd7..e02a3828ea2 100644 --- a/mysql-test/suite/gcol/inc/gcol_ins_upd.inc +++ b/mysql-test/suite/gcol/inc/gcol_ins_upd.inc @@ -660,3 +660,25 @@ INSERT IGNORE INTO t1 SELECT * FROM t1; DROP TABLE t1; } + +--echo # +--echo # MDEV-23597 Assertion `marked_for_read()' failed while evaluating DEFAULT +--echo # + +CREATE TABLE t1 (a INT UNIQUE, b INT DEFAULT (c+1), c int); +INSERT INTO t1 VALUES (1,1,1); +UPDATE t1 SET b=DEFAULT; +SELECT * from t1; + +REPLACE t1 VALUES(1,1,1); +INSERT INTO t1 VALUES (1,1,1) ON DUPLICATE KEY UPDATE b= DEFAULT; +SELECT * from t1; + +REPLACE t1 VALUES(1,1,1); +CREATE TABLE t2 (a INT, b INT DEFAULT (c+1), c int); +INSERT INTO t2 VALUES (5,5,5); +UPDATE t1 join t2 set t1.b= DEFAULT, t2.b= DEFAULT; +SELECT * from t1, t2; + +DROP TABLE t1, t2; + diff --git a/mysql-test/suite/gcol/r/gcol_ins_upd_innodb.result b/mysql-test/suite/gcol/r/gcol_ins_upd_innodb.result index 1d85fc837dc..143e1b725c4 100644 --- a/mysql-test/suite/gcol/r/gcol_ins_upd_innodb.result +++ b/mysql-test/suite/gcol/r/gcol_ins_upd_innodb.result @@ -791,6 +791,28 @@ Warnings: Warning 1906 The value specified for generated column 'v' in table 't1' has been ignored Warning 1906 The value specified for generated column 'v' in table 't1' has been ignored DROP TABLE t1; +# +# MDEV-23597 Assertion `marked_for_read()' failed while evaluating DEFAULT +# +CREATE TABLE t1 (a INT UNIQUE, b INT DEFAULT (c+1), c int); +INSERT INTO t1 VALUES (1,1,1); +UPDATE t1 SET b=DEFAULT; +SELECT * from t1; +a b c +1 2 1 +REPLACE t1 VALUES(1,1,1); +INSERT INTO t1 VALUES (1,1,1) ON DUPLICATE KEY UPDATE b= DEFAULT; +SELECT * from t1; +a b c +1 2 1 +REPLACE t1 VALUES(1,1,1); +CREATE TABLE t2 (a INT, b INT DEFAULT (c+1), c int); +INSERT INTO t2 VALUES (5,5,5); +UPDATE t1 join t2 set t1.b= DEFAULT, t2.b= DEFAULT; +SELECT * from t1, t2; +a b c a b c +1 2 1 5 6 5 +DROP TABLE t1, t2; DROP VIEW IF EXISTS v1,v2; DROP TABLE IF EXISTS t1,t2,t3; DROP PROCEDURE IF EXISTS p1; diff --git a/mysql-test/suite/gcol/r/gcol_ins_upd_myisam.result b/mysql-test/suite/gcol/r/gcol_ins_upd_myisam.result index e10b83cabf5..2c883b2de35 100644 --- a/mysql-test/suite/gcol/r/gcol_ins_upd_myisam.result +++ b/mysql-test/suite/gcol/r/gcol_ins_upd_myisam.result @@ -713,6 +713,28 @@ Warnings: Warning 1906 The value specified for generated column 'v' in table 't1' has been ignored Warning 1906 The value specified for generated column 'v' in table 't1' has been ignored DROP TABLE t1; +# +# MDEV-23597 Assertion `marked_for_read()' failed while evaluating DEFAULT +# +CREATE TABLE t1 (a INT UNIQUE, b INT DEFAULT (c+1), c int); +INSERT INTO t1 VALUES (1,1,1); +UPDATE t1 SET b=DEFAULT; +SELECT * from t1; +a b c +1 2 1 +REPLACE t1 VALUES(1,1,1); +INSERT INTO t1 VALUES (1,1,1) ON DUPLICATE KEY UPDATE b= DEFAULT; +SELECT * from t1; +a b c +1 2 1 +REPLACE t1 VALUES(1,1,1); +CREATE TABLE t2 (a INT, b INT DEFAULT (c+1), c int); +INSERT INTO t2 VALUES (5,5,5); +UPDATE t1 join t2 set t1.b= DEFAULT, t2.b= DEFAULT; +SELECT * from t1, t2; +a b c a b c +1 2 1 5 6 5 +DROP TABLE t1, t2; DROP VIEW IF EXISTS v1,v2; DROP TABLE IF EXISTS t1,t2,t3; DROP PROCEDURE IF EXISTS p1; diff --git a/mysql-test/t/default.test b/mysql-test/t/default.test index 31cf589c487..aec518d94a6 100644 --- a/mysql-test/t/default.test +++ b/mysql-test/t/default.test @@ -1855,7 +1855,7 @@ DROP TABLE t1; --echo # --error ER_BAD_DATA -CREATE TABLE t1 (a VARCHAR(20) CHARACTER SET latin1 DEFAULT CONCAT('ö')) CHARACTER SET koi8r COLLATE koi8r_bin; +CREATE TABLE t1 (a VARCHAR(20) CHARACTER SET latin1 DEFAULT CONCAT('�')) CHARACTER SET koi8r COLLATE koi8r_bin; CREATE OR REPLACE TABLE t1 (a char(2) default concat('A') COLLATE utf8mb4_unicode_ci); SHOW CREATE TABLE t1; DROP TABLE t1; diff --git a/sql/item.cc b/sql/item.cc index d7a3659a2ce..96e118e6365 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -9003,6 +9003,12 @@ error: return TRUE; } +bool Item_default_value::enchant_default_with_arg_processor(void *proc_arg) +{ + if (!arg) arg= (Item *)proc_arg; + return 0; +} + void Item_default_value::cleanup() { delete cached_field; // Free cached blob data diff --git a/sql/item.h b/sql/item.h index cc1914a7ad4..8be9a7fe417 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1713,6 +1713,7 @@ public: virtual bool limit_index_condition_pushdown_processor(void *arg) { return 0; } virtual bool exists2in_processor(void *arg) { return 0; } virtual bool find_selective_predicates_list_processor(void *arg) { return 0; } + virtual bool enchant_default_with_arg_processor(void *arg) { return 0; } bool cleanup_is_expensive_cache_processor(void *arg) { is_expensive_cache= (int8)(-1); @@ -5449,6 +5450,11 @@ public: class Item_default_value : public Item_field { void calculate(); +protected: + Item_default_value(THD *thd, Name_resolution_context *context_arg, Item *a) + :Item_field(thd, context_arg, (const char *)NULL, (const char *)NULL, + (const char *)NULL), + arg(a), cached_field(NULL) {} public: Item *arg; Field *cached_field; @@ -5456,16 +5462,12 @@ public: :Item_field(thd, context_arg, (const char *)NULL, (const char *)NULL, (const char *)NULL), arg(NULL), cached_field(NULL) {} - Item_default_value(THD *thd, Name_resolution_context *context_arg, Item *a) - :Item_field(thd, context_arg, (const char *)NULL, (const char *)NULL, - (const char *)NULL), - arg(a), cached_field(NULL) {} Item_default_value(THD *thd, Name_resolution_context *context_arg, Field *a) :Item_field(thd, context_arg, (const char *)NULL, (const char *)NULL, (const char *)NULL), arg(NULL),cached_field(NULL) {} enum Type type() const { return DEFAULT_VALUE_ITEM; } - bool vcol_assignment_allowed_value() const { return arg == NULL; } + bool vcol_assignment_allowed_value() const { return true; } bool eq(const Item *item, bool binary_cmp) const; bool fix_fields(THD *, Item **); void cleanup(); @@ -5495,6 +5497,7 @@ public: Item_field *field_for_view_update() { return 0; } bool update_vcol_processor(void *arg) { return 0; } bool check_func_default_processor(void *arg) { return true; } + bool enchant_default_with_arg_processor(void *arg); bool walk(Item_processor processor, bool walk_subquery, void *args) { @@ -5505,6 +5508,15 @@ public: Item *transform(THD *thd, Item_transformer transformer, uchar *args); }; +class Item_default_value_arg: public Item_default_value +{ +public: + Item_default_value_arg(THD *thd, Name_resolution_context *context, Item *a) + :Item_default_value(thd, context, a) {} + + bool vcol_assignment_allowed_value() const { return arg == NULL; } +}; + /** This class is used as bulk parameter INGNORE representation. diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 3471297ac7d..9a66b27a454 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -7193,6 +7193,18 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List &fields, DBUG_RETURN(0); } +/** Transforms b= F(DEFAULT) -> b= F(DEFAULT(b)) */ +void setup_defaults(THD *thd, List &fields, List &values) +{ + List_iterator fit(fields); + List_iterator vit(values); + + for (Item *value= vit++, *f_item= fit++; value; value= vit++, f_item= fit++) + { + value->walk(&Item::enchant_default_with_arg_processor, false, f_item); + } +} + /**************************************************************************** ** Check that all given fields exists and fill struct with current data ****************************************************************************/ diff --git a/sql/sql_base.h b/sql/sql_base.h index 5674e8378c5..b3b0a11795d 100644 --- a/sql/sql_base.h +++ b/sql/sql_base.h @@ -172,6 +172,7 @@ bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array, List &item, enum_mark_columns mark_used_columns, List *sum_func_list, List *pre_fix, bool allow_sum_func); +void setup_defaults(THD *thd, List &fields, List &values); void unfix_fields(List &items); bool fill_record(THD * thd, TABLE *table_arg, List &fields, List &values, bool ignore_errors, bool update); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 8af6c8f80a2..0344d8e0082 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -370,6 +370,8 @@ int mysql_update(THD *thd, DBUG_RETURN(1); } + setup_defaults(thd, fields, values); + #ifndef NO_EMBEDDED_ACCESS_CHECKS /* Check values */ table_list->grant.want_privilege= table->grant.want_privilege= @@ -1749,6 +1751,8 @@ int multi_update::prepare(List ¬_used_values, } } + setup_defaults(thd, *fields, *values); + /* We have to check values after setup_tables to get covering_keys right in reference tables diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 25826d2d6b0..ec82c7f9f07 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -9466,8 +9466,8 @@ column_default_non_parenthesized_expr: Item_splocal *il= $3->get_item_splocal(); if (il) my_yyabort_error((ER_WRONG_COLUMN_NAME, MYF(0), il->my_name()->str)); - $$= new (thd->mem_root) Item_default_value(thd, Lex->current_context(), - $3); + $$= new (thd->mem_root) Item_default_value_arg(thd, Lex->current_context(), + $3); if ($$ == NULL) MYSQL_YYABORT; }