mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
MDEV-16974 Application-time periods: UPDATE
This commit is contained in:
committed by
Sergei Golubchik
parent
47e28a94d5
commit
b2bd52290a
@ -132,7 +132,8 @@ bool compare_record(const TABLE *table)
|
||||
FALSE Items are OK
|
||||
*/
|
||||
|
||||
static bool check_fields(THD *thd, List<Item> &items, bool update_view)
|
||||
static bool check_fields(THD *thd, TABLE_LIST *table, List<Item> &items,
|
||||
bool update_view)
|
||||
{
|
||||
Item *item;
|
||||
if (update_view)
|
||||
@ -177,6 +178,22 @@ static bool check_fields(THD *thd, List<Item> &items, bool update_view)
|
||||
f->set_has_explicit_value();
|
||||
}
|
||||
}
|
||||
|
||||
if (table->has_period())
|
||||
{
|
||||
DBUG_ASSERT(thd->lex->sql_command == SQLCOM_UPDATE);
|
||||
for (List_iterator_fast<Item> it(items); (item=it++);)
|
||||
{
|
||||
Field *f= item->field_for_view_update()->field;
|
||||
vers_select_conds_t &period= table->period_conditions;
|
||||
if (period.field_start->field == f || period.field_end->field == f)
|
||||
{
|
||||
my_error(ER_PERIOD_COLUMNS_UPDATED, MYF(0),
|
||||
item->name.str, period.name.str);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -267,6 +284,31 @@ static void prepare_record_for_error_message(int error, TABLE *table)
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int cut_fields_for_portion_of_time(THD *thd, TABLE *table,
|
||||
const vers_select_conds_t &period_conds)
|
||||
{
|
||||
bool lcond= period_conds.field_start->val_datetime_packed(thd)
|
||||
< period_conds.start.item->val_datetime_packed(thd);
|
||||
bool rcond= period_conds.field_end->val_datetime_packed(thd)
|
||||
> period_conds.end.item->val_datetime_packed(thd);
|
||||
|
||||
Field *start_field= table->field[table->s->period.start_fieldno];
|
||||
Field *end_field= table->field[table->s->period.end_fieldno];
|
||||
|
||||
DBUG_ASSERT(!start_field->has_explicit_value()
|
||||
&& !end_field->has_explicit_value());
|
||||
|
||||
int res= 0;
|
||||
if (lcond)
|
||||
res= period_conds.start.item->save_in_field(start_field, true);
|
||||
|
||||
if (likely(!res) && rcond)
|
||||
res= period_conds.end.item->save_in_field(end_field, true);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
Process usual UPDATE
|
||||
|
||||
@ -330,7 +372,7 @@ int mysql_update(THD *thd,
|
||||
query_plan.using_filesort= FALSE;
|
||||
|
||||
// For System Versioning (may need to insert new fields to a table).
|
||||
ha_rows updated_sys_ver= 0;
|
||||
ha_rows rows_inserted= 0;
|
||||
|
||||
DBUG_ENTER("mysql_update");
|
||||
|
||||
@ -398,7 +440,7 @@ int mysql_update(THD *thd,
|
||||
if (setup_fields_with_no_wrap(thd, Ref_ptr_array(),
|
||||
fields, MARK_COLUMNS_WRITE, 0, 0))
|
||||
DBUG_RETURN(1); /* purecov: inspected */
|
||||
if (check_fields(thd, fields, table_list->view))
|
||||
if (check_fields(thd, table_list, fields, table_list->view))
|
||||
{
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
@ -509,7 +551,10 @@ int mysql_update(THD *thd,
|
||||
if (unlikely(init_ftfuncs(thd, select_lex, 1)))
|
||||
goto err;
|
||||
|
||||
table->mark_columns_needed_for_update();
|
||||
if (table_list->has_period())
|
||||
table->use_all_columns();
|
||||
else
|
||||
table->mark_columns_needed_for_update();
|
||||
|
||||
table->update_const_key_parts(conds);
|
||||
order= simple_remove_const(order, conds);
|
||||
@ -590,6 +635,14 @@ int mysql_update(THD *thd,
|
||||
TRG_ACTION_BEFORE) ||
|
||||
table->triggers->has_triggers(TRG_EVENT_UPDATE,
|
||||
TRG_ACTION_AFTER)));
|
||||
|
||||
if (table_list->has_period())
|
||||
has_triggers= table->triggers &&
|
||||
(table->triggers->has_triggers(TRG_EVENT_INSERT,
|
||||
TRG_ACTION_BEFORE)
|
||||
|| table->triggers->has_triggers(TRG_EVENT_INSERT,
|
||||
TRG_ACTION_AFTER)
|
||||
|| has_triggers);
|
||||
DBUG_PRINT("info", ("has_triggers: %s", has_triggers ? "TRUE" : "FALSE"));
|
||||
binlog_is_row= thd->is_current_stmt_binlog_format_row();
|
||||
DBUG_PRINT("info", ("binlog_is_row: %s", binlog_is_row ? "TRUE" : "FALSE"));
|
||||
@ -880,14 +933,25 @@ update_begin:
|
||||
explain->tracker.on_record_after_where();
|
||||
store_record(table,record[1]);
|
||||
|
||||
if (table_list->has_period())
|
||||
cut_fields_for_portion_of_time(thd, table,
|
||||
table_list->period_conditions);
|
||||
|
||||
if (fill_record_n_invoke_before_triggers(thd, table, fields, values, 0,
|
||||
TRG_EVENT_UPDATE))
|
||||
break; /* purecov: inspected */
|
||||
|
||||
found++;
|
||||
|
||||
if (!can_compare_record || compare_record(table))
|
||||
bool record_was_same= false;
|
||||
bool need_update= !can_compare_record || compare_record(table);
|
||||
|
||||
if (need_update)
|
||||
{
|
||||
if (table->versioned(VERS_TIMESTAMP) &&
|
||||
thd->lex->sql_command == SQLCOM_DELETE)
|
||||
table->vers_update_end();
|
||||
|
||||
if (table->default_field && table->update_default_fields(1, ignore))
|
||||
{
|
||||
error= 1;
|
||||
@ -946,7 +1010,9 @@ update_begin:
|
||||
error= table->file->ha_update_row(table->record[1],
|
||||
table->record[0]);
|
||||
}
|
||||
if (unlikely(error == HA_ERR_RECORD_IS_THE_SAME))
|
||||
|
||||
record_was_same= error == HA_ERR_RECORD_IS_THE_SAME;
|
||||
if (unlikely(record_was_same))
|
||||
{
|
||||
error= 0;
|
||||
}
|
||||
@ -961,12 +1027,22 @@ update_begin:
|
||||
restore_record(table, record[2]);
|
||||
}
|
||||
if (likely(!error))
|
||||
updated_sys_ver++;
|
||||
rows_inserted++;
|
||||
}
|
||||
if (likely(!error))
|
||||
updated++;
|
||||
}
|
||||
|
||||
if (likely(!error) && !record_was_same && table_list->has_period())
|
||||
{
|
||||
store_record(table, record[2]);
|
||||
restore_record(table, record[1]);
|
||||
error= table->insert_portion_of_time(thd,
|
||||
table_list->period_conditions,
|
||||
&rows_inserted);
|
||||
restore_record(table, record[2]);
|
||||
}
|
||||
|
||||
if (unlikely(error) &&
|
||||
(!ignore || table->file->is_fatal_error(error, HA_CHECK_ALL)))
|
||||
{
|
||||
@ -1107,6 +1183,8 @@ update_end:
|
||||
delete select;
|
||||
select= NULL;
|
||||
THD_STAGE_INFO(thd, stage_end);
|
||||
if (table_list->has_period())
|
||||
table->file->ha_release_auto_increment();
|
||||
(void) table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
|
||||
|
||||
/*
|
||||
@ -1169,14 +1247,14 @@ update_end:
|
||||
if (likely(error < 0) && likely(!thd->lex->analyze_stmt))
|
||||
{
|
||||
char buff[MYSQL_ERRMSG_SIZE];
|
||||
if (!table->versioned(VERS_TIMESTAMP))
|
||||
if (!table->versioned(VERS_TIMESTAMP) && !table_list->has_period())
|
||||
my_snprintf(buff, sizeof(buff), ER_THD(thd, ER_UPDATE_INFO), (ulong) found,
|
||||
(ulong) updated,
|
||||
(ulong) thd->get_stmt_da()->current_statement_warn_count());
|
||||
else
|
||||
my_snprintf(buff, sizeof(buff),
|
||||
ER_THD(thd, ER_UPDATE_INFO_WITH_SYSTEM_VERSIONING),
|
||||
(ulong) found, (ulong) updated, (ulong) updated_sys_ver,
|
||||
(ulong) found, (ulong) updated, (ulong) rows_inserted,
|
||||
(ulong) thd->get_stmt_da()->current_statement_warn_count());
|
||||
my_ok(thd, (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated,
|
||||
id, buff);
|
||||
@ -1257,6 +1335,19 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
|
||||
|
||||
thd->lex->allow_sum_func.clear_all();
|
||||
|
||||
if (table_list->has_period())
|
||||
{
|
||||
if (table_list->is_view_or_derived())
|
||||
{
|
||||
my_error(ER_IT_IS_A_VIEW, MYF(0), table_list->table_name.str);
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
|
||||
*conds= select_lex->period_setup_conds(thd, table_list, *conds);
|
||||
if (!*conds)
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
|
||||
/*
|
||||
We do not call DT_MERGE_FOR_INSERT because it has no sense for simple
|
||||
(not multi-) update
|
||||
@ -1276,6 +1367,16 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
|
||||
setup_ftfuncs(select_lex))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
if (table_list->has_period())
|
||||
{
|
||||
if (!table_list->period_conditions.start.item->const_item()
|
||||
|| !table_list->period_conditions.end.item->const_item())
|
||||
{
|
||||
my_error(ER_NOT_CONSTANT_EXPRESSION, MYF(0), "FOR PORTION OF");
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
}
|
||||
|
||||
select_lex->fix_prepare_information(thd, conds, &fake_conds);
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
@ -1589,7 +1690,7 @@ int mysql_multi_update_prepare(THD *thd)
|
||||
}
|
||||
}
|
||||
|
||||
if (check_fields(thd, *fields, update_view))
|
||||
if (check_fields(thd, table_list, *fields, update_view))
|
||||
{
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
|
Reference in New Issue
Block a user