MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:Evgeny Potemkin Date:December 1 2009 9:25pm
Subject:bzr commit into mysql-5.6-next-mr-bugfixing branch (epotemkin:2912)
Bug#33546
View as plain text  
#At file:///work/bzrroot/33546-bug-next-mr-bugfixing/ based on revid:epotemkin@stripped

 2912 Evgeny Potemkin	2009-12-02
      Bug#33546: Slowdown on re-evaluation of constant expressions.
            
      Constant expressions in WHERE/HAVING/ON clauses aren't cached and evaluated
      for each row. This causes slowdown of query execution especially if constant
      UDF/SP function are used.
            
      Now WHERE/HAVING/ON expressions are analyzed in the top-bottom direction with
      help of the compile function. When analyzer meets a constant item it
      sets a flag for the tree transformer to cache the item and doesn't allow tree
      walker to go deeper. Thus, the topmost item of a constant expression if
      cached. This is done after all other optimizations were applied to
      WHERE/HAVING/ON expressions
            
      A helper function called cache_const_exprs is added to the JOIN class.
      It calls compile method with caching analyzer and transformer on WHERE,
      HAVING, ON expressions if they're present.
      The cache_const_expr_analyzer and cache_const_expr_transformer functions are
      added to the Item class. The first one check if the item can be cached and
      the second caches it if so.
      A new Item_cache_datetime class is derived from the Item_cache class.
      It caches both int and string values of the underlying item independently to
      avoid DATETIME aware int-to-string conversion. Thus it completely relies on
      the ability of the underlying item to correctly convert DATETIME value from
      int to string and vice versa.
     @ mysql-test/r/func_like.result
        A test case result is corrected after fixing bug#33546.
     @ mysql-test/r/func_time.result
        A test case result is corrected after fixing bug#33546.
     @ mysql-test/r/select.result
        Added a test case for the bug#33546.
     @ mysql-test/r/subselect.result
        A test case result is corrected after fixing bug#33546.
     @ mysql-test/r/udf.result
        Added a test case for the bug#33546.
     @ mysql-test/t/select.test
        Added a test case for the bug#33546.
     @ mysql-test/t/udf.test
        Added a test case for the bug#33546.
     @ sql/item.cc
        Bug#33546: Slowdown on re-evaluation of constant expressions.
        The cache_const_expr_analyzer and cache_const_expr_transformer functions are
        added to the Item class. The first one check if the item can be cached and
        the second caches it if so.
        Item_cache_datetime class implementation is added.
     @ sql/item.h
        Bug#33546: Slowdown on re-evaluation of constant expressions.
        Item_ref and Item_cache classes now returns basic_const_item
        from underlying item.
        The cache_const_expr_analyzer and cache_const_expr_transformer functions are
        added to the Item class.
     @ sql/sql_select.cc
        Bug#33546: Slowdown on re-evaluation of constant expressions.
                
        A helper function called cache_const_exprs is added to the JOIN class.
        It calls compile method with caching analyzer and transformer on WHERE,
        HAVING, ON expressions if they're present.
     @ sql/sql_select.h
        Bug#33546: Slowdown on re-evaluation of constant expressions.
        A helper function called cache_const_exprs is added to the JOIN class.

    modified:
      mysql-test/r/func_like.result
      mysql-test/r/func_time.result
      mysql-test/r/select.result
      mysql-test/r/subselect.result
      mysql-test/r/udf.result
      mysql-test/t/select.test
      mysql-test/t/udf.test
      sql/item.cc
      sql/item.h
      sql/sql_select.cc
      sql/sql_select.h
=== modified file 'mysql-test/r/func_like.result'
--- a/mysql-test/r/func_like.result	2008-02-12 19:09:16 +0000
+++ b/mysql-test/r/func_like.result	2009-12-01 21:25:51 +0000
@@ -10,7 +10,7 @@ explain extended select * from t1 where 
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	index	a	a	13	NULL	5	20.00	Using where; Using index
 Warnings:
-Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` like concat('abc','%'))
+Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` like <cache>(concat('abc','%')))
 select * from t1 where a like "abc%";
 a
 abc

=== modified file 'mysql-test/r/func_time.result'
--- a/mysql-test/r/func_time.result	2009-11-03 22:29:16 +0000
+++ b/mysql-test/r/func_time.result	2009-12-01 21:25:51 +0000
@@ -928,7 +928,6 @@ select f1 from t1 where cast("2006-1-1" 
 f1
 Warnings:
 Warning	1292	Incorrect datetime value: 'zzz'
-Warning	1292	Incorrect datetime value: 'zzz'
 select f1 from t1 where makedate(2006,1) between date(f1) and date(f3);
 f1
 2006-01-01

=== modified file 'mysql-test/r/select.result'
--- a/mysql-test/r/select.result	2009-11-06 14:20:27 +0000
+++ b/mysql-test/r/select.result	2009-12-01 21:25:51 +0000
@@ -4423,9 +4423,14 @@ CREATE TABLE t1(a INT);
 INSERT INTO t1 VALUES (2),(3);
 # Should not crash
 SELECT 1 FROM t1 WHERE a <> 1 AND NOT
-ROW(a,a) <=> ROW((SELECT 1 FROM t1 WHERE 1=2),(SELECT 1 FROM t1))
+ROW(1,a) <=> ROW(1,(SELECT 1 FROM t1))
 INTO @var0;
 ERROR 21000: Subquery returns more than 1 row
+SELECT 1 FROM t1 WHERE a <> 1 AND NOT
+ROW(a,a) <=> ROW((SELECT 1 FROM t1 WHERE 1=2),(SELECT 1 FROM t1));
+1
+1
+1
 DROP TABLE t1;
 End of 5.0 tests
 create table t1(a INT, KEY (a));
@@ -4577,4 +4582,70 @@ field2
 15:13:38
 drop table A,AA,B,BB;
 #end of test for bug#45266
+#
+# Bug#33546: Slowdown on re-evaluation of constant expressions.
+#
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+CREATE TABLE t2 (b INT);
+INSERT INTO t2 VALUES (2);
+SELECT * FROM t1 WHERE a = 1 + 1;
+a
+2
+EXPLAIN EXTENDED SELECT * FROM t1 WHERE a = 1 + 1;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	10	100.00	Using where
+Warnings:
+Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = <cache>((1 + 1)))
+SELECT * FROM t1 HAVING a = 1 + 1;
+a
+2
+EXPLAIN EXTENDED SELECT * FROM t1 HAVING a = 1 + 1;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	10	100.00	
+Warnings:
+Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` having (`test`.`t1`.`a` = <cache>((1 + 1)))
+SELECT * FROM t1, t2 WHERE a = b + (1 + 1);
+a	b
+4	2
+EXPLAIN EXTENDED SELECT * FROM t1, t2 WHERE a = b + (1 + 1);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	SIMPLE	t2	system	NULL	NULL	NULL	NULL	1	100.00	
+1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	10	100.00	Using where
+Warnings:
+Note	1003	select `test`.`t1`.`a` AS `a`,'2' AS `b` from `test`.`t1` where (`test`.`t1`.`a` = <cache>(('2' + (1 + 1))))
+SELECT * FROM t2 LEFT JOIN t1 ON a = b + 1;
+b	a
+2	3
+EXPLAIN EXTENDED SELECT * FROM t2 LEFT JOIN t1 ON a = b + 1;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	SIMPLE	t2	system	NULL	NULL	NULL	NULL	1	100.00	
+1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	10	100.00	
+Warnings:
+Note	1003	select '2' AS `b`,`test`.`t1`.`a` AS `a` from `test`.`t1` where 1
+EXPLAIN EXTENDED SELECT * FROM t1 WHERE a > UNIX_TIMESTAMP('2009-03-10 00:00:00');
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	10	100.00	Using where
+Warnings:
+Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` > <cache>(unix_timestamp('2009-03-10 00:00:00')))
+CREATE FUNCTION f1() RETURNS INT DETERMINISTIC
+BEGIN
+SET @cnt := @cnt + 1;
+RETURN 1;
+END;|
+SET @cnt := 0;
+SELECT * FROM t1 WHERE a = f1();
+a
+1
+SELECT @cnt;
+@cnt
+1
+EXPLAIN EXTENDED SELECT * FROM t1 WHERE a = f1();
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	10	100.00	Using where
+Warnings:
+Note	1003	select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = <cache>(`f1`()))
+DROP TABLE t1, t2;
+DROP FUNCTION f1;
+# End of bug#33546
 End of 5.1 tests

=== modified file 'mysql-test/r/subselect.result'
--- a/mysql-test/r/subselect.result	2009-11-20 12:29:43 +0000
+++ b/mysql-test/r/subselect.result	2009-12-01 21:25:51 +0000
@@ -735,7 +735,7 @@ id	select_type	table	type	possible_keys	
 Warnings:
 Note	1249	Select 3 was reduced during optimization
 Note	1249	Select 2 was reduced during optimization
-Note	1003	select `test`.`t2`.`id` AS `id` from `test`.`t2` where (`test`.`t2`.`id` = (1 + 1))
+Note	1003	select `test`.`t2`.`id` AS `id` from `test`.`t2` where (`test`.`t2`.`id` = <cache>((1 + 1)))
 EXPLAIN EXTENDED SELECT * FROM t2 WHERE id IN (SELECT 1 UNION SELECT 3);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	PRIMARY	t2	index	NULL	id	5	NULL	2	100.00	Using where; Using index

=== modified file 'mysql-test/r/udf.result'
--- a/mysql-test/r/udf.result	2009-09-07 09:57:22 +0000
+++ b/mysql-test/r/udf.result	2009-12-01 21:25:51 +0000
@@ -409,3 +409,18 @@ b
 1
 DROP TABLE t1;
 End of 5.0 tests.
+#
+# Bug#33546: Slowdown on re-evaluation of constant expressions.
+#
+CREATE TABLE t1 (f1 INT);
+INSERT INTO t1 VALUES(1),(50);
+CREATE FUNCTION myfunc_double RETURNS INTEGER SONAME "UDF_EXAMPLE_LIB";
+EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE f1=1 + myfunc_double(1);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	100.00	Using where
+Warnings:
+Note	1003	select 1 AS `1` from `test`.`t1` where (`test`.`t1`.`f1` = <cache>((1 + myfunc_double(1 AS `1`))))
+DROP FUNCTION myfunc_double;
+DROP TABLE t1;
+#
+End of 5.1 tests.

=== modified file 'mysql-test/t/select.test'
--- a/mysql-test/t/select.test	2009-10-30 14:13:13 +0000
+++ b/mysql-test/t/select.test	2009-12-01 21:25:51 +0000
@@ -3767,9 +3767,14 @@ INSERT INTO t1 VALUES (2),(3);
 --echo # Should not crash
 --error ER_SUBQUERY_NO_1_ROW
 SELECT 1 FROM t1 WHERE a <> 1 AND NOT
-ROW(a,a) <=> ROW((SELECT 1 FROM t1 WHERE 1=2),(SELECT 1 FROM t1))
+ROW(1,a) <=> ROW(1,(SELECT 1 FROM t1))
 INTO @var0;
 
+# Query correctly return 2 rows since comparison a <=> fisrt_subquery is
+# always false, thus the second query is never executed.
+SELECT 1 FROM t1 WHERE a <> 1 AND NOT
+ROW(a,a) <=> ROW((SELECT 1 FROM t1 WHERE 1=2),(SELECT 1 FROM t1));
+
 DROP TABLE t1;
  
 
@@ -3918,4 +3923,38 @@ SELECT table1 .`time_key` field2  FROM B
 
 drop table A,AA,B,BB;
 --echo #end of test for bug#45266
+
+--echo #
+--echo # Bug#33546: Slowdown on re-evaluation of constant expressions.
+--echo #
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+CREATE TABLE t2 (b INT);
+INSERT INTO t2 VALUES (2);
+SELECT * FROM t1 WHERE a = 1 + 1;
+EXPLAIN EXTENDED SELECT * FROM t1 WHERE a = 1 + 1;
+SELECT * FROM t1 HAVING a = 1 + 1;
+EXPLAIN EXTENDED SELECT * FROM t1 HAVING a = 1 + 1;
+SELECT * FROM t1, t2 WHERE a = b + (1 + 1);
+EXPLAIN EXTENDED SELECT * FROM t1, t2 WHERE a = b + (1 + 1);
+SELECT * FROM t2 LEFT JOIN t1 ON a = b + 1;
+EXPLAIN EXTENDED SELECT * FROM t2 LEFT JOIN t1 ON a = b + 1;
+EXPLAIN EXTENDED SELECT * FROM t1 WHERE a > UNIX_TIMESTAMP('2009-03-10 00:00:00');
+
+delimiter |;
+CREATE FUNCTION f1() RETURNS INT DETERMINISTIC
+BEGIN
+  SET @cnt := @cnt + 1;
+  RETURN 1;
+END;|
+delimiter ;|
+
+SET @cnt := 0;
+SELECT * FROM t1 WHERE a = f1();
+SELECT @cnt;
+EXPLAIN EXTENDED SELECT * FROM t1 WHERE a = f1();
+DROP TABLE t1, t2;
+DROP FUNCTION f1;
+--echo # End of bug#33546
+
 --echo End of 5.1 tests

=== modified file 'mysql-test/t/udf.test'
--- a/mysql-test/t/udf.test	2009-09-07 09:57:22 +0000
+++ b/mysql-test/t/udf.test	2009-12-01 21:25:51 +0000
@@ -449,3 +449,17 @@ SELECT IF( a = 1, a, a ) AS `b` FROM t1 
 DROP TABLE t1;
 
 --echo End of 5.0 tests.
+
+--echo #
+--echo # Bug#33546: Slowdown on re-evaluation of constant expressions.
+--echo #
+CREATE TABLE t1 (f1 INT);
+INSERT INTO t1 VALUES(1),(50);
+--replace_result $UDF_EXAMPLE_LIB UDF_EXAMPLE_LIB
+eval CREATE FUNCTION myfunc_double RETURNS INTEGER SONAME "$UDF_EXAMPLE_LIB";
+EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE f1=1 + myfunc_double(1);
+DROP FUNCTION myfunc_double;
+DROP TABLE t1;
+--echo #
+--echo End of 5.1 tests.
+

=== modified file 'sql/item.cc'
--- a/sql/item.cc	2009-12-01 19:41:39 +0000
+++ b/sql/item.cc	2009-12-01 21:25:51 +0000
@@ -5766,6 +5766,67 @@ bool Item::send(Protocol *protocol, Stri
 }
 
 
+/**
+  Check if an item is a constant one and can be cached.
+
+  @param arg [out] TRUE <=> Cache this item.
+
+  @return TRUE  Go deeper in item tree.
+  @return FALSE Don't go deeper in item tree.
+*/
+
+bool Item::cache_const_expr_analyzer(uchar **arg)
+{
+  bool *cache_flag= (bool*)*arg;
+  if (!*cache_flag)
+  {
+    Item *item= real_item();
+    /*
+      Cache constant items unless it's a basic constant, constant field or
+      a subselect (they use their own cache).
+    */
+    if (const_item() &&
+        !(item->basic_const_item() || item->type() == Item::FIELD_ITEM ||
+          item->type() == SUBSELECT_ITEM ||
+           /*
+             Do not cache GET_USER_VAR() function as its const_item() may
+             return TRUE for the current thread but it still may change
+             during the execution.
+           */
+          (item->type() == Item::FUNC_ITEM &&
+           ((Item_func*)item)->functype() == Item_func::GUSERVAR_FUNC)))
+      *cache_flag= TRUE;
+    return TRUE;
+  }
+  return FALSE;
+}
+
+
+/**
+  Cache item if needed.
+
+  @param arg   TRUE <=> Cache this item.
+
+  @return cache if cache needed.
+  @return this otherwise.
+*/
+
+Item* Item::cache_const_expr_transformer(uchar *arg)
+{
+  if (*(bool*)arg)
+  {
+    *((bool*)arg)= FALSE;
+    Item_cache *cache= Item_cache::get_cache(this);
+    if (!cache)
+      return NULL;
+    cache->setup(this);
+    cache->store(this);
+    return cache;
+  }
+  return this;
+}
+
+
 bool Item_field::send(Protocol *protocol, String *buffer)
 {
   return protocol->store(result_field);
@@ -7127,6 +7188,10 @@ Item_cache* Item_cache::get_cache(const 
   case DECIMAL_RESULT:
     return new Item_cache_decimal();
   case STRING_RESULT:
+    if (item->field_type() == MYSQL_TYPE_DATE ||
+        item->field_type() == MYSQL_TYPE_DATETIME ||
+        item->field_type() == MYSQL_TYPE_TIME)
+      return new Item_cache_datetime(item->field_type());
     return new Item_cache_str(item);
   case ROW_RESULT:
     return new Item_cache_row();
@@ -7208,6 +7273,72 @@ longlong Item_cache_int::val_int()
   return value;
 }
 
+void  Item_cache_datetime::cache_value_int()
+{
+  value_cached= TRUE;
+  /* Assume here that the underlying item will do correct conversion.*/
+  int_value= example->val_int_result();
+  null_value= example->null_value;
+  unsigned_flag= example->unsigned_flag;
+}
+
+
+void  Item_cache_datetime::cache_value()
+{
+  str_value_cached= TRUE;
+  /* Assume here that the underlying item will do correct conversion.*/
+  String *res= example->str_result(&str_value);
+  if (res && res != &str_value)
+    str_value.copy(*res);
+  null_value= example->null_value;
+  unsigned_flag= example->unsigned_flag;
+}
+
+
+void Item_cache_datetime::store(Item *item, longlong val_arg)
+{
+  /* An explicit values is given, save it. */
+  value_cached= TRUE;
+  int_value= val_arg;
+  null_value= item->null_value;
+  unsigned_flag= item->unsigned_flag;
+}
+
+
+String *Item_cache_datetime::val_str(String *str)
+{
+  DBUG_ASSERT(fixed == 1);
+  if (!str_value_cached)
+    cache_value();
+  return &str_value;
+}
+
+
+my_decimal *Item_cache_datetime::val_decimal(my_decimal *decimal_val)
+{
+  DBUG_ASSERT(fixed == 1);
+  if (!value_cached)
+    cache_value_int();
+  int2my_decimal(E_DEC_FATAL_ERROR, int_value, unsigned_flag, decimal_val);
+  return decimal_val;
+}
+
+double Item_cache_datetime::val_real()
+{
+  DBUG_ASSERT(fixed == 1);
+  if (!value_cached)
+    cache_value_int();
+  return (double) int_value;
+}
+
+longlong Item_cache_datetime::val_int()
+{
+  DBUG_ASSERT(fixed == 1);
+  if (!value_cached)
+    cache_value_int();
+  return int_value;
+}
+
 void Item_cache_real::cache_value()
 {
   value_cached= TRUE;

=== modified file 'sql/item.h'
--- a/sql/item.h	2009-12-01 19:41:39 +0000
+++ b/sql/item.h	2009-12-01 21:25:51 +0000
@@ -903,6 +903,9 @@ public:
   virtual bool reset_query_id_processor(uchar *query_id_arg) { return 0; }
   virtual bool is_expensive_processor(uchar *arg) { return 0; }
   virtual bool register_field_in_read_map(uchar *arg) { return 0; }
+
+  virtual bool cache_const_expr_analyzer(uchar **arg);
+  virtual Item* cache_const_expr_transformer(uchar *arg);
   /*
     Check if a partition function is allowed
     SYNOPSIS
@@ -2292,6 +2295,7 @@ public:
     if (ref && result_type() == ROW_RESULT)
       (*ref)->bring_value();
   }
+  bool basic_const_item() { return (*ref)->basic_const_item(); }
 
 };
 
@@ -2977,6 +2981,8 @@ public:
   }
   virtual void store(Item *item);
   virtual void cache_value()= 0;
+  bool basic_const_item() const
+  { return test(example && example->basic_const_item());}
 };
 
 
@@ -3127,6 +3133,38 @@ public:
 };
 
 
+class Item_cache_datetime: public Item_cache
+{
+protected:
+  String str_value;
+  ulonglong int_value;
+  bool str_value_cached;
+public:
+  Item_cache_datetime(enum_field_types field_type_arg):
+    Item_cache(field_type_arg), int_value(0), str_value_cached(0)
+  {
+    cmp_context= STRING_RESULT;
+  }
+
+  void store(Item *item, longlong val_arg);
+  double val_real();
+  longlong val_int();
+  String* val_str(String *str);
+  my_decimal *val_decimal(my_decimal *);
+  enum Item_result result_type() const { return STRING_RESULT; }
+  bool result_as_longlong() { return TRUE; }
+  /*
+    In order to avoid INT <-> STRING conversion of a DATETIME value
+    two cache_value functions are introduced. One (cache_value) caches STRING
+    value, another (cache_value_int) - INT value. Thus this cache item
+    completely relies on the ability of the underlying item to do the
+    correct conversion.
+  */
+  void cache_value_int();
+  void cache_value();
+};
+
+
 /*
   Item_type_holder used to store type. name, length of Item for UNIONS &
   derived tables.

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2009-11-25 15:03:05 +0000
+++ b/sql/sql_select.cc	2009-12-01 21:25:51 +0000
@@ -1076,6 +1076,10 @@ JOIN::optimize()
   {
     conds=new Item_int((longlong) 0,1);	// Always false
   }
+
+  /* Cache constant expressions in WHERE, HAVING, ON clauses. */
+  cache_const_exprs();
+
   if (make_join_select(this, select, conds))
   {
     zero_result_cause=
@@ -17142,5 +17146,40 @@ bool JOIN::change_result(select_result *
 }
 
 /**
+  Cache constant expressions in WHERE, HAVING, ON conditions.
+*/
+
+void JOIN::cache_const_exprs()
+{
+  bool cache_flag= FALSE;
+  bool *analyzer_arg= &cache_flag;
+
+  /* No need in cache if all tables are constant. */
+  if (const_tables == tables)
+    return;
+
+  if (conds)
+    conds->compile(&Item::cache_const_expr_analyzer, (uchar **)&analyzer_arg,
+                  &Item::cache_const_expr_transformer, (uchar *)&cache_flag);
+  cache_flag= FALSE;
+  if (having)
+    having->compile(&Item::cache_const_expr_analyzer, (uchar **)&analyzer_arg,
+                    &Item::cache_const_expr_transformer, (uchar *)&cache_flag);
+
+  for (JOIN_TAB *tab= join_tab + const_tables; tab < join_tab + tables ; tab++)
+  {
+    if (*tab->on_expr_ref)
+    {
+      cache_flag= FALSE;
+      (*tab->on_expr_ref)->compile(&Item::cache_const_expr_analyzer,
+                                 (uchar **)&analyzer_arg,
+                                 &Item::cache_const_expr_transformer,
+                                 (uchar *)&cache_flag);
+    }
+  }
+}
+
+
+/**
   @} (end of group Query_Optimizer)
 */

=== modified file 'sql/sql_select.h'
--- a/sql/sql_select.h	2009-11-06 16:13:33 +0000
+++ b/sql/sql_select.h	2009-12-01 21:25:51 +0000
@@ -555,6 +555,7 @@ public:
     return (unit == &thd->lex->unit && (unit->fake_select_lex == 0 ||
                                         select_lex == unit->fake_select_lex));
   }
+  void cache_const_exprs();
 private:
   /**
     TRUE if the query contains an aggregate function but has no GROUP


Attachment: [text/bzr-bundle] bzr/epotemkin@mysql.com-20091201212551-amf9utmatlvsbbar.bundle
Thread
bzr commit into mysql-5.6-next-mr-bugfixing branch (epotemkin:2912)Bug#33546Evgeny Potemkin1 Dec