maria-developers team mailing list archive
-
maria-developers team
-
Mailing list archive
-
Message #13188
review for (MDEV-28632) bugfix: DEFAULT NULL was allowed for NOT NULL columns
Hello Sergei,
commit 5a362d486b30fdaf3c7a360737331767154b4ee8
Author: Sergei Golubchik <serg@xxxxxxxxxxx>
Date: Mon Jul 18 22:53:27 2022 +0200
bugfix: DEFAULT NULL was allowed for NOT NULL columns
this was detected during parsing (so NOT NULL DEFAULT NULL was an error),
but if a column was made NOT NULL later (e.g. as a part of primary key,
in mysql_prepare_create_table()), DEFAULT NULL was accepted and ignored.
to fix this the NOT NULL DEFAULT NULL was moved into
mysql_prepare_create_table().
I'm not sure that in case of auto_increment we
should really disallow DEFAULT NULL under terms of this TIMESTAMP task.
Look at this script:
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY);
INSERT INTO t1 VALUES (NULL);
Query OK, 1 row affected (0.012 sec)
NULL can be inserted without errors.
Yes, it's inserted with a side effect -
it's replaced to the next auto increment value.
But why this side effect makes NULL an invalid default?
Note, I'm not against this change. Stricter behavior is good :)
But I'm worried that:
- It can break compatibility on one hand.
- It goes without it's own MDEV on the other hand.
This change deserves it's own MDEV
(with motivation and consequences explained)
and should be properly documented and mentioned in release notes.
<cut>
index 712b8629c09..d8471894db9 100644
--- a/mysql-test/main/view.result
+++ b/mysql-test/main/view.result
@@ -4082,12 +4082,12 @@ DROP TABLE t1,t2;
# MDEV-6251: SIGSEGV in query optimizer (in set_check_materialized
# with MERGE view)
#
-CREATE TABLE t1 (a1 INT(11) NOT NULL DEFAULT NULL AUTO_INCREMENT PRIMARY KEY);
-CREATE TABLE t2 (b1 INT(11) NOT NULL DEFAULT NULL AUTO_INCREMENT PRIMARY KEY);
-CREATE TABLE t3 (c1 INT(11) NOT NULL DEFAULT NULL AUTO_INCREMENT PRIMARY KEY);
-CREATE TABLE t4 (d1 INT(11) NOT NULL DEFAULT NULL AUTO_INCREMENT PRIMARY KEY);
-CREATE TABLE t5 (e1 INT(11) NOT NULL DEFAULT NULL AUTO_INCREMENT PRIMARY KEY);
-CREATE TABLE t6 (f1 INT(11) NOT NULL DEFAULT NULL AUTO_INCREMENT PRIMARY KEY);
+CREATE TABLE t1 (a1 INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY);
+CREATE TABLE t2 (b1 INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY);
+CREATE TABLE t3 (c1 INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY);
+CREATE TABLE t4 (d1 INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY);
+CREATE TABLE t5 (e1 INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY);
+CREATE TABLE t6 (f1 INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY);
It seems you removed all cases with the old syntax.
So now it's not recorded in MTR what happens on this statement:
CREATE TABLE t1 (a INT NOT NULL DEFAULT NULL AUTO_INCREMENT PRIMARY KEY);
Please cover this scenario in some relevant *.test file.
<cut>
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index cf0bbfb1130..3eeabe20c71 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
<cut>
@@ -3647,6 +3643,15 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
{
Field::utype type= (Field::utype) MTYP_TYPENR(sql_field->unireg_check);
+ if (sql_field->default_value &&
+ sql_field->default_value->expr->type() == Item::NULL_ITEM &&
+ sql_field->flags & NOT_NULL_FLAG &&
+ !(sql_field->flags & AUTO_INCREMENT_FLAG))
+ {
+ my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name.str);
+ DBUG_RETURN(TRUE);
+ }
^^^ now obvious errors are caught only during EXECUTE,
although it's already clear at the PREPARE stage that the DEFAULT is wrong:
MariaDB [test]> PREPARE stmt FROM 'CREATE TABLE T1 (a INT NOT NULL
DEFAULT NULL)';
Query OK, 0 rows affected (0.000 sec)
Statement prepared
MariaDB [test]> EXECUTE stmt;
ERROR 1067 (42000): Invalid default value for 'a'
I suggest we still catch non-unambiguous cases
(when nothing depends on system variables) during PREPARE.
Inside some existing or a new Type_handler method.
Also, please add PS tests:
- for unambiguous scenarios like here
- for ambiguous scenarios, e.g. with TIMESTAMP columns changing
OPTION_EXPLICIT_DEF_TIMESTAMP between PREPARE and EXECUTE.
It seems this code needs to be changed:
/*
Set NO_DEFAULT_VALUE_FLAG if this field doesn't have a default value and
it is NOT NULL, not an AUTO_INCREMENT field, not a TIMESTAMP and not
updated trough a NOW() function.
*/
if (!sql_field->default_value &&
!sql_field->has_default_function() &&
(sql_field->flags & NOT_NULL_FLAG) &&
(!sql_field->is_timestamp_type() ||
(thd->variables.option_bits & OPTION_EXPLICIT_DEF_TIMESTAMP))&&
!sql_field->vers_sys_field())
{
sql_field->flags|= NO_DEFAULT_VALUE_FLAG;
sql_field->pack_flag|= FIELDFLAG_NO_DEFAULT;
}
It can only add NO DEFAULT related flags.
Shouldn't it also remove NO DEFAULT flags
if the current PS EXECUTE time option OPTION_EXPLICIT_DEF_TIMESTAMP
is unset?
<cut>
diff --git a/storage/spider/mysql-test/spider/bg/t/spider_fixes.test b/storage/spider/mysql-test/spider/bg/t/spider_fixes.test
index b222f494ba1..41f87e61416 100644
--- a/storage/spider/mysql-test/spider/bg/t/spider_fixes.test
+++ b/storage/spider/mysql-test/spider/bg/t/spider_fixes.test
@@ -294,14 +294,14 @@ if ($USE_CHILD_GROUP2)
--disable_query_log
echo CREATE TABLE ta_l (
a int(11) NOT NULL DEFAULT '0',
- b char(1) DEFAULT NULL,
- c datetime DEFAULT NULL,
+ b char(1),
+ c datetime,
PRIMARY KEY (a, b, c)
) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT5_2_1;
eval CREATE TABLE ta_l (
a int(11) NOT NULL DEFAULT '0',
- b char(1) DEFAULT NULL,
- c datetime DEFAULT NULL,
+ b char(1),
+ c datetime,
PRIMARY KEY (a, b, c)
) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT5_2_1;
--enable_query_log
Why this change ^^^ ?
diff --git a/storage/spider/mysql-test/spider/t/spider_fixes.test b/storage/spider/mysql-test/spider/t/spider_fixes.test
index 47bc225d614..75f108f1164 100644
--- a/storage/spider/mysql-test/spider/t/spider_fixes.test
+++ b/storage/spider/mysql-test/spider/t/spider_fixes.test
@@ -294,14 +294,14 @@ if ($USE_CHILD_GROUP2)
--disable_query_log
echo CREATE TABLE ta_l (
a int(11) NOT NULL DEFAULT '0',
- b char(1) DEFAULT NULL,
- c datetime DEFAULT NULL,
+ b char(1),
+ c datetime,
PRIMARY KEY (a, b, c)
) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT5_2_1;
eval CREATE TABLE ta_l (
a int(11) NOT NULL DEFAULT '0',
- b char(1) DEFAULT NULL,
- c datetime DEFAULT NULL,
+ b char(1),
+ c datetime,
PRIMARY KEY (a, b, c)
) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT5_2_1;
--enable_query_log
Same question.
Follow ups