From e3816cb461ed9ca617436e36c01745c359b7ef21 Mon Sep 17 00:00:00 2001 From: "dlenev@mysql.com" <> Date: Fri, 30 Jan 2004 15:13:19 +0300 Subject: [PATCH] Fix for bugs #1885, #2464, #2539. Proper handling of default values for TIMESTAMP columns. The solution is not perfect since we just silently ignoring default value for first TIMESTAMP column and properly reflecting this fact in SHOW CREATE TABLE. We can't give a warning or simply support standard syntax (niladic functions as legal value for default) for first field since it is 4.0 tree. --- mysql-test/r/type_timestamp.result | 47 ++++++++++++++++++++++++++++-- mysql-test/t/type_timestamp.test | 33 +++++++++++++++++++-- sql/field.cc | 3 +- sql/field.h | 5 +++- sql/sql_parse.cc | 12 ++++---- sql/sql_show.cc | 14 +++++++-- 6 files changed, 98 insertions(+), 16 deletions(-) diff --git a/mysql-test/r/type_timestamp.result b/mysql-test/r/type_timestamp.result index b513f958787..cd45bcf911d 100644 --- a/mysql-test/r/type_timestamp.result +++ b/mysql-test/r/type_timestamp.result @@ -122,5 +122,48 @@ t2 t4 t6 t8 t10 t12 t14 0000-00-00 00:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00 1997-12-31 23:47:59 1997-12-31 23:47:59 1997-12-31 23:47:59 1997-12-31 23:47:59 1997-12-31 23:47:59 1997-12-31 23:47:59 1997-12-31 23:47:59 drop table t1; -create table t1 (a timestamp default 1); -Invalid default value for 'a' +create table t1 (t1 timestamp default '2003-01-01 00:00:00', +t2 timestamp default '2003-01-01 00:00:00'); +set TIMESTAMP=1000000000; +insert into t1 values(); +select * from t1; +t1 t2 +2001-09-09 04:46:40 2003-01-01 00:00:00 +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `t1` timestamp(14) NOT NULL, + `t2` timestamp(14) NOT NULL default '2003-01-01 00:00:00' +) TYPE=MyISAM +show columns from t1; +Field Type Null Key Default Extra +t1 timestamp(14) YES NULL +t2 timestamp(14) YES 2003-01-01 00:00:00 +show columns from t1 like 't2'; +Field Type Null Key Default Extra +t2 timestamp(14) YES 2003-01-01 00:00:00 +create table t2 (select * from t1); +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `t1` timestamp(14) NOT NULL, + `t2` timestamp(14) NOT NULL default '2003-01-01 00:00:00' +) TYPE=MyISAM +alter table t1 add column t0 timestamp first; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `t0` timestamp(14) NOT NULL, + `t1` timestamp(14) NOT NULL default '2003-01-01 00:00:00', + `t2` timestamp(14) NOT NULL default '2003-01-01 00:00:00' +) TYPE=MyISAM +drop table t1,t2; +create table t1 (ts1 timestamp, ts2 timestamp); +set TIMESTAMP=1000000000; +insert into t1 values (); +insert into t1 values (DEFAULT, DEFAULT); +select * from t1; +ts1 ts2 +2001-09-09 04:46:40 0000-00-00 00:00:00 +2001-09-09 04:46:40 0000-00-00 00:00:00 +drop table t1; diff --git a/mysql-test/t/type_timestamp.test b/mysql-test/t/type_timestamp.test index 17f7b7c487f..3483227376e 100644 --- a/mysql-test/t/type_timestamp.test +++ b/mysql-test/t/type_timestamp.test @@ -73,8 +73,35 @@ select * from t1; drop table t1; # -# Bug #1885 +# Bug #1885, bug #2539. +# Not perfect but still sensible attitude towards defaults for TIMESTAMP +# We will ignore default value for first TIMESTAMP column. +# +create table t1 (t1 timestamp default '2003-01-01 00:00:00', + t2 timestamp default '2003-01-01 00:00:00'); +set TIMESTAMP=1000000000; +insert into t1 values(); +select * from t1; +show create table t1; +show columns from t1; +show columns from t1 like 't2'; +create table t2 (select * from t1); +show create table t2; + +# Ugly, but we can't do anything about this in 4.0 +alter table t1 add column t0 timestamp first; +show create table t1; + +drop table t1,t2; + +# +# Test for bug 2464, DEFAULT keyword in INSERT statement should return +# default value for column. # ---error 1067 -create table t1 (a timestamp default 1); +create table t1 (ts1 timestamp, ts2 timestamp); +set TIMESTAMP=1000000000; +insert into t1 values (); +insert into t1 values (DEFAULT, DEFAULT); +select * from t1; +drop table t1; diff --git a/sql/field.cc b/sql/field.cc index 8bcbf8ecc56..687c22bb69b 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5124,8 +5124,7 @@ create_field::create_field(Field *old_field,Field *orig_field) interval=0; def=0; if (!old_field->is_real_null() && ! (flags & BLOB_FLAG) && - old_field->type() != FIELD_TYPE_TIMESTAMP && old_field->ptr && - orig_field) + old_field->ptr && orig_field) { char buff[MAX_FIELD_WIDTH],*pos; String tmp(buff,sizeof(buff)); diff --git a/sql/field.h b/sql/field.h index 413a08f08d4..6f049e3809e 100644 --- a/sql/field.h +++ b/sql/field.h @@ -564,7 +564,10 @@ public: void set_time(); virtual void set_default() { - set_time(); + if (table->timestamp_field == this) + set_time(); + else + Field::set_default(); } inline long get_timestamp() { diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 608cdd23282..69257913b5b 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3056,12 +3056,12 @@ bool add_field_to_list(char *field_name, enum_field_types type, if (default_value) { - if (type == FIELD_TYPE_TIMESTAMP) - { - net_printf(&thd->net, ER_INVALID_DEFAULT, field_name); - DBUG_RETURN(1); - } - else if (default_value->type() == Item::NULL_ITEM) + /* + We allow specifying value for first TIMESTAMP column + altough it is silently ignored. This should be fixed in 4.1 + (by proper warning or real support for default values) + */ + if (default_value->type() == Item::NULL_ITEM) { default_value=0; if ((type_modifier & (NOT_NULL_FLAG | AUTO_INCREMENT_FLAG)) == diff --git a/sql/sql_show.cc b/sql/sql_show.cc index d34e2e68067..1aca352a894 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -508,6 +508,12 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild, field->sql_type(type); net_store_data(packet,convert,type.ptr(),type.length()); + /* + Altough TIMESTAMP fields can't contain NULL as its value they + will accept NULL if you will try to insert such value and will + convert it to current TIMESTAMP. So YES here means that NULL + is allowed for assignment but can't be returned. + */ pos=(byte*) ((flags & NOT_NULL_FLAG) && field->type() != FIELD_TYPE_TIMESTAMP ? "" : "YES"); @@ -517,7 +523,11 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild, (field->flags & MULTIPLE_KEY_FLAG) ? "MUL":""); net_store_data(packet,convert,(char*) pos); - if (field->type() == FIELD_TYPE_TIMESTAMP || + /* + We handle first TIMESTAMP column in special way because its + default value is ignored and current timestamp used instead. + */ + if (table->timestamp_field == field || field->unireg_check == Field::NEXT_NUMBER) null_default_value=1; if (!null_default_value && !field->is_null()) @@ -888,7 +898,7 @@ store_create_info(THD *thd, TABLE *table, String *packet) packet->append(type.ptr(),type.length()); has_default= (field->type() != FIELD_TYPE_BLOB && - field->type() != FIELD_TYPE_TIMESTAMP && + table->timestamp_field != field && field->unireg_check != Field::NEXT_NUMBER); if (flags & NOT_NULL_FLAG) packet->append(" NOT NULL", 9);