Commit c6bff469 authored by Nikita Malyavin's avatar Nikita Malyavin

MDEV-16026 MDEV-16481 refactor Sys_var_vers_asof

MDEV-16026: Forbid global system_versioning_asof in non-default time zone

* store `system_versioning_asof` in unix time;
* both session and global vars are processed in session timezone;
* setting `default` does not copy global variable anymore. Instead, it sets
  system_time to SYSTEM_TIME_UNSPECIFIED, which means that no 'AS OF' time
  is applied and `now()` can be assumed

As a regression, we cannot assign values below 1970 (UTC) anymore

MDEV-16481: set global system_versioning_asof=sf() crashes in specific case

* sys_vars.h: add `MYSQL_TIME` field to `set_var::save_result`
* sys_vars.ic: get rid of calling `var->value->get_date()` from
 `Sys_var_vers_asof::update()`
* versioning.sysvars: add test; remove double warning

refactor Sys_var_vers_asof

* inherit from sys_var rather than Sys_var_enum
* remove junk "DEFAULT" keyword. There is DEFAULT in SQL grammar for it.
* make all conversions in check() to avoid possible errors
* avoid double var->value evaluation, which could
  consequence in undefined behavior
parent f50eb0d3
...@@ -3959,7 +3959,7 @@ VARIABLE_COMMENT Default value for the FOR SYSTEM_TIME AS OF clause ...@@ -3959,7 +3959,7 @@ VARIABLE_COMMENT Default value for the FOR SYSTEM_TIME AS OF clause
NUMERIC_MIN_VALUE NULL NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST DEFAULT ENUM_VALUE_LIST NULL
READ_ONLY NO READ_ONLY NO
COMMAND_LINE_ARGUMENT NULL COMMAND_LINE_ARGUMENT NULL
VARIABLE_NAME TABLE_DEFINITION_CACHE VARIABLE_NAME TABLE_DEFINITION_CACHE
......
create table t (a int) with system versioning; create table t (a int) with system versioning;
set @before= UNIX_TIMESTAMP(now(6));
insert into t values (1); insert into t values (1);
set @after= UNIX_TIMESTAMP(now(6));
update t set a= 2; update t set a= 2;
show global variables like 'system_versioning_asof'; show global variables like 'system_versioning_asof';
Variable_name Value Variable_name Value
...@@ -56,65 +58,71 @@ ERROR 42000: Variable 'system_versioning_asof' can't be set to the value of '201 ...@@ -56,65 +58,71 @@ ERROR 42000: Variable 'system_versioning_asof' can't be set to the value of '201
set system_versioning_asof= '0000-00-00 00:00'; set system_versioning_asof= '0000-00-00 00:00';
ERROR 42000: Variable 'system_versioning_asof' can't be set to the value of '0000-00-00 00:00' ERROR 42000: Variable 'system_versioning_asof' can't be set to the value of '0000-00-00 00:00'
# GLOBAL @@system_versioning_asof # GLOBAL @@system_versioning_asof
set global system_versioning_asof= '1911-11-11 11:11:11.1111119'; set global system_versioning_asof= '1991-11-11 11:11:11.1111119';
Warnings: Warnings:
Note 1292 Truncated incorrect datetime value: '1911-11-11 11:11:11.1111119' Note 1292 Truncated incorrect datetime value: '1991-11-11 11:11:11.1111119'
Note 1292 Truncated incorrect datetime value: '1911-11-11 11:11:11.1111119'
show global variables like 'system_versioning_asof'; show global variables like 'system_versioning_asof';
Variable_name Value Variable_name Value
system_versioning_asof 1911-11-11 11:11:11.111111 system_versioning_asof 1991-11-11 11:11:11.111111
set global system_versioning_asof= '1900-01-01 00:00:00'; set global system_versioning_asof= '1990-01-01 00:00:00';
show global variables like 'system_versioning_asof'; show global variables like 'system_versioning_asof';
Variable_name Value Variable_name Value
system_versioning_asof 1900-01-01 00:00:00.000000 system_versioning_asof 1990-01-01 00:00:00.000000
set global system_versioning_asof= timestamp'1911-11-11 11:11:11.1111119'; set global system_versioning_asof= timestamp'1991-11-11 11:11:11.1111119';
Warnings: Warnings:
Note 1292 Truncated incorrect datetime value: '1911-11-11 11:11:11.1111119' Note 1292 Truncated incorrect datetime value: '1991-11-11 11:11:11.1111119'
show global variables like 'system_versioning_asof'; show global variables like 'system_versioning_asof';
Variable_name Value Variable_name Value
system_versioning_asof 1911-11-11 11:11:11.111111 system_versioning_asof 1991-11-11 11:11:11.111111
set @ts= timestamp'1900-01-01 00:00:00'; set @ts= timestamp'1990-01-01 00:00:00';
set global system_versioning_asof= @ts; set global system_versioning_asof= @ts;
show global variables like 'system_versioning_asof'; show global variables like 'system_versioning_asof';
Variable_name Value Variable_name Value
system_versioning_asof 1900-01-01 00:00:00.000000 system_versioning_asof 1990-01-01 00:00:00.000000
set global system_versioning_asof= default; set global system_versioning_asof= default;
select @@global.system_versioning_asof; select @@global.system_versioning_asof;
@@global.system_versioning_asof @@global.system_versioning_asof
DEFAULT DEFAULT
# SESSION @@system_versioning_asof # SESSION @@system_versioning_asof
set system_versioning_asof= '1911-11-11 11:11:11.1111119'; set system_versioning_asof= '1991-11-11 11:11:11.1111119';
Warnings: Warnings:
Note 1292 Truncated incorrect datetime value: '1911-11-11 11:11:11.1111119' Note 1292 Truncated incorrect datetime value: '1991-11-11 11:11:11.1111119'
Note 1292 Truncated incorrect datetime value: '1911-11-11 11:11:11.1111119'
show variables like 'system_versioning_asof'; show variables like 'system_versioning_asof';
Variable_name Value Variable_name Value
system_versioning_asof 1911-11-11 11:11:11.111111 system_versioning_asof 1991-11-11 11:11:11.111111
set system_versioning_asof= '1900-01-01 00:00:00'; set system_versioning_asof= '1990-01-01 00:00:00';
show variables like 'system_versioning_asof'; show variables like 'system_versioning_asof';
Variable_name Value Variable_name Value
system_versioning_asof 1900-01-01 00:00:00.000000 system_versioning_asof 1990-01-01 00:00:00.000000
set system_versioning_asof= timestamp'1911-11-11 11:11:11.1111119'; set system_versioning_asof= timestamp'1991-11-11 11:11:11.1111119';
Warnings: Warnings:
Note 1292 Truncated incorrect datetime value: '1911-11-11 11:11:11.1111119' Note 1292 Truncated incorrect datetime value: '1991-11-11 11:11:11.1111119'
show variables like 'system_versioning_asof'; show variables like 'system_versioning_asof';
Variable_name Value Variable_name Value
system_versioning_asof 1911-11-11 11:11:11.111111 system_versioning_asof 1991-11-11 11:11:11.111111
set @ts= timestamp'1900-01-01 00:00:00'; set @ts= timestamp'1990-01-01 00:00:00';
set system_versioning_asof= @ts; set system_versioning_asof= @ts;
show variables like 'system_versioning_asof'; show variables like 'system_versioning_asof';
Variable_name Value Variable_name Value
system_versioning_asof 1900-01-01 00:00:00.000000 system_versioning_asof 1990-01-01 00:00:00.000000
# DEFAULT: value is copied from GLOBAL to SESSION # DEFAULT: value is copied from GLOBAL to SESSION
set global system_versioning_asof= timestamp'1911-11-11 11:11:11.111111'; set global time_zone= "+03:00";
set system_versioning_asof= '1900-01-01 00:00:00'; set time_zone= "+10:00";
set global system_versioning_asof= timestamp'1991-11-11 11:11:11.111111';
set system_versioning_asof= '1990-01-01 00:00:00';
select @@global.system_versioning_asof != @@system_versioning_asof as different; select @@global.system_versioning_asof != @@system_versioning_asof as different;
different different
1 1
set system_versioning_asof= default; set system_versioning_asof= default;
select @@global.system_versioning_asof != @@system_versioning_asof as different;
different
1
set global system_versioning_asof= default;
select @@global.system_versioning_asof = @@system_versioning_asof as equal; select @@global.system_versioning_asof = @@system_versioning_asof as equal;
equal equal
1 1
set global time_zone= DEFAULT;
set time_zone= DEFAULT;
set global system_versioning_asof= DEFAULT; set global system_versioning_asof= DEFAULT;
set system_versioning_asof= DEFAULT; set system_versioning_asof= DEFAULT;
select @@global.system_versioning_asof, @@system_versioning_asof; select @@global.system_versioning_asof, @@system_versioning_asof;
...@@ -142,6 +150,77 @@ select * from t for system_time between '1970-01-01 00:00' and current_timestamp ...@@ -142,6 +150,77 @@ select * from t for system_time between '1970-01-01 00:00' and current_timestamp
a a
2 2
1 1
# MDEV-16026: Global system_versioning_asof must not be used if client sessions can have non-default time zone
# changing time zone should not abuse `system_versioning_asof`
set session time_zone = '+10:00';
set global system_versioning_asof = '1999-09-08 00:00:00.000000';
show global variables like 'system_versioning_asof';
Variable_name Value
system_versioning_asof 1999-09-08 00:00:00.000000
set session time_zone = '+03:00';
show global variables like 'system_versioning_asof';
Variable_name Value
system_versioning_asof 1999-09-07 17:00:00.000000
set session time_zone = '+03:00';
set session system_versioning_asof = '2000-09-08 00:00:00.000000';
show session variables like 'system_versioning_asof';
Variable_name Value
system_versioning_asof 2000-09-08 00:00:00.000000
set session time_zone = '+10:00';
show session variables like 'system_versioning_asof';
Variable_name Value
system_versioning_asof 2000-09-08 07:00:00.000000
# global and local time zones should not interfere
show global variables like 'system_versioning_asof';
Variable_name Value
system_versioning_asof 1999-09-08 00:00:00.000000
set time_zone= "+10:00";
set system_versioning_asof= FROM_UNIXTIME(@before);
select * from t as empty;
a
set system_versioning_asof= FROM_UNIXTIME(@after);
select * from t as nonempty;
a
1
set time_zone= "+03:00";
set system_versioning_asof= FROM_UNIXTIME(@before);
select * from t as empty;
a
set system_versioning_asof= FROM_UNIXTIME(@after);
select * from t as nonempty;
a
1
set global system_versioning_asof= FROM_UNIXTIME(@after);
select * from t as nonempty;
a
1
connect subcon,127.0.0.1,root,,,$SERVER_MYPORT_1;
connection subcon;
select * from t as nonempty;
a
1
disconnect subcon;
connection default;
set global system_versioning_asof= FROM_UNIXTIME(@before);
select * from t as nonempty;
a
1
connect subcon,127.0.0.1,root,,,$SERVER_MYPORT_1;
connection subcon;
select * from t as empty;
a
disconnect subcon;
connection default;
# MDEV-16481: set global system_versioning_asof=sf() crashes in specific case
# Using global variable inside a stored function should not crash
create or replace function now_global() returns timestamp
return CONVERT_TZ(now(), @@session.time_zone, @@global.time_zone);
set global system_versioning_asof= now_global();
drop function now_global;
set global time_zone= "SYSTEM";
set time_zone= "SYSTEM";
set global system_versioning_asof= default;
set system_versioning_asof= default;
show status like "Feature_system_versioning"; show status like "Feature_system_versioning";
Variable_name Value Variable_name Value
Feature_system_versioning 2 Feature_system_versioning 2
...@@ -153,7 +232,7 @@ create or replace table t1 (x int) with system versioning; ...@@ -153,7 +232,7 @@ create or replace table t1 (x int) with system versioning;
create or replace table t2 (y int); create or replace table t2 (y int);
insert into t1 values (1); insert into t1 values (1);
insert into t2 values (1); insert into t2 values (1);
set system_versioning_asof= '1970-01-01 00:00:00'; set system_versioning_asof= '1970-01-02 00:00:00';
delete t1, t2 from t1 join t2 where t1.x = t2.y; delete t1, t2 from t1 join t2 where t1.x = t2.y;
select * from t1 for system_time as of timestamp now(6); select * from t1 for system_time as of timestamp now(6);
x x
......
create table t (a int) with system versioning; create table t (a int) with system versioning;
set @before= UNIX_TIMESTAMP(now(6));
insert into t values (1); insert into t values (1);
set @after= UNIX_TIMESTAMP(now(6));
update t set a= 2; update t set a= 2;
show global variables like 'system_versioning_asof'; show global variables like 'system_versioning_asof';
...@@ -51,16 +53,16 @@ set system_versioning_asof= '2011-00-28 00:00'; ...@@ -51,16 +53,16 @@ set system_versioning_asof= '2011-00-28 00:00';
set system_versioning_asof= '0000-00-00 00:00'; set system_versioning_asof= '0000-00-00 00:00';
--echo # GLOBAL @@system_versioning_asof --echo # GLOBAL @@system_versioning_asof
set global system_versioning_asof= '1911-11-11 11:11:11.1111119'; set global system_versioning_asof= '1991-11-11 11:11:11.1111119';
show global variables like 'system_versioning_asof'; show global variables like 'system_versioning_asof';
set global system_versioning_asof= '1900-01-01 00:00:00'; set global system_versioning_asof= '1990-01-01 00:00:00';
show global variables like 'system_versioning_asof'; show global variables like 'system_versioning_asof';
set global system_versioning_asof= timestamp'1911-11-11 11:11:11.1111119'; set global system_versioning_asof= timestamp'1991-11-11 11:11:11.1111119';
show global variables like 'system_versioning_asof'; show global variables like 'system_versioning_asof';
set @ts= timestamp'1900-01-01 00:00:00'; set @ts= timestamp'1990-01-01 00:00:00';
set global system_versioning_asof= @ts; set global system_versioning_asof= @ts;
show global variables like 'system_versioning_asof'; show global variables like 'system_versioning_asof';
...@@ -68,26 +70,32 @@ set global system_versioning_asof= default; ...@@ -68,26 +70,32 @@ set global system_versioning_asof= default;
select @@global.system_versioning_asof; select @@global.system_versioning_asof;
--echo # SESSION @@system_versioning_asof --echo # SESSION @@system_versioning_asof
set system_versioning_asof= '1911-11-11 11:11:11.1111119'; set system_versioning_asof= '1991-11-11 11:11:11.1111119';
show variables like 'system_versioning_asof'; show variables like 'system_versioning_asof';
set system_versioning_asof= '1900-01-01 00:00:00'; set system_versioning_asof= '1990-01-01 00:00:00';
show variables like 'system_versioning_asof'; show variables like 'system_versioning_asof';
set system_versioning_asof= timestamp'1911-11-11 11:11:11.1111119'; set system_versioning_asof= timestamp'1991-11-11 11:11:11.1111119';
show variables like 'system_versioning_asof'; show variables like 'system_versioning_asof';
set @ts= timestamp'1900-01-01 00:00:00'; set @ts= timestamp'1990-01-01 00:00:00';
set system_versioning_asof= @ts; set system_versioning_asof= @ts;
show variables like 'system_versioning_asof'; show variables like 'system_versioning_asof';
--echo # DEFAULT: value is copied from GLOBAL to SESSION --echo # DEFAULT: value is copied from GLOBAL to SESSION
set global system_versioning_asof= timestamp'1911-11-11 11:11:11.111111'; set global time_zone= "+03:00";
set system_versioning_asof= '1900-01-01 00:00:00'; set time_zone= "+10:00";
set global system_versioning_asof= timestamp'1991-11-11 11:11:11.111111';
set system_versioning_asof= '1990-01-01 00:00:00';
select @@global.system_versioning_asof != @@system_versioning_asof as different; select @@global.system_versioning_asof != @@system_versioning_asof as different;
set system_versioning_asof= default; set system_versioning_asof= default;
select @@global.system_versioning_asof != @@system_versioning_asof as different;
set global system_versioning_asof= default;
select @@global.system_versioning_asof = @@system_versioning_asof as equal; select @@global.system_versioning_asof = @@system_versioning_asof as equal;
set global time_zone= DEFAULT;
set time_zone= DEFAULT;
set global system_versioning_asof= DEFAULT; set global system_versioning_asof= DEFAULT;
set system_versioning_asof= DEFAULT; set system_versioning_asof= DEFAULT;
select @@global.system_versioning_asof, @@system_versioning_asof; select @@global.system_versioning_asof, @@system_versioning_asof;
...@@ -100,6 +108,65 @@ select * from t for system_time all; ...@@ -100,6 +108,65 @@ select * from t for system_time all;
select * from t for system_time from '1970-01-01 00:00' to current_timestamp(6); select * from t for system_time from '1970-01-01 00:00' to current_timestamp(6);
select * from t for system_time between '1970-01-01 00:00' and current_timestamp(6); select * from t for system_time between '1970-01-01 00:00' and current_timestamp(6);
-- echo # MDEV-16026: Global system_versioning_asof must not be used if client sessions can have non-default time zone
-- echo # changing time zone should not abuse `system_versioning_asof`
set session time_zone = '+10:00';
set global system_versioning_asof = '1999-09-08 00:00:00.000000';
show global variables like 'system_versioning_asof';
set session time_zone = '+03:00';
show global variables like 'system_versioning_asof';
set session time_zone = '+03:00';
set session system_versioning_asof = '2000-09-08 00:00:00.000000';
show session variables like 'system_versioning_asof';
set session time_zone = '+10:00';
show session variables like 'system_versioning_asof';
-- echo # global and local time zones should not interfere
show global variables like 'system_versioning_asof';
set time_zone= "+10:00";
set system_versioning_asof= FROM_UNIXTIME(@before);
select * from t as empty;
set system_versioning_asof= FROM_UNIXTIME(@after);
select * from t as nonempty;
set time_zone= "+03:00";
set system_versioning_asof= FROM_UNIXTIME(@before);
select * from t as empty;
set system_versioning_asof= FROM_UNIXTIME(@after);
select * from t as nonempty;
set global system_versioning_asof= FROM_UNIXTIME(@after);
select * from t as nonempty;
--connect (subcon,127.0.0.1,root,,,$SERVER_MYPORT_1)
--connection subcon
select * from t as nonempty;
--disconnect subcon
--connection default
set global system_versioning_asof= FROM_UNIXTIME(@before);
select * from t as nonempty;
--connect (subcon,127.0.0.1,root,,,$SERVER_MYPORT_1)
--connection subcon
select * from t as empty;
--disconnect subcon
--connection default
--echo # MDEV-16481: set global system_versioning_asof=sf() crashes in specific case
--echo # Using global variable inside a stored function should not crash
create or replace function now_global() returns timestamp
return CONVERT_TZ(now(), @@session.time_zone, @@global.time_zone);
set global system_versioning_asof= now_global();
drop function now_global;
set global time_zone= "SYSTEM";
set time_zone= "SYSTEM";
set global system_versioning_asof= default;
set system_versioning_asof= default;
show status like "Feature_system_versioning"; show status like "Feature_system_versioning";
drop table t; drop table t;
...@@ -111,7 +178,7 @@ create or replace table t1 (x int) with system versioning; ...@@ -111,7 +178,7 @@ create or replace table t1 (x int) with system versioning;
create or replace table t2 (y int); create or replace table t2 (y int);
insert into t1 values (1); insert into t1 values (1);
insert into t2 values (1); insert into t2 values (1);
set system_versioning_asof= '1970-01-01 00:00:00'; set system_versioning_asof= '1970-01-02 00:00:00';
delete t1, t2 from t1 join t2 where t1.x = t2.y; delete t1, t2 from t1 join t2 where t1.x = t2.y;
select * from t1 for system_time as of timestamp now(6); select * from t1 for system_time as of timestamp now(6);
......
...@@ -197,7 +197,8 @@ enum vers_system_time_t ...@@ -197,7 +197,8 @@ enum vers_system_time_t
struct vers_asof_timestamp_t struct vers_asof_timestamp_t
{ {
ulong type; ulong type;
MYSQL_TIME ltime; my_time_t unix_time;
ulong second_part;
}; };
enum vers_alter_history_enum enum vers_alter_history_enum
......
...@@ -278,6 +278,16 @@ class set_var_base :public Sql_alloc ...@@ -278,6 +278,16 @@ class set_var_base :public Sql_alloc
}; };
/**
Structure for holding unix timestamp and high precision second part.
*/
typedef struct my_time_t_hires
{
my_time_t unix_time;
ulong second_part;
} my_time_t_hires;
/** /**
set_var_base descendant for assignments to the system variables. set_var_base descendant for assignments to the system variables.
*/ */
...@@ -296,6 +306,7 @@ class set_var :public set_var_base ...@@ -296,6 +306,7 @@ class set_var :public set_var_base
plugin_ref *plugins; ///< for Sys_var_pluginlist plugin_ref *plugins; ///< for Sys_var_pluginlist
Time_zone *time_zone; ///< for Sys_var_tz Time_zone *time_zone; ///< for Sys_var_tz
LEX_STRING string_value; ///< for Sys_var_charptr and others LEX_STRING string_value; ///< for Sys_var_charptr and others
my_time_t_hires timestamp; ///< for Sys_var_vers_asof
const void *ptr; ///< for Sys_var_struct const void *ptr; ///< for Sys_var_struct
} save_result; } save_result;
LEX_CSTRING base; /**< for structured variables, like keycache_name.variable_name */ LEX_CSTRING base; /**< for structured variables, like keycache_name.variable_name */
......
...@@ -696,8 +696,12 @@ bool vers_select_conds_t::init_from_sysvar(THD *thd) ...@@ -696,8 +696,12 @@ bool vers_select_conds_t::init_from_sysvar(THD *thd)
if (type != SYSTEM_TIME_UNSPECIFIED && type != SYSTEM_TIME_ALL) if (type != SYSTEM_TIME_UNSPECIFIED && type != SYSTEM_TIME_ALL)
{ {
DBUG_ASSERT(type == SYSTEM_TIME_AS_OF); DBUG_ASSERT(type == SYSTEM_TIME_AS_OF);
MYSQL_TIME ltime;
thd->variables.time_zone->gmt_sec_to_TIME(&ltime, in.unix_time);
ltime.second_part = in.second_part;
start.item= new (thd->mem_root) start.item= new (thd->mem_root)
Item_datetime_literal(thd, &in.ltime, TIME_SECOND_PART_DIGITS); Item_datetime_literal(thd, &ltime, TIME_SECOND_PART_DIGITS);
if (!start.item) if (!start.item)
return true; return true;
} }
......
...@@ -438,11 +438,10 @@ static Sys_var_charptr Sys_my_bind_addr( ...@@ -438,11 +438,10 @@ static Sys_var_charptr Sys_my_bind_addr(
READ_ONLY GLOBAL_VAR(my_bind_addr_str), CMD_LINE(REQUIRED_ARG), READ_ONLY GLOBAL_VAR(my_bind_addr_str), CMD_LINE(REQUIRED_ARG),
IN_FS_CHARSET, DEFAULT(0)); IN_FS_CHARSET, DEFAULT(0));
const char *Sys_var_vers_asof::asof_keywords[]= {"DEFAULT", NULL};
static Sys_var_vers_asof Sys_vers_asof_timestamp( static Sys_var_vers_asof Sys_vers_asof_timestamp(
"system_versioning_asof", "Default value for the FOR SYSTEM_TIME AS OF clause", "system_versioning_asof", "Default value for the FOR SYSTEM_TIME AS OF clause",
SESSION_VAR(vers_asof_timestamp.type), NO_CMD_LINE, SESSION_VAR(vers_asof_timestamp.type), NO_CMD_LINE,
Sys_var_vers_asof::asof_keywords, DEFAULT(SYSTEM_TIME_UNSPECIFIED)); DEFAULT(SYSTEM_TIME_UNSPECIFIED));
static const char *vers_alter_history_keywords[]= {"ERROR", "KEEP", NullS}; static const char *vers_alter_history_keywords[]= {"ERROR", "KEEP", NullS};
static Sys_var_enum Sys_vers_alter_history( static Sys_var_enum Sys_vers_alter_history(
......
...@@ -2631,63 +2631,82 @@ public: ...@@ -2631,63 +2631,82 @@ public:
}; };
class Sys_var_vers_asof: public Sys_var_enum class Sys_var_vers_asof: public sys_var
{ {
public:
static const char *asof_keywords[];
public: public:
Sys_var_vers_asof(const char *name_arg, Sys_var_vers_asof(const char *name_arg,
const char *comment, int flag_args, ptrdiff_t off, size_t size, const char *comment, int flag_args, ptrdiff_t off, size_t size,
CMD_LINE getopt, const char *values[], CMD_LINE getopt, uint def_val,
uint def_val) PolyLock *lock= NO_MUTEX_GUARD,
: Sys_var_enum(name_arg, comment, flag_args, off, size, binlog_status_enum binlog_status_arg= VARIABLE_NOT_IN_BINLOG,
getopt, values, def_val) on_check_function on_check_func= NULL,
on_update_function on_update_func= NULL,
const char *substitute= NULL)
: sys_var(&all_sys_vars, name_arg, comment, flag_args, off,
getopt.id, getopt.arg_type, SHOW_CHAR, def_val, lock,
binlog_status_arg, on_check_func, on_update_func, substitute)
{ {
// setval() accepts string rather enum
option.var_type= GET_STR; option.var_type= GET_STR;
} }
virtual bool do_check(THD *thd, set_var *var) virtual bool do_check(THD *thd, set_var *var)
{ {
if (!Sys_var_enum::do_check(thd, var)) if (!var->value)
return false; return false;
MYSQL_TIME ltime; MYSQL_TIME ltime;
bool res= var->value->get_date(&ltime, TIME_NO_ZERO_IN_DATE|TIME_NO_ZERO_DATE); bool res= var->value->get_date(&ltime,
TIME_NO_ZERO_IN_DATE | TIME_NO_ZERO_DATE);
if (!res) if (!res)
{ {
var->save_result.ulonglong_value= SYSTEM_TIME_AS_OF; uint error;
var->save_result.timestamp.unix_time=
thd->variables.time_zone->TIME_to_gmt_sec(&ltime, &error);
var->save_result.timestamp.second_part= ltime.second_part;
res= error != 0;
} }
return res; return res;
} }
private: private:
bool update(set_var *var, vers_asof_timestamp_t &out) static bool update(THD *thd, set_var *var, vers_asof_timestamp_t *out)
{ {
bool res= false; if (var->value)
out.type= static_cast<enum_var_type>(var->save_result.ulonglong_value);
if (out.type == SYSTEM_TIME_AS_OF)
{ {
if (var->value) out->type = SYSTEM_TIME_AS_OF;
{ out->unix_time = var->save_result.timestamp.unix_time;
res= var->value->get_date(&out.ltime, TIME_NO_ZERO_IN_DATE|TIME_NO_ZERO_DATE); out->second_part= var->save_result.timestamp.second_part;
}
else // set DEFAULT from global var
{
out= global_var(vers_asof_timestamp_t);
res= false;
}
} }
return res; return 0;
}
static void save_default(set_var *var, vers_asof_timestamp_t *out)
{
out->type= SYSTEM_TIME_UNSPECIFIED;
} }
public: public:
virtual bool global_update(THD *thd, set_var *var) virtual bool global_update(THD *thd, set_var *var)
{ {
return update(var, global_var(vers_asof_timestamp_t)); return update(thd, var, &global_var(vers_asof_timestamp_t));
} }
virtual bool session_update(THD *thd, set_var *var) virtual bool session_update(THD *thd, set_var *var)
{ {
return update(var, session_var(thd, vers_asof_timestamp_t)); return update(thd, var, &session_var(thd, vers_asof_timestamp_t));
}
virtual bool session_is_default(THD *thd)
{
const vers_asof_timestamp_t &var= session_var(thd, vers_asof_timestamp_t);
return var.type == SYSTEM_TIME_UNSPECIFIED;
}
virtual void session_save_default(THD *thd, set_var *var)
{
save_default(var, &session_var(thd, vers_asof_timestamp_t));
}
virtual void global_save_default(THD *thd, set_var *var)
{
save_default(var, &global_var(vers_asof_timestamp_t));
} }
private: private:
...@@ -2696,15 +2715,19 @@ private: ...@@ -2696,15 +2715,19 @@ private:
switch (val.type) switch (val.type)
{ {
case SYSTEM_TIME_UNSPECIFIED: case SYSTEM_TIME_UNSPECIFIED:
case SYSTEM_TIME_ALL: return (uchar*)"DEFAULT";
return (uchar*) thd->strdup(asof_keywords[val.type]); break;
case SYSTEM_TIME_AS_OF: case SYSTEM_TIME_AS_OF:
{ {
uchar *buf= (uchar*) thd->alloc(MAX_DATE_STRING_REP_LENGTH); uchar *buf= (uchar*) thd->alloc(MAX_DATE_STRING_REP_LENGTH);
if (buf &&!my_datetime_to_str(&val.ltime, (char*) buf, 6)) MYSQL_TIME ltime;
thd->variables.time_zone->gmt_sec_to_TIME(&ltime, val.unix_time);
ltime.second_part= val.second_part;
if (buf && !my_datetime_to_str(&ltime, (char*) buf, 6))
{ {
// TODO: figure out variable name my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name.str, "NULL (wrong datetime)");
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "system_versioning_asof_timestamp", "NULL (wrong datetime)");
return (uchar*) thd->strdup("Error: wrong datetime"); return (uchar*) thd->strdup("Error: wrong datetime");
} }
return buf; return buf;
...@@ -2712,7 +2735,7 @@ private: ...@@ -2712,7 +2735,7 @@ private:
default: default:
break; break;
} }
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "system_versioning_asof_timestamp", "NULL (wrong range type)"); my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name.str, "NULL (wrong range type)");
return (uchar*) thd->strdup("Error: wrong range type"); return (uchar*) thd->strdup("Error: wrong range type");
} }
......
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