List:Commits« Previous MessageNext Message »
From:Sergei Golubchik Date:September 1 2008 11:35am
Subject:Re: bzr commit into mysql-5.0 branch (kgeorge:2672) Bug#32124
View as plain text  
Hi!

On Aug 29, Georgi Kodinov wrote:
> #At file:///home/kgeorge/mysql/bzr/B32124-5.0-bugteam/
> 
>  2672 Georgi Kodinov	2008-08-29
>       Bug #32124: crash if prepared statements refer to variables in the where
> clause
>       
>       The code to get read the value of a system variable was extracting its value 
>       on PREPARE stage and was substituting the value (as a constant) into the parse
> tree.
>       Note that this must be a reversible transformation, i.e. it must be reversed
> before
>       each re-execution.
>       Unfortunately this cannot be reliably done using the current code, because
> there are 
>       other non-reversible source tree transformations that can interfere with this
>       reversible transformation.
>       Fixed by not resolving the value at PREPARE, but at EXECUTE (as the rest of the
> 
>       functions operate).
>       Updated an obsolete related test suite (variables-big) and the code to test the
> 
>       result type of system variables (as per bug 74).

> === modified file 'sql/item_func.cc'
> --- a/sql/item_func.cc	2008-07-30 11:07:37 +0000
> +++ b/sql/item_func.cc	2008-08-29 15:16:59 +0000
...
> +void Item_func_get_system_var::print(String *str)
> +
> +{
> +  str->append('(');
> +  str->append(name, name_length);
> +  str->append(')');

Why the parentheses ?

> +longlong Item_func_get_system_var::val_int()
> +{
> +  THD *thd= current_thd;
> +  switch (var->show_type())
> +  {
> +    case SHOW_INT:
> +      {
> +        uint value;
> +        pthread_mutex_lock(&LOCK_global_system_variables);
> +        value= *(uint*) var->value_ptr(thd, var_type, &component);
> +        pthread_mutex_unlock(&LOCK_global_system_variables);
> +        return (longlong)(ulonglong) value;
> +      }
> +    case SHOW_LONG:
> +      {
> +        ulong value;
> +        pthread_mutex_lock(&LOCK_global_system_variables);
> +        value= *(ulong*) var->value_ptr(thd, var_type, &component);
> +        pthread_mutex_unlock(&LOCK_global_system_variables);
> +        return (longlong)(ulonglong) value;
> +      }
> +    case SHOW_LONGLONG:
> +      {
> +        longlong value;
> +        pthread_mutex_lock(&LOCK_global_system_variables);
> +        value= *(longlong*) var->value_ptr(thd, var_type, &component);
> +        pthread_mutex_unlock(&LOCK_global_system_variables);
> +        return value;
> +      }
> +    case SHOW_HA_ROWS:
> +      {
> +        ha_rows value;
> +        pthread_mutex_lock(&LOCK_global_system_variables);
> +        value= *(ha_rows*) var->value_ptr(thd, var_type, &component);
> +        pthread_mutex_unlock(&LOCK_global_system_variables);
> +        return (longlong) value;
> +      }
> +    case SHOW_MY_BOOL:
> +      return (longlong) (int32) *(my_bool*) 
> +        var->value_ptr(thd, var_type, &component);

Where's a mutex ?

> +    default:
> +      my_error(ER_VAR_CANT_BE_READ, MYF(0), name);

What about  SELECT CONCAT(@@sort_buffer_size) ?

> +      break;
> +  }
> +}

I suggest to reduce copy-pasting (and simplify the code) with a macro
like

#define xxx_whatever(TYPE)
       do {
         TYPE value;
         pthread_mutex_lock(&LOCK_global_system_variables);
         value= *(TYPE*) var->value_ptr(thd, var_type, &component);
         pthread_mutex_unlock(&LOCK_global_system_variables);
         return (longlong)value;
       } while(0)

(fixing the name and adding \'s at the end of every line is left as an
excercise for the reader :).

> +String* Item_func_get_system_var::val_str(String* str)
> +{
> +  THD *thd= current_thd;
> +  switch (var->show_type())
> +  {
> +    case SHOW_CHAR:
> +    {
> +      pthread_mutex_lock(&LOCK_global_system_variables);
> +      char *cptr= (char*) var->value_ptr(thd, var_type, &component);
> +      if (cptr)
> +      {
> +        if (str->copy(cptr, strlen(cptr), system_charset_info))
> +          str= NULL;
> +      }
> +      else
> +      {
> +        null_value= TRUE;
> +        str= NULL;
> +      }
> +      pthread_mutex_unlock(&LOCK_global_system_variables);
> +      return str;
> +    }
> +    default:
> +      my_error(ER_VAR_CANT_BE_READ, MYF(0), name);

Same question: SELECT LEFT("12345", @@tmpdir);

> +      break;
> +  }
> +  return str;
> +}

And one more issue: you don't prevent a variable from modifications in
another connection. Thus, SELECT * FROM t1 where pk=@@sort_buffer_size;
may return many rows, is @@sort_buffer_size will be modified in a
concurrent connection.

Regards / Mit vielen Grüßen,
Sergei

-- 
   __  ___     ___ ____  __
  /  |/  /_ __/ __/ __ \/ /   Sergei Golubchik <serg@stripped>
 / /|_/ / // /\ \/ /_/ / /__  Principal Software Engineer/Server Architect
/_/  /_/\_, /___/\___\_\___/  Sun Microsystems GmbH, HRB München 161028
       <___/                  Sonnenallee 1, 85551 Kirchheim-Heimstetten
Geschäftsführer: Thomas Schroeder, Wolfgang Engels, Dr. Roland Boemer
Vorsitzender des Aufsichtsrates: Martin Häring
Thread
bzr commit into mysql-5.0 branch (kgeorge:2672) Bug#32124Georgi Kodinov29 Aug
  • Re: bzr commit into mysql-5.0 branch (kgeorge:2672) Bug#32124Sergei Golubchik1 Sep