1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

MDEV-452 Add full support for auto-initialized/updated timestamp and datetime

Generalized support for auto-updated and/or auto-initialized timestamp
and datetime columns. This patch is a reimplementation of MySQL's
"WL#5874: CURRENT_TIMESTAMP as DEFAULT for DATETIME columns". In order to
ease future merges, this implementation reused few function and variable
names from MySQL's patch, however the implementation is quite different.

TODO:
The only unresolved problem in this patch is the semantics of LOAD DATA for
TIMESTAMP and DATETIME columns in the cases when there are missing or NULL
columns. I couldn't fully comprehend the logic behind MySQL's behavior and
its relationship with their own documentation, so I left the results to be
more consistent with all other LOAD cases.

The problematic test cases can be seen by running the test file function_defaults,
and observing the test case differences. Those were left on purpose for discussion.
This commit is contained in:
unknown
2012-10-17 15:43:56 +03:00
parent 620d14f8c3
commit bc4a456758
61 changed files with 5375 additions and 540 deletions

View File

@ -342,19 +342,8 @@ int mysql_update(THD *thd,
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "UPDATE");
DBUG_RETURN(1);
}
if (table->timestamp_field)
{
// Don't set timestamp column if this is modified
if (bitmap_is_set(table->write_set,
table->timestamp_field->field_index))
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
else
{
if (((uint) table->timestamp_field_type) & TIMESTAMP_AUTO_SET_ON_UPDATE)
bitmap_set_bit(table->write_set,
table->timestamp_field->field_index);
}
}
if (table->default_field)
table->mark_default_fields_for_write();
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/* Check values */
@ -389,7 +378,7 @@ int mysql_update(THD *thd,
to compare records and detect data change.
*/
if ((table->file->ha_table_flags() & HA_PARTIAL_COLUMN_READ) &&
(((uint) table->timestamp_field_type) & TIMESTAMP_AUTO_SET_ON_UPDATE))
table->default_field && table->has_default_function(true))
bitmap_union(table->read_set, table->write_set);
// Don't count on usage of 'only index' when calculating which key to use
table->covering_keys.clear_all();
@ -686,8 +675,7 @@ int mysql_update(THD *thd,
continue; /* repeat the read of the same row if it still exists */
store_record(table,record[1]);
if (fill_record_n_invoke_before_triggers(thd, fields, values, 0,
table->triggers,
if (fill_record_n_invoke_before_triggers(thd, table, fields, values, 0,
TRG_EVENT_UPDATE))
break; /* purecov: inspected */
@ -695,6 +683,11 @@ int mysql_update(THD *thd,
if (!can_compare_record || compare_record(table))
{
if (table->default_field && table->update_default_fields())
{
error= 1;
break;
}
if ((res= table_list->view_check_option(thd, ignore)) !=
VIEW_CHECK_OK)
{
@ -1241,11 +1234,6 @@ int mysql_multi_update_prepare(THD *thd)
while ((tl= ti++))
{
TABLE *table= tl->table;
/* Only set timestamp column if this is not modified */
if (table->timestamp_field &&
bitmap_is_set(table->write_set,
table->timestamp_field->field_index))
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
/* if table will be updated then check that it is unique */
if (table->map & tables_for_update)
@ -1495,8 +1483,7 @@ int multi_update::prepare(List<Item> &not_used_values,
to compare records and detect data change.
*/
if ((table->file->ha_table_flags() & HA_PARTIAL_COLUMN_READ) &&
(((uint) table->timestamp_field_type) &
TIMESTAMP_AUTO_SET_ON_UPDATE))
table->default_field && table->has_default_function(true))
bitmap_union(table->read_set, table->write_set);
}
}
@ -1875,10 +1862,10 @@ int multi_update::send_data(List<Item> &not_used_values)
table->status|= STATUS_UPDATED;
store_record(table,record[1]);
if (fill_record_n_invoke_before_triggers(thd, *fields_for_table[offset],
if (fill_record_n_invoke_before_triggers(thd, table, *fields_for_table[offset],
*values_for_table[offset], 0,
table->triggers,
TRG_EVENT_UPDATE))
TRG_EVENT_UPDATE) ||
(table->default_field && table->update_default_fields()))
DBUG_RETURN(1);
/*
@ -1979,7 +1966,7 @@ int multi_update::send_data(List<Item> &not_used_values)
} while ((tbl= tbl_it++));
/* Store regular updated fields in the row. */
fill_record(thd,
fill_record(thd, tmp_table,
tmp_table->field + 1 + unupdated_check_opt_tables.elements,
*values_for_table[offset], TRUE, FALSE);
@ -2169,7 +2156,10 @@ int multi_update::do_updates()
for (copy_field_ptr=copy_field;
copy_field_ptr != copy_field_end;
copy_field_ptr++)
{
(*copy_field_ptr->do_copy)(copy_field_ptr);
copy_field_ptr->to_field->set_explicit_default(NULL);
}
if (table->triggers &&
table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
@ -2179,6 +2169,8 @@ int multi_update::do_updates()
if (!can_compare_record || compare_record(table))
{
int error;
if (table->default_field && (error= table->update_default_fields()))
goto err2;
if ((error= cur_table->view_check_option(thd, ignore)) !=
VIEW_CHECK_OK)
{