diff options
author | Alexander Barkov <bar@mariadb.com> | 2022-06-24 17:21:31 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.com> | 2022-06-27 12:49:40 +0400 |
commit | 0bed4d72c03184ceaafb82a0a4b7d8deea55bd61 (patch) | |
tree | dbec562245c68cd48146fc82bdfca3664a72a0b6 /sql/table.cc | |
parent | 925999bb97a495d0af02840270938b76cc7471c3 (diff) | |
download | mariadb-git-0bed4d72c03184ceaafb82a0a4b7d8deea55bd61.tar.gz |
MDEV-28918 Implicit cast from INET6 UNSIGNED works differently on UPDATE vs ALTER
Now INSERT, UPDATE, ALTER statements involving incompatible data type pairs, e.g.:
UPDATE TABLE t1 SET col_inet6=col_int;
INSERT INTO t1 (col_inet6) SELECT col_in FROM t2;
ALTER TABLE t1 MODIFY col_inet6 INT;
consistently return an error at the statement preparation time:
ERROR HY000: Illegal parameter data types inet6 and int for operation 'SET'
and abort the statement before starting interating rows.
This error is the same with what is raised for queries like:
SELECT col_inet6 FROM t1 UNION SELECT col_int FROM t2;
SELECT COALESCE(col_inet6, col_int) FROM t1;
Before this change the error was caught only during the execution time,
when a Field_xxx::store_xxx() was called for the very firts row.
The behavior was not consistent between various statements and could do different things:
- abort the statement
- set a column to the data type default value (e.g. '::' for INET6)
- set a column to NULL
A typical old error was:
ERROR 22007: Incorrect inet6 value: '1' for column `test`.`t1`.`a` at row 1
EXCEPTION:
Note, there is an exception: a multi-row INSERT..VALUES, e.g.:
INSERT INTO t1 (col_a,col_b) VALUES (a1,b1),(a2,b2);
checks assignment compability at the preparation time for the very first row only:
(col_a,col_b) vs (a1,b1)
Other rows are still checked at the execution time and return the old warnings
or errors in case of a failure. This is done because catching all rows at the
preparation time would change behavior significantly. So it still works
according to the STRICT_XXX_TABLES sql_mode flags and the table transaction ability.
This is too late to change this behavior in 10.7.
There is no a firm decision yet if a multi-row INSERT..VALUES
behavior will change in later versions.
Diffstat (limited to 'sql/table.cc')
-rw-r--r-- | sql/table.cc | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/sql/table.cc b/sql/table.cc index f6f293290cd..98b487ba991 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -9242,6 +9242,60 @@ bool TABLE::validate_default_values_of_unset_fields(THD *thd) const } +/* + Check assignment compatibility of a value list against an explicitly + specified field list, e.g. + INSERT INTO t1 (a,b) VALUES (1,2); +*/ +bool TABLE::check_assignability_explicit_fields(List<Item> fields, + List<Item> values) +{ + DBUG_ENTER("TABLE::check_assignability_explicit_fields"); + DBUG_ASSERT(fields.elements == values.elements); + + List_iterator<Item> fi(fields); + List_iterator<Item> vi(values); + Item *f, *value; + while ((f= fi++) && (value= vi++)) + { + Item_field *item_field= f->field_for_view_update(); + if (!item_field) + { + /* + A non-updatable field of a view found. + This scenario is caught later and an error is raised. + We could eventually move error reporting here. For now just continue. + */ + continue; + } + if (value->check_assignability_to(item_field->field)) + DBUG_RETURN(true); + } + DBUG_RETURN(false); +} + + +/* + Check assignment compatibility for a value list against + all visible fields of the table, e.g. + INSERT INTO t1 VALUES (1,2); +*/ +bool TABLE::check_assignability_all_visible_fields(List<Item> &values) const +{ + DBUG_ENTER("TABLE::check_assignability_all_visible_fields"); + DBUG_ASSERT(s->visible_fields == values.elements); + + List_iterator<Item> vi(values); + for (uint i= 0; i < s->fields; i++) + { + if (!field[i]->invisible && + (vi++)->check_assignability_to(field[i])) + DBUG_RETURN(true); + } + DBUG_RETURN(false); +} + + bool TABLE::insert_all_rows_into_tmp_table(THD *thd, TABLE *tmp_table, TMP_TABLE_PARAM *tmp_table_param, |