From 5704c7fe2cf52fb8bec0f8e8006f7a4b181e1660 Mon Sep 17 00:00:00 2001
From: unknown <anozdrin/alik@quad.>
Date: Thu, 14 Feb 2008 18:13:40 +0300
Subject: [PATCH] A patch for Bug#18834: ALTER TABLE ADD INDEX on table with
 two timestamp fields.

The actual problem here was that CREATE TABLE allowed zero
date as a default value for a TIMESTAMP column in NO_ZERO_DATE mode.

The thing is that for TIMESTAMP date type specific rule is applied:
  column_name TIMESTAMP == column_name TIMESTAMP DEFAULT 0
whever for any other date data type
  column_name TYPE == column_name TYPE DEFAULT NULL

The fix is to raise an error when we're in NO_ZERO_DATE mode and
there is TIMESTAMP column w/o default value.


mysql-test/r/create.result:
  Update result file.
mysql-test/t/create.test:
  Test case for Bug#18834: ALTER TABLE ADD INDEX on table with
  two timestamp fields.
sql/sql_table.cc:
  Report an error if NO_ZERO_MODE is set and we have zero date
  as a default.
---
 mysql-test/r/create.result | 44 ++++++++++++++++++++++++++
 mysql-test/t/create.test   | 64 ++++++++++++++++++++++++++++++++++++++
 sql/sql_table.cc           | 31 ++++++++++++++++++
 3 files changed, 139 insertions(+)

diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result
index 4bdcca81b74..0dfc9c1e761 100644
--- a/mysql-test/r/create.result
+++ b/mysql-test/r/create.result
@@ -1789,4 +1789,48 @@ DROP TABLE t2;
 
 # -- End of test case for Bug#21380.
 
+# --
+# -- Bug#18834: ALTER TABLE ADD INDEX on table with two timestamp fields
+# --
+
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+DROP TABLE IF EXISTS t3;
+
+CREATE TABLE t1(c1 TIMESTAMP, c2 TIMESTAMP);
+
+SET sql_mode = NO_ZERO_DATE;
+
+CREATE TABLE t2(c1 TIMESTAMP, c2 TIMESTAMP DEFAULT 0);
+ERROR 42000: Invalid default value for 'c2'
+
+CREATE TABLE t2(c1 TIMESTAMP, c2 TIMESTAMP);
+ERROR 42000: Invalid default value for 'c2'
+
+# -- Check that NULL column still can be created.
+CREATE TABLE t2(c1 TIMESTAMP NULL);
+
+# -- Check ALTER TABLE.
+ALTER TABLE t1 ADD INDEX(c1);
+ERROR 42000: Invalid default value for 'c2'
+
+# -- Check DATETIME.
+SET sql_mode = '';
+
+CREATE TABLE t3(c1 DATETIME NOT NULL);
+INSERT INTO t3 VALUES (0);
+
+SET sql_mode = TRADITIONAL;
+
+ALTER TABLE t3 ADD INDEX(c1);
+ERROR 22007: Incorrect datetime value: '0000-00-00 00:00:00' for column 'c1' at row 1
+
+# -- Cleanup.
+SET sql_mode = '';
+DROP TABLE t1;
+DROP TABLE t2;
+DROP TABLE t3;
+
+# -- End of Bug#18834.
+
 End of 5.1 tests
diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test
index 09170cbc4f5..8912fd46b42 100644
--- a/mysql-test/t/create.test
+++ b/mysql-test/t/create.test
@@ -1385,4 +1385,68 @@ DROP TABLE t2;
 --echo # -- End of test case for Bug#21380.
 --echo
 
+--echo # --
+--echo # -- Bug#18834: ALTER TABLE ADD INDEX on table with two timestamp fields
+--echo # --
+--echo
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+DROP TABLE IF EXISTS t3;
+--enable_warnings
+
+--echo
+
+CREATE TABLE t1(c1 TIMESTAMP, c2 TIMESTAMP);
+
+--echo
+
+SET sql_mode = NO_ZERO_DATE;
+
+--echo
+--error ER_INVALID_DEFAULT
+CREATE TABLE t2(c1 TIMESTAMP, c2 TIMESTAMP DEFAULT 0);
+
+--echo
+--error ER_INVALID_DEFAULT
+CREATE TABLE t2(c1 TIMESTAMP, c2 TIMESTAMP);
+
+--echo
+--echo # -- Check that NULL column still can be created.
+CREATE TABLE t2(c1 TIMESTAMP NULL);
+
+--echo
+--echo # -- Check ALTER TABLE.
+--error ER_INVALID_DEFAULT
+ALTER TABLE t1 ADD INDEX(c1);
+
+--echo
+--echo # -- Check DATETIME.
+SET sql_mode = '';
+
+--echo
+
+CREATE TABLE t3(c1 DATETIME NOT NULL);
+INSERT INTO t3 VALUES (0);
+
+--echo
+SET sql_mode = TRADITIONAL;
+
+--echo
+--error ER_TRUNCATED_WRONG_VALUE
+ALTER TABLE t3 ADD INDEX(c1);
+
+--echo
+--echo # -- Cleanup.
+
+SET sql_mode = '';
+DROP TABLE t1;
+DROP TABLE t2;
+DROP TABLE t3;
+
+--echo
+--echo # -- End of Bug#18834.
+--echo
+
 --echo End of 5.1 tests
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 505bcd1b421..05c73044ddd 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -3001,6 +3001,37 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
 	   (qsort_cmp) sort_keys);
   create_info->null_bits= null_fields;
 
+  /* Check fields. */
+  it.rewind();
+  while ((sql_field=it++))
+  {
+    Field::utype type= (Field::utype) MTYP_TYPENR(sql_field->unireg_check);
+
+    if (thd->variables.sql_mode & MODE_NO_ZERO_DATE &&
+        !sql_field->def &&
+        sql_field->sql_type == MYSQL_TYPE_TIMESTAMP &&
+        (sql_field->flags & NOT_NULL_FLAG) &&
+        (type == Field::NONE || type == Field::TIMESTAMP_UN_FIELD))
+    {
+      /*
+        An error should be reported if:
+          - NO_ZERO_DATE SQL mode is active;
+          - there is no explicit DEFAULT clause (default column value);
+          - this is a TIMESTAMP column;
+          - the column is not NULL;
+          - this is not the DEFAULT CURRENT_TIMESTAMP column.
+
+        In other words, an error should be reported if
+          - NO_ZERO_DATE SQL mode is active;
+          - the column definition is equivalent to
+            'column_name TIMESTAMP DEFAULT 0'.
+      */
+
+      my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
+      DBUG_RETURN(TRUE);
+    }
+  }
+
   DBUG_RETURN(FALSE);
 }
 
-- 
2.30.9