MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:kgeorge Date:April 26 2006 7:39am
Subject:bk commit into 4.1 tree (gkodinov:1.2459) BUG#18492
View as plain text  
Below is the list of changes that have just been committed into a local
4.1 repository of kgeorge. When kgeorge does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet
  1.2459 06/04/26 10:38:59 gkodinov@stripped +6 -0
  BUG#18492: mysqld reports ER_ILLEGAL_REFERENCE in --ps-protocol
  
  In the code that converts IN predicates to EXISTS predicates it is changing
  the select list elements to constant 1. Example :
  
  SELECT ... FROM ... WHERE a IN (SELECT c FROM ...)
  
  is transformed to :
  
  SELECT ... FROM ... WHERE EXISTS (SELECT 1 FROM ... HAVING a = c)
  
  However there can no FROM clause in the IN subquery and it may not be a
  simple select :
  
  SELECT ... FROM ... WHERE a IN (SELECT f(..) AS c UNION SELECT ...)
  
  This query is transformed to :
  
   SELECT ... FROM ... WHERE
     EXISTS (SELECT 1 FROM (SELECT f(..) AS c UNION SELECT ...) x HAVING a = c)
  
  In the above query the c in the HAVING clause is made to be an Item_null_helper
  (a subclass of Item_ref) pointing to the real Item_field (witch is not
  referenced anywhere else in the query anymore). This is done because
  Item_ref_null_helper collects information whether there are NULL values in
  the result.
  This is OK for directly executed statements, because the Item_field pointed
  by the Item_null_helper is already fixed when the transformation is done.
  But when executed as a prepared statement all the Item instances are
  "un-fixed" before the recompilation of the prepared statement. So when the
  Item_null_helper gets fixed it discovers that the Item_field it points to
  is not fixed and issues an error.
  
  The remedy is to keep the original select list references when there are
  no tables in the FROM clause. So the above becomes :
  
   SELECT ... FROM ... WHERE
     EXISTS (SELECT c FROM (SELECT f(..) AS c UNION SELECT ...) x HAVING a = c)
  
  In this way the c is referenced directly in the select list as well as by
  reference in the HAVING clause. So it gets correctly fixed even with
  prepared statements.
  
  And since the Item_null_helper subclass of Item_ref_null_helper is not used
  anywhere else it's taken out.

  sql/item_subselect.cc
    1.140 06/04/26 10:38:55 gkodinov@stripped +9 -7
    The described change to the IN->EXISTS transformation

  sql/item.h
    1.193 06/04/26 10:38:55 gkodinov@stripped +0 -13
    Taking out the Item_null_helper as it's no longer needed

  sql/item.cc
    1.232 06/04/26 10:38:55 gkodinov@stripped +0 -8
    Taking out the Item_null_helper as it's no longer needed

  mysql-test/t/ps_11bugs.test
    1.6 06/04/26 10:38:55 gkodinov@stripped +14 -0
    Testcase for the bug

  mysql-test/r/subselect.result
    1.175 06/04/26 10:38:55 gkodinov@stripped +1 -1
    Explain updated because of the tranformation

  mysql-test/r/ps_11bugs.result
    1.4 06/04/26 10:38:55 gkodinov@stripped +14 -0
    Test case for the bug

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	gkodinov
# Host:	rakia.progem.bg
# Root:	/home/kgeorge/mysql/4.1/B18492

--- 1.231/sql/item.cc	2006-03-01 15:53:13 +02:00
+++ 1.232/sql/item.cc	2006-04-26 10:38:55 +03:00
@@ -2716,14 +2716,6 @@
 }
 
 
-void Item_null_helper::print(String *str)
-{
-  str->append("<null_helper>(", 14);
-  store->print(str);
-  str->append(')');
-}
-
-
 bool Item_default_value::eq(const Item *item, bool binary_cmp) const
 {
   return item->type() == DEFAULT_VALUE_ITEM && 

--- 1.192/sql/item.h	2005-10-12 23:27:47 +03:00
+++ 1.193/sql/item.h	2006-04-26 10:38:55 +03:00
@@ -1045,19 +1045,6 @@
   }
 };
 
-class Item_null_helper :public Item_ref_null_helper
-{
-  Item *store;
-public:
-  Item_null_helper(Item_in_subselect* master, Item *item,
-		   const char *table_name_par, const char *field_name_par)
-    :Item_ref_null_helper(master, &item, table_name_par, field_name_par),
-     store(item)
-    { ref= &store; }
-  void print(String *str);
-};
-
-
 /*
   The following class is used to optimize comparing of date and bigint columns
   We need to save the original item ('ref') to be able to call

--- 1.174/mysql-test/r/subselect.result	2005-10-15 17:46:09 +03:00
+++ 1.175/mysql-test/r/subselect.result	2006-04-26 10:38:55 +03:00
@@ -734,7 +734,7 @@
 3	DEPENDENT UNION	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
 NULL	UNION RESULT	<union2,3>	ALL	NULL	NULL	NULL	NULL	NULL	
 Warnings:
-Note	1003	select test.t2.id AS `id` from test.t2 where <in_optimizer>(test.t2.id,<exists>(select 1 AS `Not_used` having (<cache>(test.t2.id) = <null_helper>(1)) union select 1 AS `Not_used` having (<cache>(test.t2.id) = <null_helper>(3))))
+Note	1003	select test.t2.id AS `id` from test.t2 where <in_optimizer>(test.t2.id,<exists>(select 1 AS `1` having (<cache>(test.t2.id) = <ref_null_helper>(1)) union select 3 AS `3` having (<cache>(test.t2.id) = <ref_null_helper>(3))))
 SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 3);
 id
 SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 2);

--- 1.139/sql/item_subselect.cc	2005-08-13 07:45:07 +03:00
+++ 1.140/sql/item_subselect.cc	2006-04-26 10:38:55 +03:00
@@ -822,13 +822,13 @@
   }
   else
   {
-    select_lex->item_list.empty();
-    select_lex->item_list.push_back(new Item_int("Not_used",
-						 (longlong) 1, 21));
-    select_lex->ref_pointer_array[0]= select_lex->item_list.head();
     if (select_lex->table_list.elements)
     {
       Item *having= item, *orig_item= item;
+      select_lex->item_list.empty();
+      select_lex->item_list.push_back(new Item_int("Not_used",
+                                                   (longlong) 1, 21));
+      select_lex->ref_pointer_array[0]= select_lex->item_list.head();
       item= func->create(expr, item);
       if (!abort_on_null && orig_item->maybe_null)
       {
@@ -875,9 +875,11 @@
 	select_lex->having=
 	  join->having=
 	  func->create(expr,
-		       new Item_null_helper(this, item,
-					    (char *)"<no matter>",
-					    (char *)"<result>"));
+                       new Item_ref_null_helper(this,
+                                            select_lex->ref_pointer_array,
+                                            (char *)"<no matter>",
+                                            (char *)"<result>"));
+
 	select_lex->having_fix_field= 1;
 	if (join->having->fix_fields(thd, join->tables_list,
 				     0))

--- 1.3/mysql-test/r/ps_11bugs.result	2004-10-15 13:56:54 +03:00
+++ 1.4/mysql-test/r/ps_11bugs.result	2006-04-26 10:38:55 +03:00
@@ -116,3 +116,17 @@
 cola	colb	cold
 aaaa	yyyy	R
 drop table t1, t2;
+create table t1 (a int primary key);
+insert into t1 values (1);
+explain select * from t1 where 3 in (select (1+1) union select 1);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Impossible WHERE noticed after reading const tables
+2	DEPENDENT SUBQUERY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+3	DEPENDENT UNION	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+NULL	UNION RESULT	<union2,3>	ALL	NULL	NULL	NULL	NULL	NULL	
+select * from t1 where 3 in (select (1+1) union select 1);
+a
+prepare st_18492 from 'select * from t1 where 3 in (select (1+1) union select 1)';
+execute st_18492;
+a
+drop table t1;

--- 1.5/mysql-test/t/ps_11bugs.test	2005-07-28 03:21:46 +03:00
+++ 1.6/mysql-test/t/ps_11bugs.test	2006-04-26 10:38:55 +03:00
@@ -130,3 +130,17 @@
 # end of bug#1676
 
 # End of 4.1 tests
+
+# bug#18492: mysqld reports ER_ILLEGAL_REFERENCE in --ps-protocol
+
+create table t1 (a int primary key);
+insert into t1 values (1);
+
+explain select * from t1 where 3 in (select (1+1) union select 1);
+
+select * from t1 where 3 in (select (1+1) union select 1);
+
+prepare st_18492 from 'select * from t1 where 3 in (select (1+1) union select 1)';
+execute st_18492;
+
+drop table t1;
Thread
bk commit into 4.1 tree (gkodinov:1.2459) BUG#18492kgeorge26 Apr