Commit 438811b4 authored by Monty's avatar Monty

Fixed two bugs related to column level constraints

- CREATE TABLE ... SELECT drops constraints for columns that
  are both in the create and select part.
  - Fixed by copying the constraint in
    Column_definiton::redefine_stage1_common()
- If one has both a default expression and check constraint for a
  column, one can get the error "Expression for field `a` is refering
  to uninitialized field `a`.
  - Fixed by ignoring default expressions for current column when checking
    for CHECK constraint
parent 44898d28
...@@ -111,3 +111,20 @@ long_enough_name CREATE TABLE `long_enough_name` ( ...@@ -111,3 +111,20 @@ long_enough_name CREATE TABLE `long_enough_name` (
CONSTRAINT `constr` CHECK (`f6` >= 0) CONSTRAINT `constr` CHECK (`f6` >= 0)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE long_enough_name; DROP TABLE long_enough_name;
create table t1 (a int check (a>10)) select 100 as 'a';
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL CHECK (`a` > 10)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a text default(length(now())) check (length(a) > 1));
insert into t1 values ();
insert into t1 values ("ccc");
insert into t1 values ("");
ERROR 23000: CONSTRAINT `t1.a` failed for `test`.`t1`
select * from t1;
a
19
ccc
drop table t1;
...@@ -102,3 +102,23 @@ SELECT * FROM long_enough_name AS tbl; ...@@ -102,3 +102,23 @@ SELECT * FROM long_enough_name AS tbl;
SHOW CREATE TABLE long_enough_name; SHOW CREATE TABLE long_enough_name;
DROP TABLE long_enough_name; DROP TABLE long_enough_name;
#
# Check that we don't loose constraints as part of CREATE ... SELECT
#
create table t1 (a int check (a>10)) select 100 as 'a';
show create table t1;
drop table t1;
#
# Check that we constraints on field with default expressions work
#
create table t1 (a text default(length(now())) check (length(a) > 1));
insert into t1 values ();
insert into t1 values ("ccc");
--error ER_CONSTRAINT_FAILED
insert into t1 values ("");
select * from t1;
drop table t1;
...@@ -11047,6 +11047,7 @@ Column_definition::redefine_stage1_common(const Column_definition *dup_field, ...@@ -11047,6 +11047,7 @@ Column_definition::redefine_stage1_common(const Column_definition *dup_field,
interval= dup_field->interval; interval= dup_field->interval;
vcol_info= dup_field->vcol_info; vcol_info= dup_field->vcol_info;
invisible= dup_field->invisible; invisible= dup_field->invisible;
check_constraint= dup_field->check_constraint;
} }
......
...@@ -51,7 +51,8 @@ ...@@ -51,7 +51,8 @@
static Virtual_column_info * unpack_vcol_info_from_frm(THD *, MEM_ROOT *, static Virtual_column_info * unpack_vcol_info_from_frm(THD *, MEM_ROOT *,
TABLE *, String *, Virtual_column_info **, bool *); TABLE *, String *, Virtual_column_info **, bool *);
static bool check_vcol_forward_refs(Field *, Virtual_column_info *); static bool check_vcol_forward_refs(Field *, Virtual_column_info *,
bool check_constraint);
/* INFORMATION_SCHEMA name */ /* INFORMATION_SCHEMA name */
LEX_CSTRING INFORMATION_SCHEMA_NAME= {STRING_WITH_LEN("information_schema")}; LEX_CSTRING INFORMATION_SCHEMA_NAME= {STRING_WITH_LEN("information_schema")};
...@@ -1135,9 +1136,9 @@ bool parse_vcol_defs(THD *thd, MEM_ROOT *mem_root, TABLE *table, ...@@ -1135,9 +1136,9 @@ bool parse_vcol_defs(THD *thd, MEM_ROOT *mem_root, TABLE *table,
for (field_ptr= table->field; *field_ptr; field_ptr++) for (field_ptr= table->field; *field_ptr; field_ptr++)
{ {
Field *field= *field_ptr; Field *field= *field_ptr;
if (check_vcol_forward_refs(field, field->vcol_info) || if (check_vcol_forward_refs(field, field->vcol_info, 0) ||
check_vcol_forward_refs(field, field->check_constraint) || check_vcol_forward_refs(field, field->check_constraint, 1) ||
check_vcol_forward_refs(field, field->default_value)) check_vcol_forward_refs(field, field->default_value, 0))
goto end; goto end;
} }
...@@ -3087,11 +3088,19 @@ unpack_vcol_info_from_frm(THD *thd, MEM_ROOT *mem_root, TABLE *table, ...@@ -3087,11 +3088,19 @@ unpack_vcol_info_from_frm(THD *thd, MEM_ROOT *mem_root, TABLE *table,
DBUG_RETURN(vcol_info); DBUG_RETURN(vcol_info);
} }
static bool check_vcol_forward_refs(Field *field, Virtual_column_info *vcol) static bool check_vcol_forward_refs(Field *field, Virtual_column_info *vcol,
bool check_constraint)
{ {
bool res= vcol && bool res;
vcol->expr->walk(&Item::check_field_expression_processor, 0, uint32 flags= field->flags;
field); if (check_constraint)
{
/* Check constraints can refer it itself */
field->flags|= NO_DEFAULT_VALUE_FLAG;
}
res= (vcol &&
vcol->expr->walk(&Item::check_field_expression_processor, 0, field));
field->flags= flags;
return res; return res;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment