summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/include/function_defaults.inc17
-rw-r--r--mysql-test/r/function_defaults.result42
-rw-r--r--sql/sql_insert.cc11
-rw-r--r--sql/sql_load.cc1
-rw-r--r--sql/sql_update.cc3
-rw-r--r--sql/table.cc10
-rw-r--r--sql/table.h1
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> &not_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();