summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/join_cache.result36
-rw-r--r--mysql-test/t/join_cache.test35
-rw-r--r--sql/sql_join_cache.cc27
-rw-r--r--sql/sql_join_cache.h1
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