Skip to content

Commit 1668efb

Browse files
committed
MDEV-14645: AS OF TIMESTAMP is misused as TRX_ID [fixes #396]
1 parent 7655696 commit 1668efb

File tree

10 files changed

+194
-14
lines changed

10 files changed

+194
-14
lines changed

mysql-test/suite/versioning/r/derived.result

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,12 +212,12 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
212212
1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 Using where
213213
1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00 Using where; Using join buffer (flat, BNL join)
214214
Query A:
215-
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))
215+
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)))
216216
id select_type table type possible_keys key key_len ref rows filtered Extra
217217
1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 Using where
218218
1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00 Using where; Using join buffer (flat, BNL join)
219219
Query B:
220-
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))
220+
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)))
221221
Fine result: queries A and B are equal.
222222
## LEFT JOIN: t1, t2 versioned
223223
select * from (

mysql-test/suite/versioning/r/select.result

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ ASOF_x y
4040
7 107
4141
8 108
4242
9 109
43-
select x as FROMTO_x, y from t1 for system_time from '0-0-0 0:0:0' to timestamp @t1;
43+
select x as FROMTO_x, y from t1 for system_time from timestamp '0-0-0 0:0:0' to timestamp @t1;
4444
FROMTO_x y
4545
0 100
4646
1 101
@@ -52,7 +52,7 @@ FROMTO_x y
5252
7 107
5353
8 108
5454
9 109
55-
select x as BETWAND_x, y from t1 for system_time between '0-0-0 0:0:0' and timestamp @t1;
55+
select x as BETWAND_x, y from t1 for system_time between timestamp '0-0-0 0:0:0' and timestamp @t1;
5656
BETWAND_x y
5757
0 100
5858
1 101
@@ -282,6 +282,44 @@ x y
282282
2 1
283283
select * from t1 for system_time all, t2 for system_time all for system_time all;
284284
ERROR HY000: Unused clause: 'SYSTEM_TIME'
285+
# TRANSACTION/TIMESTAMP specifier in SYSTEM_TIME [MDEV-14645, Issue #396]
286+
create or replace table t1 (x int) with system versioning engine myisam;
287+
select * from t1 for system_time as of transaction 1;
288+
ERROR HY000: Engine does not support System Versioning for `t1`
289+
create or replace table t1 (x int) with system versioning engine innodb;
290+
insert into t1 values (1);
291+
set @ts= now(6);
292+
delete from t1;
293+
select sys_trx_start from t1 for system_time all into @trx_start;
294+
## ensure @trx_start is much lower than unix timestamp
295+
select @trx_start < unix_timestamp(@ts) - 100 as trx_start_good;
296+
trx_start_good
297+
1
298+
## TIMESTAMP specifier
299+
select * from t1 for system_time as of timestamp @ts;
300+
x
301+
1
302+
select * from t1 for system_time as of timestamp unix_timestamp(@ts);
303+
x
304+
1
305+
select * from t1 for system_time as of timestamp @trx_start;
306+
x
307+
## TRANSACTION specifier
308+
select * from t1 for system_time as of transaction @ts;
309+
x
310+
select * from t1 for system_time as of transaction unix_timestamp(@ts);
311+
x
312+
select * from t1 for system_time as of transaction @trx_start;
313+
x
314+
1
315+
## no specifier (auto-detection)
316+
select * from t1 for system_time as of @ts;
317+
x
318+
select * from t1 for system_time as of unix_timestamp(@ts);
319+
x
320+
select * from t1 for system_time as of @trx_start;
321+
x
322+
1
285323
### Issue #365, bug 4 (related to #226, optimized fields)
286324
create or replace table t1 (i int, b int) with system versioning;
287325
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;
320358
a b
321359
drop view v1;
322360
drop table t1, t2;
323-
call innodb_verify_vtq(30);
361+
call innodb_verify_vtq(32);
324362
No A B C D
325363
1 1 1 1 1
326364
2 1 1 1 1
@@ -352,3 +390,5 @@ No A B C D
352390
28 1 1 1 1
353391
29 1 1 1 1
354392
30 1 1 1 1
393+
31 1 1 1 1
394+
32 1 1 1 1

mysql-test/suite/versioning/t/select.test

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ insert into t1 (x, y) values
2121
(9, 109);
2222

2323
set @t0= now(6);
24-
if ($default_engine == 'innodb')
24+
if ($default_engine == 'InnoDB')
2525
{
2626
--disable_query_log
2727
select sys_trx_start from t1 limit 1 into @x0;
@@ -33,7 +33,7 @@ delete from t1 where x > 7;
3333

3434
insert into t1(x, y) values(3, 33);
3535
select sys_trx_start from t1 where x = 3 and y = 33 into @t1;
36-
if ($default_engine == 'innodb')
36+
if ($default_engine == 'InnoDB')
3737
{
3838
--disable_query_log
3939
set @x1= @t1;
@@ -43,21 +43,21 @@ if ($default_engine == 'innodb')
4343

4444
select x, y from t1;
4545
select x as ASOF_x, y from t1 for system_time as of timestamp @t0;
46-
select x as FROMTO_x, y from t1 for system_time from '0-0-0 0:0:0' to timestamp @t1;
47-
select x as BETWAND_x, y from t1 for system_time between '0-0-0 0:0:0' and timestamp @t1;
46+
select x as FROMTO_x, y from t1 for system_time from timestamp '0-0-0 0:0:0' to timestamp @t1;
47+
select x as BETWAND_x, y from t1 for system_time between timestamp '0-0-0 0:0:0' and timestamp @t1;
4848
select x as ALL_x, y from t1 for system_time all;
4949

5050
--disable_query_log
51-
if ($default_engine == 'innodb')
51+
if ($default_engine == 'InnoDB')
5252
{
5353
select x as ASOF2_x, y from t1 for system_time as of @x0;
5454
select x as FROMTO2_x, y from t1 for system_time from @x0 to @x1;
5555
select x as BETWAND2_x, y from t1 for system_time between transaction @x0 and transaction @x1;
5656
}
57-
if ($default_engine != 'innodb')
57+
if ($default_engine != 'InnoDB')
5858
{
5959
select x as ASOF2_x, y from t1 for system_time as of @t0;
60-
select x as FROMTO2_x, y from t1 for system_time from '0-0-0 0:0:0' to @t1;
60+
select x as FROMTO2_x, y from t1 for system_time from timestamp '0-0-0 0:0:0' to timestamp @t1;
6161
select x as BETWAND2_x, y from t1 for system_time between timestamp '0-0-0 0:0:0' and timestamp @t1;
6262
}
6363
--enable_query_log
@@ -182,6 +182,35 @@ select * from t1, t2 for system_time all;
182182
--error ER_VERS_UNUSED_CLAUSE
183183
select * from t1 for system_time all, t2 for system_time all for system_time all;
184184

185+
--echo # TRANSACTION/TIMESTAMP specifier in SYSTEM_TIME [MDEV-14645, Issue #396]
186+
create or replace table t1 (x int) with system versioning engine myisam;
187+
--error ER_VERS_ENGINE_UNSUPPORTED
188+
select * from t1 for system_time as of transaction 1;
189+
create or replace table t1 (x int) with system versioning engine innodb;
190+
insert into t1 values (1);
191+
set @ts= now(6);
192+
delete from t1;
193+
select sys_trx_start from t1 for system_time all into @trx_start;
194+
195+
--echo ## ensure @trx_start is much lower than unix timestamp
196+
select @trx_start < unix_timestamp(@ts) - 100 as trx_start_good;
197+
198+
--echo ## TIMESTAMP specifier
199+
select * from t1 for system_time as of timestamp @ts;
200+
select * from t1 for system_time as of timestamp unix_timestamp(@ts);
201+
select * from t1 for system_time as of timestamp @trx_start;
202+
203+
--echo ## TRANSACTION specifier
204+
select * from t1 for system_time as of transaction @ts;
205+
select * from t1 for system_time as of transaction unix_timestamp(@ts);
206+
select * from t1 for system_time as of transaction @trx_start;
207+
208+
--echo ## no specifier (auto-detection)
209+
select * from t1 for system_time as of @ts;
210+
select * from t1 for system_time as of unix_timestamp(@ts);
211+
select * from t1 for system_time as of @trx_start;
212+
213+
185214
--echo ### Issue #365, bug 4 (related to #226, optimized fields)
186215
create or replace table t1 (i int, b int) with system versioning;
187216
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;
216245
drop view v1;
217246
drop table t1, t2;
218247

219-
call innodb_verify_vtq(30);
248+
call innodb_verify_vtq(32);
220249

221250
-- source suite/versioning/common_finish.inc

plugin/versioning/versioning.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,6 @@ maria_declare_plugin(versioning)
199199
NULL, /* status variables */
200200
NULL, /* system variables */
201201
"1.0", /* string version */
202-
MariaDB_PLUGIN_MATURITY_EXPERIMENTAL /* maturity */
202+
MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
203203
}
204204
maria_declare_plugin_end;

sql/item_func.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -988,6 +988,30 @@ class Item_double_typecast :public Item_real_func
988988
};
989989

990990

991+
class Item_longlong_typecast :public Item_int_func
992+
{
993+
public:
994+
Item_longlong_typecast(THD *thd, Item *a): Item_int_func(thd, a)
995+
{
996+
}
997+
const char *func_name() const { return "cast_as_longlong"; }
998+
const char *cast_type() const { return "longlong"; }
999+
const Type_handler *type_handler() const { return &type_handler_longlong; }
1000+
longlong val_int()
1001+
{
1002+
return args[0]->val_int();
1003+
}
1004+
void fix_length_and_dec_generic() {}
1005+
void fix_length_and_dec()
1006+
{
1007+
args[0]->type_handler()->Item_longlong_typecast_fix_length_and_dec(this);
1008+
}
1009+
bool need_parentheses_in_default() { return true; }
1010+
Item *get_copy(THD *thd)
1011+
{ return get_item_copy<Item_longlong_typecast>(thd, this); }
1012+
};
1013+
1014+
9911015

9921016
class Item_func_additive_op :public Item_num_op
9931017
{

sql/item_timefunc.cc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2652,6 +2652,26 @@ bool Item_datetime_typecast::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
26522652
}
26532653

26542654

2655+
void Item_datetime_from_unixtime_typecast::fix_length_and_dec()
2656+
{
2657+
Item_datetime_typecast::fix_length_and_dec();
2658+
2659+
switch (args[0]->result_type())
2660+
{
2661+
case INT_RESULT:
2662+
case REAL_RESULT:
2663+
case DECIMAL_RESULT:
2664+
{
2665+
Item_func_from_unixtime *a= new (thd->mem_root) Item_func_from_unixtime(thd, args[0]);
2666+
a->fix_length_and_dec();
2667+
args[0]= a;
2668+
break;
2669+
}
2670+
default:;
2671+
}
2672+
}
2673+
2674+
26552675
/**
26562676
MAKEDATE(a,b) is a date function that creates a date value
26572677
from a year and day value.

sql/item_timefunc.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1184,6 +1184,20 @@ class Item_datetime_typecast :public Item_temporal_typecast
11841184
};
11851185

11861186

1187+
class Item_datetime_from_unixtime_typecast :public Item_datetime_typecast
1188+
{
1189+
THD *thd;
1190+
public:
1191+
Item_datetime_from_unixtime_typecast(THD *_thd, Item *a, uint dec_arg):
1192+
Item_datetime_typecast(_thd, a, dec_arg), thd(_thd) {}
1193+
const char *func_name() const { return "cast_as_datetime_from_unixtime"; }
1194+
const char *cast_type() const { return "datetime"; }
1195+
void fix_length_and_dec();
1196+
Item *get_copy(THD *thd)
1197+
{ return get_item_copy<Item_datetime_from_unixtime_typecast>(thd, this); }
1198+
};
1199+
1200+
11871201
class Item_func_makedate :public Item_datefunc
11881202
{
11891203
bool check_arguments() const

sql/sql_select.cc

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -912,6 +912,48 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables, COND **where_expr
912912
if (tmp_from_ib || t->versioned_by_sql() ||
913913
thd->variables.vers_innodb_algorithm_simple)
914914
{
915+
if (vers_conditions)
916+
{
917+
if (vers_conditions.start)
918+
{
919+
switch (vers_conditions.unit_start)
920+
{
921+
case UNIT_TIMESTAMP:
922+
{
923+
vers_conditions.start= newx Item_datetime_from_unixtime_typecast(
924+
thd, vers_conditions.start, 6);
925+
break;
926+
}
927+
case UNIT_TRX_ID:
928+
{
929+
vers_conditions.start= newx Item_longlong_typecast(
930+
thd, vers_conditions.start);
931+
break;
932+
}
933+
default:;
934+
}
935+
}
936+
937+
if (vers_conditions.end)
938+
{
939+
switch (vers_conditions.unit_end)
940+
{
941+
case UNIT_TIMESTAMP:
942+
{
943+
vers_conditions.end= newx Item_datetime_from_unixtime_typecast(
944+
thd, vers_conditions.end, 6);
945+
break;
946+
}
947+
case UNIT_TRX_ID:
948+
{
949+
vers_conditions.end= newx Item_longlong_typecast(
950+
thd, vers_conditions.end);
951+
break;
952+
}
953+
default:;
954+
}
955+
}
956+
}
915957
switch (vers_conditions.type)
916958
{
917959
case FOR_SYSTEM_TIME_UNSPECIFIED:

sql/sql_type.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4447,6 +4447,14 @@ bool Type_handler::
44474447
}
44484448

44494449

4450+
bool Type_handler::
4451+
Item_longlong_typecast_fix_length_and_dec(Item_longlong_typecast *item) const
4452+
{
4453+
item->fix_length_and_dec_generic();
4454+
return false;
4455+
}
4456+
4457+
44504458
#ifdef HAVE_SPATIAL
44514459

44524460
bool Type_handler_geometry::

sql/sql_type.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class Item_char_typecast;
5555
class Item_time_typecast;
5656
class Item_date_typecast;
5757
class Item_datetime_typecast;
58+
class Item_longlong_typecast;
5859
class Item_func_plus;
5960
class Item_func_minus;
6061
class Item_func_mul;
@@ -983,6 +984,8 @@ class Type_handler
983984
Item_date_typecast_fix_length_and_dec(Item_date_typecast *item) const;
984985
virtual bool
985986
Item_datetime_typecast_fix_length_and_dec(Item_datetime_typecast *item) const;
987+
virtual bool
988+
Item_longlong_typecast_fix_length_and_dec(Item_longlong_typecast *item) const;
986989

987990
virtual bool
988991
Item_func_plus_fix_length_and_dec(Item_func_plus *func) const= 0;

0 commit comments

Comments
 (0)