diff options
-rw-r--r-- | mysql-test/include/function_defaults.inc | 17 | ||||
-rw-r--r-- | mysql-test/r/function_defaults.result | 42 | ||||
-rw-r--r-- | sql/sql_insert.cc | 11 | ||||
-rw-r--r-- | sql/sql_load.cc | 1 | ||||
-rw-r--r-- | sql/sql_update.cc | 3 | ||||
-rw-r--r-- | sql/table.cc | 10 | ||||
-rw-r--r-- | sql/table.h | 1 |
7 files changed, 72 insertions, 13 deletions
diff --git a/mysql-test/include/function_defaults.inc b/mysql-test/include/function_defaults.inc index e588c82df1b..ae058eddff6 100644 --- a/mysql-test/include/function_defaults.inc +++ b/mysql-test/include/function_defaults.inc @@ -408,15 +408,28 @@ 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 = 2; +UPDATE t1 t11, t1 t12 SET t11.c = 3; SELECT * FROM t1; -UPDATE t1 t11, t1 t12 SET t11.c = 3; +UPDATE t1 t11, t1 t12 SET t11.c = 2; SELECT * FROM t1; DROP TABLE t1; diff --git a/mysql-test/r/function_defaults.result b/mysql-test/r/function_defaults.result index 27b9ee0a323..105e899ea08 100644 --- a/mysql-test/r/function_defaults.result +++ b/mysql-test/r/function_defaults.result @@ -435,18 +435,31 @@ 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 = 2; +UPDATE t1 t11, t1 t12 SET t11.c = 3; SELECT * FROM t1; a b c -2011-04-20 09:53:41 2011-04-20 09:53:41 2 -UPDATE t1 t11, t1 t12 SET t11.c = 3; +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 15:06:13 2011-04-20 15:06:13 3 +2011-04-20 15:06:13 2011-04-20 15:06:13 2 DROP TABLE t1; # # Test of a multiple-table update where only one table is updated and @@ -1967,18 +1980,31 @@ 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 = 2; +UPDATE t1 t11, t1 t12 SET t11.c = 3; SELECT * FROM t1; a b c -2011-04-20 09:53:41.794613 2011-04-20 09:53:41.794613 2 -UPDATE t1 t11, t1 t12 SET t11.c = 3; +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 15:06:13.534231 2011-04-20 15:06:13.534231 3 +2011-04-20 15:06:13.534231 2011-04-20 15:06:13.534231 2 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 041074a815e..0ecc6418cb2 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -868,6 +868,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, table_list->prepare_check_option(thd)) error= 1; + table->reset_default_fields(); + while ((values= its++)) { if (fields.elements || !value_count) @@ -1661,6 +1663,13 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) DBUG_ASSERT(table->insert_values != NULL); store_record(table,insert_values); restore_record(table,record[1]); + + /* + in INSERT ... ON DUPLICATE KEY UPDATE the set of modified fields can + change per row. Thus, we have to do reset_default_fields() per row. + Twice (before insert and before update). + */ + table->reset_default_fields(); DBUG_ASSERT(info->update_fields->elements == info->update_values->elements); if (fill_record_n_invoke_before_triggers(thd, table, *info->update_fields, @@ -1688,6 +1697,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) if (res) goto err; } + table->reset_default_fields(); /* CHECK OPTION for VIEW ... ON DUPLICATE KEY UPDATE ... */ if (info->view && @@ -3473,6 +3483,7 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) table->file->ha_start_bulk_insert((ha_rows) 0); } restore_record(table,s->default_values); // Get empty record + table->reset_default_fields(); table->next_number_field=table->found_next_number_field; #ifdef HAVE_REPLICATION diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 5ce32305449..c0d9b58569e 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -478,6 +478,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, thd_proc_info(thd, "reading file"); if (!(error= MY_TEST(read_info.error))) { + table->reset_default_fields(); table->next_number_field=table->found_next_number_field; if (ignore || handle_duplicates == DUP_REPLACE) diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 788448563ac..d676ec11ad0 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -717,6 +717,8 @@ int mysql_update(THD *thd, if (table->file->ha_table_flags() & HA_PARTIAL_COLUMN_READ) table->prepare_for_position(); + table->reset_default_fields(); + /* We can use compare_record() to optimize away updates if the table handler is returning all columns OR if @@ -1693,6 +1695,7 @@ int multi_update::prepare(List<Item> ¬_used_values, table->covering_keys.clear_all(); table->pos_in_table_list= tl; table->prepare_triggers_for_update_stmt_or_event(); + table->reset_default_fields(); } } diff --git a/sql/table.cc b/sql/table.cc index c84b8ab17f6..c7c17fc7b3a 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -6736,7 +6736,7 @@ int TABLE::update_default_fields() DBUG_ASSERT(default_field); - /* Iterate over virtual fields in the table */ + /* Iterate over fields with default functions in the table */ for (dfield_ptr= default_field; *dfield_ptr; dfield_ptr++) { dfield= (*dfield_ptr); @@ -6753,12 +6753,16 @@ 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); } +void TABLE::reset_default_fields() +{ + if (default_field) + for (Field **df= default_field; *df; df++) + (*df)->flags&= ~HAS_EXPLICIT_VALUE; +} /* Prepare triggers for INSERT-like statement. diff --git a/sql/table.h b/sql/table.h index 8e31c0e2600..58b78af6836 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1377,6 +1377,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(); |