diff --git a/mysql-test/include/function_defaults.inc b/mysql-test/include/function_defaults.inc index e588c82..5f8d160 100644 --- a/mysql-test/include/function_defaults.inc +++ b/mysql-test/include/function_defaults.inc @@ -246,6 +246,19 @@ INSERT INTO t1 VALUES (NULL, NULL, 1), (DEFAULT, DEFAULT, 2); INSERT INTO t1 ( a, b, c ) VALUES (NULL, NULL, 3), (DEFAULT, DEFAULT, 4); SELECT * FROM t1; +--echo # +--echo # Test that DEFAULT CURRENT_TIMESTAMP works after inserting explicit +--echo # values. +--echo # + +INSERT INTO t1 (c, a, b) + VALUES (10, '2011-04-20 07:05:39.195624', '2011-04-20 07:05:39.195624'); +SELECT * FROM t1; + +INSERT INTO t1 (c) VALUES (20); +SELECT * FROM t1; + + SET TIME_ZONE = "+03:00"; SELECT * FROM t1; SET TIME_ZONE = "+00:00"; @@ -408,14 +421,41 @@ UPDATE t1 SET c = 2; SELECT * FROM t1; --echo # +--echo # Test that ON UPDATE CURRENT_TIMESTAMP works after non-changing UPDATE. +--echo # + +--echo # 2011-04-20 09:54:13 UTC +SET TIMESTAMP = 1303293253.794613; + +UPDATE t1 SET c = 2, b = '2011-04-20 09:53:41.794613'; +SELECT * FROM t1; + +UPDATE t1 SET c = 3; +SELECT * FROM t1; + +--echo # --echo # Test of multiple-table UPDATE for ON UPDATE CURRENT_TIMESTAMP --echo # --echo # 2011-04-20 15:06:13 UTC SET TIMESTAMP = 1303311973.534231; +UPDATE t1 t11, t1 t12 SET t11.c = 3; +SELECT * FROM t1; + UPDATE t1 t11, t1 t12 SET t11.c = 2; SELECT * FROM t1; +--echo # +--echo # Test that ON UPDATE CURRENT_TIMESTAMP with multiple-table UPDATE +--echo # works after non-changing UPDATE. +--echo # + +--echo # 2011-04-20 09:54:13 UTC +SET TIMESTAMP = 1303293253.794613; + +UPDATE t1 t11, t1 t12 SET t11.c = 2, t11.b = '2011-04-20 15:06:13.534231'; +SELECT * FROM t1; + UPDATE t1 t11, t1 t12 SET t11.c = 3; SELECT * FROM t1; diff --git a/mysql-test/r/function_defaults.result b/mysql-test/r/function_defaults.result index 27b9ee0..ec2b63d 100644 --- a/mysql-test/r/function_defaults.result +++ b/mysql-test/r/function_defaults.result @@ -264,6 +264,28 @@ a b c 2011-04-20 09:53:41 2011-04-20 09:53:41 2 2011-04-20 09:53:41 NULL 3 2011-04-20 09:53:41 2011-04-20 09:53:41 4 +# +# Test that DEFAULT CURRENT_TIMESTAMP works after inserting explicit +# values. +# +INSERT INTO t1 (c, a, b) +VALUES (10, '2011-04-20 07:05:39.195624', '2011-04-20 07:05:39.195624'); +SELECT * FROM t1; +a b c +2011-04-20 09:53:41 NULL 1 +2011-04-20 09:53:41 2011-04-20 09:53:41 2 +2011-04-20 09:53:41 NULL 3 +2011-04-20 09:53:41 2011-04-20 09:53:41 4 +2011-04-20 07:05:39 2011-04-20 07:05:39 10 +INSERT INTO t1 (c) VALUES (20); +SELECT * FROM t1; +a b c +2011-04-20 09:53:41 NULL 1 +2011-04-20 09:53:41 2011-04-20 09:53:41 2 +2011-04-20 09:53:41 NULL 3 +2011-04-20 09:53:41 2011-04-20 09:53:41 4 +2011-04-20 07:05:39 2011-04-20 07:05:39 10 +2011-04-20 09:53:41 2011-04-20 09:53:41 20 SET TIME_ZONE = "+03:00"; SELECT * FROM t1; a b c @@ -271,6 +293,8 @@ a b c 2011-04-20 12:53:41 2011-04-20 09:53:41 2 2011-04-20 12:53:41 NULL 3 2011-04-20 12:53:41 2011-04-20 09:53:41 4 +2011-04-20 10:05:39 2011-04-20 07:05:39 10 +2011-04-20 12:53:41 2011-04-20 09:53:41 20 SET TIME_ZONE = "+00:00"; DROP TABLE t1; # 2011-04-20 07:05:39 UTC @@ -435,18 +459,45 @@ SELECT * FROM t1; a b c 2011-04-20 09:53:41 2011-04-20 09:53:41 2 # +# Test that ON UPDATE CURRENT_TIMESTAMP works after non-changing UPDATE. +# +# 2011-04-20 09:54:13 UTC +SET TIMESTAMP = 1303293253.794613; +UPDATE t1 SET c = 2, b = '2011-04-20 09:53:41.794613'; +SELECT * FROM t1; +a b c +2011-04-20 09:53:41 2011-04-20 09:53:41 2 +UPDATE t1 SET c = 3; +SELECT * FROM t1; +a b c +2011-04-20 09:54:13 2011-04-20 09:54:13 3 +# # Test of multiple-table UPDATE for ON UPDATE CURRENT_TIMESTAMP # # 2011-04-20 15:06:13 UTC SET TIMESTAMP = 1303311973.534231; +UPDATE t1 t11, t1 t12 SET t11.c = 3; +SELECT * FROM t1; +a b c +2011-04-20 09:54:13 2011-04-20 09:54:13 3 UPDATE t1 t11, t1 t12 SET t11.c = 2; SELECT * FROM t1; a b c -2011-04-20 09:53:41 2011-04-20 09:53:41 2 +2011-04-20 15:06:13 2011-04-20 15:06:13 2 +# +# Test that ON UPDATE CURRENT_TIMESTAMP with multiple-table UPDATE +# works after non-changing UPDATE. +# +# 2011-04-20 09:54:13 UTC +SET TIMESTAMP = 1303293253.794613; +UPDATE t1 t11, t1 t12 SET t11.c = 2, t11.b = '2011-04-20 15:06:13.534231'; +SELECT * FROM t1; +a b c +2011-04-20 15:06:13 2011-04-20 15:06:13 2 UPDATE t1 t11, t1 t12 SET t11.c = 3; SELECT * FROM t1; a b c -2011-04-20 15:06:13 2011-04-20 15:06:13 3 +2011-04-20 09:54:13 2011-04-20 09:54:13 3 DROP TABLE t1; # # Test of a multiple-table update where only one table is updated and @@ -1796,6 +1847,28 @@ a b c 2011-04-20 09:53:41.163578 2011-04-20 09:53:41.163578 2 2011-04-20 09:53:41.163578 NULL 3 2011-04-20 09:53:41.163578 2011-04-20 09:53:41.163578 4 +# +# Test that DEFAULT CURRENT_TIMESTAMP works after inserting explicit +# values. +# +INSERT INTO t1 (c, a, b) +VALUES (10, '2011-04-20 07:05:39.195624', '2011-04-20 07:05:39.195624'); +SELECT * FROM t1; +a b c +2011-04-20 09:53:41.163578 NULL 1 +2011-04-20 09:53:41.163578 2011-04-20 09:53:41.163578 2 +2011-04-20 09:53:41.163578 NULL 3 +2011-04-20 09:53:41.163578 2011-04-20 09:53:41.163578 4 +2011-04-20 07:05:39.195624 2011-04-20 07:05:39.195624 10 +INSERT INTO t1 (c) VALUES (20); +SELECT * FROM t1; +a b c +2011-04-20 09:53:41.163578 NULL 1 +2011-04-20 09:53:41.163578 2011-04-20 09:53:41.163578 2 +2011-04-20 09:53:41.163578 NULL 3 +2011-04-20 09:53:41.163578 2011-04-20 09:53:41.163578 4 +2011-04-20 07:05:39.195624 2011-04-20 07:05:39.195624 10 +2011-04-20 09:53:41.163578 2011-04-20 09:53:41.163578 20 SET TIME_ZONE = "+03:00"; SELECT * FROM t1; a b c @@ -1803,6 +1876,8 @@ a b c 2011-04-20 12:53:41.163578 2011-04-20 09:53:41.163578 2 2011-04-20 12:53:41.163578 NULL 3 2011-04-20 12:53:41.163578 2011-04-20 09:53:41.163578 4 +2011-04-20 10:05:39.195624 2011-04-20 07:05:39.195624 10 +2011-04-20 12:53:41.163578 2011-04-20 09:53:41.163578 20 SET TIME_ZONE = "+00:00"; DROP TABLE t1; # 2011-04-20 07:05:39 UTC @@ -1967,18 +2042,45 @@ SELECT * FROM t1; a b c 2011-04-20 09:53:41.794613 2011-04-20 09:53:41.794613 2 # +# Test that ON UPDATE CURRENT_TIMESTAMP works after non-changing UPDATE. +# +# 2011-04-20 09:54:13 UTC +SET TIMESTAMP = 1303293253.794613; +UPDATE t1 SET c = 2, b = '2011-04-20 09:53:41.794613'; +SELECT * FROM t1; +a b c +2011-04-20 09:53:41.794613 2011-04-20 09:53:41.794613 2 +UPDATE t1 SET c = 3; +SELECT * FROM t1; +a b c +2011-04-20 09:54:13.794613 2011-04-20 09:54:13.794613 3 +# # Test of multiple-table UPDATE for ON UPDATE CURRENT_TIMESTAMP # # 2011-04-20 15:06:13 UTC SET TIMESTAMP = 1303311973.534231; +UPDATE t1 t11, t1 t12 SET t11.c = 3; +SELECT * FROM t1; +a b c +2011-04-20 09:54:13.794613 2011-04-20 09:54:13.794613 3 UPDATE t1 t11, t1 t12 SET t11.c = 2; SELECT * FROM t1; a b c -2011-04-20 09:53:41.794613 2011-04-20 09:53:41.794613 2 +2011-04-20 15:06:13.534231 2011-04-20 15:06:13.534231 2 +# +# Test that ON UPDATE CURRENT_TIMESTAMP with multiple-table UPDATE +# works after non-changing UPDATE. +# +# 2011-04-20 09:54:13 UTC +SET TIMESTAMP = 1303293253.794613; +UPDATE t1 t11, t1 t12 SET t11.c = 2, t11.b = '2011-04-20 15:06:13.534231'; +SELECT * FROM t1; +a b c +2011-04-20 15:06:13.534231 2011-04-20 15:06:13.534231 2 UPDATE t1 t11, t1 t12 SET t11.c = 3; SELECT * FROM t1; a b c -2011-04-20 15:06:13.534231 2011-04-20 15:06:13.534231 3 +2011-04-20 09:54:13.794613 2011-04-20 09:54:13.794613 3 DROP TABLE t1; # # Test of a multiple-table update where only one table is updated and diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index e771e57..ceff447 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -870,6 +870,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, while ((values= its++)) { + table->reset_default_fields(); + if (fields.elements || !value_count) { restore_record(table,s->default_values); // Get empty record @@ -1699,6 +1701,9 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) if (info->handle_duplicates == DUP_UPDATE) { int res= 0; + + table->reset_default_fields(); + /* We don't check for other UNIQUE keys - the first row that matches, is updated. If update causes a conflict again, @@ -3522,6 +3527,8 @@ select_insert::prepare(List &values, SELECT_LEX_UNIT *u) restore_record(table,s->default_values); // Get empty record table->next_number_field=table->found_next_number_field; + table->reset_default_fields(); + #ifdef HAVE_REPLICATION if (thd->rgi_slave && (info.handle_duplicates == DUP_UPDATE) && diff --git a/sql/sql_load.cc b/sql/sql_load.cc index c9eced5..82399f0 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -830,6 +830,7 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, #endif restore_record(table, s->default_values); + table->reset_default_fields(); /* There is no variables in fields_vars list in this format so this conversion is safe. @@ -970,6 +971,7 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, } } restore_record(table, s->default_values); + table->reset_default_fields(); while ((item= it++)) { @@ -1198,6 +1200,7 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, #endif restore_record(table, s->default_values); + table->reset_default_fields(); while ((item= it++)) { diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 1b808d3..1b0cf04 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -352,7 +352,10 @@ int mysql_update(THD *thd, DBUG_RETURN(1); } if (table->default_field) + { table->mark_default_fields_for_write(); + table->reset_default_fields(); + } #ifndef NO_EMBEDDED_ACCESS_CHECKS /* Check values */ @@ -2280,6 +2283,8 @@ int multi_update::do_updates() } copy_field_end=copy_field_ptr; + table->reset_default_fields(); + if ((local_error= tmp_table->file->ha_rnd_init(1))) { err_table= tmp_table; diff --git a/sql/table.cc b/sql/table.cc index 23761e0..5464354 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -6684,13 +6684,26 @@ int TABLE::update_default_fields() if (res) DBUG_RETURN(res); } - /* Unset the explicit default flag for the next record. */ - dfield->flags&= ~HAS_EXPLICIT_VALUE; } DBUG_RETURN(res); } +/** + Unset the explicit default flag for all default fields to not carry over + from previous record. + */ + +void TABLE::reset_default_fields() +{ + if (default_field) + { + for (Field **dfield_ptr= default_field; *dfield_ptr; dfield_ptr++) + (*dfield_ptr)->flags&= ~HAS_EXPLICIT_VALUE; + } +} + + /* Prepare triggers for INSERT-like statement. diff --git a/sql/table.h b/sql/table.h index ad8bcd0..aadbbd7 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1375,6 +1375,7 @@ public: uint actual_n_key_parts(KEY *keyinfo); ulong actual_key_flags(KEY *keyinfo); int update_default_fields(); + void reset_default_fields(); inline ha_rows stat_records() { return used_stat_records; } void prepare_triggers_for_insert_stmt_or_event();