summaryrefslogtreecommitdiff
path: root/sql/table.cc
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.com>2022-06-24 17:21:31 +0400
committerAlexander Barkov <bar@mariadb.com>2022-06-27 12:49:40 +0400
commit0bed4d72c03184ceaafb82a0a4b7d8deea55bd61 (patch)
treedbec562245c68cd48146fc82bdfca3664a72a0b6 /sql/table.cc
parent925999bb97a495d0af02840270938b76cc7471c3 (diff)
downloadmariadb-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.cc54
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,