Skip to content
This repository
Browse code

The fractional part of the def, min and max values of system variables

is ignored.

Allow the default, minimum and maximum values of system variables of
type double to have a meaningful fractional part. Since the command-line
option parsing interface (my_getopt) uses fields of type unsigned long
long (ull) to store these values, the double values were being stored in
a lossy way that discards the fractional part.

This change introduces a couple of functions that can be used to store
the raw representation of a double value in the raw bits of unsigned
long long field in a way that the binary representation remains the
same. Using these function the real value can be converted back and
forth between the types.
  • Loading branch information...
commit 1b9de642d95963c24885a28751411f1c5be88aad 1 parent 9cca1d8
Davi Arnaut authored
3  include/my_getopt.h
@@ -120,6 +120,9 @@ double getopt_double_limit_value(double num, const struct my_option *optp,
120 120 my_bool *fix);
121 121 my_bool getopt_compare_strings(const char *s, const char *t, uint length);
122 122
  123 +ulonglong getopt_double2ulonglong(double);
  124 +double getopt_ulonglong2double(ulonglong);
  125 +
123 126 C_MODE_END
124 127
125 128 #endif /* _my_getopt_h */
28 mysql-test/r/plugin.result
@@ -16,10 +16,10 @@ set global example_ulong_var=500;
16 16 set global example_enum_var= e1;
17 17 show status like 'example%';
18 18 Variable_name Value
19   -example_func_example enum_var is 0, ulong_var is 500, double_var is 8.000000, really
  19 +example_func_example enum_var is 0, ulong_var is 500, double_var is 8.500000, really
20 20 show variables like 'example%';
21 21 Variable_name Value
22   -example_double_var 8.000000
  22 +example_double_var 8.500000
23 23 example_enum_var e1
24 24 example_ulong_var 500
25 25 UNINSTALL PLUGIN example;
@@ -69,11 +69,23 @@ Warnings:
69 69 Warning 1292 Truncated incorrect example_double_var value: '-0.1'
70 70 SELECT @@GLOBAL.example_double_var;
71 71 @@GLOBAL.example_double_var
72   -0.000000
  72 +0.500000
73 73 SET GLOBAL example_double_var = 0.000001;
  74 +Warnings:
  75 +Warning 1292 Truncated incorrect example_double_var value: '0.000001'
  76 +SELECT @@GLOBAL.example_double_var;
  77 +@@GLOBAL.example_double_var
  78 +0.500000
  79 +SET GLOBAL example_double_var = 0.4;
  80 +Warnings:
  81 +Warning 1292 Truncated incorrect example_double_var value: '0.4'
74 82 SELECT @@GLOBAL.example_double_var;
75 83 @@GLOBAL.example_double_var
76   -0.000001
  84 +0.500000
  85 +SET GLOBAL example_double_var = 0.5;
  86 +SELECT @@GLOBAL.example_double_var;
  87 +@@GLOBAL.example_double_var
  88 +0.500000
77 89 SET GLOBAL example_double_var = 123.456789;
78 90 SELECT @@GLOBAL.example_double_var;
79 91 @@GLOBAL.example_double_var
@@ -87,9 +99,13 @@ SELECT @@GLOBAL.example_double_var;
87 99 @@GLOBAL.example_double_var
88 100 999.999999
89 101 SET GLOBAL example_double_var = 1000.1;
  102 +SELECT @@GLOBAL.example_double_var;
  103 +@@GLOBAL.example_double_var
  104 +1000.100000
  105 +SET GLOBAL example_double_var = 1000.51;
90 106 Warnings:
91   -Warning 1292 Truncated incorrect example_double_var value: '1000.1'
  107 +Warning 1292 Truncated incorrect example_double_var value: '1000.51'
92 108 SELECT @@GLOBAL.example_double_var;
93 109 @@GLOBAL.example_double_var
94   -1000.000000
  110 +1000.500000
95 111 UNINSTALL PLUGIN example;
9 mysql-test/t/plugin.test
@@ -91,6 +91,12 @@ SELECT @@GLOBAL.example_double_var;
91 91 SET GLOBAL example_double_var = 0.000001;
92 92 SELECT @@GLOBAL.example_double_var;
93 93
  94 +SET GLOBAL example_double_var = 0.4;
  95 +SELECT @@GLOBAL.example_double_var;
  96 +
  97 +SET GLOBAL example_double_var = 0.5;
  98 +SELECT @@GLOBAL.example_double_var;
  99 +
94 100 SET GLOBAL example_double_var = 123.456789;
95 101 SELECT @@GLOBAL.example_double_var;
96 102
@@ -103,4 +109,7 @@ SELECT @@GLOBAL.example_double_var;
103 109 SET GLOBAL example_double_var = 1000.1;
104 110 SELECT @@GLOBAL.example_double_var;
105 111
  112 +SET GLOBAL example_double_var = 1000.51;
  113 +SELECT @@GLOBAL.example_double_var;
  114 +
106 115 UNINSTALL PLUGIN example;
44 mysys/my_getopt.c
@@ -90,6 +90,35 @@ void my_getopt_register_get_addr(my_getopt_value func_addr)
90 90 getopt_get_addr= func_addr;
91 91 }
92 92
  93 +union ull_dbl
  94 +{
  95 + ulonglong ull;
  96 + double dbl;
  97 +};
  98 +
  99 +/**
  100 + Returns an ulonglong value containing a raw
  101 + representation of the given double value.
  102 +*/
  103 +ulonglong getopt_double2ulonglong(double v)
  104 +{
  105 + union ull_dbl u;
  106 + u.dbl= v;
  107 + compile_time_assert(sizeof(ulonglong) >= sizeof(double));
  108 + return u.ull;
  109 +}
  110 +
  111 +/**
  112 + Returns the double value which corresponds to
  113 + the given raw representation.
  114 +*/
  115 +double getopt_ulonglong2double(ulonglong v)
  116 +{
  117 + union ull_dbl u;
  118 + u.ull= v;
  119 + return u.dbl;
  120 +}
  121 +
93 122 /**
94 123 Handle command line options.
95 124 Sort options.
@@ -1044,14 +1073,19 @@ double getopt_double_limit_value(double num, const struct my_option *optp,
1044 1073 {
1045 1074 my_bool adjusted= FALSE;
1046 1075 double old= num;
1047   - if (optp->max_value && num > (double) optp->max_value)
  1076 + double max, min;
  1077 +
  1078 + max= getopt_ulonglong2double(optp->max_value);
  1079 + min= getopt_ulonglong2double(optp->min_value);
  1080 +
  1081 + if (max && num > max)
1048 1082 {
1049   - num= (double) optp->max_value;
  1083 + num= max;
1050 1084 adjusted= TRUE;
1051 1085 }
1052   - if (num < (double) optp->min_value)
  1086 + if (num < min)
1053 1087 {
1054   - num= (double) optp->min_value;
  1088 + num= min;
1055 1089 adjusted= TRUE;
1056 1090 }
1057 1091 if (fix)
@@ -1134,7 +1168,7 @@ static void init_one_value(const struct my_option *option, void *variable,
1134 1168 *((ulonglong*) variable)= (ulonglong) value;
1135 1169 break;
1136 1170 case GET_DOUBLE:
1137   - *((double*) variable)= ulonglong2double(value);
  1171 + *((double*) variable)= getopt_ulonglong2double(value);
1138 1172 break;
1139 1173 case GET_STR:
1140 1174 /*
12 sql/sql_plugin.cc
@@ -3135,6 +3135,14 @@ bool sys_var_pluginvar::global_update(THD *thd, set_var *var)
3135 3135 options->block_size= (long) (opt)->blk_sz
3136 3136
3137 3137
  3138 +#define OPTION_SET_LIMITS_DOUBLE(options, opt) \
  3139 + options->var_type= GET_DOUBLE; \
  3140 + options->def_value= (longlong) getopt_double2ulonglong((opt)->def_val); \
  3141 + options->min_value= (longlong) getopt_double2ulonglong((opt)->min_val); \
  3142 + options->max_value= getopt_double2ulonglong((opt)->max_val); \
  3143 + options->block_size= (long) (opt)->blk_sz
  3144 +
  3145 +
3138 3146 static void plugin_opt_set_limits(struct my_option *options,
3139 3147 const struct st_mysql_sys_var *opt)
3140 3148 {
@@ -3162,7 +3170,7 @@ static void plugin_opt_set_limits(struct my_option *options,
3162 3170 OPTION_SET_LIMITS(GET_ULL, options, (sysvar_ulonglong_t*) opt);
3163 3171 break;
3164 3172 case PLUGIN_VAR_DOUBLE:
3165   - OPTION_SET_LIMITS(GET_DOUBLE, options, (sysvar_double_t*) opt);
  3173 + OPTION_SET_LIMITS_DOUBLE(options, (sysvar_double_t*) opt);
3166 3174 break;
3167 3175 case PLUGIN_VAR_ENUM:
3168 3176 options->var_type= GET_ENUM;
@@ -3207,7 +3215,7 @@ static void plugin_opt_set_limits(struct my_option *options,
3207 3215 OPTION_SET_LIMITS(GET_ULL, options, (thdvar_ulonglong_t*) opt);
3208 3216 break;
3209 3217 case PLUGIN_VAR_DOUBLE | PLUGIN_VAR_THDLOCAL:
3210   - OPTION_SET_LIMITS(GET_DOUBLE, options, (thdvar_double_t*) opt);
  3218 + OPTION_SET_LIMITS_DOUBLE(options, (thdvar_double_t*) opt);
3211 3219 break;
3212 3220 case PLUGIN_VAR_ENUM | PLUGIN_VAR_THDLOCAL:
3213 3221 options->var_type= GET_ENUM;
11 sql/sys_vars.h
@@ -771,14 +771,15 @@ class Sys_var_double: public sys_var
771 771 const char *substitute=0,
772 772 int parse_flag= PARSE_NORMAL)
773 773 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
774   - getopt.arg_type, SHOW_DOUBLE, (longlong) double2ulonglong(def_val),
  774 + getopt.arg_type, SHOW_DOUBLE,
  775 + (longlong) getopt_double2ulonglong(def_val),
775 776 lock, binlog_status_arg, on_check_func, on_update_func,
776 777 substitute, parse_flag)
777 778 {
778 779 option.var_type= GET_DOUBLE;
779   - option.min_value= (longlong) double2ulonglong(min_val);
780   - option.max_value= (longlong) double2ulonglong(max_val);
781   - global_var(double)= (double)option.def_value;
  780 + option.min_value= (longlong) getopt_double2ulonglong(min_val);
  781 + option.max_value= (longlong) getopt_double2ulonglong(max_val);
  782 + global_var(double)= def_val;
782 783 DBUG_ASSERT(min_val < max_val);
783 784 DBUG_ASSERT(min_val <= def_val);
784 785 DBUG_ASSERT(max_val >= def_val);
@@ -809,7 +810,7 @@ class Sys_var_double: public sys_var
809 810 void session_save_default(THD *thd, set_var *var)
810 811 { var->save_result.double_value= global_var(double); }
811 812 void global_save_default(THD *thd, set_var *var)
812   - { var->save_result.double_value= (double)option.def_value; }
  813 + { var->save_result.double_value= getopt_ulonglong2double(option.def_value); }
813 814 };
814 815
815 816 /**
6 storage/example/ha_example.cc
@@ -1046,9 +1046,9 @@ static MYSQL_SYSVAR_DOUBLE(
1046 1046 "0.0..1000.0",
1047 1047 NULL,
1048 1048 NULL,
1049   - 8.0,
1050   - 0.0,
1051   - 1000.0,
  1049 + 8.5,
  1050 + 0.5,
  1051 + 1000.5,
1052 1052 0);
1053 1053
1054 1054 static struct st_mysql_sys_var* example_system_variables[]= {

0 comments on commit 1b9de64

Please sign in to comment.
Something went wrong with that request. Please try again.