mirror of
https://github.com/MariaDB/server.git
synced 2025-07-05 12:42:17 +03:00
MDEV-14645: AS OF TIMESTAMP is misused as TRX_ID [fixes #396]
This commit is contained in:
@ -212,12 +212,12 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00 Using where; Using join buffer (flat, BNL join)
|
||||
Query A:
|
||||
Note 1003 select `test`.`t1`.`x` AS `x`,`test`.`t1`.`y` AS `y1`,`test`.`t2`.`x` AS `x2`,`test`.`t2`.`y` AS `y2` from `test`.`t1` FOR SYSTEM_TIME ALL join `test`.`t2` FOR SYSTEM_TIME ALL where `test`.`t1`.`x` = `test`.`t2`.`x` and `test`.`t1`.`sys_trx_end` > <cache>(current_timestamp(6)) and `test`.`t1`.`sys_trx_start` <= <cache>(current_timestamp(6)) and `test`.`t2`.`sys_trx_end` > <cache>(current_timestamp(6)) and `test`.`t2`.`sys_trx_start` <= <cache>(current_timestamp(6))
|
||||
Note 1003 select `test`.`t1`.`x` AS `x`,`test`.`t1`.`y` AS `y1`,`test`.`t2`.`x` AS `x2`,`test`.`t2`.`y` AS `y2` from `test`.`t1` FOR SYSTEM_TIME ALL join `test`.`t2` FOR SYSTEM_TIME ALL where `test`.`t1`.`x` = `test`.`t2`.`x` and `test`.`t1`.`sys_trx_end` > <cache>(cast(current_timestamp(6) as datetime(6))) and `test`.`t1`.`sys_trx_start` <= <cache>(cast(current_timestamp(6) as datetime(6))) and `test`.`t2`.`sys_trx_end` > <cache>(cast(current_timestamp(6) as datetime(6))) and `test`.`t2`.`sys_trx_start` <= <cache>(cast(current_timestamp(6) as datetime(6)))
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00 Using where; Using join buffer (flat, BNL join)
|
||||
Query B:
|
||||
Note 1003 select `test`.`t1`.`x` AS `x`,`test`.`t1`.`y` AS `y1`,`test`.`t2`.`x` AS `x2`,`test`.`t2`.`y` AS `y2` from `test`.`t1` FOR SYSTEM_TIME ALL join `test`.`t2` FOR SYSTEM_TIME ALL where `test`.`t1`.`x` = `test`.`t2`.`x` and `test`.`t1`.`sys_trx_end` > <cache>(current_timestamp(6)) and `test`.`t1`.`sys_trx_start` <= <cache>(current_timestamp(6)) and `test`.`t2`.`sys_trx_end` > <cache>(current_timestamp(6)) and `test`.`t2`.`sys_trx_start` <= <cache>(current_timestamp(6))
|
||||
Note 1003 select `test`.`t1`.`x` AS `x`,`test`.`t1`.`y` AS `y1`,`test`.`t2`.`x` AS `x2`,`test`.`t2`.`y` AS `y2` from `test`.`t1` FOR SYSTEM_TIME ALL join `test`.`t2` FOR SYSTEM_TIME ALL where `test`.`t1`.`x` = `test`.`t2`.`x` and `test`.`t1`.`sys_trx_end` > <cache>(cast(current_timestamp(6) as datetime(6))) and `test`.`t1`.`sys_trx_start` <= <cache>(cast(current_timestamp(6) as datetime(6))) and `test`.`t2`.`sys_trx_end` > <cache>(cast(current_timestamp(6) as datetime(6))) and `test`.`t2`.`sys_trx_start` <= <cache>(cast(current_timestamp(6) as datetime(6)))
|
||||
Fine result: queries A and B are equal.
|
||||
## LEFT JOIN: t1, t2 versioned
|
||||
select * from (
|
||||
|
@ -40,7 +40,7 @@ ASOF_x y
|
||||
7 107
|
||||
8 108
|
||||
9 109
|
||||
select x as FROMTO_x, y from t1 for system_time from '0-0-0 0:0:0' to timestamp @t1;
|
||||
select x as FROMTO_x, y from t1 for system_time from timestamp '0-0-0 0:0:0' to timestamp @t1;
|
||||
FROMTO_x y
|
||||
0 100
|
||||
1 101
|
||||
@ -52,7 +52,7 @@ FROMTO_x y
|
||||
7 107
|
||||
8 108
|
||||
9 109
|
||||
select x as BETWAND_x, y from t1 for system_time between '0-0-0 0:0:0' and timestamp @t1;
|
||||
select x as BETWAND_x, y from t1 for system_time between timestamp '0-0-0 0:0:0' and timestamp @t1;
|
||||
BETWAND_x y
|
||||
0 100
|
||||
1 101
|
||||
@ -282,6 +282,44 @@ x y
|
||||
2 1
|
||||
select * from t1 for system_time all, t2 for system_time all for system_time all;
|
||||
ERROR HY000: Unused clause: 'SYSTEM_TIME'
|
||||
# TRANSACTION/TIMESTAMP specifier in SYSTEM_TIME [MDEV-14645, Issue #396]
|
||||
create or replace table t1 (x int) with system versioning engine myisam;
|
||||
select * from t1 for system_time as of transaction 1;
|
||||
ERROR HY000: Engine does not support System Versioning for `t1`
|
||||
create or replace table t1 (x int) with system versioning engine innodb;
|
||||
insert into t1 values (1);
|
||||
set @ts= now(6);
|
||||
delete from t1;
|
||||
select sys_trx_start from t1 for system_time all into @trx_start;
|
||||
## ensure @trx_start is much lower than unix timestamp
|
||||
select @trx_start < unix_timestamp(@ts) - 100 as trx_start_good;
|
||||
trx_start_good
|
||||
1
|
||||
## TIMESTAMP specifier
|
||||
select * from t1 for system_time as of timestamp @ts;
|
||||
x
|
||||
1
|
||||
select * from t1 for system_time as of timestamp unix_timestamp(@ts);
|
||||
x
|
||||
1
|
||||
select * from t1 for system_time as of timestamp @trx_start;
|
||||
x
|
||||
## TRANSACTION specifier
|
||||
select * from t1 for system_time as of transaction @ts;
|
||||
x
|
||||
select * from t1 for system_time as of transaction unix_timestamp(@ts);
|
||||
x
|
||||
select * from t1 for system_time as of transaction @trx_start;
|
||||
x
|
||||
1
|
||||
## no specifier (auto-detection)
|
||||
select * from t1 for system_time as of @ts;
|
||||
x
|
||||
select * from t1 for system_time as of unix_timestamp(@ts);
|
||||
x
|
||||
select * from t1 for system_time as of @trx_start;
|
||||
x
|
||||
1
|
||||
### Issue #365, bug 4 (related to #226, optimized fields)
|
||||
create or replace table t1 (i int, b int) with system versioning;
|
||||
insert into t1 values (0, 0), (0, 0);
|
||||
@ -320,7 +358,7 @@ select * from t1 where (a, 2) in ((1, 1), (2, 2)) and b = 1;
|
||||
a b
|
||||
drop view v1;
|
||||
drop table t1, t2;
|
||||
call innodb_verify_vtq(30);
|
||||
call innodb_verify_vtq(32);
|
||||
No A B C D
|
||||
1 1 1 1 1
|
||||
2 1 1 1 1
|
||||
@ -352,3 +390,5 @@ No A B C D
|
||||
28 1 1 1 1
|
||||
29 1 1 1 1
|
||||
30 1 1 1 1
|
||||
31 1 1 1 1
|
||||
32 1 1 1 1
|
||||
|
@ -21,7 +21,7 @@ insert into t1 (x, y) values
|
||||
(9, 109);
|
||||
|
||||
set @t0= now(6);
|
||||
if ($default_engine == 'innodb')
|
||||
if ($default_engine == 'InnoDB')
|
||||
{
|
||||
--disable_query_log
|
||||
select sys_trx_start from t1 limit 1 into @x0;
|
||||
@ -33,7 +33,7 @@ delete from t1 where x > 7;
|
||||
|
||||
insert into t1(x, y) values(3, 33);
|
||||
select sys_trx_start from t1 where x = 3 and y = 33 into @t1;
|
||||
if ($default_engine == 'innodb')
|
||||
if ($default_engine == 'InnoDB')
|
||||
{
|
||||
--disable_query_log
|
||||
set @x1= @t1;
|
||||
@ -43,21 +43,21 @@ if ($default_engine == 'innodb')
|
||||
|
||||
select x, y from t1;
|
||||
select x as ASOF_x, y from t1 for system_time as of timestamp @t0;
|
||||
select x as FROMTO_x, y from t1 for system_time from '0-0-0 0:0:0' to timestamp @t1;
|
||||
select x as BETWAND_x, y from t1 for system_time between '0-0-0 0:0:0' and timestamp @t1;
|
||||
select x as FROMTO_x, y from t1 for system_time from timestamp '0-0-0 0:0:0' to timestamp @t1;
|
||||
select x as BETWAND_x, y from t1 for system_time between timestamp '0-0-0 0:0:0' and timestamp @t1;
|
||||
select x as ALL_x, y from t1 for system_time all;
|
||||
|
||||
--disable_query_log
|
||||
if ($default_engine == 'innodb')
|
||||
if ($default_engine == 'InnoDB')
|
||||
{
|
||||
select x as ASOF2_x, y from t1 for system_time as of @x0;
|
||||
select x as FROMTO2_x, y from t1 for system_time from @x0 to @x1;
|
||||
select x as BETWAND2_x, y from t1 for system_time between transaction @x0 and transaction @x1;
|
||||
}
|
||||
if ($default_engine != 'innodb')
|
||||
if ($default_engine != 'InnoDB')
|
||||
{
|
||||
select x as ASOF2_x, y from t1 for system_time as of @t0;
|
||||
select x as FROMTO2_x, y from t1 for system_time from '0-0-0 0:0:0' to @t1;
|
||||
select x as FROMTO2_x, y from t1 for system_time from timestamp '0-0-0 0:0:0' to timestamp @t1;
|
||||
select x as BETWAND2_x, y from t1 for system_time between timestamp '0-0-0 0:0:0' and timestamp @t1;
|
||||
}
|
||||
--enable_query_log
|
||||
@ -182,6 +182,35 @@ select * from t1, t2 for system_time all;
|
||||
--error ER_VERS_UNUSED_CLAUSE
|
||||
select * from t1 for system_time all, t2 for system_time all for system_time all;
|
||||
|
||||
--echo # TRANSACTION/TIMESTAMP specifier in SYSTEM_TIME [MDEV-14645, Issue #396]
|
||||
create or replace table t1 (x int) with system versioning engine myisam;
|
||||
--error ER_VERS_ENGINE_UNSUPPORTED
|
||||
select * from t1 for system_time as of transaction 1;
|
||||
create or replace table t1 (x int) with system versioning engine innodb;
|
||||
insert into t1 values (1);
|
||||
set @ts= now(6);
|
||||
delete from t1;
|
||||
select sys_trx_start from t1 for system_time all into @trx_start;
|
||||
|
||||
--echo ## ensure @trx_start is much lower than unix timestamp
|
||||
select @trx_start < unix_timestamp(@ts) - 100 as trx_start_good;
|
||||
|
||||
--echo ## TIMESTAMP specifier
|
||||
select * from t1 for system_time as of timestamp @ts;
|
||||
select * from t1 for system_time as of timestamp unix_timestamp(@ts);
|
||||
select * from t1 for system_time as of timestamp @trx_start;
|
||||
|
||||
--echo ## TRANSACTION specifier
|
||||
select * from t1 for system_time as of transaction @ts;
|
||||
select * from t1 for system_time as of transaction unix_timestamp(@ts);
|
||||
select * from t1 for system_time as of transaction @trx_start;
|
||||
|
||||
--echo ## no specifier (auto-detection)
|
||||
select * from t1 for system_time as of @ts;
|
||||
select * from t1 for system_time as of unix_timestamp(@ts);
|
||||
select * from t1 for system_time as of @trx_start;
|
||||
|
||||
|
||||
--echo ### Issue #365, bug 4 (related to #226, optimized fields)
|
||||
create or replace table t1 (i int, b int) with system versioning;
|
||||
insert into t1 values (0, 0), (0, 0);
|
||||
@ -216,6 +245,6 @@ select * from t1 where (a, 2) in ((1, 1), (2, 2)) and b = 1;
|
||||
drop view v1;
|
||||
drop table t1, t2;
|
||||
|
||||
call innodb_verify_vtq(30);
|
||||
call innodb_verify_vtq(32);
|
||||
|
||||
-- source suite/versioning/common_finish.inc
|
||||
|
@ -199,6 +199,6 @@ maria_declare_plugin(versioning)
|
||||
NULL, /* status variables */
|
||||
NULL, /* system variables */
|
||||
"1.0", /* string version */
|
||||
MariaDB_PLUGIN_MATURITY_EXPERIMENTAL /* maturity */
|
||||
MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
|
||||
}
|
||||
maria_declare_plugin_end;
|
||||
|
@ -988,6 +988,30 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class Item_longlong_typecast :public Item_int_func
|
||||
{
|
||||
public:
|
||||
Item_longlong_typecast(THD *thd, Item *a): Item_int_func(thd, a)
|
||||
{
|
||||
}
|
||||
const char *func_name() const { return "cast_as_longlong"; }
|
||||
const char *cast_type() const { return "longlong"; }
|
||||
const Type_handler *type_handler() const { return &type_handler_longlong; }
|
||||
longlong val_int()
|
||||
{
|
||||
return args[0]->val_int();
|
||||
}
|
||||
void fix_length_and_dec_generic() {}
|
||||
void fix_length_and_dec()
|
||||
{
|
||||
args[0]->type_handler()->Item_longlong_typecast_fix_length_and_dec(this);
|
||||
}
|
||||
bool need_parentheses_in_default() { return true; }
|
||||
Item *get_copy(THD *thd)
|
||||
{ return get_item_copy<Item_longlong_typecast>(thd, this); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
class Item_func_additive_op :public Item_num_op
|
||||
{
|
||||
|
@ -2652,6 +2652,26 @@ bool Item_datetime_typecast::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
|
||||
}
|
||||
|
||||
|
||||
void Item_datetime_from_unixtime_typecast::fix_length_and_dec()
|
||||
{
|
||||
Item_datetime_typecast::fix_length_and_dec();
|
||||
|
||||
switch (args[0]->result_type())
|
||||
{
|
||||
case INT_RESULT:
|
||||
case REAL_RESULT:
|
||||
case DECIMAL_RESULT:
|
||||
{
|
||||
Item_func_from_unixtime *a= new (thd->mem_root) Item_func_from_unixtime(thd, args[0]);
|
||||
a->fix_length_and_dec();
|
||||
args[0]= a;
|
||||
break;
|
||||
}
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
MAKEDATE(a,b) is a date function that creates a date value
|
||||
from a year and day value.
|
||||
|
@ -1184,6 +1184,20 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class Item_datetime_from_unixtime_typecast :public Item_datetime_typecast
|
||||
{
|
||||
THD *thd;
|
||||
public:
|
||||
Item_datetime_from_unixtime_typecast(THD *_thd, Item *a, uint dec_arg):
|
||||
Item_datetime_typecast(_thd, a, dec_arg), thd(_thd) {}
|
||||
const char *func_name() const { return "cast_as_datetime_from_unixtime"; }
|
||||
const char *cast_type() const { return "datetime"; }
|
||||
void fix_length_and_dec();
|
||||
Item *get_copy(THD *thd)
|
||||
{ return get_item_copy<Item_datetime_from_unixtime_typecast>(thd, this); }
|
||||
};
|
||||
|
||||
|
||||
class Item_func_makedate :public Item_datefunc
|
||||
{
|
||||
bool check_arguments() const
|
||||
|
@ -912,6 +912,48 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables, COND **where_expr
|
||||
if (tmp_from_ib || t->versioned_by_sql() ||
|
||||
thd->variables.vers_innodb_algorithm_simple)
|
||||
{
|
||||
if (vers_conditions)
|
||||
{
|
||||
if (vers_conditions.start)
|
||||
{
|
||||
switch (vers_conditions.unit_start)
|
||||
{
|
||||
case UNIT_TIMESTAMP:
|
||||
{
|
||||
vers_conditions.start= newx Item_datetime_from_unixtime_typecast(
|
||||
thd, vers_conditions.start, 6);
|
||||
break;
|
||||
}
|
||||
case UNIT_TRX_ID:
|
||||
{
|
||||
vers_conditions.start= newx Item_longlong_typecast(
|
||||
thd, vers_conditions.start);
|
||||
break;
|
||||
}
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
if (vers_conditions.end)
|
||||
{
|
||||
switch (vers_conditions.unit_end)
|
||||
{
|
||||
case UNIT_TIMESTAMP:
|
||||
{
|
||||
vers_conditions.end= newx Item_datetime_from_unixtime_typecast(
|
||||
thd, vers_conditions.end, 6);
|
||||
break;
|
||||
}
|
||||
case UNIT_TRX_ID:
|
||||
{
|
||||
vers_conditions.end= newx Item_longlong_typecast(
|
||||
thd, vers_conditions.end);
|
||||
break;
|
||||
}
|
||||
default:;
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (vers_conditions.type)
|
||||
{
|
||||
case FOR_SYSTEM_TIME_UNSPECIFIED:
|
||||
|
@ -4447,6 +4447,14 @@ bool Type_handler::
|
||||
}
|
||||
|
||||
|
||||
bool Type_handler::
|
||||
Item_longlong_typecast_fix_length_and_dec(Item_longlong_typecast *item) const
|
||||
{
|
||||
item->fix_length_and_dec_generic();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_SPATIAL
|
||||
|
||||
bool Type_handler_geometry::
|
||||
|
@ -55,6 +55,7 @@ class Item_char_typecast;
|
||||
class Item_time_typecast;
|
||||
class Item_date_typecast;
|
||||
class Item_datetime_typecast;
|
||||
class Item_longlong_typecast;
|
||||
class Item_func_plus;
|
||||
class Item_func_minus;
|
||||
class Item_func_mul;
|
||||
@ -983,6 +984,8 @@ public:
|
||||
Item_date_typecast_fix_length_and_dec(Item_date_typecast *item) const;
|
||||
virtual bool
|
||||
Item_datetime_typecast_fix_length_and_dec(Item_datetime_typecast *item) const;
|
||||
virtual bool
|
||||
Item_longlong_typecast_fix_length_and_dec(Item_longlong_typecast *item) const;
|
||||
|
||||
virtual bool
|
||||
Item_func_plus_fix_length_and_dec(Item_func_plus *func) const= 0;
|
||||
|
Reference in New Issue
Block a user