mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 04:22:27 +01:00
MDEV-23597 Assertion `marked_for_read()' failed while evaluating DEFAULT
The columns that are part of DEFAULT expression were not read-marked in statements like UPDATE...SET b=DEFAULT. The problem is `F(DEFAULT)` expression depends of the left-hand side of an assignment. However, setup_fields accepts only right-hand side value. Neither Item::fix_fields does. Suchwise, b=DEFAULT(b) works fine, because Item_default_field has information on what field it is default of: if (thd->mark_used_columns != MARK_COLUMNS_NONE) def_field->default_value->expr->update_used_tables(); in Item_default_value::fix_fields(). It is not reasonable to pass a left-hand side to Item:fix_fields, because the case is rare, so the rewrite b= F(DEFAULT) -> b= F(DEFAULT(b)) is made instead. Both UPDATE and multi-UPDATE are affected, however any form of INSERT is not: it marks all the fields in DEFAULT expressions for read in TABLE::mark_default_fields_for_write().
This commit is contained in:
parent
6a89f346de
commit
c47e4aab62
11 changed files with 111 additions and 10 deletions
|
@ -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('<EFBFBD>')) CHARACTER SET koi8r COLLATE koi8r_bin;
|
||||
ERROR 22007: Encountered illegal value '<EFBFBD>' 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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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('<EFBFBD>')) 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;
|
||||
|
|
|
@ -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
|
||||
|
|
22
sql/item.h
22
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.
|
||||
|
||||
|
|
|
@ -7193,6 +7193,18 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
|
|||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
/** Transforms b= F(DEFAULT) -> b= F(DEFAULT(b)) */
|
||||
void setup_defaults(THD *thd, List<Item> &fields, List<Item> &values)
|
||||
{
|
||||
List_iterator<Item> fit(fields);
|
||||
List_iterator<Item> 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
|
||||
****************************************************************************/
|
||||
|
|
|
@ -172,6 +172,7 @@ bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array,
|
|||
List<Item> &item, enum_mark_columns mark_used_columns,
|
||||
List<Item> *sum_func_list, List<Item> *pre_fix,
|
||||
bool allow_sum_func);
|
||||
void setup_defaults(THD *thd, List<Item> &fields, List<Item> &values);
|
||||
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);
|
||||
|
|
|
@ -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<Item> ¬_used_values,
|
|||
}
|
||||
}
|
||||
|
||||
setup_defaults(thd, *fields, *values);
|
||||
|
||||
/*
|
||||
We have to check values after setup_tables to get covering_keys right in
|
||||
reference tables
|
||||
|
|
|
@ -9466,7 +9466,7 @@ 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(),
|
||||
$$= new (thd->mem_root) Item_default_value_arg(thd, Lex->current_context(),
|
||||
$3);
|
||||
if ($$ == NULL)
|
||||
MYSQL_YYABORT;
|
||||
|
|
Loading…
Reference in a new issue