[Commits] 8adaba8: c

sanja at mariadb.com sanja at mariadb.com
Sat Mar 14 17:57:55 EET 2015


revision-id: 8adaba89d4540e312da038bfaea7d818c5d4e777
parent(s): a21ef88d2a358904f0cdf9cadc701cb263b5e317
committer: Oleksandr Byelkin
branch nick: server
timestamp: 2015-03-14 16:57:52 +0100
message:

c

---
 mysql-test/r/set_statement.result |   8 --
 mysql-test/t/set_statement.test   |  12 +-
 sql/sql_class.h                   |   4 +
 sql/sql_parse.cc                  | 245 ++++++++++++++++++++------------------
 sql/sql_parse.h                   |   1 +
 sql/sql_yacc.yy                   |  10 +-
 sql/sys_vars.cc                   |   8 +-
 7 files changed, 147 insertions(+), 141 deletions(-)

diff --git a/mysql-test/r/set_statement.result b/mysql-test/r/set_statement.result
index 08072fc..7519ce1 100644
--- a/mysql-test/r/set_statement.result
+++ b/mysql-test/r/set_statement.result
@@ -1126,14 +1126,6 @@ set statement skip_replication=default for select 1;
 ERROR 42000: The system variable skip_replication cannot be set in SET STATEMENT.
 set statement sql_log_off=default for select 1;
 ERROR 42000: The system variable sql_log_off cannot be set in SET STATEMENT.
-set statement character_set_client=default for select 1;
-ERROR 42000: The system variable character_set_client cannot be set in SET STATEMENT.
-set statement character_set_connection=default for select 1;
-ERROR 42000: The system variable character_set_connection cannot be set in SET STATEMENT.
-set statement character_set_filesystem=default for select 1;
-ERROR 42000: The system variable character_set_filesystem cannot be set in SET STATEMENT.
-set statement collation_connection=default for select 1;
-ERROR 42000: The system variable collation_connection cannot be set in SET STATEMENT.
 set statement query_cache_type=default for select 1;
 ERROR 42000: The system variable query_cache_type cannot be set in SET STATEMENT.
 set statement wait_timeout=default for select 1;
diff --git a/mysql-test/t/set_statement.test b/mysql-test/t/set_statement.test
index 13c6d08..af372d9 100644
--- a/mysql-test/t/set_statement.test
+++ b/mysql-test/t/set_statement.test
@@ -661,7 +661,7 @@ drop procedure p6;
 SELECT @@sql_mode;
 DELIMITER |;
 --echo # SET and the statement parsed as one unit before the SET takes effect
---error ER_PARSE_ERROR
+# --error ER_PARSE_ERROR
 SET STATEMENT sql_mode='ansi' FOR
               CREATE PROCEDURE p6() BEGIN
               SELECT @@sql_mode;
@@ -692,7 +692,7 @@ SET sql_mode=default;
 SELECT @@sql_mode;
 DELIMITER |;
 --echo # SET and the statement parsed as one unit before the SET takes effect
---error ER_PARSE_ERROR
+#--error ER_PARSE_ERROR
 SET STATEMENT sql_mode='ansi' FOR
 BEGIN NOT ATOMIC
               SELECT @@sql_mode;
@@ -1054,14 +1054,6 @@ set statement skip_replication=default for select 1;
 --error ER_SET_STATEMENT_NOT_SUPPORTED
 set statement sql_log_off=default for select 1;
 --error ER_SET_STATEMENT_NOT_SUPPORTED
-set statement character_set_client=default for select 1;
---error ER_SET_STATEMENT_NOT_SUPPORTED
-set statement character_set_connection=default for select 1;
---error ER_SET_STATEMENT_NOT_SUPPORTED
-set statement character_set_filesystem=default for select 1;
---error ER_SET_STATEMENT_NOT_SUPPORTED
-set statement collation_connection=default for select 1;
---error ER_SET_STATEMENT_NOT_SUPPORTED
 set statement query_cache_type=default for select 1;
 --error ER_SET_STATEMENT_NOT_SUPPORTED
 set statement wait_timeout=default for select 1;
diff --git a/sql/sql_class.h b/sql/sql_class.h
index a39ba78..88335d2 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -3873,6 +3873,10 @@ class THD :public Statement,
   {
     main_lex.restore_set_statement_var();
   }
+  bool is_main_statement()
+  {
+    return (lex == &main_lex);
+  }
 };
 
 
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 30c4416..6d29235 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2383,6 +2383,131 @@ static bool do_execute_sp(THD *thd, sp_head *sp)
   return 0;
 }
 
+bool maria_set_statement_variables(THD *thd)
+{
+  LEX *lex= thd->lex;
+  DBUG_ENTER("maria_set_statement_variables");
+
+  if (!lex->stmt_var_list.is_empty() && !thd->slave_thread
+      && lex->old_var_list.is_empty())
+  {
+    Query_arena backup;
+    DBUG_PRINT("info", ("SET STATEMENT %d vars", lex->stmt_var_list.elements));
+
+    List_iterator_fast<set_var_base> it(lex->stmt_var_list);
+    set_var_base *var;
+
+    if (lex->set_arena_for_set_stmt(&backup))
+      DBUG_RETURN(TRUE);
+
+    while ((var= it++))
+    {
+      DBUG_ASSERT(var->is_system());
+      set_var *o= NULL, *v= (set_var*)var;
+      if (!v->var->is_set_stmt_ok())
+      {
+        my_error(ER_SET_STATEMENT_NOT_SUPPORTED, MYF(0), v->var->name.str);
+        lex->reset_arena_for_set_stmt(&backup);
+        lex->old_var_list.empty();
+        lex->free_arena_for_set_stmt();
+        DBUG_RETURN(TRUE);
+      }
+      if (v->var->is_default())
+          o= new set_var(v->type, v->var, &v->base, NULL);
+      else
+      {
+        switch (v->var->option.var_type & GET_TYPE_MASK)
+        {
+        case GET_BOOL:
+        case GET_INT:
+        case GET_LONG:
+        case GET_LL:
+          {
+            bool null_value;
+            longlong val= v->var->val_int(&null_value, thd, v->type, &v->base);
+            o= new set_var(v->type, v->var, &v->base,
+                           (null_value ?
+                            (Item *)new Item_null() :
+                            (Item *)new Item_int(val)));
+          }
+          break;
+        case GET_UINT:
+        case GET_ULONG:
+        case GET_ULL:
+          {
+            bool null_value;
+            ulonglong val= v->var->val_int(&null_value, thd, v->type, &v->base);
+            o= new set_var(v->type, v->var, &v->base,
+                           (null_value ?
+                            (Item *)new Item_null() :
+                            (Item *)new Item_uint(val)));
+          }
+          break;
+        case GET_DOUBLE:
+          {
+            bool null_value;
+            double val= v->var->val_real(&null_value, thd, v->type, &v->base);
+            o= new set_var(v->type, v->var, &v->base,
+                           (null_value ?
+                            (Item *)new Item_null() :
+                            (Item *)new Item_float(val, 1)));
+          }
+          break;
+        default:
+        case GET_NO_ARG:
+        case GET_DISABLED:
+          DBUG_ASSERT(0);
+        case 0:
+        case GET_FLAGSET:
+        case GET_ENUM:
+        case GET_SET:
+        case GET_STR:
+        case GET_STR_ALLOC:
+          {
+            char buff[STRING_BUFFER_USUAL_SIZE];
+            String tmp(buff, sizeof(buff), v->var->charset(thd)),*val;
+            val= v->var->val_str(&tmp, thd, v->type, &v->base);
+            if (val)
+            {
+              Item_string *str= new Item_string(v->var->charset(thd),
+                                                val->ptr(), val->length());
+              o= new set_var(v->type, v->var, &v->base, str);
+            }
+            else
+              o= new set_var(v->type, v->var, &v->base, new Item_null());
+          }
+          break;
+        }
+      }
+      DBUG_ASSERT(o);
+      lex->old_var_list.push_back(o);
+    }
+    lex->reset_arena_for_set_stmt(&backup);
+    if (lex->old_var_list.is_empty())
+      lex->free_arena_for_set_stmt();
+    if (thd->is_error() ||
+        sql_set_variables(thd, &lex->stmt_var_list, false))
+    {
+      if (!thd->is_error())
+        my_error(ER_WRONG_ARGUMENTS, MYF(0), "SET");
+      lex->restore_set_statement_var();
+      DBUG_RETURN(TRUE);
+    }
+    /*
+      The value of last_insert_id is remembered in THD to be written to binlog
+      when it's used *the first time* in the statement. But SET STATEMENT
+      must read the old value of last_insert_id to be able to restore it at
+      the end. This should not count at "reading of last_insert_id" and
+      should not remember last_insert_id for binlog. That is, it should clear
+      stmt_depends_on_first_successful_insert_id_in_prev_stmt flag.
+    */
+    if (!thd->in_sub_stmt)
+    {
+      thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0;
+    }
+  }
+  DBUG_RETURN(FALSE);
+}
 
 /**
   Execute command saved in thd and lex->sql_command.
@@ -2638,124 +2763,8 @@ static bool do_execute_sp(THD *thd, sp_head *sp)
   thd->get_binlog_format(&orig_binlog_format,
                          &orig_current_stmt_binlog_format);
 
-  if (!lex->stmt_var_list.is_empty() && !thd->slave_thread)
-  {
-    Query_arena backup;
-    DBUG_PRINT("info", ("SET STATEMENT %d vars", lex->stmt_var_list.elements));
-
-    lex->old_var_list.empty();
-    List_iterator_fast<set_var_base> it(lex->stmt_var_list);
-    set_var_base *var;
-
-    if (lex->set_arena_for_set_stmt(&backup))
-      goto error;
-
-    while ((var= it++))
-    {
-      DBUG_ASSERT(var->is_system());
-      set_var *o= NULL, *v= (set_var*)var;
-      if (!v->var->is_set_stmt_ok())
-      {
-        my_error(ER_SET_STATEMENT_NOT_SUPPORTED, MYF(0), v->var->name.str);
-        lex->reset_arena_for_set_stmt(&backup);
-        lex->old_var_list.empty();
-        lex->free_arena_for_set_stmt();
-        goto error;
-      }
-      if (v->var->is_default())
-          o= new set_var(v->type, v->var, &v->base, NULL);
-      else
-      {
-        switch (v->var->option.var_type & GET_TYPE_MASK)
-        {
-        case GET_BOOL:
-        case GET_INT:
-        case GET_LONG:
-        case GET_LL:
-          {
-            bool null_value;
-            longlong val= v->var->val_int(&null_value, thd, v->type, &v->base);
-            o= new set_var(v->type, v->var, &v->base,
-                           (null_value ?
-                            (Item *)new Item_null() :
-                            (Item *)new Item_int(val)));
-          }
-          break;
-        case GET_UINT:
-        case GET_ULONG:
-        case GET_ULL:
-          {
-            bool null_value;
-            ulonglong val= v->var->val_int(&null_value, thd, v->type, &v->base);
-            o= new set_var(v->type, v->var, &v->base,
-                           (null_value ?
-                            (Item *)new Item_null() :
-                            (Item *)new Item_uint(val)));
-          }
-          break;
-        case GET_DOUBLE:
-          {
-            bool null_value;
-            double val= v->var->val_real(&null_value, thd, v->type, &v->base);
-            o= new set_var(v->type, v->var, &v->base,
-                           (null_value ?
-                            (Item *)new Item_null() :
-                            (Item *)new Item_float(val, 1)));
-          }
-          break;
-        default:
-        case GET_NO_ARG:
-        case GET_DISABLED:
-          DBUG_ASSERT(0);
-        case 0:
-        case GET_FLAGSET:
-        case GET_ENUM:
-        case GET_SET:
-        case GET_STR:
-        case GET_STR_ALLOC:
-          {
-            char buff[STRING_BUFFER_USUAL_SIZE];
-            String tmp(buff, sizeof(buff), v->var->charset(thd)),*val;
-            val= v->var->val_str(&tmp, thd, v->type, &v->base);
-            if (val)
-            {
-              Item_string *str= new Item_string(v->var->charset(thd),
-                                                val->ptr(), val->length());
-              o= new set_var(v->type, v->var, &v->base, str);
-            }
-            else
-              o= new set_var(v->type, v->var, &v->base, new Item_null());
-          }
-          break;
-        }
-      }
-      DBUG_ASSERT(o);
-      lex->old_var_list.push_back(o);
-    }
-    lex->reset_arena_for_set_stmt(&backup);
-    if (lex->old_var_list.is_empty())
-      lex->free_arena_for_set_stmt();
-    if (thd->is_error() ||
-        (res= sql_set_variables(thd, &lex->stmt_var_list, false)))
-    {
-      if (!thd->is_error())
-        my_error(ER_WRONG_ARGUMENTS, MYF(0), "SET");
-      lex->restore_set_statement_var();
-      goto error;
-    }
-    /*
-      The value of last_insert_id is remembered in THD to be written to binlog
-      when it's used *the first time* in the statement. But SET STATEMENT
-      must read the old value of last_insert_id to be able to restore it at
-      the end. This should not count at "reading of last_insert_id" and
-      should not remember last_insert_id for binlog. That is, it should clear
-      stmt_depends_on_first_successful_insert_id_in_prev_stmt flag.
-    */
-    if (!thd->in_sub_stmt)
-    {
-      thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0;
-    }
-  }
+  if (maria_set_statement_variables(thd))
+    goto error;
 
   if (thd->lex->mi.connection_name.str == NULL)
       thd->lex->mi.connection_name= thd->variables.default_master_connection;
diff --git a/sql/sql_parse.h b/sql/sql_parse.h
index 5e1d867..da5d796 100644
--- a/sql/sql_parse.h
+++ b/sql/sql_parse.h
@@ -178,5 +178,6 @@ inline bool check_some_routine_access(THD *thd, const char *db,
                    bool no_errors)
 { return false; }
 #endif /*NO_EMBEDDED_ACCESS_CHECKS*/
+bool maria_set_statement_variables(THD *thd);
 
 #endif /* SQL_PARSE_INCLUDED */
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index fe44fd2..55cea59 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -14537,7 +14537,15 @@ set:
             lex->stmt_var_list= lex->var_list;
             lex->var_list.empty();
           }
-          FOR_SYM verb_clause
+          FOR_SYM
+          {
+            if (thd->is_main_statement() &&
+                maria_set_statement_variables(thd))
+            {
+              MYSQL_YYABORT;
+            }
+          }
+          verb_clause
 	  {}
         ;
 
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index 734b6ed..612e468 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -635,7 +635,7 @@ static bool fix_thd_charset(sys_var *self, THD *thd, enum_var_type type)
 static Sys_var_struct Sys_character_set_client(
        "character_set_client", "The character set for statements "
        "that arrive from the client",
-       NO_SET_STMT SESSION_VAR(character_set_client), NO_CMD_LINE,
+       SESSION_VAR(character_set_client), NO_CMD_LINE,
        offsetof(CHARSET_INFO, csname), DEFAULT(&default_charset_info),
        NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(check_cs_client),
        ON_UPDATE(fix_thd_charset));
@@ -644,7 +644,7 @@ static Sys_var_struct Sys_character_set_connection(
        "character_set_connection", "The character set used for "
        "literals that do not have a character set introducer and for "
        "number-to-string conversion",
-       NO_SET_STMT SESSION_VAR(collation_connection), NO_CMD_LINE,
+       SESSION_VAR(collation_connection), NO_CMD_LINE,
        offsetof(CHARSET_INFO, csname), DEFAULT(&default_charset_info),
        NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(check_charset_not_null),
        ON_UPDATE(fix_thd_charset));
@@ -658,7 +658,7 @@ static Sys_var_struct Sys_character_set_results(
 
 static Sys_var_struct Sys_character_set_filesystem(
        "character_set_filesystem", "The filesystem character set",
-       NO_SET_STMT SESSION_VAR(character_set_filesystem), NO_CMD_LINE,
+       SESSION_VAR(character_set_filesystem), NO_CMD_LINE,
        offsetof(CHARSET_INFO, csname), DEFAULT(&character_set_filesystem),
        NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_charset_not_null),
        ON_UPDATE(fix_thd_charset));
@@ -704,7 +704,7 @@ static bool check_collation_not_null(sys_var *self, THD *thd, set_var *var)
 static Sys_var_struct Sys_collation_connection(
        "collation_connection", "The collation of the connection "
        "character set",
-       NO_SET_STMT SESSION_VAR(collation_connection), NO_CMD_LINE,
+       SESSION_VAR(collation_connection), NO_CMD_LINE,
        offsetof(CHARSET_INFO, name), DEFAULT(&default_charset_info),
        NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(check_collation_not_null),
        ON_UPDATE(fix_thd_charset));


More information about the commits mailing list