From a624f99e98bdfaca785fb1bfeb33931b6fbd130a Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Wed, 26 Jan 2011 11:30:29 -0800 Subject: [PATCH] Fixed LP bug #707555. The bug was in the code of the patch fixing bug 698882. With improper casting the method store_key_field::change_source_field was called for the elements of the array TABLE_REF::key_copy that were either of a different type or not allocated at all. This caused crashes in some queries. --- mysql-test/r/select.result | 40 ++++++++++++++++++++++++++ mysql-test/r/select_jcl6.result | 40 ++++++++++++++++++++++++++ mysql-test/r/select_pkeycache.result | 40 ++++++++++++++++++++++++++ mysql-test/t/select.test | 43 ++++++++++++++++++++++++++++ sql/sql_select.cc | 11 ++++--- sql/sql_select.h | 10 ++++++- 6 files changed, 179 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 0de259574f6..935e7d806c9 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -4977,4 +4977,44 @@ a1 b1 a2 b2 a3 b3 2 xx 2 yy 2 zzz SET SESSION optimizer_switch=DEFAULT; DROP TABLE t1,t2,t3; +# +# Bug #707555: crash with equality substitution in ref +# +CREATE TABLE t1 (f11 int, f12 int, PRIMARY KEY (f11), KEY (f12)) ; +INSERT INTO t1 VALUES (1,NULL), (8,NULL); +CREATE TABLE t2 (f21 int, f22 int, f23 int, KEY (f22)) ; +INSERT INTO t2 VALUES (1,NULL,3), (2,7,8); +CREATE TABLE t3 (f31 int, f32 int(11), PRIMARY KEY (f31), KEY (f32)) ; +INSERT INTO t3 VALUES (1,494862336); +CREATE TABLE t4 (f41 int, f42 int, PRIMARY KEY (f41), KEY (f42)) ; +INSERT INTO t4 VALUES (1,NULL), (8,NULL); +CREATE TABLE t5 (f51 int, PRIMARY KEY (f51)) ; +INSERT IGNORE INTO t5 VALUES (100); +CREATE TABLE t6 (f61 int, f62 int, KEY (f61)) ; +INSERT INTO t6 VALUES (NULL,1), (3,10); +CREATE TABLE t7 (f71 int, f72 int, KEY (f72)) ; +INSERT INTO t7 VALUES (1,NULL), (2,7); +EXPLAIN +SELECT t2.f23 FROM +(t1 LEFT JOIN (t2 JOIN t3 ON t2.f22=t3.f32) ON t1.f11=t3.f31) +LEFT JOIN +(((t4 JOIN t5 ON t4.f42=t5.f51) LEFT JOIN t6 ON t6.f62>0) JOIN t7 ON t6.f61>0) +ON t3.f31 = t6.f61 +WHERE t7.f71>0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t3 system PRIMARY,f32 NULL NULL NULL 1 +1 SIMPLE t5 system PRIMARY NULL NULL NULL 1 +1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 Using index +1 SIMPLE t2 ref f22 f22 5 const 1 +1 SIMPLE t6 ref f61 f61 5 const 1 Using where +1 SIMPLE t4 ref f42 f42 5 const 1 Using index +1 SIMPLE t7 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join) +SELECT t2.f23 FROM +(t1 LEFT JOIN (t2 JOIN t3 ON t2.f22=t3.f32) ON t1.f11=t3.f31) +LEFT JOIN +(((t4 JOIN t5 ON t4.f42=t5.f51) LEFT JOIN t6 ON t6.f62>0) JOIN t7 ON t6.f61>0) +ON t3.f31 = t6.f61 +WHERE t7.f71>0; +f23 +DROP TABLE t1,t2,t3,t4,t5,t6,t7; End of 5.1 tests diff --git a/mysql-test/r/select_jcl6.result b/mysql-test/r/select_jcl6.result index bda9d789e18..1093bf54ccd 100644 --- a/mysql-test/r/select_jcl6.result +++ b/mysql-test/r/select_jcl6.result @@ -4984,6 +4984,46 @@ a1 b1 a2 b2 a3 b3 2 xx 2 yy 2 zzz SET SESSION optimizer_switch=DEFAULT; DROP TABLE t1,t2,t3; +# +# Bug #707555: crash with equality substitution in ref +# +CREATE TABLE t1 (f11 int, f12 int, PRIMARY KEY (f11), KEY (f12)) ; +INSERT INTO t1 VALUES (1,NULL), (8,NULL); +CREATE TABLE t2 (f21 int, f22 int, f23 int, KEY (f22)) ; +INSERT INTO t2 VALUES (1,NULL,3), (2,7,8); +CREATE TABLE t3 (f31 int, f32 int(11), PRIMARY KEY (f31), KEY (f32)) ; +INSERT INTO t3 VALUES (1,494862336); +CREATE TABLE t4 (f41 int, f42 int, PRIMARY KEY (f41), KEY (f42)) ; +INSERT INTO t4 VALUES (1,NULL), (8,NULL); +CREATE TABLE t5 (f51 int, PRIMARY KEY (f51)) ; +INSERT IGNORE INTO t5 VALUES (100); +CREATE TABLE t6 (f61 int, f62 int, KEY (f61)) ; +INSERT INTO t6 VALUES (NULL,1), (3,10); +CREATE TABLE t7 (f71 int, f72 int, KEY (f72)) ; +INSERT INTO t7 VALUES (1,NULL), (2,7); +EXPLAIN +SELECT t2.f23 FROM +(t1 LEFT JOIN (t2 JOIN t3 ON t2.f22=t3.f32) ON t1.f11=t3.f31) +LEFT JOIN +(((t4 JOIN t5 ON t4.f42=t5.f51) LEFT JOIN t6 ON t6.f62>0) JOIN t7 ON t6.f61>0) +ON t3.f31 = t6.f61 +WHERE t7.f71>0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t3 system PRIMARY,f32 NULL NULL NULL 1 +1 SIMPLE t5 system PRIMARY NULL NULL NULL 1 +1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 Using index +1 SIMPLE t2 ref f22 f22 5 const 1 +1 SIMPLE t6 ref f61 f61 5 const 1 Using where; Using join buffer (flat, BKA join) +1 SIMPLE t4 ref f42 f42 5 const 1 Using index +1 SIMPLE t7 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join) +SELECT t2.f23 FROM +(t1 LEFT JOIN (t2 JOIN t3 ON t2.f22=t3.f32) ON t1.f11=t3.f31) +LEFT JOIN +(((t4 JOIN t5 ON t4.f42=t5.f51) LEFT JOIN t6 ON t6.f62>0) JOIN t7 ON t6.f61>0) +ON t3.f31 = t6.f61 +WHERE t7.f71>0; +f23 +DROP TABLE t1,t2,t3,t4,t5,t6,t7; End of 5.1 tests set join_cache_level=default; show variables like 'join_cache_level'; diff --git a/mysql-test/r/select_pkeycache.result b/mysql-test/r/select_pkeycache.result index 0de259574f6..935e7d806c9 100644 --- a/mysql-test/r/select_pkeycache.result +++ b/mysql-test/r/select_pkeycache.result @@ -4977,4 +4977,44 @@ a1 b1 a2 b2 a3 b3 2 xx 2 yy 2 zzz SET SESSION optimizer_switch=DEFAULT; DROP TABLE t1,t2,t3; +# +# Bug #707555: crash with equality substitution in ref +# +CREATE TABLE t1 (f11 int, f12 int, PRIMARY KEY (f11), KEY (f12)) ; +INSERT INTO t1 VALUES (1,NULL), (8,NULL); +CREATE TABLE t2 (f21 int, f22 int, f23 int, KEY (f22)) ; +INSERT INTO t2 VALUES (1,NULL,3), (2,7,8); +CREATE TABLE t3 (f31 int, f32 int(11), PRIMARY KEY (f31), KEY (f32)) ; +INSERT INTO t3 VALUES (1,494862336); +CREATE TABLE t4 (f41 int, f42 int, PRIMARY KEY (f41), KEY (f42)) ; +INSERT INTO t4 VALUES (1,NULL), (8,NULL); +CREATE TABLE t5 (f51 int, PRIMARY KEY (f51)) ; +INSERT IGNORE INTO t5 VALUES (100); +CREATE TABLE t6 (f61 int, f62 int, KEY (f61)) ; +INSERT INTO t6 VALUES (NULL,1), (3,10); +CREATE TABLE t7 (f71 int, f72 int, KEY (f72)) ; +INSERT INTO t7 VALUES (1,NULL), (2,7); +EXPLAIN +SELECT t2.f23 FROM +(t1 LEFT JOIN (t2 JOIN t3 ON t2.f22=t3.f32) ON t1.f11=t3.f31) +LEFT JOIN +(((t4 JOIN t5 ON t4.f42=t5.f51) LEFT JOIN t6 ON t6.f62>0) JOIN t7 ON t6.f61>0) +ON t3.f31 = t6.f61 +WHERE t7.f71>0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t3 system PRIMARY,f32 NULL NULL NULL 1 +1 SIMPLE t5 system PRIMARY NULL NULL NULL 1 +1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 Using index +1 SIMPLE t2 ref f22 f22 5 const 1 +1 SIMPLE t6 ref f61 f61 5 const 1 Using where +1 SIMPLE t4 ref f42 f42 5 const 1 Using index +1 SIMPLE t7 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join) +SELECT t2.f23 FROM +(t1 LEFT JOIN (t2 JOIN t3 ON t2.f22=t3.f32) ON t1.f11=t3.f31) +LEFT JOIN +(((t4 JOIN t5 ON t4.f42=t5.f51) LEFT JOIN t6 ON t6.f62>0) JOIN t7 ON t6.f61>0) +ON t3.f31 = t6.f61 +WHERE t7.f71>0; +f23 +DROP TABLE t1,t2,t3,t4,t5,t6,t7; End of 5.1 tests diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 017e69c8a1a..fb04562a173 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -4167,4 +4167,47 @@ SET SESSION optimizer_switch=DEFAULT; DROP TABLE t1,t2,t3; + +--echo # +--echo # Bug #707555: crash with equality substitution in ref +--echo # + +CREATE TABLE t1 (f11 int, f12 int, PRIMARY KEY (f11), KEY (f12)) ; +INSERT INTO t1 VALUES (1,NULL), (8,NULL); + +CREATE TABLE t2 (f21 int, f22 int, f23 int, KEY (f22)) ; +INSERT INTO t2 VALUES (1,NULL,3), (2,7,8); + +CREATE TABLE t3 (f31 int, f32 int(11), PRIMARY KEY (f31), KEY (f32)) ; +INSERT INTO t3 VALUES (1,494862336); + +CREATE TABLE t4 (f41 int, f42 int, PRIMARY KEY (f41), KEY (f42)) ; +INSERT INTO t4 VALUES (1,NULL), (8,NULL); + +CREATE TABLE t5 (f51 int, PRIMARY KEY (f51)) ; +INSERT IGNORE INTO t5 VALUES (100); + +CREATE TABLE t6 (f61 int, f62 int, KEY (f61)) ; +INSERT INTO t6 VALUES (NULL,1), (3,10); + +CREATE TABLE t7 (f71 int, f72 int, KEY (f72)) ; +INSERT INTO t7 VALUES (1,NULL), (2,7); + +EXPLAIN +SELECT t2.f23 FROM + (t1 LEFT JOIN (t2 JOIN t3 ON t2.f22=t3.f32) ON t1.f11=t3.f31) + LEFT JOIN + (((t4 JOIN t5 ON t4.f42=t5.f51) LEFT JOIN t6 ON t6.f62>0) JOIN t7 ON t6.f61>0) + ON t3.f31 = t6.f61 + WHERE t7.f71>0; + +SELECT t2.f23 FROM + (t1 LEFT JOIN (t2 JOIN t3 ON t2.f22=t3.f32) ON t1.f11=t3.f31) + LEFT JOIN + (((t4 JOIN t5 ON t4.f42=t5.f51) LEFT JOIN t6 ON t6.f62>0) JOIN t7 ON t6.f61>0) + ON t3.f31 = t6.f61 + WHERE t7.f71>0; + +DROP TABLE t1,t2,t3,t4,t5,t6,t7; + --echo End of 5.1 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index d1beb2e4666..16c6674d664 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1059,6 +1059,8 @@ JOIN::optimize() Item **ref_item_ptr= tab->ref.items+i; Item *ref_item= *ref_item_ptr; + if (!ref_item->used_tables() && !(select_options & SELECT_DESCRIBE)) + continue; COND_EQUAL *equals= tab->first_inner ? tab->first_inner->cond_equal : cond_equal; ref_item= substitute_for_best_equal_field(ref_item, equals, map2table); @@ -1067,10 +1069,11 @@ JOIN::optimize() { *ref_item_ptr= ref_item; Item *item= ref_item->real_item(); - if (item->type() == Item::FIELD_ITEM) - { - store_key_field *key_copy= (store_key_field *) tab->ref.key_copy[i]; - key_copy->change_source_field((Item_field *) item); + store_key *key_copy= tab->ref.key_copy[i]; + if (key_copy->type() == store_key::FIELD_STORE_KEY) + { + store_key_field *field_copy= ((store_key_field *)key_copy); + field_copy->change_source_field((Item_field *) item); } } } diff --git a/sql/sql_select.h b/sql/sql_select.h index 8f0feb0e766..2d74d3b86d7 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -997,6 +997,7 @@ class store_key :public Sql_alloc public: bool null_key; /* TRUE <=> the value of the key has a null part */ enum store_key_result { STORE_KEY_OK, STORE_KEY_FATAL, STORE_KEY_CONV }; + enum Type { FIELD_STORE_KEY, ITEM_STORE_KEY, CONST_ITEM_STORE_KEY }; store_key(THD *thd, Field *field_arg, uchar *ptr, uchar *null, uint length) :null_key(0), null_ptr(null), err(0) { @@ -1017,6 +1018,7 @@ public: ptr, null, 1); } virtual ~store_key() {} /** Not actually needed */ + virtual enum Type type() const=0; virtual const char *name() const=0; /** @@ -1068,7 +1070,9 @@ class store_key_field: public store_key { copy_field.set(to_field,from_field,0); } - } + } + + enum Type type() const { return FIELD_STORE_KEY; } const char *name() const { return field_name; } void change_source_field(Item_field *fld_item) @@ -1116,6 +1120,8 @@ public: null_ptr_arg ? null_ptr_arg : item_arg->maybe_null ? &err : (uchar*) 0, length), item(item_arg), use_value(val) {} + + enum Type type() const { return ITEM_STORE_KEY; } const char *name() const { return "func"; } protected: @@ -1164,6 +1170,8 @@ public: &err : (uchar*) 0, length, item_arg, FALSE), inited(0) { } + + enum Type type() const { return CONST_ITEM_STORE_KEY; } const char *name() const { return "const"; } protected: