summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2021-02-04 16:06:54 +0100
committerSergei Golubchik <serg@mariadb.org>2021-02-07 16:22:11 +0100
commitef5adf520760536c7396bdfe884fc509ac065694 (patch)
tree8b4074b80354de5126ce4604321874b439e03ec8
parentc2c23e598d49fc991b34853d864c77d02741b61c (diff)
downloadmariadb-git-ef5adf520760536c7396bdfe884fc509ac065694.tar.gz
MDEV-24274 ALTER TABLE with CHECK CONSTRAINTS gives "Out of Memory" error
partially revert 76063c2a13. Item::clone() is not an all-purpose Item copying machine, it was specifically created for pushdown of predicates into derived tables and views and it does not copy everything. In particular, it does not copy Item_func_regex. Fix the bug differently by preserving the old constraint name. But keep setting automatic_name=true to have it regenerated for cases like ALTER TABLE ... ADD CONSTRAINT.
-rw-r--r--mysql-test/main/check_constraint.result12
-rw-r--r--mysql-test/main/check_constraint.test8
-rw-r--r--sql/sql_table.cc38
-rw-r--r--sql/unireg.cc8
4 files changed, 34 insertions, 32 deletions
diff --git a/mysql-test/main/check_constraint.result b/mysql-test/main/check_constraint.result
index 3511af84166..f851b99e5c1 100644
--- a/mysql-test/main/check_constraint.result
+++ b/mysql-test/main/check_constraint.result
@@ -235,3 +235,15 @@ a b
insert t1 (b) values (1);
ERROR 23000: CONSTRAINT `CONSTRAINT_1` failed for `test`.`t1`
drop table t1;
+#
+# MDEV-24274 ALTER TABLE with CHECK CONSTRAINTS gives "Out of Memory" error
+#
+create table t1 (id varchar(2), constraint id check (id regexp '[a-z]'));
+alter table t1 force;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` varchar(2) DEFAULT NULL,
+ CONSTRAINT `id` CHECK (`id` regexp '[a-z]')
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
diff --git a/mysql-test/main/check_constraint.test b/mysql-test/main/check_constraint.test
index 93538fd1666..1258a9e3be6 100644
--- a/mysql-test/main/check_constraint.test
+++ b/mysql-test/main/check_constraint.test
@@ -176,3 +176,11 @@ select * from t1 where a is null;
--error ER_CONSTRAINT_FAILED
insert t1 (b) values (1);
drop table t1;
+
+--echo #
+--echo # MDEV-24274 ALTER TABLE with CHECK CONSTRAINTS gives "Out of Memory" error
+--echo #
+create table t1 (id varchar(2), constraint id check (id regexp '[a-z]'));
+alter table t1 force;
+show create table t1;
+drop table t1;
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 4ddfcabf6c8..50fe0eb3a6f 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -76,9 +76,8 @@ static int copy_data_between_tables(THD *, TABLE *,TABLE *,
static int mysql_prepare_create_table(THD *, HA_CREATE_INFO *, Alter_info *,
uint *, handler *, KEY **, uint *, int);
static uint blob_length_by_type(enum_field_types type);
-static bool fix_constraints_names(THD *thd, List<Virtual_column_info>
- *check_constraint_list,
- const HA_CREATE_INFO *create_info);
+static bool fix_constraints_names(THD *, List<Virtual_column_info> *,
+ const HA_CREATE_INFO *);
/**
@brief Helper function for explain_filename
@@ -4347,8 +4346,6 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
const Virtual_column_info *dup_check;
while ((dup_check= dup_it++) && dup_check != check)
{
- if (!dup_check->name.length || dup_check->automatic_name)
- continue;
if (!lex_string_cmp(system_charset_info,
&check->name, &dup_check->name))
{
@@ -8682,37 +8679,28 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
}
}
- // NB: `check` is TABLE resident, we must keep it intact.
- if (keep)
- {
- check= check->clone(thd);
- if (!check)
- {
- my_error(ER_OUT_OF_RESOURCES, MYF(0));
- goto err;
- }
- }
-
if (share->period.constr_name.streq(check->name.str))
{
- if (drop_period)
- {
- keep= false;
- }
- else if(!keep)
+ if (!drop_period && !keep)
{
my_error(ER_PERIOD_CONSTRAINT_DROP, MYF(0), check->name.str,
share->period.name.str);
goto err;
}
- else
+ keep= keep && !drop_period;
+
+ DBUG_ASSERT(create_info->period_info.constr == NULL || drop_period);
+
+ if (keep)
{
- DBUG_ASSERT(create_info->period_info.constr == NULL);
+ Item *expr_copy= check->expr->get_copy(thd);
+ check= new Virtual_column_info();
+ check->name= share->period.constr_name;
+ check->automatic_name= true;
+ check->expr= expr_copy;
create_info->period_info.constr= check;
- create_info->period_info.constr->automatic_name= true;
}
}
-
/* see if the constraint depends on *only* on dropped fields */
if (keep && dropped_fields)
{
diff --git a/sql/unireg.cc b/sql/unireg.cc
index 17222efe791..8e432c54b15 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -57,13 +57,7 @@ static bool make_empty_rec(THD *, uchar *, uint, List<Create_field> &, uint,
*/
static uchar *extra2_write_len(uchar *pos, size_t len)
{
- /* TODO: should be
- if (len > 0 && len <= 255)
- *pos++= (uchar)len;
- ...
- because extra2_read_len() uses 0 for 2-byte lengths.
- extra2_str_size() must be fixed too.
- */
+ DBUG_ASSERT(len);
if (len <= 255)
*pos++= (uchar)len;
else