Commit 6a2c1701 authored by Sergei Golubchik's avatar Sergei Golubchik

MDEV-6849 ON UPDATE CURRENT_TIMESTAMP doesn't always work

reset default fields not for every modified row, but only once,
at the beginning, as the set of modified fields doesn't change.

exception: INSERT ... ON DUPLICATE KEY UPDATE - the set of fields
does change per row and in that case we reset default fields per row.
parent 81566708
...@@ -407,16 +407,29 @@ SELECT * FROM t1; ...@@ -407,16 +407,29 @@ SELECT * FROM t1;
UPDATE t1 SET c = 2; UPDATE t1 SET c = 2;
SELECT * FROM t1; 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 #
--echo # Test of multiple-table UPDATE for ON UPDATE CURRENT_TIMESTAMP --echo # Test of multiple-table UPDATE for ON UPDATE CURRENT_TIMESTAMP
--echo # --echo #
--echo # 2011-04-20 15:06:13 UTC --echo # 2011-04-20 15:06:13 UTC
SET TIMESTAMP = 1303311973.534231; 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; SELECT * FROM t1;
UPDATE t1 t11, t1 t12 SET t11.c = 3; UPDATE t1 t11, t1 t12 SET t11.c = 2;
SELECT * FROM t1; SELECT * FROM t1;
DROP TABLE t1; DROP TABLE t1;
......
...@@ -435,18 +435,31 @@ SELECT * FROM t1; ...@@ -435,18 +435,31 @@ SELECT * FROM t1;
a b c a b c
2011-04-20 09:53:41 2011-04-20 09:53:41 2 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 # Test of multiple-table UPDATE for ON UPDATE CURRENT_TIMESTAMP
# #
# 2011-04-20 15:06:13 UTC # 2011-04-20 15:06:13 UTC
SET TIMESTAMP = 1303311973.534231; 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; SELECT * FROM t1;
a b c a b c
2011-04-20 09:53:41 2011-04-20 09:53:41 2 2011-04-20 09:54:13 2011-04-20 09:54:13 3
UPDATE t1 t11, t1 t12 SET t11.c = 3; UPDATE t1 t11, t1 t12 SET t11.c = 2;
SELECT * FROM t1; SELECT * FROM t1;
a b c 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; DROP TABLE t1;
# #
# Test of a multiple-table update where only one table is updated and # Test of a multiple-table update where only one table is updated and
...@@ -1967,18 +1980,31 @@ SELECT * FROM t1; ...@@ -1967,18 +1980,31 @@ SELECT * FROM t1;
a b c a b c
2011-04-20 09:53:41.794613 2011-04-20 09:53:41.794613 2 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 # Test of multiple-table UPDATE for ON UPDATE CURRENT_TIMESTAMP
# #
# 2011-04-20 15:06:13 UTC # 2011-04-20 15:06:13 UTC
SET TIMESTAMP = 1303311973.534231; 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; SELECT * FROM t1;
a b c a b c
2011-04-20 09:53:41.794613 2011-04-20 09:53:41.794613 2 2011-04-20 09:54:13.794613 2011-04-20 09:54:13.794613 3
UPDATE t1 t11, t1 t12 SET t11.c = 3; UPDATE t1 t11, t1 t12 SET t11.c = 2;
SELECT * FROM t1; SELECT * FROM t1;
a b c 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; DROP TABLE t1;
# #
# Test of a multiple-table update where only one table is updated and # Test of a multiple-table update where only one table is updated and
......
...@@ -868,6 +868,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, ...@@ -868,6 +868,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
table_list->prepare_check_option(thd)) table_list->prepare_check_option(thd))
error= 1; error= 1;
table->reset_default_fields();
while ((values= its++)) while ((values= its++))
{ {
if (fields.elements || !value_count) if (fields.elements || !value_count)
...@@ -1661,6 +1663,13 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) ...@@ -1661,6 +1663,13 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
DBUG_ASSERT(table->insert_values != NULL); DBUG_ASSERT(table->insert_values != NULL);
store_record(table,insert_values); store_record(table,insert_values);
restore_record(table,record[1]); 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 == DBUG_ASSERT(info->update_fields->elements ==
info->update_values->elements); info->update_values->elements);
if (fill_record_n_invoke_before_triggers(thd, table, *info->update_fields, 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) ...@@ -1688,6 +1697,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
if (res) if (res)
goto err; goto err;
} }
table->reset_default_fields();
/* CHECK OPTION for VIEW ... ON DUPLICATE KEY UPDATE ... */ /* CHECK OPTION for VIEW ... ON DUPLICATE KEY UPDATE ... */
if (info->view && if (info->view &&
...@@ -3473,6 +3483,7 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) ...@@ -3473,6 +3483,7 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
table->file->ha_start_bulk_insert((ha_rows) 0); table->file->ha_start_bulk_insert((ha_rows) 0);
} }
restore_record(table,s->default_values); // Get empty record restore_record(table,s->default_values); // Get empty record
table->reset_default_fields();
table->next_number_field=table->found_next_number_field; table->next_number_field=table->found_next_number_field;
#ifdef HAVE_REPLICATION #ifdef HAVE_REPLICATION
......
...@@ -478,6 +478,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, ...@@ -478,6 +478,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
thd_proc_info(thd, "reading file"); thd_proc_info(thd, "reading file");
if (!(error= MY_TEST(read_info.error))) if (!(error= MY_TEST(read_info.error)))
{ {
table->reset_default_fields();
table->next_number_field=table->found_next_number_field; table->next_number_field=table->found_next_number_field;
if (ignore || if (ignore ||
handle_duplicates == DUP_REPLACE) handle_duplicates == DUP_REPLACE)
......
...@@ -717,6 +717,8 @@ int mysql_update(THD *thd, ...@@ -717,6 +717,8 @@ int mysql_update(THD *thd,
if (table->file->ha_table_flags() & HA_PARTIAL_COLUMN_READ) if (table->file->ha_table_flags() & HA_PARTIAL_COLUMN_READ)
table->prepare_for_position(); table->prepare_for_position();
table->reset_default_fields();
/* /*
We can use compare_record() to optimize away updates if We can use compare_record() to optimize away updates if
the table handler is returning all columns OR if the table handler is returning all columns OR if
...@@ -1693,6 +1695,7 @@ int multi_update::prepare(List<Item> &not_used_values, ...@@ -1693,6 +1695,7 @@ int multi_update::prepare(List<Item> &not_used_values,
table->covering_keys.clear_all(); table->covering_keys.clear_all();
table->pos_in_table_list= tl; table->pos_in_table_list= tl;
table->prepare_triggers_for_update_stmt_or_event(); table->prepare_triggers_for_update_stmt_or_event();
table->reset_default_fields();
} }
} }
......
...@@ -6736,7 +6736,7 @@ int TABLE::update_default_fields() ...@@ -6736,7 +6736,7 @@ int TABLE::update_default_fields()
DBUG_ASSERT(default_field); 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++) for (dfield_ptr= default_field; *dfield_ptr; dfield_ptr++)
{ {
dfield= (*dfield_ptr); dfield= (*dfield_ptr);
...@@ -6753,12 +6753,16 @@ int TABLE::update_default_fields() ...@@ -6753,12 +6753,16 @@ int TABLE::update_default_fields()
if (res) if (res)
DBUG_RETURN(res); DBUG_RETURN(res);
} }
/* Unset the explicit default flag for the next record. */
dfield->flags&= ~HAS_EXPLICIT_VALUE;
} }
DBUG_RETURN(res); 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. Prepare triggers for INSERT-like statement.
......
...@@ -1377,6 +1377,7 @@ public: ...@@ -1377,6 +1377,7 @@ public:
uint actual_n_key_parts(KEY *keyinfo); uint actual_n_key_parts(KEY *keyinfo);
ulong actual_key_flags(KEY *keyinfo); ulong actual_key_flags(KEY *keyinfo);
int update_default_fields(); int update_default_fields();
void reset_default_fields();
inline ha_rows stat_records() { return used_stat_records; } inline ha_rows stat_records() { return used_stat_records; }
void prepare_triggers_for_insert_stmt_or_event(); void prepare_triggers_for_insert_stmt_or_event();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment