summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOleksandr Byelkin <sanja@mariadb.com>2022-04-06 09:31:59 +0200
committerOleksandr Byelkin <sanja@mariadb.com>2022-04-06 09:35:58 +0200
commit16f2cf8f6fff884d75c5680230e2a54009ae5097 (patch)
tree116d781590c61e2c59e2e3e0f98910068eec2b6e
parent75b9014fedd8bb85d15501a2281fbade6b56fe78 (diff)
downloadmariadb-git-bb-10.2-MDEV-25638.tar.gz
MDEV-25638 Assertion `!result' failed in convert_const_to_intbb-10.2-MDEV-25638
The test suite triggers 3 bugs: I. Absence of STATUS_NO_RECORD on an empty record II. Mismatch signed and unsigned becaue parameter is not taking from the item but was a constant. III. Problem with rollback changes made for Items in the TABLE object: A cycle of live of Items (expressions) in table is following: 1) Parsed in the query arena of the table 2) Prepared with the permanent query arena of the table be active as a runtime and stmt (permanent) arena (here is difference from usual execution) 3) usage (can be sorter of one query live (CREATE TABLE for example) or longer then several queries (SELECT and using table cache), it is not a problem because all fields are local to the table). 4) cleanup and deallocate with the TABLE object So looking on the above all changes in the expressions belonged to a TABLE object should be just ignored.
-rw-r--r--mysql-test/r/check.result34
-rw-r--r--mysql-test/t/check.test21
-rw-r--r--sql/item_cmpfunc.cc2
-rw-r--r--sql/sql_class.h1
-rw-r--r--sql/table.cc25
5 files changed, 82 insertions, 1 deletions
diff --git a/mysql-test/r/check.result b/mysql-test/r/check.result
index 11ed734da0c..33f89735a15 100644
--- a/mysql-test/r/check.result
+++ b/mysql-test/r/check.result
@@ -102,3 +102,37 @@ Note 1091 Can't DROP CONSTRAINT `non_existing_constraint`; check that it exists
insert into t1 () values ();
ERROR 23000: CONSTRAINT `CONSTRAINT_1` failed for `test`.`t1`
drop table t1;
+#
+# MDEV-25638: Assertion `!result' failed in convert_const_to_int
+#
+CREATE TABLE v0 ( v1 bigint CHECK ( v1 NOT IN ( 'x' , 'x111' ) ) ) ;
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'x'
+Warning 1292 Truncated incorrect DOUBLE value: 'x111'
+select * from v0;
+v1
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'x'
+Warning 1292 Truncated incorrect DOUBLE value: 'x111'
+select v1 from v0;
+v1
+select * from v0;
+v1
+prepare stmt from "select * from v0";
+execute stmt;
+v1
+execute stmt;
+v1
+flush tables;
+select * from v0;
+v1
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'x'
+Warning 1292 Truncated incorrect DOUBLE value: 'x111'
+select * from v0;
+v1
+deallocate prepare stmt;
+drop table v0;
+#
+# End of 10.2 test
+#
diff --git a/mysql-test/t/check.test b/mysql-test/t/check.test
index 29587a9f623..9cefdee8418 100644
--- a/mysql-test/t/check.test
+++ b/mysql-test/t/check.test
@@ -124,3 +124,24 @@ alter table t1 drop constraint if exists non_existing_constraint;
--error ER_CONSTRAINT_FAILED
insert into t1 () values ();
drop table t1;
+
+--echo #
+--echo # MDEV-25638: Assertion `!result' failed in convert_const_to_int
+--echo #
+
+CREATE TABLE v0 ( v1 bigint CHECK ( v1 NOT IN ( 'x' , 'x111' ) ) ) ;
+select * from v0;
+select v1 from v0;
+select * from v0;
+prepare stmt from "select * from v0";
+execute stmt;
+execute stmt;
+flush tables;
+select * from v0;
+select * from v0;
+deallocate prepare stmt;
+drop table v0;
+
+--echo #
+--echo # End of 10.2 test
+--echo #
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 3a76982d80e..0907ec64232 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -471,7 +471,7 @@ static bool convert_const_to_int(THD *thd, Item_field *field_item,
/* Restore the original field value. */
if (save_field_value)
{
- result= field->store(orig_field_val, TRUE);
+ result= field->store(orig_field_val, field_item->unsigned_flag);
/* orig_field_val must be a valid value that can be restored back. */
DBUG_ASSERT(!result);
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index d3d54e11671..6d9118cf0c4 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1342,6 +1342,7 @@ public:
change_list.move_elements_to(&to->change_list);
}
bool is_empty() { return change_list.is_empty(); }
+ void empty_change_list() { change_list.empty(); }
};
diff --git a/sql/table.cc b/sql/table.cc
index 1f7b6452303..662b2b0830a 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -1016,6 +1016,7 @@ bool parse_vcol_defs(THD *thd, MEM_ROOT *mem_root, TABLE *table,
Virtual_column_info **check_constraint_ptr= table->check_constraints;
sql_mode_t saved_mode= thd->variables.sql_mode;
Query_arena backup_arena;
+ Item_change_list change_list_backup;
Virtual_column_info *vcol= 0;
StringBuffer<MAX_FIELD_WIDTH> expr_str;
bool res= 1;
@@ -1039,6 +1040,8 @@ bool parse_vcol_defs(THD *thd, MEM_ROOT *mem_root, TABLE *table,
thd->set_n_backup_active_arena(table->expr_arena, &backup_arena);
thd->stmt_arena= table->expr_arena;
+ // see following comment after end: label and near thd->empty_change_list()
+ thd->move_elements_to(&change_list_backup);
thd->update_charset(&my_charset_utf8mb4_general_ci, table->s->table_charset);
expr_str.append(&parse_vcol_keyword);
thd->variables.sql_mode &= ~MODE_NO_BACKSLASH_ESCAPES;
@@ -1167,6 +1170,27 @@ bool parse_vcol_defs(THD *thd, MEM_ROOT *mem_root, TABLE *table,
end:
thd->restore_active_arena(table->expr_arena, &backup_arena);
thd->stmt_arena= backup_stmt_arena_ptr;
+ /*
+ A cycle of live of Items (expressions) in table is following:
+
+ 1) Parsed in the query arena of the table
+ 2) Prepared with the permanent query arena of the table be active as a
+ runtime and stmt (permanent) arena (here is difference from usual
+ execution)
+ 3) usage (can be sorter of one query live (CREATE TABLE for example) or
+ longer then several queries (SELECT and using table cache), it is not a
+ problem because all fields are local to the table).
+ 4) cleanup and deallocate with the TABLE object
+
+ With such live cycle we do not need to rollback temporary changes in
+ this item tree so can just remove them to avoid problem of a try to be
+ rollback with current query (if the cycle was sorter then the query it
+ will lead to changes in freed memory, in the other case it will
+ rollback changes after the first query which will not be redone for
+ the next query).
+ */
+ thd->empty_change_list();
+ change_list_backup.move_elements_to(thd);
if (save_character_set_client)
thd->update_charset(save_character_set_client, save_collation);
thd->variables.sql_mode= saved_mode;
@@ -3104,6 +3128,7 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share,
outparam->s= share;
outparam->db_stat= db_stat;
outparam->write_row_record= NULL;
+ outparam->status= STATUS_NO_RECORD;
if (share->incompatible_version &&
!(ha_open_flags & (HA_OPEN_FOR_ALTER | HA_OPEN_FOR_REPAIR)))