List:Commits« Previous MessageNext Message »
From:Sergey Glukhov Date:December 14 2010 11:16am
Subject:bzr push into mysql-5.1-bugteam branch (sergey.glukhov:3519 to 3520)
Bug#52157 Bug#54475 Bug#57352 Bug#57703
View as plain text  
 3520 Sergey Glukhov	2010-12-14
      Fixed following problems:
      --Bug#52157 various crashes and assertions with multi-table update, stored function
      --Bug#54475 improper error handling causes cascading crashing failures in innodb/ndb
      --Bug#57703 create view cause Assertion failed: 0, file .\item_subselect.cc, line 846
      --Bug#57352 valgrind warnings when creating view
      --Recently discovered problem when a nested materialized derived table is used
        before being populated and it leads to incorrect result
      
      We have several modes when we should disable subquery evaluation.
      The reasons for disabling are different. It could be
      uselessness of the evaluation as in case of 'CREATE VIEW'
      or 'PREPARE stmt', or we should disable subquery evaluation
      if tables are not locked yet as it happens in bug#54475, or
      too early evaluation of subqueries can lead to wrong result
      as it happened in Bug#19077.
      Main problem is that if subquery items are treated as const
      they are evaluated in ::fix_fields(), ::fix_length_and_dec()
      of the parental items as a lot of these methods have
      Item::val_...() calls inside.
      We have to make subqueries non-const to prevent unnecessary
      subquery evaluation. At the moment we have different methods
      for this. Here is a list of these modes:
      
      1. PREPARE stmt;
      We use UNCACHEABLE_PREPARE flag.
      It is set during parsing in sql_parse.cc, mysql_new_select() for
      each SELECT_LEX object and cleared at the end of PREPARE in
      sql_prepare.cc, init_stmt_after_parse(). If this flag is set
      subquery becomes non-const and evaluation does not happen.
      
      2. CREATE|ALTER VIEW, SHOW CREATE VIEW, I_S tables which
         process FRM files
      We use LEX::view_prepare_mode field. We set it before
      view preparation and check this flag in
      ::fix_fields(), ::fix_length_and_dec().
      Some bugs are fixed using this approach,
      some are not(Bug#57352, Bug#57703). The problem here is
      that we have a lot of ::fix_fields(), ::fix_length_and_dec()
      where we use Item::val_...() calls for const items.
      
      3. Derived tables with subquery = wrong result(Bug19077)
      The reason of this bug is too early subquery evaluation.
      It was fixed by adding Item::with_subselect field
      The check of this field in appropriate places prevents
      const item evaluation if the item have subquery.
      The fix for Bug19077 fixes only the problem with
      convert_constant_item() function and does not cover
      other places(::fix_fields(), ::fix_length_and_dec() again)
      where subqueries could be evaluated.
      
      Example:
      CREATE TABLE t1 (i INT, j BIGINT);
      INSERT INTO t1 VALUES (1, 2), (2, 2), (3, 2);
      SELECT * FROM (SELECT MIN(i) FROM t1
      WHERE j = SUBSTRING('12', (SELECT * FROM (SELECT MIN(j) FROM t1) t2))) t3;
      DROP TABLE t1;
      
      4. Derived tables with subquery where subquery
         is evaluated before table locking(Bug#54475, Bug#52157)
      
      Suggested solution is following:
      
      -Introduce new field LEX::context_analysis_only with the following
       possible flags:
       #define CONTEXT_ANALYSIS_ONLY_PREPARE 1
       #define CONTEXT_ANALYSIS_ONLY_VIEW    2
       #define CONTEXT_ANALYSIS_ONLY_DERIVED 4
      -Set/clean these flags when we perform
       context analysis operation
      -Item_subselect::const_item() returns
       result depending on LEX::context_analysis_only.
       If context_analysis_only is set then we return
       FALSE that means that subquery is non-const.
       As all subquery types are wrapped by Item_subselect
       it allow as to make subquery non-const when
       it's necessary.
     @ mysql-test/r/derived.result
        test case
     @ mysql-test/r/multi_update.result
        test case
     @ mysql-test/r/view.result
        test case
     @ mysql-test/suite/innodb/r/innodb_multi_update.result
        test case
     @ mysql-test/suite/innodb/t/innodb_multi_update.test
        test case
     @ mysql-test/suite/innodb_plugin/r/innodb_multi_update.result
        test case
     @ mysql-test/suite/innodb_plugin/t/innodb_multi_update.test
        test case
     @ mysql-test/t/derived.test
        test case
     @ mysql-test/t/multi_update.test
        test case
     @ mysql-test/t/view.test
        test case
     @ sql/item.cc
        --removed unnecessary code
     @ sql/item_cmpfunc.cc
        --removed unnecessary checks
        --THD::is_context_analysis_only() is replaced with LEX::is_ps_or_view_context_analysis()
     @ sql/item_func.cc
        --refactored context analysis checks
     @ sql/item_row.cc
        --removed unnecessary checks
     @ sql/item_subselect.cc
        --removed unnecessary code
        --added DBUG_ASSERT into Item_subselect::exec()
          which asserts that subquery execution can not happen
          if LEX::context_analysis_only is set, i.e. at context
          analysis stage.
        --Item_subselect::const_item()
          Return FALSE if LEX::context_analysis_only is set.
          It prevents subquery evaluation in ::fix_fields &
          ::fix_length_and_dec at context analysis stage.
     @ sql/item_subselect.h
        --removed unnecessary code
     @ sql/mysql_priv.h
        --Added new set of flags.
     @ sql/sql_class.h
        --removed unnecessary code
     @ sql/sql_derived.cc
        --added LEX::context_analysis_only analysis intialization/cleanup
     @ sql/sql_lex.cc
        --init LEX::context_analysis_only field
     @ sql/sql_lex.h
        --New LEX::context_analysis_only field
     @ sql/sql_parse.cc
        --removed unnecessary code
     @ sql/sql_prepare.cc
        --removed unnecessary code
        --added LEX::context_analysis_only analysis intialization/cleanup
     @ sql/sql_select.cc
        --refactored context analysis checks
     @ sql/sql_show.cc
        --added LEX::context_analysis_only analysis intialization/cleanup
     @ sql/sql_view.cc
        --added LEX::context_analysis_only analysis intialization/cleanup

    modified:
      mysql-test/r/derived.result
      mysql-test/r/multi_update.result
      mysql-test/r/view.result
      mysql-test/suite/innodb/r/innodb_multi_update.result
      mysql-test/suite/innodb/t/innodb_multi_update.test
      mysql-test/suite/innodb_plugin/r/innodb_multi_update.result
      mysql-test/suite/innodb_plugin/t/innodb_multi_update.test
      mysql-test/t/derived.test
      mysql-test/t/multi_update.test
      mysql-test/t/view.test
      sql/item.cc
      sql/item_cmpfunc.cc
      sql/item_func.cc
      sql/item_row.cc
      sql/item_subselect.cc
      sql/item_subselect.h
      sql/mysql_priv.h
      sql/sql_class.h
      sql/sql_derived.cc
      sql/sql_lex.cc
      sql/sql_lex.h
      sql/sql_parse.cc
      sql/sql_prepare.cc
      sql/sql_select.cc
      sql/sql_show.cc
      sql/sql_view.cc
 3519 Tor Didriksen	2010-12-13
      Bug #58426 Crashing tests not failing as they are supposed to on Solaris 10 debug
        
      On this platform we seem to get lots of other signals
      while waiting for SIGKILL to be delivered.
      
      Solution: use sigsuspend(<all signals blocked>)
     @ dbug/dbug.c
        New function _db_suicide_() which does kill(myself, -9) and then waits forever.
     @ include/my_dbug.h
        Let DBUG_SUICE wait forever until the KILL signal is delivered, and process dies.

    modified:
      dbug/dbug.c
      include/my_dbug.h
=== modified file 'mysql-test/r/derived.result'
--- a/mysql-test/r/derived.result	2009-07-11 18:44:29 +0000
+++ b/mysql-test/r/derived.result	2010-12-14 09:33:03 +0000
@@ -400,4 +400,15 @@ SELECT 0 FROM
 (SELECT 0) t61;
 0
 0
+#
+#  A nested materialized derived table is used before being populated.
+#  (addon for bug#19077)
+#
+CREATE TABLE t1 (i INT, j BIGINT);
+INSERT INTO t1 VALUES (1, 2), (2, 2), (3, 2);
+SELECT * FROM (SELECT MIN(i) FROM t1
+WHERE j = SUBSTRING('12', (SELECT * FROM (SELECT MIN(j) FROM t1) t2))) t3;
+MIN(i)
+1
+DROP TABLE t1;
 # End of 5.0 tests

=== modified file 'mysql-test/r/multi_update.result'
--- a/mysql-test/r/multi_update.result	2010-09-07 07:58:05 +0000
+++ b/mysql-test/r/multi_update.result	2010-12-14 09:33:03 +0000
@@ -659,4 +659,15 @@ Error	1242	Subquery returns more than 1 
 Error	1242	Subquery returns more than 1 row
 DROP TABLE t1, t2, t3;
 SET SESSION sql_safe_updates = DEFAULT;
+#
+# Bug#52157 various crashes and assertions with multi-table update, stored function
+#
+CREATE FUNCTION f1 () RETURNS BLOB RETURN 1;
+CREATE TABLE t1 (f1 DATE);
+INSERT INTO t1 VALUES('2001-01-01');
+UPDATE (SELECT 1 FROM t1 WHERE f1 = (SELECT f1() FROM t1)) x, t1 SET f1 = 1;
+Warnings:
+Warning	1292	Truncated incorrect datetime value: '1'
+DROP FUNCTION f1;
+DROP TABLE t1;
 end of tests

=== modified file 'mysql-test/r/view.result'
--- a/mysql-test/r/view.result	2010-11-30 17:51:25 +0000
+++ b/mysql-test/r/view.result	2010-12-14 09:33:03 +0000
@@ -3884,6 +3884,19 @@ CREATE VIEW v1 AS SELECT 1 from t1
 WHERE t1.b <=> (SELECT a FROM t1 WHERE a < SOME(SELECT '1'));
 DROP VIEW v1;
 DROP TABLE t1;
+#
+# Bug#57703 create view cause Assertion failed: 0, file .\item_subselect.cc, line 846
+#
+CREATE TABLE t1(a int);
+CREATE VIEW v1 AS SELECT 1 FROM t1 GROUP BY
+SUBSTRING(1 FROM (SELECT 3 FROM t1 WHERE a >= ANY(SELECT 1)));
+DROP VIEW v1;
+DROP TABLE t1;
+#
+# Bug#57352 valgrind warnings when creating view
+#
+CREATE VIEW v1 AS SELECT 1 IN (1 LIKE 2,0) AS f;
+DROP VIEW v1;
 # -----------------------------------------------------------------
 # -- End of 5.1 tests.
 # -----------------------------------------------------------------

=== modified file 'mysql-test/suite/innodb/r/innodb_multi_update.result'
--- a/mysql-test/suite/innodb/r/innodb_multi_update.result	2010-05-05 10:40:01 +0000
+++ b/mysql-test/suite/innodb/r/innodb_multi_update.result	2010-12-14 09:33:03 +0000
@@ -74,3 +74,11 @@ a	b
 4	14
 5	15
 drop table bug38999_1,bug38999_2;
+#
+# Bug#54475 improper error handling causes cascading crashing failures in innodb/ndb
+#
+CREATE TABLE t1(f1 INT) ENGINE=INNODB;
+INSERT INTO t1 VALUES(1);
+UPDATE (SELECT ((SELECT 1 FROM t1), 1) FROM t1 WHERE (SELECT 1 FROM t1)) x, (SELECT 1) AS d SET d.f1 = 1;
+ERROR 21000: Operand should contain 1 column(s)
+DROP TABLE t1;

=== modified file 'mysql-test/suite/innodb/t/innodb_multi_update.test'
--- a/mysql-test/suite/innodb/t/innodb_multi_update.test	2010-05-05 10:40:01 +0000
+++ b/mysql-test/suite/innodb/t/innodb_multi_update.test	2010-12-14 09:33:03 +0000
@@ -27,3 +27,14 @@ select * from bug38999_1;
 select * from bug38999_2;
 
 drop table bug38999_1,bug38999_2;
+
+
+--echo #
+--echo # Bug#54475 improper error handling causes cascading crashing failures in innodb/ndb
+--echo #
+CREATE TABLE t1(f1 INT) ENGINE=INNODB;
+INSERT INTO t1 VALUES(1);
+--error ER_OPERAND_COLUMNS
+UPDATE (SELECT ((SELECT 1 FROM t1), 1) FROM t1 WHERE (SELECT 1 FROM t1)) x, (SELECT 1) AS d SET d.f1 = 1;
+DROP TABLE t1;
+

=== modified file 'mysql-test/suite/innodb_plugin/r/innodb_multi_update.result'
--- a/mysql-test/suite/innodb_plugin/r/innodb_multi_update.result	2010-05-05 10:44:25 +0000
+++ b/mysql-test/suite/innodb_plugin/r/innodb_multi_update.result	2010-12-14 09:33:03 +0000
@@ -74,3 +74,11 @@ a	b
 4	14
 5	15
 drop table bug38999_1,bug38999_2;
+#
+# Bug#54475 improper error handling causes cascading crashing failures in innodb/ndb
+#
+CREATE TABLE t1(f1 INT) ENGINE=INNODB;
+INSERT INTO t1 VALUES(1);
+UPDATE (SELECT ((SELECT 1 FROM t1), 1) FROM t1 WHERE (SELECT 1 FROM t1)) x, (SELECT 1) AS d SET d.f1 = 1;
+ERROR 21000: Operand should contain 1 column(s)
+DROP TABLE t1;

=== modified file 'mysql-test/suite/innodb_plugin/t/innodb_multi_update.test'
--- a/mysql-test/suite/innodb_plugin/t/innodb_multi_update.test	2010-06-03 09:46:37 +0000
+++ b/mysql-test/suite/innodb_plugin/t/innodb_multi_update.test	2010-12-14 09:33:03 +0000
@@ -27,3 +27,14 @@ select * from bug38999_1;
 select * from bug38999_2;
 
 drop table bug38999_1,bug38999_2;
+
+
+--echo #
+--echo # Bug#54475 improper error handling causes cascading crashing failures in innodb/ndb
+--echo #
+CREATE TABLE t1(f1 INT) ENGINE=INNODB;
+INSERT INTO t1 VALUES(1);
+--error ER_OPERAND_COLUMNS
+UPDATE (SELECT ((SELECT 1 FROM t1), 1) FROM t1 WHERE (SELECT 1 FROM t1)) x, (SELECT 1) AS d SET d.f1 = 1;
+DROP TABLE t1;
+

=== modified file 'mysql-test/t/derived.test'
--- a/mysql-test/t/derived.test	2009-07-11 18:44:29 +0000
+++ b/mysql-test/t/derived.test	2010-12-14 09:33:03 +0000
@@ -301,4 +301,15 @@ SELECT 0 FROM
 (SELECT 0) t56, (SELECT 0) t57, (SELECT 0) t58, (SELECT 0) t59, (SELECT 0) t60,
 (SELECT 0) t61; # 61 == MAX_TABLES
 
+--echo #
+--echo #  A nested materialized derived table is used before being populated.
+--echo #  (addon for bug#19077)
+--echo #
+
+CREATE TABLE t1 (i INT, j BIGINT);
+INSERT INTO t1 VALUES (1, 2), (2, 2), (3, 2);
+SELECT * FROM (SELECT MIN(i) FROM t1
+WHERE j = SUBSTRING('12', (SELECT * FROM (SELECT MIN(j) FROM t1) t2))) t3;
+DROP TABLE t1;
+
 --echo # End of 5.0 tests

=== modified file 'mysql-test/t/multi_update.test'
--- a/mysql-test/t/multi_update.test	2010-09-07 07:58:05 +0000
+++ b/mysql-test/t/multi_update.test	2010-12-14 09:33:03 +0000
@@ -673,4 +673,15 @@ SET t3.a = 0;
 DROP TABLE t1, t2, t3;
 SET SESSION sql_safe_updates = DEFAULT;
 
+--echo #
+--echo # Bug#52157 various crashes and assertions with multi-table update, stored function
+--echo #
+
+CREATE FUNCTION f1 () RETURNS BLOB RETURN 1;
+CREATE TABLE t1 (f1 DATE);
+INSERT INTO t1 VALUES('2001-01-01');
+UPDATE (SELECT 1 FROM t1 WHERE f1 = (SELECT f1() FROM t1)) x, t1 SET f1 = 1;
+DROP FUNCTION f1;
+DROP TABLE t1;
+
 --echo end of tests

=== modified file 'mysql-test/t/view.test'
--- a/mysql-test/t/view.test	2010-04-06 07:26:59 +0000
+++ b/mysql-test/t/view.test	2010-12-14 09:33:03 +0000
@@ -3925,6 +3925,22 @@ WHERE t1.b <=> (SELECT a FROM t1 WHERE a
 DROP VIEW v1;
 DROP TABLE t1;
 
+--echo #
+--echo # Bug#57703 create view cause Assertion failed: 0, file .\item_subselect.cc, line 846
+--echo #
+
+CREATE TABLE t1(a int);
+CREATE VIEW v1 AS SELECT 1 FROM t1 GROUP BY
+SUBSTRING(1 FROM (SELECT 3 FROM t1 WHERE a >= ANY(SELECT 1)));
+DROP VIEW v1;
+DROP TABLE t1;
+
+--echo #
+--echo # Bug#57352 valgrind warnings when creating view
+--echo #
+CREATE VIEW v1 AS SELECT 1 IN (1 LIKE 2,0) AS f;
+DROP VIEW v1;
+
 --echo # -----------------------------------------------------------------
 --echo # -- End of 5.1 tests.
 --echo # -----------------------------------------------------------------

=== modified file 'sql/item.cc'
--- a/sql/item.cc	2010-11-18 13:11:18 +0000
+++ b/sql/item.cc	2010-12-14 09:33:03 +0000
@@ -1712,16 +1712,7 @@ bool agg_item_set_converter(DTCollation 
 
     if (!(conv= (*arg)->safe_charset_converter(coll.collation)) &&
         ((*arg)->collation.repertoire == MY_REPERTOIRE_ASCII))
-    {
-      /*
-        We should disable const subselect item evaluation because
-        subselect transformation does not happen in view_prepare_mode
-        and thus val_...() methods can not be called for const items.
-      */
-      bool resolve_const= ((*arg)->type() == Item::SUBSELECT_ITEM &&
-                           thd->lex->view_prepare_mode) ? FALSE : TRUE;
-      conv= new Item_func_conv_charset(*arg, coll.collation, resolve_const);
-    }
+      conv= new Item_func_conv_charset(*arg, coll.collation, 1);
 
     if (!conv)
     {

=== modified file 'sql/item_cmpfunc.cc'
--- a/sql/item_cmpfunc.cc	2010-09-09 12:48:06 +0000
+++ b/sql/item_cmpfunc.cc	2010-12-14 09:33:03 +0000
@@ -401,7 +401,7 @@ static bool convert_constant_item(THD *t
   Field *field= field_item->field;
   int result= 0;
 
-  if (!(*item)->with_subselect && (*item)->const_item())
+  if ((*item)->const_item())
   {
     TABLE *table= field->table;
     ulong orig_sql_mode= thd->variables.sql_mode;
@@ -497,7 +497,7 @@ void Item_bool_func2::fix_length_and_dec
   }
 
   thd= current_thd;
-  if (!thd->is_context_analysis_only())
+  if (!thd->lex->is_ps_or_view_context_analysis())
   {
     if (args[0]->real_item()->type() == FIELD_ITEM)
     {
@@ -801,7 +801,7 @@ Arg_comparator::can_compare_as_dates(Ite
       confuse storage engines since in context analysis mode tables 
       aren't locked.
     */
-    if (!thd->is_context_analysis_only() &&
+    if (!thd->lex->is_ps_or_view_context_analysis() &&
         cmp_type != CMP_DATE_WITH_DATE && str_arg->const_item() &&
         (str_arg->type() != Item::FUNC_ITEM ||
         ((Item_func*)str_arg)->functype() != Item_func::GUSERVAR_FUNC))
@@ -1027,7 +1027,7 @@ Item** Arg_comparator::cache_converted_c
                                                 Item_result type)
 {
   /* Don't need cache if doing context analysis only. */
-  if (!thd_arg->is_context_analysis_only() &&
+  if (!thd->lex->is_ps_or_view_context_analysis() &&
       (*value)->const_item() && type != (*value)->result_type())
   {
     Item_cache *cache= Item_cache::get_cache(*value, type);
@@ -4686,7 +4686,7 @@ bool Item_func_like::fix_fields(THD *thd
     return TRUE;
   }
   
-  if (escape_item->const_item() && !thd->lex->view_prepare_mode)
+  if (escape_item->const_item())
   {
     /* If we are on execution stage */
     String *escape_str= escape_item->val_str(&cmp.value1);

=== modified file 'sql/item_func.cc'
--- a/sql/item_func.cc	2010-11-26 12:51:48 +0000
+++ b/sql/item_func.cc	2010-12-14 09:33:03 +0000
@@ -6066,7 +6066,7 @@ Item_func_sp::fix_fields(THD *thd, Item 
   if (res)
     DBUG_RETURN(res);
 
-  if (thd->lex->view_prepare_mode)
+  if (thd->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_VIEW)
   {
     /*
       Here we check privileges of the stored routine only during view

=== modified file 'sql/item_row.cc'
--- a/sql/item_row.cc	2010-03-19 06:21:37 +0000
+++ b/sql/item_row.cc	2010-12-14 09:33:03 +0000
@@ -73,12 +73,8 @@ bool Item_row::fix_fields(THD *thd, Item
     used_tables_cache |= item->used_tables();
     const_item_cache&= item->const_item() && !with_null;
     not_null_tables_cache|= item->not_null_tables();
-    /*
-      Some subqueries transformations aren't done in the view_prepare_mode thus
-      is_null() will fail. So we skip is_null() calculation for CREATE VIEW as
-      not necessary.
-    */
-    if (const_item_cache && !thd->lex->view_prepare_mode)
+
+    if (const_item_cache)
     {
       if (item->cols() > 1)
 	with_null|= item->null_inside();

=== modified file 'sql/item_subselect.cc'
--- a/sql/item_subselect.cc	2010-10-18 12:12:27 +0000
+++ b/sql/item_subselect.cc	2010-12-14 09:33:03 +0000
@@ -123,20 +123,6 @@ void Item_subselect::cleanup()
 }
 
 
-/*
-   We cannot use generic Item::safe_charset_converter() because
-   Subselect transformation does not happen in view_prepare_mode
-   and thus we can not evaluate val_...() for const items.
-*/
-
-Item *Item_subselect::safe_charset_converter(CHARSET_INFO *tocs)
-{
-  Item_func_conv_charset *conv=
-    new Item_func_conv_charset(this, tocs, thd->lex->view_prepare_mode ? 0 : 1);
-  return conv->safe ? conv : NULL;
-}
-
-
 void Item_singlerow_subselect::cleanup()
 {
   DBUG_ENTER("Item_singlerow_subselect::cleanup");
@@ -271,6 +257,7 @@ bool Item_subselect::exec()
   if (thd->is_error() || thd->killed)
     return 1;
 
+  DBUG_ASSERT(!thd->lex->context_analysis_only);
   /*
     Simulate a failure in sub-query execution. Used to test e.g.
     out of memory or query being killed conditions.
@@ -307,7 +294,7 @@ table_map Item_subselect::used_tables() 
 
 bool Item_subselect::const_item() const
 {
-  return const_item_cache;
+  return thd->lex->context_analysis_only ? FALSE : const_item_cache;
 }
 
 Item *Item_subselect::get_tmp_table_item(THD *thd_arg)
@@ -1638,7 +1625,8 @@ bool Item_in_subselect::fix_fields(THD *
 {
   bool result = 0;
   
-  if (thd_arg->lex->view_prepare_mode && left_expr && !left_expr->fixed)
+  if ((thd_arg->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_VIEW) &&
+      left_expr && !left_expr->fixed)
     result = left_expr->fix_fields(thd_arg, &left_expr);
 
   return result || Item_subselect::fix_fields(thd_arg, ref);

=== modified file 'sql/item_subselect.h'
--- a/sql/item_subselect.h	2010-04-06 07:26:59 +0000
+++ b/sql/item_subselect.h	2010-12-14 09:33:03 +0000
@@ -126,7 +126,6 @@ public:
   virtual void reset_value_registration() {}
   enum_parsing_place place() { return parsing_place; }
   bool walk(Item_processor processor, bool walk_subquery, uchar *arg);
-  Item *safe_charset_converter(CHARSET_INFO *tocs);
 
   /**
     Get the SELECT_LEX structure associated with this Item.

=== modified file 'sql/mysql_priv.h'
--- a/sql/mysql_priv.h	2010-10-07 08:13:11 +0000
+++ b/sql/mysql_priv.h	2010-12-14 09:33:03 +0000
@@ -566,17 +566,42 @@ protected:
 
 #define MY_CHARSET_BIN_MB_MAXLEN 1
 
+/*
+  Flags below are set when we perform
+  context analysis of the statement and make
+  subqueries non-const. It prevents subquery
+  evaluation at context analysis stage.
+*/
+
+/*
+  Don't evaluate this subquery during statement prepare even if
+  it's a constant one. The flag is switched off in the end of
+  mysqld_stmt_prepare.
+*/ 
+#define CONTEXT_ANALYSIS_ONLY_PREPARE 1
+/*
+  Special JOIN::prepare mode: changing of query is prohibited.
+  When creating a view, we need to just check its syntax omitting
+  any optimizations: afterwards definition of the view will be
+  reconstructed by means of ::print() methods and written to
+  to an .frm file. We need this definition to stay untouched.
+*/ 
+#define CONTEXT_ANALYSIS_ONLY_VIEW    2
+/*
+  Don't evaluate this subquery during derived table prepare even if
+  it's a constant one.
+*/
+#define CONTEXT_ANALYSIS_ONLY_DERIVED 4
+
 // uncachable cause
 #define UNCACHEABLE_DEPENDENT   1
 #define UNCACHEABLE_RAND        2
 #define UNCACHEABLE_SIDEEFFECT	4
 /// forcing to save JOIN for explain
 #define UNCACHEABLE_EXPLAIN     8
-/** Don't evaluate subqueries in prepare even if they're not correlated */
-#define UNCACHEABLE_PREPARE    16
 /* For uncorrelated SELECT in an UNION with some correlated SELECTs */
-#define UNCACHEABLE_UNITED     32
-#define UNCACHEABLE_CHECKOPTION   64
+#define UNCACHEABLE_UNITED     16
+#define UNCACHEABLE_CHECKOPTION 32
 
 /* Used to check GROUP BY list in the MODE_ONLY_FULL_GROUP_BY mode */
 #define UNDEF_POS (-1)

=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h	2010-10-23 12:55:44 +0000
+++ b/sql/sql_class.h	2010-12-14 09:33:03 +0000
@@ -2180,8 +2180,6 @@ public:
              (variables.sql_mode & MODE_STRICT_ALL_TABLES)));
   }
   void set_status_var_init();
-  bool is_context_analysis_only()
-    { return stmt_arena->is_stmt_prepare() || lex->view_prepare_mode; }
   void reset_n_backup_open_tables_state(Open_tables_state *backup);
   void restore_backup_open_tables_state(Open_tables_state *backup);
   void reset_sub_statement_state(Sub_statement_state *backup, uint new_state);

=== modified file 'sql/sql_derived.cc'
--- a/sql/sql_derived.cc	2010-06-10 20:45:22 +0000
+++ b/sql/sql_derived.cc	2010-12-14 09:33:03 +0000
@@ -147,10 +147,11 @@ bool mysql_derived_prepare(THD *thd, LEX
     if (!(derived_result= new select_union))
       DBUG_RETURN(TRUE); // out of memory
 
+    lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_DERIVED;
     // st_select_lex_unit::prepare correctly work for single select
     if ((res= unit->prepare(thd, derived_result, 0)))
       goto exit;
-
+    lex->context_analysis_only&= ~CONTEXT_ANALYSIS_ONLY_DERIVED;
     if ((res= check_duplicate_names(unit->types, 0)))
       goto exit;
 

=== modified file 'sql/sql_lex.cc'
--- a/sql/sql_lex.cc	2010-07-30 20:33:10 +0000
+++ b/sql/sql_lex.cc	2010-12-14 09:33:03 +0000
@@ -305,7 +305,7 @@ void lex_start(THD *thd)
   lex->select_lex.group_list.empty();
   lex->describe= 0;
   lex->subqueries= FALSE;
-  lex->view_prepare_mode= FALSE;
+  lex->context_analysis_only= 0;
   lex->derived_tables= 0;
   lex->lock_option= TL_READ;
   lex->safe_to_cache_query= 1;

=== modified file 'sql/sql_lex.h'
--- a/sql/sql_lex.h	2010-08-18 04:56:06 +0000
+++ b/sql/sql_lex.h	2010-12-14 09:33:03 +0000
@@ -1715,14 +1715,8 @@ typedef struct st_lex : public Query_tab
   bool verbose, no_write_to_binlog;
 
   bool tx_chain, tx_release;
-  /*
-    Special JOIN::prepare mode: changing of query is prohibited.
-    When creating a view, we need to just check its syntax omitting
-    any optimizations: afterwards definition of the view will be
-    reconstructed by means of ::print() methods and written to
-    to an .frm file. We need this definition to stay untouched.
-  */
-  bool view_prepare_mode;
+
+  uint8 context_analysis_only;
   bool safe_to_cache_query;
   bool subqueries, ignore;
   st_parsing_options parsing_options;
@@ -1843,6 +1837,13 @@ typedef struct st_lex : public Query_tab
     delete_dynamic(&plugins);
   }
 
+  inline bool is_ps_or_view_context_analysis()
+  {
+    return (context_analysis_only &
+            (CONTEXT_ANALYSIS_ONLY_PREPARE |
+             CONTEXT_ANALYSIS_ONLY_VIEW));
+  }
+
   inline void uncacheable(uint8 cause)
   {
     safe_to_cache_query= 0;

=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc	2010-10-23 12:55:44 +0000
+++ b/sql/sql_parse.cc	2010-12-14 09:33:03 +0000
@@ -5865,13 +5865,6 @@ mysql_new_select(LEX *lex, bool move_dow
     DBUG_RETURN(1);
   }
   select_lex->nest_level= lex->nest_level;
-  /*
-    Don't evaluate this subquery during statement prepare even if
-    it's a constant one. The flag is switched off in the end of
-    mysqld_stmt_prepare.
-  */
-  if (thd->stmt_arena->is_stmt_prepare())
-    select_lex->uncacheable|= UNCACHEABLE_PREPARE;
   if (move_down)
   {
     SELECT_LEX_UNIT *unit;

=== modified file 'sql/sql_prepare.cc'
--- a/sql/sql_prepare.cc	2010-11-03 10:24:47 +0000
+++ b/sql/sql_prepare.cc	2010-12-14 09:33:03 +0000
@@ -1688,7 +1688,7 @@ static bool mysql_test_create_view(Prepa
   if (open_normal_and_derived_tables(thd, tables, 0))
     goto err;
 
-  lex->view_prepare_mode= 1;
+  lex->context_analysis_only|=  CONTEXT_ANALYSIS_ONLY_VIEW;
   res= select_like_stmt_test(stmt, 0, 0);
 
 err:
@@ -2234,19 +2234,6 @@ end:
 }
 
 
-/** Init PS/SP specific parse tree members.  */
-
-static void init_stmt_after_parse(LEX *lex)
-{
-  SELECT_LEX *sl= lex->all_selects_list;
-  /*
-    Switch off a temporary flag that prevents evaluation of
-    subqueries in statement prepare.
-  */
-  for (; sl; sl= sl->next_select_in_list())
-   sl->uncacheable&= ~UNCACHEABLE_PREPARE;
-}
-
 /**
   SQLCOM_PREPARE implementation.
 
@@ -3080,6 +3067,7 @@ bool Prepared_statement::prepare(const c
 
   parser_state.m_lip.stmt_prepare_mode= TRUE;
   lex_start(thd);
+  lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_PREPARE;
 
   error= parse_sql(thd, & parser_state, NULL) ||
     thd->is_error() ||
@@ -3132,7 +3120,7 @@ bool Prepared_statement::prepare(const c
   if (error == 0)
   {
     setup_set_params();
-    init_stmt_after_parse(lex);
+    lex->context_analysis_only&= ~CONTEXT_ANALYSIS_ONLY_PREPARE;
     state= Query_arena::PREPARED;
     flags&= ~ (uint) IS_IN_USE;
     /*

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2010-11-26 12:51:48 +0000
+++ b/sql/sql_select.cc	2010-12-14 09:33:03 +0000
@@ -538,7 +538,8 @@ JOIN::prepare(Item ***rref_pointer_array
     thd->lex->allow_sum_func= save_allow_sum_func;
   }
 
-  if (!thd->lex->view_prepare_mode && !(select_options & SELECT_DESCRIBE))
+  if (!(thd->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_VIEW) &&
+      !(select_options & SELECT_DESCRIBE))
   {
     Item_subselect *subselect;
     /* Is it subselect? */

=== modified file 'sql/sql_show.cc'
--- a/sql/sql_show.cc	2010-11-30 17:51:25 +0000
+++ b/sql/sql_show.cc	2010-12-14 09:33:03 +0000
@@ -718,7 +718,7 @@ mysqld_show_create(THD *thd, TABLE_LIST 
                       table_list->table_name));
 
   /* We want to preserve the tree for views. */
-  thd->lex->view_prepare_mode= TRUE;
+  thd->lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_VIEW;
 
   {
     Show_create_error_handler view_error_suppressor(thd, table_list);
@@ -3315,7 +3315,7 @@ int get_all_tables(THD *thd, TABLE_LIST 
   uint derived_tables= lex->derived_tables; 
   int error= 1;
   Open_tables_state open_tables_state_backup;
-  bool save_view_prepare_mode= lex->view_prepare_mode;
+  uint8 save_context_analysis_only= lex->context_analysis_only;
   Query_tables_list query_tables_list_backup;
 #ifndef NO_EMBEDDED_ACCESS_CHECKS
   Security_context *sctx= thd->security_ctx;
@@ -3323,7 +3323,7 @@ int get_all_tables(THD *thd, TABLE_LIST 
   uint table_open_method;
   DBUG_ENTER("get_all_tables");
 
-  lex->view_prepare_mode= TRUE;
+  lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_VIEW;
   lex->reset_n_backup_query_tables_list(&query_tables_list_backup);
 
   /*
@@ -3540,7 +3540,7 @@ err:
   lex->restore_backup_query_tables_list(&query_tables_list_backup);
   lex->derived_tables= derived_tables;
   lex->all_selects_list= old_all_select_lex;
-  lex->view_prepare_mode= save_view_prepare_mode;
+  lex->context_analysis_only= save_context_analysis_only;
   lex->sql_command= save_sql_command;
   DBUG_RETURN(error);
 }

=== modified file 'sql/sql_view.cc'
--- a/sql/sql_view.cc	2010-06-11 12:52:06 +0000
+++ b/sql/sql_view.cc	2010-12-14 09:33:03 +0000
@@ -545,7 +545,7 @@ bool mysql_create_view(THD *thd, TABLE_L
   }
 
   /* prepare select to resolve all fields */
-  lex->view_prepare_mode= 1;
+  lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_VIEW;
   if (unit->prepare(thd, 0, 0))
   {
     /*

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-5.1-bugteam branch (sergey.glukhov:3519 to 3520)Bug#52157 Bug#54475 Bug#57352 Bug#57703Sergey Glukhov14 Dec