List:Commits« Previous MessageNext Message »
From:Tatiana A. Nurnberg Date:February 26 2009 4:37pm
Subject:bzr commit into mysql-5.1 branch (azundris:2722) Bug#40657
View as plain text  
#At file:///misc/mysql/forest/40657/51-40657/ based on revid:azundris@stripped

 2722 Tatiana A. Nurnberg	2009-02-26
      Bug#40657: assertion with out of range variables and traditional sql_mode
      
      In STRICT mode, out-of-bounds values caused an error message
      to be queued (rather than just a warning), without any further
      error-like processing happening. (The error is queued during
      update, at which time it's too late. For it to be processed
      properly, it would need to be queued during check-stage.)
      The assertion rightfully complains that we're trying to send
      an OK while having an error queued.
      
      Changeset breaks a lot of tests out into check-stage. This also
      allows us to send more correct warnings/error messages.
     @ sql/set_var.cc
        cleanup: fold get_unsigned() and fix_unsigned() into one,
        as well as all the semi-common code from the ::check
        functions.

    modified:
      sql/set_var.cc
=== modified file 'sql/set_var.cc'
--- a/sql/set_var.cc	2009-02-24 15:42:18 +0000
+++ b/sql/set_var.cc	2009-02-26 16:36:49 +0000
@@ -1405,22 +1405,38 @@ bool throw_bounds_warning(THD *thd, bool
 /**
   check an unsigned user-supplied value for a systemvariable against bounds.
 
+  TODO: This is a wrapper function to call clipping from within an update()
+        function.  Calling bounds from within update() is fair game in theory,
+        but we can only send warnings from in there, not errors, and besides,
+        it violates our model of separating check from update phase.
+        To avoid breaking out of the server with an ASSERT() in strict mode,
+        we pretend we're not in strict mode when we go through here. Bug#43233
+        was opened to remind us to replace this kludge with The Right Thing,
+        which of course is to do the check in the actual check phase, and then
+        throw an error or warning accordingly.
+
   @param thd             thread handle
   @param num             the value to limit
-  @param option_limits   the bounds-record, or NULL
-
-  @retval                whether or not we needed to bound
+  @param option_limits   the bounds-record, or NULL if none
  */
-static my_bool bound_unsigned(THD *thd, ulonglong *num,
+static void bound_unsigned(THD *thd, ulonglong *num,
                               const struct my_option *option_limits)
 {
-  my_bool   fixed     = FALSE;
-  ulonglong unadjusted= *num;
-
   if (option_limits)
+  {
+    my_bool   fixed     = FALSE;
+    ulonglong unadjusted= *num;
+
     *num= getopt_ull_limit_value(unadjusted, option_limits, &fixed);
 
-  return fixed;
+    if (fixed)
+    {
+      ulong ssm= thd->variables.sql_mode;
+      thd->variables.sql_mode&= ~MODE_STRICT_ALL_TABLES;
+      throw_bounds_warning(thd, fixed, TRUE, option_limits->name, unadjusted);
+      thd->variables.sql_mode= ssm;
+    }
+  }
 }
 
 
@@ -1445,6 +1461,7 @@ static bool get_unsigned(THD *thd, set_v
   int                     warnings= 0;
   ulonglong               unadjusted;
   const struct my_option *limits= var->var->option_limits;
+  struct my_option        fallback;
 
   /* get_unsigned() */
   if (var->value->unsigned_flag)
@@ -1477,6 +1494,20 @@ static bool get_unsigned(THD *thd, set_v
     warnings++;
   }
 
+  /*
+    if the sysvar doesn't have a proper bounds record but the check
+    function would like bounding to ULONG where its size differs from
+    that of ULONGLONG, we make up a bogus limits record here and let
+    the usual suspects handle the actual limiting.
+  */
+
+  if (!limits && bound2ulong)
+  {
+    bzero(&fallback, sizeof(fallback));
+    fallback.var_type= GET_ULONG;
+    limits= &fallback;
+  }
+
   /* fix_unsigned() */
   if (limits)
   {
@@ -1489,20 +1520,6 @@ static bool get_unsigned(THD *thd, set_v
                                                 (longlong) unadjusted))
       return TRUE;
   }
-  else if (bound2ulong)
-  {
-#if SIZEOF_LONG < SIZEOF_LONG_LONG
-    /* Avoid overflows on 32 bit systems */
-    if (var->save_result.ulonglong_value > ULONG_MAX)
-    {
-      var->save_result.ulonglong_value= ULONG_MAX;
-      if ((warnings == 0) && throw_bounds_warning(thd, TRUE, TRUE,
-                                                  var->var->name,
-                                                  (longlong) unadjusted))
-        return TRUE;
-    }
-#endif
-  }
 
   return FALSE;
 }
@@ -2334,7 +2351,7 @@ bool sys_var_key_buffer_size::update(THD
   bound_unsigned(thd, &tmp, option_limits);
   key_cache->param_buff_size= (ulonglong) tmp;
 
-  /* If key cache didn't existed initialize it, else resize it */
+  /* If key cache didn't exist initialize it, else resize it */
   key_cache->in_init= 1;
   pthread_mutex_unlock(&LOCK_global_system_variables);
 


Attachment: [text/bzr-bundle] bzr/azundris@mysql.com-20090226163649-mxjap5hzbawo8jk5.bundle
Thread
bzr commit into mysql-5.1 branch (azundris:2722) Bug#40657Tatiana A. Nurnberg26 Feb