From 9cca1d8bdb5283e5bb5a5aa3fa7cf23d4ccb3266 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Wed, 2 Jan 2013 10:39:10 -0800 Subject: [PATCH] Support for floating-point system variables using the plugin interface. Augment the server plugin interface to allow plugins to define and expose floating-point system variables of type double. The convenience macros MYSQL_SYSVAR_DOUBLE and MYSQL_THDVAR_DOUBLE are introduced and can be used by plugins to declare system variables of type double. --- include/mysql/plugin.h | 11 ++++++++ mysql-test/r/plugin.result | 32 +++++++++++++++++++++++- mysql-test/t/plugin.test | 19 ++++++++++++++ sql/sql_plugin.cc | 58 +++++++++++++++++++++++++++++++++++++++++++ storage/example/ha_example.cc | 19 ++++++++++++-- 5 files changed, 136 insertions(+), 3 deletions(-) diff --git a/include/mysql/plugin.h b/include/mysql/plugin.h index 8fe8665..08bd490 100644 --- a/include/mysql/plugin.h +++ b/include/mysql/plugin.h @@ -163,6 +163,7 @@ typedef int (*mysql_show_var_func)(MYSQL_THD, struct st_mysql_show_var*, char *) #define PLUGIN_VAR_STR 0x0005 #define PLUGIN_VAR_ENUM 0x0006 #define PLUGIN_VAR_SET 0x0007 +#define PLUGIN_VAR_DOUBLE 0x0008 #define PLUGIN_VAR_UNSIGNED 0x0080 #define PLUGIN_VAR_THDLOCAL 0x0100 /* Variable is per-connection */ #define PLUGIN_VAR_READONLY 0x0200 /* Server variable is read only */ @@ -345,6 +346,11 @@ DECLARE_MYSQL_SYSVAR_TYPELIB(name, unsigned long long) = { \ PLUGIN_VAR_SET | ((opt) & PLUGIN_VAR_MASK), \ #name, comment, check, update, &varname, def, typelib } +#define MYSQL_SYSVAR_DOUBLE(name, varname, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_SYSVAR_SIMPLE(name, double) = { \ + PLUGIN_VAR_DOUBLE | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, &varname, def, min, max, blk } + #define MYSQL_THDVAR_BOOL(name, opt, comment, check, update, def) \ DECLARE_MYSQL_THDVAR_BASIC(name, char) = { \ PLUGIN_VAR_BOOL | PLUGIN_VAR_THDLOCAL | ((opt) & PLUGIN_VAR_MASK), \ @@ -395,6 +401,11 @@ DECLARE_MYSQL_THDVAR_TYPELIB(name, unsigned long long) = { \ PLUGIN_VAR_SET | PLUGIN_VAR_THDLOCAL | ((opt) & PLUGIN_VAR_MASK), \ #name, comment, check, update, -1, def, NULL, typelib } +#define MYSQL_THDVAR_DOUBLE(name, opt, comment, check, update, def, min, max, blk) \ +DECLARE_MYSQL_THDVAR_SIMPLE(name, double) = { \ + PLUGIN_VAR_DOUBLE | PLUGIN_VAR_THDLOCAL | ((opt) & PLUGIN_VAR_MASK), \ + #name, comment, check, update, -1, def, min, max, blk, NULL } + /* accessor macros */ #define SYSVAR(name) \ diff --git a/mysql-test/r/plugin.result b/mysql-test/r/plugin.result index 0d5bc29..4a06573 100644 --- a/mysql-test/r/plugin.result +++ b/mysql-test/r/plugin.result @@ -16,9 +16,10 @@ set global example_ulong_var=500; set global example_enum_var= e1; show status like 'example%'; Variable_name Value -example_func_example enum_var is 0, ulong_var is 500, really +example_func_example enum_var is 0, ulong_var is 500, double_var is 8.000000, really show variables like 'example%'; Variable_name Value +example_double_var 8.000000 example_enum_var e1 example_ulong_var 500 UNINSTALL PLUGIN example; @@ -62,4 +63,33 @@ select @@global.example_ulong_var; set session sql_mode=@old_sql_mode; set session old=bla; ERROR HY000: Variable 'old' is a read only variable +# Floating-point plugin system variables. +SET GLOBAL example_double_var = -0.1; +Warnings: +Warning 1292 Truncated incorrect example_double_var value: '-0.1' +SELECT @@GLOBAL.example_double_var; +@@GLOBAL.example_double_var +0.000000 +SET GLOBAL example_double_var = 0.000001; +SELECT @@GLOBAL.example_double_var; +@@GLOBAL.example_double_var +0.000001 +SET GLOBAL example_double_var = 123.456789; +SELECT @@GLOBAL.example_double_var; +@@GLOBAL.example_double_var +123.456789 +SET GLOBAL example_double_var = 500; +SELECT @@GLOBAL.example_double_var; +@@GLOBAL.example_double_var +500.000000 +SET GLOBAL example_double_var = 999.999999; +SELECT @@GLOBAL.example_double_var; +@@GLOBAL.example_double_var +999.999999 +SET GLOBAL example_double_var = 1000.1; +Warnings: +Warning 1292 Truncated incorrect example_double_var value: '1000.1' +SELECT @@GLOBAL.example_double_var; +@@GLOBAL.example_double_var +1000.000000 UNINSTALL PLUGIN example; diff --git a/mysql-test/t/plugin.test b/mysql-test/t/plugin.test index 117eaf1..d6987f1 100644 --- a/mysql-test/t/plugin.test +++ b/mysql-test/t/plugin.test @@ -84,4 +84,23 @@ set session sql_mode=@old_sql_mode; --error ER_INCORRECT_GLOBAL_LOCAL_VAR set session old=bla; +--echo # Floating-point plugin system variables. +SET GLOBAL example_double_var = -0.1; +SELECT @@GLOBAL.example_double_var; + +SET GLOBAL example_double_var = 0.000001; +SELECT @@GLOBAL.example_double_var; + +SET GLOBAL example_double_var = 123.456789; +SELECT @@GLOBAL.example_double_var; + +SET GLOBAL example_double_var = 500; +SELECT @@GLOBAL.example_double_var; + +SET GLOBAL example_double_var = 999.999999; +SELECT @@GLOBAL.example_double_var; + +SET GLOBAL example_double_var = 1000.1; +SELECT @@GLOBAL.example_double_var; + UNINSTALL PLUGIN example; diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 4c42f37..30ca773 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -2066,6 +2066,8 @@ typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_uint_t, uint); typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_ulong_t, ulong); typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_ulonglong_t, ulonglong); +typedef DECLARE_MYSQL_SYSVAR_SIMPLE(sysvar_double_t, double); +typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_double_t, double); /**************************************************************************** default variable data check and update functions @@ -2187,6 +2189,22 @@ static int check_func_longlong(THD *thd, struct st_mysql_sys_var *var, value->is_unsigned(value), (longlong) orig); } + +static int check_func_double(THD *thd, struct st_mysql_sys_var *var, + void *save, st_mysql_value *value) +{ + double v; + my_bool fixed; + struct my_option option; + + value->val_real(value, &v); + plugin_opt_set_limits(&option, var); + *(double *) save= getopt_double_limit_value(v, &option, &fixed); + + return throw_bounds_warning(thd, var->name, fixed, v); +} + + static int check_func_str(THD *thd, struct st_mysql_sys_var *var, void *save, st_mysql_value *value) { @@ -2316,6 +2334,13 @@ static void update_func_str(THD *thd, struct st_mysql_sys_var *var, } +static void update_func_double(THD *thd, struct st_mysql_sys_var *var, + void *tgt, const void *save) +{ + *(double *) tgt= *(double *) save; +} + + /**************************************************************************** System Variables support ****************************************************************************/ @@ -2429,6 +2454,9 @@ static st_bookmark *register_var(const char *plugin, const char *name, case PLUGIN_VAR_STR: size= sizeof(char*); break; + case PLUGIN_VAR_DOUBLE: + size= sizeof(double); + break; default: DBUG_ASSERT(0); return NULL; @@ -2640,6 +2668,11 @@ static char **mysql_sys_var_str(THD* thd, int offset) return (char **) intern_sys_var_ptr(thd, offset, true); } +static double *mysql_sys_var_double(THD* thd, int offset) +{ + return (double *) intern_sys_var_ptr(thd, offset, true); +} + void plugin_thdvar_init(THD *thd) { plugin_ref old_table_plugin= thd->variables.table_plugin; @@ -2772,6 +2805,8 @@ static SHOW_TYPE pluginvar_show_type(st_mysql_sys_var *plugin_var) case PLUGIN_VAR_ENUM: case PLUGIN_VAR_SET: return SHOW_CHAR; + case PLUGIN_VAR_DOUBLE: + return SHOW_DOUBLE; default: DBUG_ASSERT(0); return SHOW_UNDEF; @@ -2922,6 +2957,8 @@ bool sys_var_pluginvar::check_update_type(Item_result type) case PLUGIN_VAR_BOOL: case PLUGIN_VAR_SET: return type != STRING_RESULT && type != INT_RESULT; + case PLUGIN_VAR_DOUBLE: + return type != INT_RESULT && type != REAL_RESULT && type != DECIMAL_RESULT; default: return true; } @@ -3047,6 +3084,9 @@ bool sys_var_pluginvar::global_update(THD *thd, set_var *var) case PLUGIN_VAR_STR: src= &((sysvar_str_t*) plugin_var)->def_val; break; + case PLUGIN_VAR_DOUBLE: + src= &((sysvar_double_t*) plugin_var)->def_val; + break; case PLUGIN_VAR_INT | PLUGIN_VAR_THDLOCAL: src= &((thdvar_uint_t*) plugin_var)->def_val; break; @@ -3068,6 +3108,9 @@ bool sys_var_pluginvar::global_update(THD *thd, set_var *var) case PLUGIN_VAR_STR | PLUGIN_VAR_THDLOCAL: src= &((thdvar_str_t*) plugin_var)->def_val; break; + case PLUGIN_VAR_DOUBLE | PLUGIN_VAR_THDLOCAL: + src= &((thdvar_double_t*) plugin_var)->def_val; + break; default: DBUG_ASSERT(0); } @@ -3118,6 +3161,9 @@ static void plugin_opt_set_limits(struct my_option *options, case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED: OPTION_SET_LIMITS(GET_ULL, options, (sysvar_ulonglong_t*) opt); break; + case PLUGIN_VAR_DOUBLE: + OPTION_SET_LIMITS(GET_DOUBLE, options, (sysvar_double_t*) opt); + break; case PLUGIN_VAR_ENUM: options->var_type= GET_ENUM; options->typelib= ((sysvar_enum_t*) opt)->typelib; @@ -3160,6 +3206,9 @@ static void plugin_opt_set_limits(struct my_option *options, case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL: OPTION_SET_LIMITS(GET_ULL, options, (thdvar_ulonglong_t*) opt); break; + case PLUGIN_VAR_DOUBLE | PLUGIN_VAR_THDLOCAL: + OPTION_SET_LIMITS(GET_DOUBLE, options, (thdvar_double_t*) opt); + break; case PLUGIN_VAR_ENUM | PLUGIN_VAR_THDLOCAL: options->var_type= GET_ENUM; options->typelib= ((thdvar_enum_t*) opt)->typelib; @@ -3322,6 +3371,9 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp, case PLUGIN_VAR_SET: ((thdvar_set_t *) opt)->resolve= mysql_sys_var_ulonglong; break; + case PLUGIN_VAR_DOUBLE: + ((thdvar_double_t *) opt)->resolve= mysql_sys_var_double; + break; default: sql_print_error("Unknown variable type code 0x%x in plugin '%s'.", opt->flags, plugin_name); @@ -3385,6 +3437,12 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp, if (!opt->update) opt->update= update_func_longlong; break; + case PLUGIN_VAR_DOUBLE: + if (!opt->check) + opt->check= check_func_double; + if (!opt->update) + opt->update= update_func_double; + break; default: sql_print_error("Unknown variable type code 0x%x in plugin '%s'.", opt->flags, plugin_name); diff --git a/storage/example/ha_example.cc b/storage/example/ha_example.cc index c4ed4d5..88f9f65 100644 --- a/storage/example/ha_example.cc +++ b/storage/example/ha_example.cc @@ -1004,6 +1004,7 @@ struct st_mysql_storage_engine example_storage_engine= static ulong srv_enum_var= 0; static ulong srv_ulong_var= 0; +static double srv_double_var= 0; const char *enum_var_names[]= { @@ -1038,9 +1039,22 @@ static MYSQL_SYSVAR_ULONG( 1000, 0); +static MYSQL_SYSVAR_DOUBLE( + double_var, + srv_double_var, + PLUGIN_VAR_RQCMDARG, + "0.0..1000.0", + NULL, + NULL, + 8.0, + 0.0, + 1000.0, + 0); + static struct st_mysql_sys_var* example_system_variables[]= { MYSQL_SYSVAR(enum_var), MYSQL_SYSVAR(ulong_var), + MYSQL_SYSVAR(double_var), NULL }; @@ -1051,8 +1065,9 @@ static int show_func_example(MYSQL_THD thd, struct st_mysql_show_var *var, var->type= SHOW_CHAR; var->value= buf; // it's of SHOW_VAR_FUNC_BUFF_SIZE bytes my_snprintf(buf, SHOW_VAR_FUNC_BUFF_SIZE, - "enum_var is %lu, ulong_var is %lu, %.6b", // %b is MySQL extension - srv_enum_var, srv_ulong_var, "really"); + "enum_var is %lu, ulong_var is %lu, " + "double_var is %f, %.6b", // %b is a MySQL extension + srv_enum_var, srv_ulong_var, srv_double_var, "really"); return 0; } -- 1.8.0