diff options
-rw-r--r-- | mysql-test/r/join_cache.result | 36 | ||||
-rw-r--r-- | mysql-test/t/join_cache.test | 35 | ||||
-rw-r--r-- | sql/sql_join_cache.cc | 27 | ||||
-rw-r--r-- | sql/sql_join_cache.h | 1 |
4 files changed, 94 insertions, 5 deletions
diff --git a/mysql-test/r/join_cache.result b/mysql-test/r/join_cache.result index bb28ed36f62..58a40bae4da 100644 --- a/mysql-test/r/join_cache.result +++ b/mysql-test/r/join_cache.result @@ -4964,4 +4964,40 @@ a SET SESSION join_cache_level = DEFAULT; SET SESSION join_buffer_size = DEFAULT; DROP TABLE t1,t2; +# +# Bug #802860: crash on join cache + derived + duplicate_weedout +# +SET SESSION optimizer_switch= +'semijoin=on,materialization=off,firstmatch=off,loosescan=off'; +CREATE TABLE t1 (a int) ; +INSERT IGNORE INTO t1 VALUES (0), (1), (0); +CREATE TABLE t2 (a int) ; +INSERT IGNORE INTO t2 VALUES (0), (3), (0), (2); +SET SESSION join_cache_level = 0; +EXPLAIN +SELECT * FROM (SELECT DISTINCT * FROM t1) t +WHERE t.a IN (SELECT t2.a FROM t2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 4 Using where; Start temporary +1 PRIMARY <derived2> ref key0 key0 5 test.t2.a 2 End temporary +2 DERIVED t1 ALL NULL NULL NULL NULL 3 Using temporary +SELECT * FROM (SELECT DISTINCT * FROM t1) t +WHERE t.a IN (SELECT t2.a FROM t2); +a +0 +SET SESSION join_cache_level = 1; +EXPLAIN +SELECT * FROM (SELECT DISTINCT * FROM t1) t +WHERE t.a IN (SELECT t2.a FROM t2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY <derived2> ALL key0 NULL NULL NULL 3 Start temporary +1 PRIMARY t2 ALL NULL NULL NULL NULL 4 Using where; End temporary; Using join buffer (flat, BNL join) +2 DERIVED t1 ALL NULL NULL NULL NULL 3 Using temporary +SELECT * FROM (SELECT DISTINCT * FROM t1) t +WHERE t.a IN (SELECT t2.a FROM t2); +a +0 +SET SESSION join_cache_level = DEFAULT; +DROP TABLE t1, t2; +SET SESSION optimizer_switch=default; set @@optimizer_switch=@save_optimizer_switch; diff --git a/mysql-test/t/join_cache.test b/mysql-test/t/join_cache.test index 0073d1e45b0..1d5addeb808 100644 --- a/mysql-test/t/join_cache.test +++ b/mysql-test/t/join_cache.test @@ -3100,5 +3100,40 @@ SET SESSION join_buffer_size = DEFAULT; DROP TABLE t1,t2; +--echo # +--echo # Bug #802860: crash on join cache + derived + duplicate_weedout +--echo # + +SET SESSION optimizer_switch= + 'semijoin=on,materialization=off,firstmatch=off,loosescan=off'; + +CREATE TABLE t1 (a int) ; +INSERT IGNORE INTO t1 VALUES (0), (1), (0); + +CREATE TABLE t2 (a int) ; +INSERT IGNORE INTO t2 VALUES (0), (3), (0), (2); + +SET SESSION join_cache_level = 0; + +EXPLAIN +SELECT * FROM (SELECT DISTINCT * FROM t1) t + WHERE t.a IN (SELECT t2.a FROM t2); +SELECT * FROM (SELECT DISTINCT * FROM t1) t + WHERE t.a IN (SELECT t2.a FROM t2); + +SET SESSION join_cache_level = 1; + +EXPLAIN +SELECT * FROM (SELECT DISTINCT * FROM t1) t + WHERE t.a IN (SELECT t2.a FROM t2); +SELECT * FROM (SELECT DISTINCT * FROM t1) t + WHERE t.a IN (SELECT t2.a FROM t2); + +SET SESSION join_cache_level = DEFAULT; + +DROP TABLE t1, t2; + +SET SESSION optimizer_switch=default; + # this must be the last command in the file set @@optimizer_switch=@save_optimizer_switch; diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc index 64b82efd8ff..f292375ee6f 100644 --- a/sql/sql_join_cache.cc +++ b/sql/sql_join_cache.cc @@ -609,8 +609,15 @@ void JOIN_CACHE::create_remaining_fields() if (tab->keep_current_rowid) { copy->str= table->file->ref; - copy->length= table->file->ref_length; - copy->type= 0; + if (copy->str) + copy->length= table->file->ref_length; + else + { + /* This may happen only for materialized derived tables and views */ + copy->length= 0; + copy->str= (uchar *) table; + } + copy->type= CACHE_ROWID; copy->field= 0; copy->referenced_field_no= 0; length+= copy->length; @@ -1325,8 +1332,7 @@ uint JOIN_CACHE::write_record_data(uchar * link, bool *is_full) { Field *field= copy->field; if (field && field->maybe_null() && field->is_null()) - { - /* Do not copy a field if its value is null */ + { if (copy->referenced_field_no) copy->offset= 0; continue; @@ -1386,6 +1392,18 @@ uint JOIN_CACHE::write_record_data(uchar * link, bool *is_full) cp+= len+2; break; } + case CACHE_ROWID: + if (!copy->length) + { + /* + This may happen only for ROWID fields of materialized + derived tables and views. + */ + TABLE *table= (TABLE *) copy->str; + copy->str= table->file->ref; + copy->length= table->file->ref_length; + } + /* fall through */ default: /* Copy the entire image of the field from the record buffer */ memcpy(cp, copy->str, copy->length); @@ -1455,7 +1473,6 @@ uint JOIN_CACHE::write_record_data(uchar * link, bool *is_full) RETURN VALUE none */ - void JOIN_CACHE::reset(bool for_writing) { pos= buff; diff --git a/sql/sql_join_cache.h b/sql/sql_join_cache.h index f87cdcec649..f5d64d5530a 100644 --- a/sql/sql_join_cache.h +++ b/sql/sql_join_cache.h @@ -16,6 +16,7 @@ #define CACHE_STRIPPED 2 /* field stripped of trailing spaces */ #define CACHE_VARSTR1 3 /* short string value (length takes 1 byte) */ #define CACHE_VARSTR2 4 /* long string value (length takes 2 bytes) */ +#define CACHE_ROWID 5 /* ROWID field */ /* The CACHE_FIELD structure used to describe fields of records that |