mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
SQL,IB: REPLACE semantics [#365 bug 8]
This commit is contained in:
@ -43,6 +43,18 @@ begin
|
|||||||
return NULL;
|
return NULL;
|
||||||
end~~
|
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))
|
create function if not exists sys_commit_ts(sys_field varchar(255))
|
||||||
returns varchar(255)
|
returns varchar(255)
|
||||||
deterministic
|
deterministic
|
||||||
|
@ -4,6 +4,7 @@ drop procedure innodb_verify_vtq;
|
|||||||
drop function default_engine;
|
drop function default_engine;
|
||||||
drop function sys_commit_ts;
|
drop function sys_commit_ts;
|
||||||
drop function sys_datatype;
|
drop function sys_datatype;
|
||||||
|
drop function current_row;
|
||||||
drop procedure concat_exec2;
|
drop procedure concat_exec2;
|
||||||
drop procedure concat_exec3;
|
drop procedure concat_exec3;
|
||||||
--enable_query_log
|
--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
|
with system versioning
|
||||||
engine ', engine);
|
engine ', engine);
|
||||||
prepare stmt from @str; execute stmt; drop prepare stmt;
|
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;
|
start transaction;
|
||||||
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 = 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 > 3;
|
||||||
|
update t1 set y= y + 1 where x > 4;
|
||||||
commit;
|
commit;
|
||||||
select x, y from t1 for system_time
|
select x, y, sys_trx_end = 18446744073709551615 as current from t1 for system_time all;
|
||||||
between timestamp '0000-0-0 0:0:0'
|
|
||||||
and timestamp '2038-01-19 04:14:07';
|
|
||||||
drop table t1;
|
drop table t1;
|
||||||
end~~
|
end~~
|
||||||
create procedure test_04(
|
create procedure test_04(
|
||||||
@ -285,19 +286,19 @@ call verify_vtq;
|
|||||||
No A B C D
|
No A B C D
|
||||||
1 1 1 1 1
|
1 1 1 1 1
|
||||||
2 1 1 1 1
|
2 1 1 1 1
|
||||||
call test_03('timestamp(6)', 'myisam', 'sys_end');
|
# Multiple UPDATE of same rows in single transaction create historical
|
||||||
x y
|
# rows only once (applicable to InnoDB only).
|
||||||
1 1
|
|
||||||
2 1
|
|
||||||
3 3
|
|
||||||
3 1
|
|
||||||
3 2
|
|
||||||
call test_03('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)');
|
call test_03('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)');
|
||||||
x y
|
x y current
|
||||||
1 1
|
1 1 1
|
||||||
2 1
|
2 2 1
|
||||||
3 3
|
3 3 1
|
||||||
3 1
|
4 2 1
|
||||||
|
5 3 1
|
||||||
|
3 1 0
|
||||||
|
2 1 0
|
||||||
|
4 1 0
|
||||||
|
5 1 0
|
||||||
call verify_vtq;
|
call verify_vtq;
|
||||||
No A B C D
|
No A B C D
|
||||||
1 1 1 1 1
|
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);
|
engine ', engine);
|
||||||
prepare stmt from @str; execute stmt; drop prepare stmt;
|
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;
|
start transaction;
|
||||||
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 = 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 > 3;
|
||||||
|
update t1 set y= y + 1 where x > 4;
|
||||||
commit;
|
commit;
|
||||||
|
|
||||||
select x, y from t1 for system_time
|
select x, y, sys_trx_end = 18446744073709551615 as current from t1 for system_time all;
|
||||||
between timestamp '0000-0-0 0:0:0'
|
|
||||||
and timestamp '2038-01-19 04:14:07';
|
|
||||||
|
|
||||||
drop table t1;
|
drop table t1;
|
||||||
end~~
|
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 test_02('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)');
|
||||||
call verify_vtq;
|
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 test_03('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)');
|
||||||
call verify_vtq;
|
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_bit_as_char(x) ((x) & FIELDFLAG_TREAT_BIT_AS_CHAR)
|
||||||
#define f_is_hex_escape(x) ((x) & FIELDFLAG_HEX_ESCAPE)
|
#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 */
|
#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();
|
table->vers_update_fields();
|
||||||
|
|
||||||
if ((res= table_list->view_check_option(thd,
|
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) &&
|
if (last_uniq_key(table,key_nr) &&
|
||||||
!table->file->referenced_by_foreign_key() &&
|
!table->file->referenced_by_foreign_key() &&
|
||||||
(!table->triggers || !table->triggers->has_delete_triggers()) &&
|
(!table->triggers || !table->triggers->has_delete_triggers()))
|
||||||
!table->versioned_by_sql())
|
|
||||||
{
|
{
|
||||||
|
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],
|
if ((error=table->file->ha_update_row(table->record[1],
|
||||||
table->record[0])) &&
|
table->record[0])) &&
|
||||||
error != HA_ERR_RECORD_IS_THE_SAME)
|
error != HA_ERR_RECORD_IS_THE_SAME)
|
||||||
goto err;
|
goto err;
|
||||||
if (error != HA_ERR_RECORD_IS_THE_SAME)
|
if (error != HA_ERR_RECORD_IS_THE_SAME)
|
||||||
|
{
|
||||||
info->deleted++;
|
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
|
else
|
||||||
error= 0;
|
error= 0;
|
||||||
thd->record_first_successful_insert_id_in_cur_stmt(table->file->insert_id_for_cur_row);
|
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);
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
thd->count_cuted_fields= CHECK_FIELD_WARN; // Calculate cuted fields
|
thd->count_cuted_fields= CHECK_FIELD_WARN; // Calculate cuted fields
|
||||||
if (table->versioned_by_sql())
|
if (table->versioned())
|
||||||
table->vers_update_fields();
|
table->vers_update_fields();
|
||||||
store_values(values);
|
store_values(values);
|
||||||
if (table->default_field && table->update_default_fields(0, info.ignore))
|
if (table->default_field && table->update_default_fields(0, info.ignore))
|
||||||
|
@ -781,7 +781,7 @@ int mysql_update(THD *thd,
|
|||||||
TRG_EVENT_UPDATE))
|
TRG_EVENT_UPDATE))
|
||||||
break; /* purecov: inspected */
|
break; /* purecov: inspected */
|
||||||
|
|
||||||
if (has_vers_fields && table->versioned_by_sql())
|
if (has_vers_fields && table->versioned())
|
||||||
table->vers_update_fields();
|
table->vers_update_fields();
|
||||||
|
|
||||||
found++;
|
found++;
|
||||||
@ -2195,7 +2195,7 @@ int multi_update::send_data(List<Item> ¬_used_values)
|
|||||||
if (table->default_field && table->update_default_fields(1, ignore))
|
if (table->default_field && table->update_default_fields(1, ignore))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
|
||||||
if (has_vers_fields && table->versioned_by_sql())
|
if (has_vers_fields && table->versioned())
|
||||||
table->vers_update_fields();
|
table->vers_update_fields();
|
||||||
|
|
||||||
if ((error= cur_table->view_check_option(thd, ignore)) !=
|
if ((error= cur_table->view_check_option(thd, ignore)) !=
|
||||||
@ -2550,7 +2550,7 @@ int multi_update::do_updates()
|
|||||||
goto err2;
|
goto err2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (has_vers_fields && table->versioned_by_sql())
|
if (has_vers_fields && table->versioned())
|
||||||
table->vers_update_fields();
|
table->vers_update_fields();
|
||||||
|
|
||||||
if ((local_error=table->file->ha_update_row(table->record[1],
|
if ((local_error=table->file->ha_update_row(table->record[1],
|
||||||
|
@ -7691,11 +7691,14 @@ void TABLE::vers_update_fields()
|
|||||||
{
|
{
|
||||||
DBUG_ENTER("vers_update_fields");
|
DBUG_ENTER("vers_update_fields");
|
||||||
|
|
||||||
|
if (versioned_by_sql())
|
||||||
|
{
|
||||||
bitmap_set_bit(write_set, vers_start_field()->field_index);
|
bitmap_set_bit(write_set, vers_start_field()->field_index);
|
||||||
bitmap_set_bit(write_set, vers_end_field()->field_index);
|
|
||||||
|
|
||||||
if (vers_start_field()->set_time())
|
if (vers_start_field()->set_time())
|
||||||
DBUG_ASSERT(0);
|
DBUG_ASSERT(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bitmap_set_bit(write_set, vers_end_field()->field_index);
|
||||||
vers_end_field()->set_max();
|
vers_end_field()->set_max();
|
||||||
|
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
|
@ -1546,6 +1546,9 @@ public:
|
|||||||
return field[s->row_end_field];
|
return field[s->row_end_field];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ulonglong vers_start_id() const;
|
||||||
|
ulonglong vers_end_id() const;
|
||||||
|
|
||||||
int delete_row();
|
int delete_row();
|
||||||
|
|
||||||
/** Number of additional fields used in versioned tables */
|
/** Number of additional fields used in versioned tables */
|
||||||
|
@ -9185,8 +9185,9 @@ ha_innobase::update_row(
|
|||||||
error = row_update_for_mysql(m_prebuilt);
|
error = row_update_for_mysql(m_prebuilt);
|
||||||
|
|
||||||
if (error == DB_SUCCESS && vers_ins_row
|
if (error == DB_SUCCESS && vers_ins_row
|
||||||
&& trx->id != static_cast<trx_id_t>(
|
/* Multiple UPDATE of same rows in single transaction create
|
||||||
table->vers_start_field()->val_int())) {
|
historical rows only once. */
|
||||||
|
&& trx->id != table->vers_start_id()) {
|
||||||
error = row_insert_for_mysql((byte*) old_row,
|
error = row_insert_for_mysql((byte*) old_row,
|
||||||
m_prebuilt,
|
m_prebuilt,
|
||||||
ROW_INS_HISTORICAL);
|
ROW_INS_HISTORICAL);
|
||||||
|
Reference in New Issue
Block a user