From 9e9af76eaf4eec4f105e029975ec5a142ec7e8f2 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Thu, 30 Mar 2017 12:57:31 +0300 Subject: [PATCH] SQL: vers_current_time refactoring [closes #117] * session sysvars; * moved value parsing to set variable phase; * renamed 'temporal_current_timestamp' to 'vers_current_time'. --- .../r/sysvars_server_notembedded.result | 36 ++-- mysql-test/suite/versioning/r/sysvars.result | 98 +++++++++-- mysql-test/suite/versioning/t/sysvars.test | 77 +++++++-- plugin/versioning/versioning.cc | 13 +- sql/handler.cc | 2 +- sql/mysqld.cc | 16 +- sql/mysqld.h | 26 ++- sql/set_var.h | 7 + sql/sql_base.cc | 1 + sql/sql_class.h | 4 + sql/sql_select.cc | 25 ++- sql/sql_show.cc | 1 + sql/sys_vars.cc | 10 +- sql/sys_vars.ic | 162 ++++++++++++++++++ sql/table.h | 10 -- 15 files changed, 395 insertions(+), 93 deletions(-) diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result index a4d7265e06e..5e8bacbc4d0 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result @@ -4769,20 +4769,6 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME TEMPORAL_CURRENT_TIMESTAMP -SESSION_VALUE NULL -GLOBAL_VALUE now -GLOBAL_VALUE_ORIGIN COMPILE-TIME -DEFAULT_VALUE now -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE VARCHAR -VARIABLE_COMMENT Default AS OF value for versioned tables -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST NULL -READ_ONLY NO -COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME THREAD_CACHE_SIZE SESSION_VALUE NULL GLOBAL_VALUE 151 @@ -5133,12 +5119,26 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST NEVER,COMPLEMENTARY,PREFERABLY READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME VERS_CURRENT_TIME +SESSION_VALUE NOW +GLOBAL_VALUE NOW +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE now +VARIABLE_SCOPE SESSION +VARIABLE_TYPE VARCHAR +VARIABLE_COMMENT Default AS OF value for versioned tables +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME VERS_FORCE -SESSION_VALUE NULL +SESSION_VALUE OFF GLOBAL_VALUE OFF GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE OFF -VARIABLE_SCOPE GLOBAL +VARIABLE_SCOPE SESSION VARIABLE_TYPE BOOLEAN VARIABLE_COMMENT Force system versioning for all created tables NUMERIC_MIN_VALUE NULL @@ -5148,11 +5148,11 @@ ENUM_VALUE_LIST OFF,ON READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME VERS_HIDE -SESSION_VALUE NULL +SESSION_VALUE AUTO GLOBAL_VALUE AUTO GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE AUTO -VARIABLE_SCOPE GLOBAL +VARIABLE_SCOPE SESSION VARIABLE_TYPE ENUM VARIABLE_COMMENT Hide system versioning from being displayed in table info. AUTO: hide implicit system fields only in non-versioned and AS OF queries; IMPLICIT: hide implicit system fields in all queries; FULL: hide any system fields in all queries and hide versioning info in SHOW commands; NEVER: don't hide system fields NUMERIC_MIN_VALUE NULL diff --git a/mysql-test/suite/versioning/r/sysvars.result b/mysql-test/suite/versioning/r/sysvars.result index 120a3583754..dbab7f2c910 100644 --- a/mysql-test/suite/versioning/r/sysvars.result +++ b/mysql-test/suite/versioning/r/sysvars.result @@ -1,27 +1,36 @@ create table t (a int) with system versioning; insert into t values (1); update t set a= 2; -select * from t; -a -2 -show variables where variable_name = "temporal_current_timestamp"; +show global variables like 'vers_current_time'; Variable_name Value -temporal_current_timestamp now -set global temporal_current_timestamp = '2031-1-1 0:0:0'; +vers_current_time NOW +show variables like 'vers_current_time'; +Variable_name Value +vers_current_time NOW select * from t; a 2 -set global temporal_current_timestamp = '2011-1-1 0:0:0'; +set vers_current_time = '2031-1-1 0:0:0'; +show variables like 'vers_current_time'; +Variable_name Value +vers_current_time 2031-01-01 00:00:00.000000 select * from t; a -set global temporal_current_timestamp = 'all'; +2 +set vers_current_time = '2011-1-1 0:0:0'; +show variables like 'vers_current_time'; +Variable_name Value +vers_current_time 2011-01-01 00:00:00.000000 +select * from t; +a +set vers_current_time = 'all'; +show variables like 'vers_current_time'; +Variable_name Value +vers_current_time ALL select * from t; a 2 1 -show variables where Variable_name like "temporal_current_timestamp%"; -Variable_name Value -temporal_current_timestamp all create view vt as select * from t; select * from t; a @@ -32,9 +41,62 @@ select * from (select * from t) as tt; a 2 1 -set session temporal_current_timestamp = 'now'; -ERROR HY000: Variable 'temporal_current_timestamp' is a GLOBAL variable and should be set with SET GLOBAL -set global temporal_current_timestamp = 'now'; +set global vers_current_time= 'alley'; +ERROR 42000: Variable 'vers_current_time' can't be set to the value of 'alley' +set global vers_current_time= null; +ERROR 42000: Variable 'vers_current_time' can't be set to the value of 'NULL' +set global vers_current_time= 1; +ERROR 42000: Incorrect argument type to variable 'vers_current_time' +set global vers_current_time= 1.1; +ERROR 42000: Incorrect argument type to variable 'vers_current_time' +set vers_current_time= 'alley'; +ERROR 42000: Variable 'vers_current_time' can't be set to the value of 'alley' +set vers_current_time= null; +ERROR 42000: Variable 'vers_current_time' can't be set to the value of 'NULL' +set vers_current_time= 1; +ERROR 42000: Incorrect argument type to variable 'vers_current_time' +set vers_current_time= 1.1; +ERROR 42000: Incorrect argument type to variable 'vers_current_time' +set global vers_current_time= '1911-11-11 11:11:11.1111119'; +show global variables like 'vers_current_time'; +Variable_name Value +vers_current_time 1911-11-11 11:11:11.111111 +set global vers_current_time= '1900-01-01 00:00:00'; +show global variables like 'vers_current_time'; +Variable_name Value +vers_current_time 1900-01-01 00:00:00.000000 +set global vers_current_time= timestamp'1911-11-11 11:11:11.1111119'; +Warnings: +Note 1292 Truncated incorrect datetime value: '1911-11-11 11:11:11.1111119' +show global variables like 'vers_current_time'; +Variable_name Value +vers_current_time 1911-11-11 11:11:11.111111 +set @ts= timestamp'1900-01-01 00:00:00'; +set global vers_current_time= @ts; +show global variables like 'vers_current_time'; +Variable_name Value +vers_current_time 1900-01-01 00:00:00.000000 +set vers_current_time= '1911-11-11 11:11:11.1111119'; +show variables like 'vers_current_time'; +Variable_name Value +vers_current_time 1911-11-11 11:11:11.111111 +set vers_current_time= '1900-01-01 00:00:00'; +show variables like 'vers_current_time'; +Variable_name Value +vers_current_time 1900-01-01 00:00:00.000000 +set vers_current_time= timestamp'1911-11-11 11:11:11.1111119'; +Warnings: +Note 1292 Truncated incorrect datetime value: '1911-11-11 11:11:11.1111119' +show variables like 'vers_current_time'; +Variable_name Value +vers_current_time 1911-11-11 11:11:11.111111 +set @ts= timestamp'1900-01-01 00:00:00'; +set vers_current_time= @ts; +show variables like 'vers_current_time'; +Variable_name Value +vers_current_time 1900-01-01 00:00:00.000000 +set global vers_current_time= 'now'; +set vers_current_time= 'now'; show variables where variable_name = "vers_hide"; Variable_name Value vers_hide IMPLICIT @@ -42,7 +104,7 @@ select * from t for system_time all; a 2 1 -set global vers_hide= AUTO; +set vers_hide= AUTO; select * from t; a 2 @@ -61,11 +123,11 @@ select * from t for system_time timestamp between '0-0-0' and current_timestamp( a sys_trx_start sys_trx_end 2 TIMESTAMP TIMESTAMP 1 TIMESTAMP TIMESTAMP -set global vers_hide= NEVER; +set vers_hide= NEVER; select * from t; a sys_trx_start sys_trx_end 2 TIMESTAMP TIMESTAMP -set global vers_hide= FULL; +set vers_hide= FULL; create or replace table t ( x int, st timestamp(6) generated always as row start, @@ -85,4 +147,4 @@ select * from t for system_time all; x 1 drop table t; -set global vers_hide= IMPLICIT; +set vers_hide= IMPLICIT; diff --git a/mysql-test/suite/versioning/t/sysvars.test b/mysql-test/suite/versioning/t/sysvars.test index ba985a92c9a..b6deadb8470 100644 --- a/mysql-test/suite/versioning/t/sysvars.test +++ b/mysql-test/suite/versioning/t/sysvars.test @@ -2,18 +2,21 @@ create table t (a int) with system versioning; insert into t values (1); update t set a= 2; -select * from t; -show variables where variable_name = "temporal_current_timestamp"; - -set global temporal_current_timestamp = '2031-1-1 0:0:0'; +show global variables like 'vers_current_time'; +show variables like 'vers_current_time'; select * from t; -set global temporal_current_timestamp = '2011-1-1 0:0:0'; +set vers_current_time = '2031-1-1 0:0:0'; +show variables like 'vers_current_time'; select * from t; -set global temporal_current_timestamp = 'all'; +set vers_current_time = '2011-1-1 0:0:0'; +show variables like 'vers_current_time'; +select * from t; + +set vers_current_time = 'all'; +show variables like 'vers_current_time'; select * from t; -show variables where Variable_name like "temporal_current_timestamp%"; create view vt as select * from t; select * from t; @@ -21,15 +24,61 @@ drop view vt; select * from (select * from t) as tt; ---error ER_GLOBAL_VARIABLE -set session temporal_current_timestamp = 'now'; +# global +--error ER_WRONG_VALUE_FOR_VAR +set global vers_current_time= 'alley'; +--error ER_WRONG_VALUE_FOR_VAR +set global vers_current_time= null; +--error ER_WRONG_TYPE_FOR_VAR +set global vers_current_time= 1; +--error ER_WRONG_TYPE_FOR_VAR +set global vers_current_time= 1.1; -set global temporal_current_timestamp = 'now'; +# session +--error ER_WRONG_VALUE_FOR_VAR +set vers_current_time= 'alley'; +--error ER_WRONG_VALUE_FOR_VAR +set vers_current_time= null; +--error ER_WRONG_TYPE_FOR_VAR +set vers_current_time= 1; +--error ER_WRONG_TYPE_FOR_VAR +set vers_current_time= 1.1; + +# global +set global vers_current_time= '1911-11-11 11:11:11.1111119'; +show global variables like 'vers_current_time'; + +set global vers_current_time= '1900-01-01 00:00:00'; +show global variables like 'vers_current_time'; + +set global vers_current_time= timestamp'1911-11-11 11:11:11.1111119'; +show global variables like 'vers_current_time'; + +set @ts= timestamp'1900-01-01 00:00:00'; +set global vers_current_time= @ts; +show global variables like 'vers_current_time'; + +# session +set vers_current_time= '1911-11-11 11:11:11.1111119'; +show variables like 'vers_current_time'; + +set vers_current_time= '1900-01-01 00:00:00'; +show variables like 'vers_current_time'; + +set vers_current_time= timestamp'1911-11-11 11:11:11.1111119'; +show variables like 'vers_current_time'; + +set @ts= timestamp'1900-01-01 00:00:00'; +set vers_current_time= @ts; +show variables like 'vers_current_time'; + +set global vers_current_time= 'now'; +set vers_current_time= 'now'; show variables where variable_name = "vers_hide"; select * from t for system_time all; -set global vers_hide= AUTO; +set vers_hide= AUTO; select * from t; select * from t for system_time as of timestamp current_timestamp(6); --replace_regex /\d{4}-\d\d-\d\d \d\d:\d\d:\d\d\.\d{6}/TIMESTAMP/ @@ -39,11 +88,11 @@ select * from t for system_time timestamp from '0-0-0' to current_timestamp(6); --replace_regex /\d{4}-\d\d-\d\d \d\d:\d\d:\d\d\.\d{6}/TIMESTAMP/ select * from t for system_time timestamp between '0-0-0' and current_timestamp(6); -set global vers_hide= NEVER; +set vers_hide= NEVER; --replace_regex /\d{4}-\d\d-\d\d \d\d:\d\d:\d\d\.\d{6}/TIMESTAMP/ select * from t; -set global vers_hide= FULL; +set vers_hide= FULL; create or replace table t ( x int, st timestamp(6) generated always as row start, @@ -59,4 +108,4 @@ select * from t; select * from t for system_time all; drop table t; -set global vers_hide= IMPLICIT; \ No newline at end of file +set vers_hide= IMPLICIT; diff --git a/plugin/versioning/versioning.cc b/plugin/versioning/versioning.cc index c1a5a7cd6a5..016367f89f4 100644 --- a/plugin/versioning/versioning.cc +++ b/plugin/versioning/versioning.cc @@ -17,6 +17,7 @@ #include #include #include "sql_plugin.h" // st_plugin_int +#include "sql_class.h" /* Disable __attribute__() on non-gcc compilers. @@ -29,16 +30,20 @@ static int forced_versioning_init(void *p __attribute__ ((unused))) { DBUG_ENTER("forced_versioning_init"); - vers_force= true; - vers_hide= VERS_HIDE_FULL; + mysql_mutex_lock(&LOCK_global_system_variables); + global_system_variables.vers_force= true; + global_system_variables.vers_hide= VERS_HIDE_FULL; + mysql_mutex_unlock(&LOCK_global_system_variables); DBUG_RETURN(0); } static int forced_versioning_deinit(void *p __attribute__ ((unused))) { DBUG_ENTER("forced_versioning_deinit"); - vers_force= false; - vers_hide= VERS_HIDE_AUTO; + mysql_mutex_lock(&LOCK_global_system_variables); + global_system_variables.vers_force= false; + global_system_variables.vers_hide= VERS_HIDE_AUTO; + mysql_mutex_unlock(&LOCK_global_system_variables); DBUG_RETURN(0); } diff --git a/sql/handler.cc b/sql/handler.cc index 62091b0f19e..13c4031b02d 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -6698,7 +6698,7 @@ bool Vers_parse_info::check_and_fix_implicit( // CREATE ... SELECT: if at least one table in SELECT is versioned, // then created table will be versioned. - if (vers_force || vers_tables > 0) + if (thd->variables.vers_force || vers_tables > 0) { declared_with_system_versioning= true; create_info->options|= HA_VERSIONED_TABLE; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 1696f689aab..454b5d10965 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -781,11 +781,6 @@ char *relay_log_info_file, *report_user, *report_password, *report_host; char *opt_relay_logname = 0, *opt_relaylog_index_name=0; char *opt_logname, *opt_slow_logname, *opt_bin_logname; -/* System Versioning */ -char *temporal_current_timestamp; -my_bool vers_force= false; -ulong vers_hide= VERS_HIDE_AUTO; - /* Static variables */ static volatile sig_atomic_t kill_in_progress; @@ -9315,6 +9310,17 @@ mysqld_get_one_option(int optid, const struct my_option *opt, char *argument) WSREP_SYNC_WAIT_BEFORE_READ); break; #endif /* WITH_WSREP */ + case OPT_VERS_CURRENT_TIME: + sys_var *var= static_cast(opt->app_type); + DBUG_ASSERT(var); + if (var->option_updated()) + { + sql_print_error("Can't start server: " + "cannot process --vers-current-time=%.*s", + FN_REFLEN, argument); + return 1; + } + break; } return 0; } diff --git a/sql/mysqld.h b/sql/mysqld.h index 8cf14cc19a5..e8a72b0b063 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -175,15 +175,34 @@ extern char *opt_backup_history_logname, *opt_backup_progress_logname, *opt_backup_settings_name; extern const char *log_output_str; extern const char *log_backup_output_str; -extern char *temporal_current_timestamp; -extern my_bool vers_force; + +enum vers_range_type_t +{ + FOR_SYSTEM_TIME_UNSPECIFIED = 0, + FOR_SYSTEM_TIME_AS_OF, + FOR_SYSTEM_TIME_FROM_TO, + FOR_SYSTEM_TIME_BETWEEN, + FOR_SYSTEM_TIME_ALL, + FOR_SYSTEM_TIME_BEFORE +}; + +struct st_vers_current_time +{ // This struct must be POD, so no virtual-anything! + char *str_value; // must be first + vers_range_type_t type; + MYSQL_TIME ltime; + st_vers_current_time() : + str_value(NULL), + type(FOR_SYSTEM_TIME_UNSPECIFIED) + {} +}; + enum vers_hide_enum { VERS_HIDE_AUTO= 0, VERS_HIDE_IMPLICIT, VERS_HIDE_FULL, VERS_HIDE_NEVER }; -extern ulong vers_hide; extern char *mysql_home_ptr, *pidfile_name_ptr; extern MYSQL_PLUGIN_IMPORT char glob_hostname[FN_REFLEN]; extern char mysql_home[FN_REFLEN]; @@ -652,6 +671,7 @@ enum options_mysqld OPT_SSL_KEY, OPT_THREAD_CONCURRENCY, OPT_WANT_CORE, + OPT_VERS_CURRENT_TIME, #ifdef WITH_WSREP OPT_WSREP_CAUSAL_READS, OPT_WSREP_SYNC_WAIT, diff --git a/sql/set_var.h b/sql/set_var.h index ddd6a225eb8..9c7d7f1135b 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -223,6 +223,13 @@ private: virtual bool session_update(THD *thd, set_var *var) = 0; virtual bool global_update(THD *thd, set_var *var) = 0; +public: + virtual bool option_updated() + { + DBUG_ASSERT(false); + return true; + } + protected: /** A pointer to a value of the variable for SHOW. diff --git a/sql/sql_base.cc b/sql/sql_base.cc index df50b2a7afa..d0c723af397 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -7478,6 +7478,7 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name, Field_iterator_table_ref field_iterator; bool found; char name_buff[SAFE_NAME_LEN+1]; + ulong vers_hide= thd->variables.vers_hide; DBUG_ENTER("insert_fields"); DBUG_PRINT("arena", ("stmt arena: 0x%lx", (ulong)thd->stmt_arena)); diff --git a/sql/sql_class.h b/sql/sql_class.h index 49f62f9ea4e..e3601f141fa 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -706,6 +706,10 @@ typedef struct system_variables uint idle_transaction_timeout; uint idle_readonly_transaction_timeout; uint idle_readwrite_transaction_timeout; + + st_vers_current_time vers_current_time; + my_bool vers_force; + ulong vers_hide; } SV; /** diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 1c57ca2e77a..6739d51f360 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -670,24 +670,19 @@ setup_without_group(THD *thd, Ref_ptr_array ref_pointer_array, bool vers_select_conds_t::init_from_sysvar(THD *thd) { - const char var[]= "temporal_current_timestamp"; - sys_var *sv= intern_find_sys_var(var, sizeof(var) - 1); - DBUG_ASSERT(sv); - const char *data= *(char **)sv->option.value; - DBUG_ASSERT(data); - if (0 == strcmp(data, "all")) + st_vers_current_time &in= thd->variables.vers_current_time; + type= in.type; + unit= UNIT_TIMESTAMP; + if (type != FOR_SYSTEM_TIME_UNSPECIFIED && type != FOR_SYSTEM_TIME_ALL) { - init(FOR_SYSTEM_TIME_ALL, UNIT_TIMESTAMP); - } - else if (0 != strcmp(data, "now")) - { - Item *ts= - create_temporal_literal(thd, data, strlen(data), system_charset_info, - MYSQL_TYPE_DATETIME, true); - if (!ts) + DBUG_ASSERT(type == FOR_SYSTEM_TIME_AS_OF); + start= new (thd->mem_root) Item_datetime_literal(thd, &in.ltime, 6); + if (!start) return true; - init(FOR_SYSTEM_TIME_AS_OF, UNIT_TIMESTAMP, ts); } + else + start= NULL; + end= NULL; return false; } diff --git a/sql/sql_show.cc b/sql/sql_show.cc index bedc32d6010..a3ce1fd19c6 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1986,6 +1986,7 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, TABLE *table= table_list->table; TABLE_SHARE *share= table->s; sql_mode_t sql_mode= thd->variables.sql_mode; + ulong vers_hide= thd->variables.vers_hide; bool foreign_db_mode= sql_mode & (MODE_POSTGRESQL | MODE_ORACLE | MODE_MSSQL | MODE_DB2 | MODE_MAXDB | MODE_ANSI); diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 9fb32174d1c..0b80684cd77 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -382,14 +382,14 @@ static Sys_var_charptr Sys_basedir( READ_ONLY GLOBAL_VAR(mysql_home_ptr), CMD_LINE(REQUIRED_ARG, 'b'), IN_FS_CHARSET, DEFAULT(0)); -static Sys_var_charptr sys_temporal_current_timestamp( - "temporal_current_timestamp", "Default AS OF value for versioned tables", - GLOBAL_VAR(temporal_current_timestamp), CMD_LINE(REQUIRED_ARG, 'b'), +static Sys_var_vers_asof Sys_vers_current_time( + "vers_current_time", "Default AS OF value for versioned tables", + SESSION_VAR(vers_current_time), CMD_LINE(REQUIRED_ARG, OPT_VERS_CURRENT_TIME), IN_FS_CHARSET, DEFAULT("now")); static Sys_var_mybool Sys_vers_force( "vers_force", "Force system versioning for all created tables", - GLOBAL_VAR(vers_force), CMD_LINE(OPT_ARG), DEFAULT(FALSE)); + SESSION_VAR(vers_force), CMD_LINE(OPT_ARG), DEFAULT(FALSE)); static const char *vers_hide_keywords[]= {"AUTO", "IMPLICIT", "FULL", "NEVER", NullS}; static Sys_var_enum Sys_vers_hide( @@ -398,7 +398,7 @@ static Sys_var_enum Sys_vers_hide( "IMPLICIT: hide implicit system fields in all queries; " "FULL: hide any system fields in all queries and hide versioning info in SHOW commands; " "NEVER: don't hide system fields", - GLOBAL_VAR(vers_hide), CMD_LINE(OPT_ARG), vers_hide_keywords, DEFAULT(VERS_HIDE_AUTO)); + SESSION_VAR(vers_hide), CMD_LINE(OPT_ARG), vers_hide_keywords, DEFAULT(VERS_HIDE_AUTO)); static Sys_var_ulonglong Sys_binlog_cache_size( "binlog_cache_size", "The size of the transactional cache for " diff --git a/sql/sys_vars.ic b/sql/sys_vars.ic index 780450b484b..76bf8631630 100644 --- a/sql/sys_vars.ic +++ b/sql/sys_vars.ic @@ -2485,3 +2485,165 @@ public: bool global_update(THD *thd, set_var *var); uchar *global_value_ptr(THD *thd, const LEX_STRING *base); }; + + +class Sys_var_vers_asof: public sys_var +{ +public: + Sys_var_vers_asof( + const char *name_arg, + const char *comment, + int flag_args, + ptrdiff_t off, + size_t size, + CMD_LINE getopt, + enum charset_enum is_os_charset_arg, + const char *def_val, + on_check_function on_check_func=0, + on_update_function on_update_func=0) : + sys_var( + &all_sys_vars, + name_arg, + comment, + flag_args, + off, + getopt.id, + getopt.arg_type, + SHOW_CHAR, + (intptr) def_val, + 0, + VARIABLE_NOT_IN_BINLOG, + on_check_func, + on_update_func, + 0) + { + option.var_type|= GET_STR; + if (global_update(def_val)) + { + DBUG_ASSERT(false); + } + } + + bool do_check(THD *thd, set_var *var) + { return false; } + + bool update(String &in, st_vers_current_time &out) + { + if (in.length() == 3 && + 0 == my_strcasecmp( + in.charset(), + "ALL", + in.ptr())) + { + out.type= FOR_SYSTEM_TIME_ALL; + } + else if (in.length() == 3 && + 0 == my_strcasecmp( + in.charset(), + "NOW", + in.ptr())) + { + out.type= FOR_SYSTEM_TIME_UNSPECIFIED; + } + else + { + MYSQL_TIME_STATUS status; + if (str_to_datetime( + in.ptr(), + in.length(), + &out.ltime, + flags, + &status) || + out.ltime.time_type != MYSQL_TIMESTAMP_DATETIME || + (status.warnings & ~MYSQL_TIME_NOTE_TRUNCATED) != 0) + { + return true; + } + out.type= FOR_SYSTEM_TIME_AS_OF; + } + return false; + } + bool update(THD *thd, set_var *var, st_vers_current_time &out) + { + Item *item= var->value; + + switch (item->result_type()) + { + case TIME_RESULT: + { + if (item->get_date(&out.ltime, 0)) + break; + out.type= FOR_SYSTEM_TIME_AS_OF; + return false; + } + + case STRING_RESULT: + { + String *str= item->val_str(); + if (!str || update(*str, out)) + break; + return false; + } + default: + break; + } + String *str= item->val_str(); + const char *cstr= str ? str->c_ptr_safe() : "NULL"; + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, cstr); + return true; + } + bool global_update(const char *in) + { + String s(in, &my_charset_utf8_general_ci); + return update(s, global_var(st_vers_current_time)); + } + bool option_updated() + { + return global_update(global_var(st_vers_current_time).str_value); + } + bool global_update(THD *thd, set_var *var) + { + return update(thd, var, global_var(st_vers_current_time)); + } + bool session_update(THD *thd, set_var *var) + { + return update(thd, var, session_var(thd, st_vers_current_time)); + } + uchar *valptr(THD *thd, st_vers_current_time &val) + { + switch (val.type) + { + case FOR_SYSTEM_TIME_UNSPECIFIED: + return (uchar*) thd->strdup("NOW"); + case FOR_SYSTEM_TIME_ALL: + return (uchar*) thd->strdup("ALL"); + case FOR_SYSTEM_TIME_AS_OF: + { + uchar *buf= (uchar*) thd->alloc(MAX_DATE_STRING_REP_LENGTH); + if (buf) + { + if (!my_datetime_to_str(&val.ltime, (char*) buf, 6)) + { + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "vers_current_time", "NULL (wrong datetime)"); + return (uchar*) thd->strdup("Error: wrong datetime"); + } + } + return buf; + } + default: + break; + } + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "vers_current_time", "NULL (wrong range type)"); + return (uchar*) thd->strdup("Error: wrong range type"); + } + void session_save_default(THD *thd, set_var *var) + { DBUG_ASSERT(false); } + void global_save_default(THD *thd, set_var *var) + { DBUG_ASSERT(false); } + uchar *session_value_ptr(THD *thd, const LEX_STRING *base) + { return valptr(thd, session_var(thd, st_vers_current_time)); } + uchar *global_value_ptr(THD *thd, const LEX_STRING *base) + { return valptr(thd, global_var(st_vers_current_time)); } + uchar *default_value_ptr(THD *thd) + { return (uchar *)option.def_value; } +}; diff --git a/sql/table.h b/sql/table.h index ba497f1c365..f6736658674 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1841,16 +1841,6 @@ class Item_in_subselect; 4) jtbm semi-join (jtbm_subselect != NULL) */ -enum vers_range_type_t -{ - FOR_SYSTEM_TIME_UNSPECIFIED = 0, - FOR_SYSTEM_TIME_AS_OF, - FOR_SYSTEM_TIME_FROM_TO, - FOR_SYSTEM_TIME_BETWEEN, - FOR_SYSTEM_TIME_ALL, - FOR_SYSTEM_TIME_BEFORE -}; - enum vers_range_unit_t { UNIT_TIMESTAMP = 0,