Commit eb29a63e authored by Sergei Golubchik's avatar Sergei Golubchik

SET STATEMENT timestamp=xxx ....

fix sys_var->is_default() method (that was using default_val property
in a global sys_var object to track per-session state):
* move timestamp to a dedicated Sys_var_timestamp class
  (in fact, rename Sys_var_session_special_double to Sys_var_timestamp)
* make session_is_default a virtual method with a special implementation
  for timestamps
* other variables don't have a special behavior for default values
  and can have session_is_default() to be always false.
parent 0a9052f5
...@@ -147,7 +147,7 @@ sys_var::sys_var(sys_var_chain *chain, const char *name_arg, ...@@ -147,7 +147,7 @@ sys_var::sys_var(sys_var_chain *chain, const char *name_arg,
flags(flags_arg), show_val_type(show_val_type_arg), flags(flags_arg), show_val_type(show_val_type_arg),
guard(lock), offset(off), on_check(on_check_func), on_update(on_update_func), guard(lock), offset(off), on_check(on_check_func), on_update(on_update_func),
deprecation_substitute(substitute), deprecation_substitute(substitute),
is_os_charset(FALSE), default_val(FALSE) is_os_charset(FALSE)
{ {
/* /*
There is a limitation in handle_options() related to short options: There is a limitation in handle_options() related to short options:
...@@ -790,7 +790,6 @@ int set_var::light_check(THD *thd) ...@@ -790,7 +790,6 @@ int set_var::light_check(THD *thd)
*/ */
int set_var::update(THD *thd) int set_var::update(THD *thd)
{ {
var->set_is_default(value == 0);
return value ? var->update(thd, this) : var->set_default(thd, this); return value ? var->update(thd, this) : var->set_default(thd, this);
} }
......
...@@ -88,7 +88,6 @@ protected: ...@@ -88,7 +88,6 @@ protected:
on_update_function on_update; on_update_function on_update;
const char *const deprecation_substitute; const char *const deprecation_substitute;
bool is_os_charset; ///< true if the value is in character_set_filesystem bool is_os_charset; ///< true if the value is in character_set_filesystem
bool default_val;
public: public:
sys_var(sys_var_chain *chain, const char *name_arg, const char *comment, sys_var(sys_var_chain *chain, const char *name_arg, const char *comment,
...@@ -194,8 +193,15 @@ public: ...@@ -194,8 +193,15 @@ public:
return insert_dynamic(array, (uchar*)&option); return insert_dynamic(array, (uchar*)&option);
} }
void do_deprecated_warning(THD *thd); void do_deprecated_warning(THD *thd);
bool is_default() { return default_val; } /**
void set_is_default(bool def) { default_val= def; } whether session value of a sysvar is a default one.
in this simple implementation we don't distinguish between default
and non-default values. for most variables it's ok, they don't treat
default values specially. this method is overwritten in descendant
classes as necessary.
*/
virtual bool session_is_default(THD *thd) { return false; }
virtual uchar *default_value_ptr(THD *thd) virtual uchar *default_value_ptr(THD *thd)
{ return (uchar*)&option.def_value; } { return (uchar*)&option.def_value; }
......
...@@ -2663,7 +2663,7 @@ mysql_execute_command(THD *thd) ...@@ -2663,7 +2663,7 @@ mysql_execute_command(THD *thd)
lex->free_arena_for_set_stmt(); lex->free_arena_for_set_stmt();
goto error; goto error;
} }
if (v->var->is_default()) if (v->var->session_is_default(thd))
o= new set_var(v->type, v->var, &v->base, NULL); o= new set_var(v->type, v->var, &v->base, NULL);
else else
{ {
......
...@@ -3708,28 +3708,11 @@ static Sys_var_harows Sys_select_limit( ...@@ -3708,28 +3708,11 @@ static Sys_var_harows Sys_select_limit(
SESSION_VAR(select_limit), NO_CMD_LINE, SESSION_VAR(select_limit), NO_CMD_LINE,
VALID_RANGE(0, HA_POS_ERROR), DEFAULT(HA_POS_ERROR), BLOCK_SIZE(1)); VALID_RANGE(0, HA_POS_ERROR), DEFAULT(HA_POS_ERROR), BLOCK_SIZE(1));
static bool update_timestamp(THD *thd, set_var *var) static Sys_var_timestamp Sys_timestamp(
{
if (var->value)
{
my_hrtime_t hrtime = { hrtime_from_time(var->save_result.double_value) };
thd->set_time(hrtime);
}
else // SET timestamp=DEFAULT
thd->user_time.val= 0;
return false;
}
static double read_timestamp(THD *thd)
{
return thd->start_time +
thd->start_time_sec_part/(double)TIME_SECOND_PART_FACTOR;
}
static Sys_var_session_special_double Sys_timestamp(
"timestamp", "Set the time for this client", "timestamp", "Set the time for this client",
sys_var::ONLY_SESSION, NO_CMD_LINE, sys_var::ONLY_SESSION, NO_CMD_LINE,
VALID_RANGE(0, TIMESTAMP_MAX_VALUE), VALID_RANGE(0, TIMESTAMP_MAX_VALUE),
NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(0), NO_MUTEX_GUARD, IN_BINLOG);
ON_UPDATE(update_timestamp), ON_READ(read_timestamp));
static bool update_last_insert_id(THD *thd, set_var *var) static bool update_last_insert_id(THD *thd, set_var *var)
{ {
......
...@@ -1657,46 +1657,57 @@ public: ...@@ -1657,46 +1657,57 @@ public:
}; };
class Sys_var_session_special_double: public Sys_var_double /*
{ Dedicated class because of a weird behavior of a default value.
typedef bool (*session_special_update_function)(THD *thd, set_var *var); Assigning timestamp to itself
typedef double (*session_special_read_function)(THD *thd);
session_special_read_function read_func; SET @@timestamp = @@timestamp
session_special_update_function update_func;
make it non-default and stops the time flow.
*/
class Sys_var_timestamp: public Sys_var_double
{
public: public:
Sys_var_session_special_double(const char *name_arg, Sys_var_timestamp(const char *name_arg,
const char *comment, int flag_args, const char *comment, int flag_args,
CMD_LINE getopt, CMD_LINE getopt,
double min_val, double max_val, double min_val, double max_val,
PolyLock *lock, enum binlog_status_enum binlog_status_arg, PolyLock *lock, enum binlog_status_enum binlog_status_arg)
on_check_function on_check_func,
session_special_update_function update_func_arg,
session_special_read_function read_func_arg,
const char *substitute=0)
: Sys_var_double(name_arg, comment, flag_args, 0, : Sys_var_double(name_arg, comment, flag_args, 0,
sizeof(double), getopt, min_val, sizeof(double), getopt, min_val,
max_val, 0, lock, binlog_status_arg, on_check_func, 0, max_val, 0, lock, binlog_status_arg)
substitute),
read_func(read_func_arg), update_func(update_func_arg)
{ {
SYSVAR_ASSERT(scope() == ONLY_SESSION); SYSVAR_ASSERT(scope() == ONLY_SESSION);
SYSVAR_ASSERT(getopt.id < 0); // NO_CMD_LINE, because the offset is fake SYSVAR_ASSERT(getopt.id < 0); // NO_CMD_LINE, because the offset is fake
} }
bool session_update(THD *thd, set_var *var) bool session_update(THD *thd, set_var *var)
{ return update_func(thd, var); } {
if (var->value)
{
my_hrtime_t hrtime = { hrtime_from_time(var->save_result.double_value) };
thd->set_time(hrtime);
}
else // SET timestamp=DEFAULT
thd->user_time.val= 0;
return false;
}
bool global_update(THD *thd, set_var *var) bool global_update(THD *thd, set_var *var)
{ {
DBUG_ASSERT(FALSE); DBUG_ASSERT(FALSE);
return true; return true;
} }
bool session_is_default(THD *thd)
{
return thd->user_time.val == 0;
}
void session_save_default(THD *thd, set_var *var) void session_save_default(THD *thd, set_var *var)
{ var->value= 0; } { var->value= 0; }
void global_save_default(THD *thd, set_var *var) void global_save_default(THD *thd, set_var *var)
{ DBUG_ASSERT(FALSE); } { DBUG_ASSERT(FALSE); }
uchar *session_value_ptr(THD *thd, const LEX_STRING *base) uchar *session_value_ptr(THD *thd, const LEX_STRING *base)
{ {
thd->sys_var_tmp.double_value= read_func(thd); thd->sys_var_tmp.double_value= thd->start_time +
thd->start_time_sec_part/(double)TIME_SECOND_PART_FACTOR;
return (uchar*) &thd->sys_var_tmp.double_value; return (uchar*) &thd->sys_var_tmp.double_value;
} }
uchar *global_value_ptr(THD *thd, const LEX_STRING *base) uchar *global_value_ptr(THD *thd, const LEX_STRING *base)
......
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