1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

0.1: SQL-level System Versioning

This commit is contained in:
Daniel Fiala
2016-06-19 07:38:28 +01:00
committed by Aleksey Midenkov
parent 14bdfa8541
commit be6f2d302c
115 changed files with 4055 additions and 1101 deletions

View File

@ -222,7 +222,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
table_list->view_db.str, table_list->view_name.str);
DBUG_RETURN(-1);
}
if (values.elements != table->s->fields)
if (values.elements != table->user_fields())
{
my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), 1L);
DBUG_RETURN(-1);
@ -1029,6 +1029,13 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
}
}
if (table->versioned() &&
table->vers_update_fields())
{
error= 1;
break;
}
if ((res= table_list->view_check_option(thd,
(values_list.elements == 1 ?
0 :
@ -1555,6 +1562,13 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
if (!table)
table= table_list->table;
if (table->versioned() && duplic == DUP_REPLACE)
{
// Additional memory may be required to create historical items.
if (table_list->set_insert_values(thd->mem_root))
DBUG_RETURN(TRUE);
}
if (!select_insert)
{
Item *fake_conds= 0;
@ -1605,6 +1619,31 @@ static int last_uniq_key(TABLE *table,uint keynr)
}
/*
Inserts one historical row to a table.
Copies content of the row from table->record[1] to table->record[0],
sets Sys_end to now() and calls ha_write_row() .
*/
int vers_insert_history_row(TABLE *table, ha_rows *inserted)
{
DBUG_ASSERT(table->versioned());
restore_record(table,record[1]);
// Set Sys_end to now()
if (table->vers_end_field()->set_time())
{
return 1;
}
const int error= table->file->ha_write_row(table->record[0]);
if (!error)
++*inserted;
return error;
}
/*
Write a record to table with optional deleting of conflicting records,
invoke proper triggers if needed.
@ -1809,7 +1848,12 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
}
if (error != HA_ERR_RECORD_IS_THE_SAME)
{
info->updated++;
if (table->versioned() &&
(error=vers_insert_history_row(table, &info->copied)))
goto err;
}
else
error= 0;
/*
@ -1861,13 +1905,16 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
tables which have ON UPDATE but have no ON DELETE triggers,
we just should not expose this fact to users by invoking
ON UPDATE triggers.
*/
if (last_uniq_key(table,key_nr) &&
!table->file->referenced_by_foreign_key() &&
(!table->triggers || !table->triggers->has_delete_triggers()))
For system versioning wa also use path through delete since we would
save nothing through this cheating.
*/
if (last_uniq_key(table,key_nr) &&
!table->file->referenced_by_foreign_key() &&
(!table->triggers || !table->triggers->has_delete_triggers()) &&
!table->versioned())
{
if ((error=table->file->ha_update_row(table->record[1],
table->record[0])) &&
table->record[0])) &&
error != HA_ERR_RECORD_IS_THE_SAME)
goto err;
if (error != HA_ERR_RECORD_IS_THE_SAME)
@ -1887,9 +1934,29 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
TRG_ACTION_BEFORE, TRUE))
goto before_trg_err;
if ((error=table->file->ha_delete_row(table->record[1])))
if (!table->versioned())
error= table->file->ha_delete_row(table->record[1]);
else
{
DBUG_ASSERT(table->insert_values);
store_record(table,insert_values);
restore_record(table,record[1]);
if (table->vers_end_field()->set_time())
{
error= 1;
goto err;
}
error= table->file->ha_update_row(table->record[1],
table->record[0]);
restore_record(table,insert_values);
}
if (error)
goto err;
info->deleted++;
if (!table->versioned())
info->deleted++;
else
info->updated++;
if (!table->file->has_transactions())
thd->transaction.stmt.modified_non_trans_table= TRUE;
if (table->triggers &&
@ -3732,6 +3799,9 @@ int select_insert::send_data(List<Item> &values)
DBUG_RETURN(0);
thd->count_cuted_fields= CHECK_FIELD_WARN; // Calculate cuted fields
if (table->versioned() &&
table->vers_update_fields())
DBUG_RETURN(1);
store_values(values);
if (table->default_field && table->update_default_fields(0, info.ignore))
DBUG_RETURN(1);
@ -3793,12 +3863,16 @@ int select_insert::send_data(List<Item> &values)
void select_insert::store_values(List<Item> &values)
{
DBUG_ENTER("select_insert::store_values");
if (fields->elements)
fill_record_n_invoke_before_triggers(thd, table, *fields, values, 1,
TRG_EVENT_INSERT);
else
fill_record_n_invoke_before_triggers(thd, table, table->field_to_fill(),
values, 1, TRG_EVENT_INSERT);
DBUG_VOID_RETURN;
}
bool select_insert::prepare_eof()