1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-01 03:47:19 +03:00

System Versioning pre0.12

Merge remote-tracking branch 'origin/archive/2017-10-17' into 10.3
This commit is contained in:
Aleksey Midenkov
2017-11-07 00:37:49 +03:00
354 changed files with 20615 additions and 1638 deletions

View File

@ -44,6 +44,9 @@
// mysql_derived_filling
#include "sql_insert.h" // For vers_insert_history_row() that may be
// needed for System Versioning.
/**
True if the table's input and output record buffers are comparable using
compare_record(TABLE*).
@ -152,6 +155,17 @@ static bool check_fields(THD *thd, List<Item> &items)
return FALSE;
}
static bool check_has_vers_fields(List<Item> &items)
{
List_iterator<Item> it(items);
while (Item *item= it++)
{
if (Item_field *item_field= item->field_for_view_update())
if (!(item_field->field->flags & VERS_OPTIMIZED_UPDATE_FLAG))
return true;
}
return false;
}
/**
Re-read record if more columns are needed for error message.
@ -281,6 +295,10 @@ int mysql_update(THD *thd,
TABLE_LIST *update_source_table;
query_plan.index= MAX_KEY;
query_plan.using_filesort= FALSE;
// For System Versioning (may need to insert new fields to a table).
ha_rows updated_sys_ver= 0;
DBUG_ENTER("mysql_update");
create_explain_query(thd->lex, thd->mem_root);
@ -351,12 +369,17 @@ int mysql_update(THD *thd,
{
DBUG_RETURN(1);
}
bool has_vers_fields=
table->versioned() ? check_has_vers_fields(fields) : false;
if (check_key_in_view(thd, table_list))
{
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "UPDATE");
DBUG_RETURN(1);
}
if (table->default_field)
table->mark_default_fields_for_write(false);
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/* Check values */
table_list->grant.want_privilege= table->grant.want_privilege=
@ -737,6 +760,11 @@ int mysql_update(THD *thd,
while (!(error=info.read_record()) && !thd->killed)
{
if (table->versioned() && !table->vers_end_field()->is_max())
{
continue;
}
explain->tracker.on_record_read();
thd->inc_examined_row_count(1);
if (!select || select->skip_record(thd) > 0)
@ -746,10 +774,14 @@ int mysql_update(THD *thd,
explain->tracker.on_record_after_where();
store_record(table,record[1]);
if (fill_record_n_invoke_before_triggers(thd, table, fields, values, 0,
TRG_EVENT_UPDATE))
break; /* purecov: inspected */
if (has_vers_fields && table->versioned_by_sql())
table->vers_update_fields();
found++;
if (!can_compare_record || compare_record(table))
@ -808,19 +840,35 @@ int mysql_update(THD *thd,
else
{
/* Non-batched update */
error= table->file->ha_update_row(table->record[1],
error= table->file->ha_update_row(table->record[1],
table->record[0]);
}
if (!error || error == HA_ERR_RECORD_IS_THE_SAME)
{
if (error != HA_ERR_RECORD_IS_THE_SAME)
updated++;
else
error= 0;
}
else if (!ignore ||
if (error == HA_ERR_RECORD_IS_THE_SAME)
{
error= 0;
}
else if (!error)
{
updated++;
if (has_vers_fields && table->versioned())
{
if (table->versioned_by_sql())
{
store_record(table, record[2]);
if ((error = vers_insert_history_row(table)))
{
restore_record(table, record[2]);
break;
}
restore_record(table, record[2]);
}
updated_sys_ver++;
}
}
else if (!ignore ||
table->file->is_fatal_error(error, HA_CHECK_ALL))
{
{
/*
If (ignore && error is ignorable) we don't have to
do anything; otherwise...
@ -991,6 +1039,9 @@ int mysql_update(THD *thd,
else
errcode= query_error_code(thd, killed_status == NOT_KILLED);
ScopedStatementReplication scoped_stmt_rpl(
table->versioned_by_engine() ? thd : NULL);
if (thd->binlog_query(THD::ROW_QUERY_TYPE,
thd->query(), thd->query_length(),
transactional_table, FALSE, FALSE, errcode))
@ -1010,9 +1061,15 @@ int mysql_update(THD *thd,
if (error < 0 && !thd->lex->analyze_stmt)
{
char buff[MYSQL_ERRMSG_SIZE];
my_snprintf(buff, sizeof(buff), ER_THD(thd, ER_UPDATE_INFO), (ulong) found,
(ulong) updated,
(ulong) thd->get_stmt_da()->current_statement_warn_count());
if (!table->versioned_by_sql())
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) thd->get_stmt_da()->current_statement_warn_count());
my_ok(thd, (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated,
id, buff);
DBUG_PRINT("info",("%ld records updated", (long) updated));
@ -1619,8 +1676,11 @@ multi_update::multi_update(THD *thd_arg, TABLE_LIST *table_list,
tmp_tables(0), updated(0), found(0), fields(field_list),
values(value_list), table_count(0), copy_field(0),
handle_duplicates(handle_duplicates_arg), do_update(1), trans_safe(1),
transactional_tables(0), ignore(ignore_arg), error_handled(0), prepared(0)
{}
transactional_tables(0), ignore(ignore_arg), error_handled(0), prepared(0),
updated_sys_ver(0)
{
has_vers_fields= check_has_vers_fields(*field_list);
}
/*
@ -1871,7 +1931,7 @@ static bool safe_update_on_fly(THD *thd, JOIN_TAB *join_tab,
return !is_key_used(table, table->s->primary_key, table->write_set);
return TRUE;
default:
break; // Avoid compler warning
break; // Avoid compiler warning
}
return FALSE;
@ -2096,6 +2156,11 @@ int multi_update::send_data(List<Item> &not_used_values)
if (table->status & (STATUS_NULL_ROW | STATUS_UPDATED))
continue;
if (table->versioned() && !table->vers_end_field()->is_max())
{
continue;
}
if (table == table_to_update)
{
/*
@ -2108,6 +2173,7 @@ 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, table,
*fields_for_table[offset],
*values_for_table[offset], 0,
@ -2126,6 +2192,9 @@ int multi_update::send_data(List<Item> &not_used_values)
if (table->default_field && table->update_default_fields(1, ignore))
DBUG_RETURN(1);
if (has_vers_fields && table->versioned_by_sql())
table->vers_update_fields();
if ((error= cur_table->view_check_option(thd, ignore)) !=
VIEW_CHECK_OK)
{
@ -2173,6 +2242,21 @@ int multi_update::send_data(List<Item> &not_used_values)
error= 0;
updated--;
}
else if (has_vers_fields && table->versioned())
{
if (table->versioned_by_sql())
{
store_record(table, record[2]);
if (vers_insert_history_row(table))
{
restore_record(table, record[2]);
error= 1;
break;
}
restore_record(table, record[2]);
}
updated_sys_ver++;
}
/* non-transactional or transactional table got modified */
/* either multi_update class' flag is raised in its branch */
if (table->file->has_transactions())
@ -2199,6 +2283,7 @@ int multi_update::send_data(List<Item> &not_used_values)
*/
uint field_num= 0;
List_iterator_fast<TABLE> tbl_it(unupdated_check_opt_tables);
/* Set first tbl = table and then tbl to tables from tbl_it */
TABLE *tbl= table;
do
{
@ -2261,10 +2346,6 @@ void multi_update::abort_result_set()
if (do_update && table_count > 1)
{
/* Add warning here */
/*
todo/fixme: do_update() is never called with the arg 1.
should it change the signature to become argless?
*/
(void) do_updates();
}
}
@ -2466,19 +2547,40 @@ int multi_update::do_updates()
goto err2;
}
}
if ((local_error=table->file->ha_update_row(table->record[1],
table->record[0])) &&
if (has_vers_fields && table->versioned_by_sql())
table->vers_update_fields();
if ((local_error=table->file->ha_update_row(table->record[1],
table->record[0])) &&
local_error != HA_ERR_RECORD_IS_THE_SAME)
{
if (!ignore ||
table->file->is_fatal_error(local_error, HA_CHECK_ALL))
{
err_table= table;
goto err;
goto err;
}
}
}
if (local_error != HA_ERR_RECORD_IS_THE_SAME)
{
updated++;
if (has_vers_fields && table->versioned())
{
if (table->versioned_by_sql())
{
store_record(table, record[2]);
if ((local_error= vers_insert_history_row(table)))
{
restore_record(table, record[2]);
err_table = table;
goto err;
}
restore_record(table, record[2]);
}
updated_sys_ver++;
}
}
else
local_error= 0;
}
@ -2594,9 +2696,21 @@ bool multi_update::send_eof()
thd->clear_error();
else
errcode= query_error_code(thd, killed_status == NOT_KILLED);
if (thd->binlog_query(THD::ROW_QUERY_TYPE,
thd->query(), thd->query_length(),
transactional_tables, FALSE, FALSE, errcode))
bool force_stmt= false;
for (TABLE *table= all_tables->table; table; table= table->next)
{
if (table->versioned_by_engine())
{
force_stmt= true;
break;
}
}
ScopedStatementReplication scoped_stmt_rpl(force_stmt ? thd : NULL);
if (thd->binlog_query(THD::ROW_QUERY_TYPE, thd->query(),
thd->query_length(), transactional_tables, FALSE,
FALSE, errcode))
{
local_error= 1; // Rollback update
}