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:
@ -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> ¬_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> ¬_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> ¬_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)
|
||||
{
|
||||
|
Reference in New Issue
Block a user