← Back to team overview

maria-developers team mailing list archive

MDEV-8441 Bad SHOW CREATE TABLE output for a table with a virtual column

 

Hi Sanja,

Please review a patch for MDEV-8441.

Thanks.
diff --git a/mysql-test/suite/vcol/r/vcol_misc.result b/mysql-test/suite/vcol/r/vcol_misc.result
index 521952f..e68adf8 100644
--- a/mysql-test/suite/vcol/r/vcol_misc.result
+++ b/mysql-test/suite/vcol/r/vcol_misc.result
@@ -322,3 +322,29 @@ drop table t1;
 create table t1 (a int, b int as (b is null) virtual);
 ERROR HY000: A computed column cannot be based on a computed column
 # end of 5.3 tests
+#
+# Start of 10.1 tests
+#
+#
+# MDEV-8441 Bad SHOW CREATE TABLE output for a table with a virtual column
+#
+CREATE TABLE t1 (a DATETIME, b TIMESTAMP AS (TIMESTAMP(a)));
+SHOW CREATE TABLE t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `a` datetime DEFAULT NULL,
+  `b` timestamp AS (TIMESTAMP(a)) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1 (a DATETIME, b TIMESTAMP AS (TIMESTAMP(a)),c TIMESTAMP);
+SHOW CREATE TABLE t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `a` datetime DEFAULT NULL,
+  `b` timestamp AS (TIMESTAMP(a)) VIRTUAL,
+  `c` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+#
+# End of 10.1 tests
+#
diff --git a/mysql-test/suite/vcol/r/vcol_supported_sql_funcs_innodb.result b/mysql-test/suite/vcol/r/vcol_supported_sql_funcs_innodb.result
index 899a19c..c2b601f 100644
--- a/mysql-test/suite/vcol/r/vcol_supported_sql_funcs_innodb.result
+++ b/mysql-test/suite/vcol/r/vcol_supported_sql_funcs_innodb.result
@@ -2539,7 +2539,7 @@ show create table t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
   `a` datetime DEFAULT NULL,
-  `b` timestamp AS (timestamp(a)) VIRTUAL NULL ON UPDATE CURRENT_TIMESTAMP
+  `b` timestamp AS (timestamp(a)) VIRTUAL
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1
 insert into t1 values ('2008-12-31',default);
 select * from t1;
@@ -2554,7 +2554,7 @@ show create table t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
   `a` datetime DEFAULT NULL,
-  `b` timestamp AS (timestampadd(minute,1,a)) VIRTUAL NULL ON UPDATE CURRENT_TIMESTAMP
+  `b` timestamp AS (timestampadd(minute,1,a)) VIRTUAL
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1
 insert into t1 values ('2003-01-02',default);
 select * from t1;
diff --git a/mysql-test/suite/vcol/r/vcol_supported_sql_funcs_myisam.result b/mysql-test/suite/vcol/r/vcol_supported_sql_funcs_myisam.result
index 0034f25..ac48c28 100644
--- a/mysql-test/suite/vcol/r/vcol_supported_sql_funcs_myisam.result
+++ b/mysql-test/suite/vcol/r/vcol_supported_sql_funcs_myisam.result
@@ -2539,7 +2539,7 @@ show create table t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
   `a` datetime DEFAULT NULL,
-  `b` timestamp AS (timestamp(a)) VIRTUAL NULL ON UPDATE CURRENT_TIMESTAMP
+  `b` timestamp AS (timestamp(a)) VIRTUAL
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
 insert into t1 values ('2008-12-31',default);
 select * from t1;
@@ -2554,7 +2554,7 @@ show create table t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
   `a` datetime DEFAULT NULL,
-  `b` timestamp AS (timestampadd(minute,1,a)) VIRTUAL NULL ON UPDATE CURRENT_TIMESTAMP
+  `b` timestamp AS (timestampadd(minute,1,a)) VIRTUAL
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
 insert into t1 values ('2003-01-02',default);
 select * from t1;
diff --git a/mysql-test/suite/vcol/t/vcol_misc.test b/mysql-test/suite/vcol/t/vcol_misc.test
index a4c1fc0..38f8670 100644
--- a/mysql-test/suite/vcol/t/vcol_misc.test
+++ b/mysql-test/suite/vcol/t/vcol_misc.test
@@ -283,3 +283,25 @@ drop table t1;
 create table t1 (a int, b int as (b is null) virtual);
 
 --echo # end of 5.3 tests
+
+
+--echo #
+--echo # Start of 10.1 tests
+--echo #
+
+--echo #
+--echo # MDEV-8441 Bad SHOW CREATE TABLE output for a table with a virtual column
+--echo #
+CREATE TABLE t1 (a DATETIME, b TIMESTAMP AS (TIMESTAMP(a)));
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+# Make sure that if the first TIMESTAMP column appears to be virtual,
+# then no further promotion is done, so the next TIMESTAMP column "c" does not
+# get the "DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" attributes.
+CREATE TABLE t1 (a DATETIME, b TIMESTAMP AS (TIMESTAMP(a)),c TIMESTAMP);
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+--echo #
+--echo # End of 10.1 tests
+--echo #
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index eda8e2d..73a5b66 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1810,35 +1810,36 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet,
       else
         packet->append(STRING_WITH_LEN(" VIRTUAL"));
     }
-
-    if (flags & NOT_NULL_FLAG)
-      packet->append(STRING_WITH_LEN(" NOT NULL"));
-    else if (field->type() == MYSQL_TYPE_TIMESTAMP)
-    {
-      /*
-        TIMESTAMP field require explicit NULL flag, because unlike
-        all other fields they are treated as NOT NULL by default.
-      */
-      packet->append(STRING_WITH_LEN(" NULL"));
-    }
-
-    if (!field->vcol_info &&
-        get_field_default_value(thd, field, &def_value, 1))
+    else
     {
-      packet->append(STRING_WITH_LEN(" DEFAULT "));
-      packet->append(def_value.ptr(), def_value.length(), system_charset_info);
-    }
+      if (flags & NOT_NULL_FLAG)
+        packet->append(STRING_WITH_LEN(" NOT NULL"));
+      else if (field->type() == MYSQL_TYPE_TIMESTAMP)
+      {
+        /*
+          TIMESTAMP field require explicit NULL flag, because unlike
+          all other fields they are treated as NOT NULL by default.
+        */
+        packet->append(STRING_WITH_LEN(" NULL"));
+      }
 
-    if (!limited_mysql_mode && print_on_update_clause(field, &def_value, false))
-    {
-      packet->append(STRING_WITH_LEN(" "));
-      packet->append(def_value);
-    }
+      if (get_field_default_value(thd, field, &def_value, 1))
+      {
+        packet->append(STRING_WITH_LEN(" DEFAULT "));
+        packet->append(def_value.ptr(), def_value.length(), system_charset_info);
+      }
 
+      if (!limited_mysql_mode &&
+          print_on_update_clause(field, &def_value, false))
+      {
+        packet->append(STRING_WITH_LEN(" "));
+        packet->append(def_value);
+      }
 
-    if (field->unireg_check == Field::NEXT_NUMBER &&
-        !(sql_mode & MODE_NO_FIELD_OPTIONS))
-      packet->append(STRING_WITH_LEN(" AUTO_INCREMENT"));
+      if (field->unireg_check == Field::NEXT_NUMBER &&
+          !(sql_mode & MODE_NO_FIELD_OPTIONS))
+        packet->append(STRING_WITH_LEN(" AUTO_INCREMENT"));
+    }
 
     if (field->comment.length)
     {
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index d359727..ce4b01f 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -3061,6 +3061,9 @@ CHARSET_INFO* get_sql_field_charset(Create_field *sql_field,
    Modifies the first column definition whose SQL type is TIMESTAMP
    by adding the features DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP.
 
+   If the first TIMESTAMP column appears to be nullable, or to have an
+   explicit default, or to be a virtual column, then no promition is done.
+
    @param column_definitions The list of column definitions, in the physical
                              order in which they appear in the table.
  */
@@ -3076,7 +3079,8 @@ void promote_first_timestamp_column(List<Create_field> *column_definitions)
     {
       if ((column_definition->flags & NOT_NULL_FLAG) != 0 && // NOT NULL,
           column_definition->def == NULL &&            // no constant default,
-          column_definition->unireg_check == Field::NONE) // no function default
+          column_definition->unireg_check == Field::NONE && // no function default
+          column_definition->vcol_info == NULL)
       {
         DBUG_PRINT("info", ("First TIMESTAMP column '%s' was promoted to "
                             "DEFAULT CURRENT_TIMESTAMP ON UPDATE "

Follow ups