mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +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:
@ -273,7 +273,6 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
||||
for (field=table->field; *field ; field++)
|
||||
fields_vars.push_back(new Item_field(*field));
|
||||
bitmap_set_all(table->write_set);
|
||||
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
|
||||
/*
|
||||
Let us also prepare SET clause, altough it is probably empty
|
||||
in this case.
|
||||
@ -289,21 +288,9 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
||||
setup_fields(thd, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) ||
|
||||
check_that_all_fields_are_given_values(thd, table, table_list))
|
||||
DBUG_RETURN(TRUE);
|
||||
/*
|
||||
Check whenever TIMESTAMP field with auto-set feature specified
|
||||
explicitly.
|
||||
*/
|
||||
if (table->timestamp_field)
|
||||
{
|
||||
if (bitmap_is_set(table->write_set,
|
||||
table->timestamp_field->field_index))
|
||||
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
|
||||
else
|
||||
{
|
||||
bitmap_set_bit(table->write_set,
|
||||
table->timestamp_field->field_index);
|
||||
}
|
||||
}
|
||||
/* Add all fields with default functions to table->write_set. */
|
||||
if (table->default_field)
|
||||
table->mark_default_fields_for_write();
|
||||
/* Fix the expressions in SET clause */
|
||||
if (setup_fields(thd, 0, set_values, MARK_COLUMNS_READ, 0, 0))
|
||||
DBUG_RETURN(TRUE);
|
||||
@ -850,7 +837,7 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
||||
ER(ER_WARN_TOO_FEW_RECORDS),
|
||||
thd->warning_info->current_row_for_warning());
|
||||
if (!field->maybe_null() && field->type() == FIELD_TYPE_TIMESTAMP)
|
||||
((Field_timestamp*) field)->set_time();
|
||||
field->set_time();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -864,6 +851,7 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
||||
pos[length]=save_chr;
|
||||
if ((pos+=length) > read_info.row_end)
|
||||
pos= read_info.row_end; /* Fills rest with space */
|
||||
field->set_explicit_default(NULL);
|
||||
}
|
||||
}
|
||||
if (pos != read_info.row_end)
|
||||
@ -876,10 +864,10 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
||||
}
|
||||
|
||||
if (thd->killed ||
|
||||
fill_record_n_invoke_before_triggers(thd, set_fields, set_values,
|
||||
fill_record_n_invoke_before_triggers(thd, table, set_fields, set_values,
|
||||
ignore_check_option_errors,
|
||||
table->triggers,
|
||||
TRG_EVENT_INSERT))
|
||||
TRG_EVENT_INSERT) ||
|
||||
(table->default_field && table->update_default_fields()))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
switch (table_list->view_check_option(thd,
|
||||
@ -994,10 +982,11 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
field->set_null();
|
||||
field->set_explicit_default(NULL);
|
||||
if (!field->maybe_null())
|
||||
{
|
||||
if (field->type() == MYSQL_TYPE_TIMESTAMP)
|
||||
((Field_timestamp*) field)->set_time();
|
||||
field->set_time();
|
||||
else if (field != table->next_number_field)
|
||||
field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
ER_WARN_NULL_TO_NOTNULL, 1);
|
||||
@ -1025,6 +1014,7 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
||||
if (field == table->next_number_field)
|
||||
table->auto_increment_field_not_null= TRUE;
|
||||
field->store((char*) pos, length, read_info.read_charset);
|
||||
field->set_explicit_default(NULL);
|
||||
}
|
||||
else if (item->type() == Item::STRING_ITEM)
|
||||
{
|
||||
@ -1066,7 +1056,7 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
if (!field->maybe_null() && field->type() == FIELD_TYPE_TIMESTAMP)
|
||||
((Field_timestamp*) field)->set_time();
|
||||
field->set_time();
|
||||
/*
|
||||
TODO: We probably should not throw warning for each field.
|
||||
But how about intention to always have the same number
|
||||
@ -1093,10 +1083,10 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
||||
}
|
||||
|
||||
if (thd->killed ||
|
||||
fill_record_n_invoke_before_triggers(thd, set_fields, set_values,
|
||||
fill_record_n_invoke_before_triggers(thd, table, set_fields, set_values,
|
||||
ignore_check_option_errors,
|
||||
table->triggers,
|
||||
TRG_EVENT_INSERT))
|
||||
TRG_EVENT_INSERT) ||
|
||||
(table->default_field && table->update_default_fields()))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
switch (table_list->view_check_option(thd,
|
||||
@ -1206,7 +1196,7 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
||||
if (!field->maybe_null())
|
||||
{
|
||||
if (field->type() == FIELD_TYPE_TIMESTAMP)
|
||||
((Field_timestamp *) field)->set_time();
|
||||
field->set_time();
|
||||
else if (field != table->next_number_field)
|
||||
field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
ER_WARN_NULL_TO_NOTNULL, 1);
|
||||
@ -1225,6 +1215,7 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
||||
if (field == table->next_number_field)
|
||||
table->auto_increment_field_not_null= TRUE;
|
||||
field->store((char *) tag->value.ptr(), tag->value.length(), cs);
|
||||
field->set_explicit_default(NULL);
|
||||
}
|
||||
else
|
||||
((Item_user_var_as_out_param *) item)->set_value(
|
||||
@ -1269,10 +1260,10 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
||||
}
|
||||
|
||||
if (thd->killed ||
|
||||
fill_record_n_invoke_before_triggers(thd, set_fields, set_values,
|
||||
fill_record_n_invoke_before_triggers(thd, table, set_fields, set_values,
|
||||
ignore_check_option_errors,
|
||||
table->triggers,
|
||||
TRG_EVENT_INSERT))
|
||||
TRG_EVENT_INSERT) ||
|
||||
(table->default_field && table->update_default_fields()))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
switch (table_list->view_check_option(thd,
|
||||
|
Reference in New Issue
Block a user