diff --git a/mysql-test/suite/versioning/r/derived.result b/mysql-test/suite/versioning/r/derived.result index d5b2b60ae38..6b71f120cc2 100644 --- a/mysql-test/suite/versioning/r/derived.result +++ b/mysql-test/suite/versioning/r/derived.result @@ -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` > (current_timestamp(6)) and `test`.`t1`.`sys_trx_start` <= (current_timestamp(6)) and `test`.`t2`.`sys_trx_end` > (current_timestamp(6)) and `test`.`t2`.`sys_trx_start` <= (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` > (cast(current_timestamp(6) as datetime(6))) and `test`.`t1`.`sys_trx_start` <= (cast(current_timestamp(6) as datetime(6))) and `test`.`t2`.`sys_trx_end` > (cast(current_timestamp(6) as datetime(6))) and `test`.`t2`.`sys_trx_start` <= (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` > (current_timestamp(6)) and `test`.`t1`.`sys_trx_start` <= (current_timestamp(6)) and `test`.`t2`.`sys_trx_end` > (current_timestamp(6)) and `test`.`t2`.`sys_trx_start` <= (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` > (cast(current_timestamp(6) as datetime(6))) and `test`.`t1`.`sys_trx_start` <= (cast(current_timestamp(6) as datetime(6))) and `test`.`t2`.`sys_trx_end` > (cast(current_timestamp(6) as datetime(6))) and `test`.`t2`.`sys_trx_start` <= (cast(current_timestamp(6) as datetime(6))) Fine result: queries A and B are equal. ## LEFT JOIN: t1, t2 versioned select * from ( diff --git a/mysql-test/suite/versioning/r/select.result b/mysql-test/suite/versioning/r/select.result index 23d4202a5a4..8557992432c 100644 --- a/mysql-test/suite/versioning/r/select.result +++ b/mysql-test/suite/versioning/r/select.result @@ -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 diff --git a/mysql-test/suite/versioning/t/select.test b/mysql-test/suite/versioning/t/select.test index f06fca1dbe4..68678146ccc 100644 --- a/mysql-test/suite/versioning/t/select.test +++ b/mysql-test/suite/versioning/t/select.test @@ -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 diff --git a/plugin/versioning/versioning.cc b/plugin/versioning/versioning.cc index 150ed23dcff..93560f4c860 100644 --- a/plugin/versioning/versioning.cc +++ b/plugin/versioning/versioning.cc @@ -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; diff --git a/sql/item_func.h b/sql/item_func.h index f6640c9b719..4c78edcb1fa 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -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(thd, this); } +}; + + class Item_func_additive_op :public Item_num_op { diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index fd170a707c9..4563f4555f5 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -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. diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index adc7b2535a9..878179105be 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -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(thd, this); } +}; + + class Item_func_makedate :public Item_datefunc { bool check_arguments() const diff --git a/sql/sql_select.cc b/sql/sql_select.cc index cd6c7877354..dca4b60dc4d 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -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: diff --git a/sql/sql_type.cc b/sql/sql_type.cc index b4860176c0c..e1fb9cb51a0 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -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:: diff --git a/sql/sql_type.h b/sql/sql_type.h index c400420586e..ac95c5a9c88 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -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;