mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01:00
SQL,IB: REPLACE semantics [#365 bug 8]
This commit is contained in:
parent
f489865558
commit
56adced376
14 changed files with 135 additions and 34 deletions
|
@ -43,6 +43,18 @@ begin
|
|||
return NULL;
|
||||
end~~
|
||||
|
||||
create function if not exists current_row(sys_trx_end varbinary(255))
|
||||
returns int
|
||||
deterministic
|
||||
begin
|
||||
if default_engine() = 'innodb' then
|
||||
return sys_trx_end = 18446744073709551615;
|
||||
elseif default_engine() = 'myisam' then
|
||||
return sys_trx_end = timestamp'2038-01-19 03:14:07.999999';
|
||||
end if;
|
||||
return NULL;
|
||||
end~~
|
||||
|
||||
create function if not exists sys_commit_ts(sys_field varchar(255))
|
||||
returns varchar(255)
|
||||
deterministic
|
||||
|
|
|
@ -4,6 +4,7 @@ drop procedure innodb_verify_vtq;
|
|||
drop function default_engine;
|
||||
drop function sys_commit_ts;
|
||||
drop function sys_datatype;
|
||||
drop function current_row;
|
||||
drop procedure concat_exec2;
|
||||
drop procedure concat_exec3;
|
||||
--enable_query_log
|
||||
|
|
2
mysql-test/suite/versioning/key_type.combinations
Normal file
2
mysql-test/suite/versioning/key_type.combinations
Normal file
|
@ -0,0 +1,2 @@
|
|||
[unique]
|
||||
[pk]
|
23
mysql-test/suite/versioning/key_type.inc
Normal file
23
mysql-test/suite/versioning/key_type.inc
Normal file
|
@ -0,0 +1,23 @@
|
|||
--disable_query_log
|
||||
if ($MTR_COMBINATION_UNIQUE)
|
||||
{
|
||||
set @KEY_TYPE= 'unique';
|
||||
}
|
||||
if ($MTR_COMBINATION_PK)
|
||||
{
|
||||
set @KEY_TYPE= 'primary key';
|
||||
}
|
||||
|
||||
delimiter ~~;
|
||||
create procedure create_table(name varchar(255), cols varchar(255))
|
||||
begin
|
||||
if (cols is null or cols = '') then
|
||||
set cols= '';
|
||||
else
|
||||
set cols= concat(', ', cols);
|
||||
end if;
|
||||
set @str= concat('create or replace table ', name, '(id int ', @KEY_TYPE, cols, ') with system versioning');
|
||||
prepare stmt from @str; execute stmt; drop prepare stmt;
|
||||
end~~
|
||||
delimiter ;~~
|
||||
--enable_query_log
|
10
mysql-test/suite/versioning/r/replace.result
Normal file
10
mysql-test/suite/versioning/r/replace.result
Normal file
|
@ -0,0 +1,10 @@
|
|||
call create_table('t', 'x int');
|
||||
insert t values (1, 2);
|
||||
replace t values (1, 3);
|
||||
select *, current_row(sys_trx_end) as current from t for system_time all
|
||||
order by x;
|
||||
id x current
|
||||
1 2 0
|
||||
1 3 1
|
||||
drop database test;
|
||||
create database test;
|
|
@ -66,14 +66,15 @@ set @str= concat('
|
|||
with system versioning
|
||||
engine ', engine);
|
||||
prepare stmt from @str; execute stmt; drop prepare stmt;
|
||||
insert into t1 (x, y) values (1, 1), (2, 1), (3, 1);
|
||||
insert into t1 (x, y) values (1, 1), (2, 1), (3, 1), (4, 1), (5, 1);
|
||||
start transaction;
|
||||
update t1 set y= y + 1 where x = 3;
|
||||
update t1 set y= y + 1 where x = 2;
|
||||
update t1 set y= y + 1 where x = 3;
|
||||
update t1 set y= y + 1 where x > 3;
|
||||
update t1 set y= y + 1 where x > 4;
|
||||
commit;
|
||||
select x, y from t1 for system_time
|
||||
between timestamp '0000-0-0 0:0:0'
|
||||
and timestamp '2038-01-19 04:14:07';
|
||||
select x, y, sys_trx_end = 18446744073709551615 as current from t1 for system_time all;
|
||||
drop table t1;
|
||||
end~~
|
||||
create procedure test_04(
|
||||
|
@ -285,19 +286,19 @@ call verify_vtq;
|
|||
No A B C D
|
||||
1 1 1 1 1
|
||||
2 1 1 1 1
|
||||
call test_03('timestamp(6)', 'myisam', 'sys_end');
|
||||
x y
|
||||
1 1
|
||||
2 1
|
||||
3 3
|
||||
3 1
|
||||
3 2
|
||||
# Multiple UPDATE of same rows in single transaction create historical
|
||||
# rows only once (applicable to InnoDB only).
|
||||
call test_03('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)');
|
||||
x y
|
||||
1 1
|
||||
2 1
|
||||
3 3
|
||||
3 1
|
||||
x y current
|
||||
1 1 1
|
||||
2 2 1
|
||||
3 3 1
|
||||
4 2 1
|
||||
5 3 1
|
||||
3 1 0
|
||||
2 1 0
|
||||
4 1 0
|
||||
5 1 0
|
||||
call verify_vtq;
|
||||
No A B C D
|
||||
1 1 1 1 1
|
||||
|
|
13
mysql-test/suite/versioning/t/replace.test
Normal file
13
mysql-test/suite/versioning/t/replace.test
Normal file
|
@ -0,0 +1,13 @@
|
|||
--source suite/versioning/common.inc
|
||||
--source suite/versioning/key_type.inc
|
||||
--source suite/versioning/engines.inc
|
||||
|
||||
call create_table('t', 'x int');
|
||||
|
||||
insert t values (1, 2);
|
||||
replace t values (1, 3);
|
||||
select *, current_row(sys_trx_end) as current from t for system_time all
|
||||
order by x;
|
||||
|
||||
drop database test;
|
||||
create database test;
|
|
@ -74,16 +74,17 @@ begin
|
|||
engine ', engine);
|
||||
prepare stmt from @str; execute stmt; drop prepare stmt;
|
||||
|
||||
insert into t1 (x, y) values (1, 1), (2, 1), (3, 1);
|
||||
insert into t1 (x, y) values (1, 1), (2, 1), (3, 1), (4, 1), (5, 1);
|
||||
|
||||
start transaction;
|
||||
update t1 set y= y + 1 where x = 3;
|
||||
update t1 set y= y + 1 where x = 2;
|
||||
update t1 set y= y + 1 where x = 3;
|
||||
update t1 set y= y + 1 where x > 3;
|
||||
update t1 set y= y + 1 where x > 4;
|
||||
commit;
|
||||
|
||||
select x, y from t1 for system_time
|
||||
between timestamp '0000-0-0 0:0:0'
|
||||
and timestamp '2038-01-19 04:14:07';
|
||||
select x, y, sys_trx_end = 18446744073709551615 as current from t1 for system_time all;
|
||||
|
||||
drop table t1;
|
||||
end~~
|
||||
|
@ -234,7 +235,8 @@ call test_02('timestamp(6)', 'myisam', 'sys_end');
|
|||
call test_02('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)');
|
||||
call verify_vtq;
|
||||
|
||||
call test_03('timestamp(6)', 'myisam', 'sys_end');
|
||||
--echo # Multiple UPDATE of same rows in single transaction create historical
|
||||
--echo # rows only once (applicable to InnoDB only).
|
||||
call test_03('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)');
|
||||
call verify_vtq;
|
||||
|
||||
|
|
15
sql/field.h
15
sql/field.h
|
@ -4642,4 +4642,19 @@ bool check_expression(Virtual_column_info *vcol, LEX_CSTRING *name,
|
|||
#define f_bit_as_char(x) ((x) & FIELDFLAG_TREAT_BIT_AS_CHAR)
|
||||
#define f_is_hex_escape(x) ((x) & FIELDFLAG_HEX_ESCAPE)
|
||||
|
||||
inline
|
||||
ulonglong TABLE::vers_end_id() const
|
||||
{
|
||||
DBUG_ASSERT(versioned_by_engine());
|
||||
return static_cast<ulonglong>(vers_end_field()->val_int());
|
||||
}
|
||||
|
||||
inline
|
||||
ulonglong TABLE::vers_start_id() const
|
||||
{
|
||||
DBUG_ASSERT(versioned_by_engine());
|
||||
return static_cast<ulonglong>(vers_start_field()->val_int());
|
||||
}
|
||||
|
||||
|
||||
#endif /* FIELD_INCLUDED */
|
||||
|
|
|
@ -1050,7 +1050,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||
}
|
||||
}
|
||||
|
||||
if (table->versioned_by_sql())
|
||||
if (table->versioned())
|
||||
table->vers_update_fields();
|
||||
|
||||
if ((res= table_list->view_check_option(thd,
|
||||
|
@ -1937,15 +1937,30 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
|
|||
*/
|
||||
if (last_uniq_key(table,key_nr) &&
|
||||
!table->file->referenced_by_foreign_key() &&
|
||||
(!table->triggers || !table->triggers->has_delete_triggers()) &&
|
||||
!table->versioned_by_sql())
|
||||
(!table->triggers || !table->triggers->has_delete_triggers()))
|
||||
{
|
||||
if (table->versioned_by_engine())
|
||||
{
|
||||
bitmap_set_bit(table->write_set, table->vers_start_field()->field_index);
|
||||
table->vers_start_field()->set_notnull();
|
||||
table->vers_start_field()->store(0, false);
|
||||
}
|
||||
if ((error=table->file->ha_update_row(table->record[1],
|
||||
table->record[0])) &&
|
||||
error != HA_ERR_RECORD_IS_THE_SAME)
|
||||
goto err;
|
||||
if (error != HA_ERR_RECORD_IS_THE_SAME)
|
||||
{
|
||||
info->deleted++;
|
||||
if (table->versioned_by_sql())
|
||||
{
|
||||
store_record(table, record[2]);
|
||||
error= vers_insert_history_row(table);
|
||||
restore_record(table, record[2]);
|
||||
if (error)
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
else
|
||||
error= 0;
|
||||
thd->record_first_successful_insert_id_in_cur_stmt(table->file->insert_id_for_cur_row);
|
||||
|
@ -3832,7 +3847,7 @@ int select_insert::send_data(List<Item> &values)
|
|||
DBUG_RETURN(0);
|
||||
|
||||
thd->count_cuted_fields= CHECK_FIELD_WARN; // Calculate cuted fields
|
||||
if (table->versioned_by_sql())
|
||||
if (table->versioned())
|
||||
table->vers_update_fields();
|
||||
store_values(values);
|
||||
if (table->default_field && table->update_default_fields(0, info.ignore))
|
||||
|
|
|
@ -781,7 +781,7 @@ int mysql_update(THD *thd,
|
|||
TRG_EVENT_UPDATE))
|
||||
break; /* purecov: inspected */
|
||||
|
||||
if (has_vers_fields && table->versioned_by_sql())
|
||||
if (has_vers_fields && table->versioned())
|
||||
table->vers_update_fields();
|
||||
|
||||
found++;
|
||||
|
@ -2195,7 +2195,7 @@ int multi_update::send_data(List<Item> ¬_used_values)
|
|||
if (table->default_field && table->update_default_fields(1, ignore))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
if (has_vers_fields && table->versioned_by_sql())
|
||||
if (has_vers_fields && table->versioned())
|
||||
table->vers_update_fields();
|
||||
|
||||
if ((error= cur_table->view_check_option(thd, ignore)) !=
|
||||
|
@ -2550,7 +2550,7 @@ int multi_update::do_updates()
|
|||
goto err2;
|
||||
}
|
||||
}
|
||||
if (has_vers_fields && table->versioned_by_sql())
|
||||
if (has_vers_fields && table->versioned())
|
||||
table->vers_update_fields();
|
||||
|
||||
if ((local_error=table->file->ha_update_row(table->record[1],
|
||||
|
|
11
sql/table.cc
11
sql/table.cc
|
@ -7691,11 +7691,14 @@ void TABLE::vers_update_fields()
|
|||
{
|
||||
DBUG_ENTER("vers_update_fields");
|
||||
|
||||
bitmap_set_bit(write_set, vers_start_field()->field_index);
|
||||
bitmap_set_bit(write_set, vers_end_field()->field_index);
|
||||
if (versioned_by_sql())
|
||||
{
|
||||
bitmap_set_bit(write_set, vers_start_field()->field_index);
|
||||
if (vers_start_field()->set_time())
|
||||
DBUG_ASSERT(0);
|
||||
}
|
||||
|
||||
if (vers_start_field()->set_time())
|
||||
DBUG_ASSERT(0);
|
||||
bitmap_set_bit(write_set, vers_end_field()->field_index);
|
||||
vers_end_field()->set_max();
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
|
|
|
@ -1546,6 +1546,9 @@ public:
|
|||
return field[s->row_end_field];
|
||||
}
|
||||
|
||||
ulonglong vers_start_id() const;
|
||||
ulonglong vers_end_id() const;
|
||||
|
||||
int delete_row();
|
||||
|
||||
/** Number of additional fields used in versioned tables */
|
||||
|
|
|
@ -9185,8 +9185,9 @@ ha_innobase::update_row(
|
|||
error = row_update_for_mysql(m_prebuilt);
|
||||
|
||||
if (error == DB_SUCCESS && vers_ins_row
|
||||
&& trx->id != static_cast<trx_id_t>(
|
||||
table->vers_start_field()->val_int())) {
|
||||
/* Multiple UPDATE of same rows in single transaction create
|
||||
historical rows only once. */
|
||||
&& trx->id != table->vers_start_id()) {
|
||||
error = row_insert_for_mysql((byte*) old_row,
|
||||
m_prebuilt,
|
||||
ROW_INS_HISTORICAL);
|
||||
|
|
Loading…
Reference in a new issue