Below is the list of changes that have just been committed into a local
5.1 repository of tnurnberg. When tnurnberg does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2008-01-07 02:47:56+01:00, tnurnberg@stripped +5 -0
Bug#32757: hang with sql_mode set when setting some global variables
If setting a system-variable provided by a plug-in failed, no OK or
error was sent in some cases, hanging the client. We now send an error
in the case from the ticket (integer-argument out of range in STRICT
mode). We also provide a semi-generic fallback message for possible
future cases like this where an error is signalled, but no message is
sent to the client.
mysql-test/r/plugin.result@stripped, 2008-01-07 02:47:54+01:00, tnurnberg@stripped +27 -0
show that on out-of-range values, plugin interface throws errors
in STRICT mode and warnings otherwise.
mysql-test/t/plugin.test@stripped, 2008-01-07 02:47:54+01:00, tnurnberg@stripped +35 -0
show that on out-of-range values, plugin interface throws errors
in STRICT mode and warnings otherwise.
sql/sql_parse.cc@stripped, 2008-01-07 02:47:54+01:00, tnurnberg@stripped +12 -0
If sql_set_variables() returns with an error but no message
was sent to the client, send a semi-generic one so the session
won't hang and we won't fail silently.
sql/sql_plugin.cc@stripped, 2008-01-07 02:47:54+01:00, tnurnberg@stripped +57 -21
For integers provided by plugins:
- handle signedness correctly in error-/warning-messages
- in STRICT mode: throw an error if value is out of range
otherwise: throw a warning if more than just block-size
was corrected (like we used to)
storage/example/ha_example.cc@stripped, 2008-01-07 02:47:54+01:00, tnurnberg@stripped +14
-0
Add a ULONG system variable to example plugin so
we can test integers in the plugin-interface without
having to depend on the presence of innobase.
diff -Nrup a/mysql-test/r/plugin.result b/mysql-test/r/plugin.result
--- a/mysql-test/r/plugin.result 2007-11-14 10:48:18 +01:00
+++ b/mysql-test/r/plugin.result 2008-01-07 02:47:54 +01:00
@@ -27,3 +27,30 @@ SET GLOBAL example_enum_var= e2;
SET GLOBAL example_enum_var= impossible;
ERROR 42000: Variable 'enum_var' can't be set to the value of 'impossible'
UNINSTALL PLUGIN example;
+INSTALL PLUGIN example SONAME 'ha_example.so';
+select @@session.sql_mode into @old_sql_mode;
+set session sql_mode='';
+set global example_ulong_var=500;
+select @@global.example_ulong_var;
+@@global.example_ulong_var
+500
+set global example_ulong_var=1111;
+Warnings:
+Warning 1292 Truncated incorrect ulong_var value: '1111'
+select @@global.example_ulong_var;
+@@global.example_ulong_var
+1000
+set session sql_mode='STRICT_ALL_TABLES';
+set global example_ulong_var=500;
+select @@global.example_ulong_var;
+@@global.example_ulong_var
+500
+set global example_ulong_var=1111;
+ERROR 42000: Variable 'ulong_var' can't be set to the value of '1111'
+select @@global.example_ulong_var;
+@@global.example_ulong_var
+500
+set session sql_mode=@old_sql_mode;
+set session old=bla;
+ERROR HY000: Variable 'old' is a read only variable
+UNINSTALL PLUGIN example;
diff -Nrup a/mysql-test/t/plugin.test b/mysql-test/t/plugin.test
--- a/mysql-test/t/plugin.test 2007-11-14 10:48:17 +01:00
+++ b/mysql-test/t/plugin.test 2008-01-07 02:47:54 +01:00
@@ -39,3 +39,38 @@ SET GLOBAL example_enum_var= e2;
SET GLOBAL example_enum_var= impossible;
UNINSTALL PLUGIN example;
+
+
+
+#
+# Bug #32757 hang with sql_mode set when setting some global variables
+#
+INSTALL PLUGIN example SONAME 'ha_example.so';
+
+select @@session.sql_mode into @old_sql_mode;
+
+# first, try normal sql_mode (no error, send OK)
+set session sql_mode='';
+set global example_ulong_var=500;
+select @@global.example_ulong_var;
+# overflow -- throw warning, do NOT change value
+set global example_ulong_var=1111;
+select @@global.example_ulong_var;
+
+# now, try STRICT (error occurrs, no message is sent, so send default)
+set session sql_mode='STRICT_ALL_TABLES';
+set global example_ulong_var=500;
+select @@global.example_ulong_var;
+# overflow -- throw warning, do NOT change value
+--error ER_WRONG_VALUE_FOR_VAR
+set global example_ulong_var=1111;
+select @@global.example_ulong_var;
+
+set session sql_mode=@old_sql_mode;
+
+# finally, show that conditions that already raised an error are not
+# adversely affected (error was already sent, do nothing)
+--error ER_INCORRECT_GLOBAL_LOCAL_VAR
+set session old=bla;
+
+UNINSTALL PLUGIN example;
diff -Nrup a/sql/sql_parse.cc b/sql/sql_parse.cc
--- a/sql/sql_parse.cc 2007-12-13 15:26:24 +01:00
+++ b/sql/sql_parse.cc 2008-01-07 02:47:54 +01:00
@@ -3127,6 +3127,18 @@ end_with_restore_list:
thd->one_shot_set|= lex->one_shot_set;
send_ok(thd);
}
+ else
+ {
+ /*
+ We encountered some sort of error, but no message was sent.
+ Send something semi-generic here since we don't know which
+ assignment in the list caused the error.
+ */
+ if (!thd->is_error())
+ my_error(ER_WRONG_ARGUMENTS,MYF(0),"SET");
+ goto error;
+ }
+
break;
}
diff -Nrup a/sql/sql_plugin.cc b/sql/sql_plugin.cc
--- a/sql/sql_plugin.cc 2007-12-13 12:49:55 +01:00
+++ b/sql/sql_plugin.cc 2008-01-07 02:47:54 +01:00
@@ -1888,16 +1888,28 @@ static int check_func_int(THD *thd, stru
else
*(int *)save= (int) getopt_ll_limit_value(tmp, &options, &fixed);
- if (fixed)
+ if (*(int *)save != (int) tmp)
{
char buf[22];
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_TRUNCATED_WRONG_VALUE,
- ER(ER_TRUNCATED_WRONG_VALUE), var->name,
- ullstr(tmp, buf));
+ if (var->flags & PLUGIN_VAR_UNSIGNED)
+ ullstr(tmp, buf);
+ else
+ llstr(tmp, buf);
+
+ if (thd->variables.sql_mode & MODE_STRICT_ALL_TABLES)
+ {
+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0),
+ var->name, buf);
+ return TRUE;
+ }
+ else if (fixed)
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_TRUNCATED_WRONG_VALUE,
+ ER(ER_TRUNCATED_WRONG_VALUE), var->name,
+ buf);
}
- return (thd->variables.sql_mode & MODE_STRICT_ALL_TABLES) &&
- (*(int *)save != (int) tmp);
+
+ return FALSE;
}
@@ -1916,16 +1928,28 @@ static int check_func_long(THD *thd, str
else
*(long *)save= (long) getopt_ll_limit_value(tmp, &options, &fixed);
- if (fixed)
+ if (*(long *)save != (long) tmp)
{
char buf[22];
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_TRUNCATED_WRONG_VALUE,
- ER(ER_TRUNCATED_WRONG_VALUE), var->name,
- ullstr(tmp, buf));
+ if (var->flags & PLUGIN_VAR_UNSIGNED)
+ ullstr(tmp, buf);
+ else
+ llstr(tmp, buf);
+
+ if (thd->variables.sql_mode & MODE_STRICT_ALL_TABLES)
+ {
+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0),
+ var->name, buf);
+ return TRUE;
+ }
+ else if (fixed)
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_TRUNCATED_WRONG_VALUE,
+ ER(ER_TRUNCATED_WRONG_VALUE), var->name,
+ buf);
}
- return (thd->variables.sql_mode & MODE_STRICT_ALL_TABLES) &&
- (*(long *)save != (long) tmp);
+
+ return FALSE;
}
@@ -1945,16 +1969,28 @@ static int check_func_longlong(THD *thd,
else
*(longlong *)save= getopt_ll_limit_value(tmp, &options, &fixed);
- if (fixed)
+ if (*(long long *)save != tmp)
{
char buf[22];
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_TRUNCATED_WRONG_VALUE,
- ER(ER_TRUNCATED_WRONG_VALUE), var->name,
- ullstr(tmp, buf));
+ if (var->flags & PLUGIN_VAR_UNSIGNED)
+ ullstr(tmp, buf);
+ else
+ llstr(tmp, buf);
+
+ if (thd->variables.sql_mode & MODE_STRICT_ALL_TABLES)
+ {
+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0),
+ var->name, buf);
+ return TRUE;
+ }
+ else if (fixed)
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_TRUNCATED_WRONG_VALUE,
+ ER(ER_TRUNCATED_WRONG_VALUE), var->name,
+ buf);
}
- return (thd->variables.sql_mode & MODE_STRICT_ALL_TABLES) &&
- (*(long long *)save != tmp);
+
+ return FALSE;
}
static int check_func_str(THD *thd, struct st_mysql_sys_var *var,
diff -Nrup a/storage/example/ha_example.cc b/storage/example/ha_example.cc
--- a/storage/example/ha_example.cc 2007-11-14 10:48:15 +01:00
+++ b/storage/example/ha_example.cc 2008-01-07 02:47:54 +01:00
@@ -849,6 +849,7 @@ struct st_mysql_storage_engine example_s
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
static ulong srv_enum_var= 0;
+static ulong srv_ulong_var= 0;
const char *enum_var_names[]=
{
@@ -871,8 +872,21 @@ static MYSQL_SYSVAR_ENUM(
0, // def
&enum_var_typelib); // typelib
+static MYSQL_SYSVAR_ULONG(
+ ulong_var,
+ srv_ulong_var,
+ PLUGIN_VAR_RQCMDARG,
+ "0..1000",
+ NULL,
+ NULL,
+ 8,
+ 0,
+ 1000,
+ 0);
+
static struct st_mysql_sys_var* example_system_variables[]= {
MYSQL_SYSVAR(enum_var),
+ MYSQL_SYSVAR(ulong_var),
NULL
};