Commit 1668efb7 authored by Aleksey Midenkov's avatar Aleksey Midenkov

MDEV-14645: AS OF TIMESTAMP is misused as TRX_ID [fixes #396]

parent 76556960
......@@ -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 @@ class Item_double_typecast :public Item_real_func
};
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 @@ class Item_datetime_typecast :public Item_temporal_typecast
};
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 @@ class Type_handler
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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment