summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <sanja@askmonty.org>2010-09-08 09:26:17 +0300
committerunknown <sanja@askmonty.org>2010-09-08 09:26:17 +0300
commit11dc256ca4ee1057d1e918326b8c76fdbbca63cd (patch)
tree8f59ac5856cdd8515b959711d450188651952d46
parentd6a9b52269c2f64a8f793c4680eed9adece0a716 (diff)
downloadmariadb-git-11dc256ca4ee1057d1e918326b8c76fdbbca63cd.tar.gz
-rw-r--r--mysql-test/r/subselect_cache.result76
-rw-r--r--mysql-test/t/subselect_cache.test83
-rw-r--r--sql/sql_expression_cache.cc63
-rw-r--r--sql/sql_expression_cache.h3
-rw-r--r--sql/table.cc8
-rw-r--r--sql/table.h3
6 files changed, 170 insertions, 66 deletions
diff --git a/mysql-test/r/subselect_cache.result b/mysql-test/r/subselect_cache.result
index 3fc1a3e0fe8..71c4a4bc88c 100644
--- a/mysql-test/r/subselect_cache.result
+++ b/mysql-test/r/subselect_cache.result
@@ -3183,7 +3183,7 @@ NULL
NULL
drop table t1,t2,t3;
set @@optimizer_switch= default;
-# LP BUG#615760 (double transformation)
+# LP BUG#615760 (part 1: double transformation)
create table t1 (a int);
insert into t1 values (1),(2);
create table t2 (b int);
@@ -3198,3 +3198,77 @@ Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where <expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(select 1 from `test`.`t2` where (<cache>(`test`.`t1`.`a`) = `test`.`t2`.`b`))))
drop table t1,t2;
set @@optimizer_switch= default;
+# LP BUG#615760 (part 2: incorrect heap table index flags)
+SET SESSION optimizer_switch = 'index_merge=off,index_merge_union=off,index_merge_sort_union=off,index_merge_intersection=off,index_condition_pushdown=off,firstmatch=off,loosescan=off,materialization=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=on,table_elimination=off';
+CREATE TABLE `t1` (
+`pk` int(11) NOT NULL AUTO_INCREMENT,
+`col_int_nokey` int(11) DEFAULT NULL,
+`col_int_key` int(11) DEFAULT NULL,
+`col_varchar_key` varchar(1) DEFAULT NULL,
+`col_varchar_nokey` varchar(1) DEFAULT NULL,
+PRIMARY KEY (`pk`),
+KEY `col_int_key` (`col_int_key`),
+KEY `col_varchar_key` (`col_varchar_key`,`col_int_key`)
+) ENGINE=MARIA AUTO_INCREMENT=30 DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1;
+INSERT INTO `t1` VALUES (10,7,8,'v','v');
+INSERT INTO `t1` VALUES (11,1,9,'r','r');
+INSERT INTO `t1` VALUES (12,5,9,'a','a');
+INSERT INTO `t1` VALUES (13,3,186,'m','m');
+INSERT INTO `t1` VALUES (14,6,NULL,'y','y');
+INSERT INTO `t1` VALUES (15,92,2,'j','j');
+INSERT INTO `t1` VALUES (16,7,3,'d','d');
+INSERT INTO `t1` VALUES (17,NULL,0,'z','z');
+INSERT INTO `t1` VALUES (18,3,133,'e','e');
+INSERT INTO `t1` VALUES (19,5,1,'h','h');
+INSERT INTO `t1` VALUES (20,1,8,'b','b');
+INSERT INTO `t1` VALUES (21,2,5,'s','s');
+INSERT INTO `t1` VALUES (22,NULL,5,'e','e');
+INSERT INTO `t1` VALUES (23,1,8,'j','j');
+INSERT INTO `t1` VALUES (24,0,6,'e','e');
+INSERT INTO `t1` VALUES (25,210,51,'f','f');
+INSERT INTO `t1` VALUES (26,8,4,'v','v');
+INSERT INTO `t1` VALUES (27,7,7,'x','x');
+INSERT INTO `t1` VALUES (28,5,6,'m','m');
+INSERT INTO `t1` VALUES (29,NULL,4,'c','c');
+CREATE TABLE `t2` (
+`pk` int(11) NOT NULL AUTO_INCREMENT,
+`col_int_nokey` int(11) DEFAULT NULL,
+`col_int_key` int(11) DEFAULT NULL,
+`col_varchar_key` varchar(1) DEFAULT NULL,
+`col_varchar_nokey` varchar(1) DEFAULT NULL,
+PRIMARY KEY (`pk`),
+KEY `col_int_key` (`col_int_key`),
+KEY `col_varchar_key` (`col_varchar_key`,`col_int_key`)
+) ENGINE=MARIA AUTO_INCREMENT=21 DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1;
+INSERT INTO `t2` VALUES (1,NULL,2,'w','w');
+INSERT INTO `t2` VALUES (2,7,9,'m','m');
+INSERT INTO `t2` VALUES (3,9,3,'m','m');
+INSERT INTO `t2` VALUES (4,7,9,'k','k');
+INSERT INTO `t2` VALUES (5,4,NULL,'r','r');
+INSERT INTO `t2` VALUES (6,2,9,'t','t');
+INSERT INTO `t2` VALUES (7,6,3,'j','j');
+INSERT INTO `t2` VALUES (8,8,8,'u','u');
+INSERT INTO `t2` VALUES (9,NULL,8,'h','h');
+INSERT INTO `t2` VALUES (10,5,53,'o','o');
+INSERT INTO `t2` VALUES (11,NULL,0,NULL,NULL);
+INSERT INTO `t2` VALUES (12,6,5,'k','k');
+INSERT INTO `t2` VALUES (13,188,166,'e','e');
+INSERT INTO `t2` VALUES (14,2,3,'n','n');
+INSERT INTO `t2` VALUES (15,1,0,'t','t');
+INSERT INTO `t2` VALUES (16,1,1,'c','c');
+INSERT INTO `t2` VALUES (17,0,9,'m','m');
+INSERT INTO `t2` VALUES (18,9,5,'y','y');
+INSERT INTO `t2` VALUES (19,NULL,6,'f','f');
+INSERT INTO `t2` VALUES (20,4,2,'d','d');
+SELECT table1 .`col_varchar_nokey`
+FROM t2 table1 RIGHT JOIN t1 LEFT JOIN (
+SELECT SUBQUERY1_t2 .*
+FROM t1 SUBQUERY1_t1 LEFT JOIN t2 SUBQUERY1_t2 ON SUBQUERY1_t2 .`col_int_key` = SUBQUERY1_t1 .`col_int_nokey` ) table3 STRAIGHT_JOIN ( (
+SELECT *
+FROM t1 ) table4 JOIN ( t1 table5 JOIN t2 table6 ON table5 .`pk` ) ON table5 .`col_varchar_nokey` ) ON table6 .`pk` = table5 .`col_int_key` ON table5 .`col_varchar_nokey` ON table5 .`col_varchar_key`
+WHERE table3 .`col_varchar_key` IN (
+SELECT `col_varchar_key`
+FROM t2 ) AND table1 .`col_varchar_key` OR table1 .`pk` ;
+col_varchar_nokey
+drop table t1,t2;
+set @@optimizer_switch= default;
diff --git a/mysql-test/t/subselect_cache.test b/mysql-test/t/subselect_cache.test
index 796d299b41c..5340f5ead54 100644
--- a/mysql-test/t/subselect_cache.test
+++ b/mysql-test/t/subselect_cache.test
@@ -1472,7 +1472,7 @@ drop table t1,t2,t3;
set @@optimizer_switch= default;
#
---echo # LP BUG#615760 (double transformation)
+--echo # LP BUG#615760 (part 1: double transformation)
#
create table t1 (a int);
insert into t1 values (1),(2);
@@ -1485,3 +1485,84 @@ select * from t1 where a in (select b from t2);
drop table t1,t2;
set @@optimizer_switch= default;
+
+#
+--echo # LP BUG#615760 (part 2: incorrect heap table index flags)
+#
+SET SESSION optimizer_switch = 'index_merge=off,index_merge_union=off,index_merge_sort_union=off,index_merge_intersection=off,index_condition_pushdown=off,firstmatch=off,loosescan=off,materialization=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=on,table_elimination=off';
+
+CREATE TABLE `t1` (
+ `pk` int(11) NOT NULL AUTO_INCREMENT,
+ `col_int_nokey` int(11) DEFAULT NULL,
+ `col_int_key` int(11) DEFAULT NULL,
+ `col_varchar_key` varchar(1) DEFAULT NULL,
+ `col_varchar_nokey` varchar(1) DEFAULT NULL,
+ PRIMARY KEY (`pk`),
+ KEY `col_int_key` (`col_int_key`),
+ KEY `col_varchar_key` (`col_varchar_key`,`col_int_key`)
+) ENGINE=MARIA AUTO_INCREMENT=30 DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1;
+INSERT INTO `t1` VALUES (10,7,8,'v','v');
+INSERT INTO `t1` VALUES (11,1,9,'r','r');
+INSERT INTO `t1` VALUES (12,5,9,'a','a');
+INSERT INTO `t1` VALUES (13,3,186,'m','m');
+INSERT INTO `t1` VALUES (14,6,NULL,'y','y');
+INSERT INTO `t1` VALUES (15,92,2,'j','j');
+INSERT INTO `t1` VALUES (16,7,3,'d','d');
+INSERT INTO `t1` VALUES (17,NULL,0,'z','z');
+INSERT INTO `t1` VALUES (18,3,133,'e','e');
+INSERT INTO `t1` VALUES (19,5,1,'h','h');
+INSERT INTO `t1` VALUES (20,1,8,'b','b');
+INSERT INTO `t1` VALUES (21,2,5,'s','s');
+INSERT INTO `t1` VALUES (22,NULL,5,'e','e');
+INSERT INTO `t1` VALUES (23,1,8,'j','j');
+INSERT INTO `t1` VALUES (24,0,6,'e','e');
+INSERT INTO `t1` VALUES (25,210,51,'f','f');
+INSERT INTO `t1` VALUES (26,8,4,'v','v');
+INSERT INTO `t1` VALUES (27,7,7,'x','x');
+INSERT INTO `t1` VALUES (28,5,6,'m','m');
+INSERT INTO `t1` VALUES (29,NULL,4,'c','c');
+CREATE TABLE `t2` (
+ `pk` int(11) NOT NULL AUTO_INCREMENT,
+ `col_int_nokey` int(11) DEFAULT NULL,
+ `col_int_key` int(11) DEFAULT NULL,
+ `col_varchar_key` varchar(1) DEFAULT NULL,
+ `col_varchar_nokey` varchar(1) DEFAULT NULL,
+ PRIMARY KEY (`pk`),
+ KEY `col_int_key` (`col_int_key`),
+ KEY `col_varchar_key` (`col_varchar_key`,`col_int_key`)
+) ENGINE=MARIA AUTO_INCREMENT=21 DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1;
+INSERT INTO `t2` VALUES (1,NULL,2,'w','w');
+INSERT INTO `t2` VALUES (2,7,9,'m','m');
+INSERT INTO `t2` VALUES (3,9,3,'m','m');
+INSERT INTO `t2` VALUES (4,7,9,'k','k');
+INSERT INTO `t2` VALUES (5,4,NULL,'r','r');
+INSERT INTO `t2` VALUES (6,2,9,'t','t');
+INSERT INTO `t2` VALUES (7,6,3,'j','j');
+INSERT INTO `t2` VALUES (8,8,8,'u','u');
+INSERT INTO `t2` VALUES (9,NULL,8,'h','h');
+INSERT INTO `t2` VALUES (10,5,53,'o','o');
+INSERT INTO `t2` VALUES (11,NULL,0,NULL,NULL);
+INSERT INTO `t2` VALUES (12,6,5,'k','k');
+INSERT INTO `t2` VALUES (13,188,166,'e','e');
+INSERT INTO `t2` VALUES (14,2,3,'n','n');
+INSERT INTO `t2` VALUES (15,1,0,'t','t');
+INSERT INTO `t2` VALUES (16,1,1,'c','c');
+INSERT INTO `t2` VALUES (17,0,9,'m','m');
+INSERT INTO `t2` VALUES (18,9,5,'y','y');
+INSERT INTO `t2` VALUES (19,NULL,6,'f','f');
+INSERT INTO `t2` VALUES (20,4,2,'d','d');
+
+# Here we just need plenty of different parameters to overflow
+# temporary heap table of expression cache
+SELECT table1 .`col_varchar_nokey`
+FROM t2 table1 RIGHT JOIN t1 LEFT JOIN (
+SELECT SUBQUERY1_t2 .*
+FROM t1 SUBQUERY1_t1 LEFT JOIN t2 SUBQUERY1_t2 ON SUBQUERY1_t2 .`col_int_key` = SUBQUERY1_t1 .`col_int_nokey` ) table3 STRAIGHT_JOIN ( (
+SELECT *
+FROM t1 ) table4 JOIN ( t1 table5 JOIN t2 table6 ON table5 .`pk` ) ON table5 .`col_varchar_nokey` ) ON table6 .`pk` = table5 .`col_int_key` ON table5 .`col_varchar_nokey` ON table5 .`col_varchar_key`
+WHERE table3 .`col_varchar_key` IN (
+SELECT `col_varchar_key`
+FROM t2 ) AND table1 .`col_varchar_key` OR table1 .`pk` ;
+
+drop table t1,t2;
+set @@optimizer_switch= default;
diff --git a/sql/sql_expression_cache.cc b/sql/sql_expression_cache.cc
index cbbafbd55c8..ca7c583292c 100644
--- a/sql/sql_expression_cache.cc
+++ b/sql/sql_expression_cache.cc
@@ -12,7 +12,7 @@ Expression_cache_tmptable::Expression_cache_tmptable(THD *thd,
List<Item*> &dependants,
Item *value)
:cache_table(NULL), table_thd(thd), list(&dependants), val(value),
- equalities(NULL), inited (0)
+ inited (0)
{
DBUG_ENTER("Expression_cache_tmptable::Expression_cache_tmptable");
DBUG_VOID_RETURN;
@@ -20,56 +20,6 @@ Expression_cache_tmptable::Expression_cache_tmptable(THD *thd,
/**
- Build and of equalities for the expression's parameters of certain types
-
- @details
- If the temporary table used as an expression cache contains fields of
- certain types then it's not enough to perform a lookup into the table to
- verify that there is no row in the table for a given set of parameters.
- Additionally for those fields we have to check equalities of the form
- fld=val, where val is the value of the parameter stored in the column
- fld.
- The function generates a conjunction of all such equality predicates
- and saves a pointer to it in the field 'equalities'.
-
- @retval FALSE OK
- @retval TRUE Error
-*/
-
-bool Expression_cache_tmptable::make_equalities()
-{
- List<Item> args;
- List_iterator_fast<Item*> li(*list);
- Item **ref;
- DBUG_ENTER("Expression_cache_tmptable::make_equalities");
-
- for (uint i= 1 /* skip result filed */; (ref= li++); i++)
- {
- Field *fld= cache_table->field[i];
- /* Only some field types should be checked after lookup */
- if (fld->type() == MYSQL_TYPE_VARCHAR ||
- fld->type() == MYSQL_TYPE_TINY_BLOB ||
- fld->type() == MYSQL_TYPE_MEDIUM_BLOB ||
- fld->type() == MYSQL_TYPE_LONG_BLOB ||
- fld->type() == MYSQL_TYPE_BLOB ||
- fld->type() == MYSQL_TYPE_VAR_STRING ||
- fld->type() == MYSQL_TYPE_STRING ||
- fld->type() == MYSQL_TYPE_NEWDECIMAL ||
- fld->type() == MYSQL_TYPE_DECIMAL)
- {
- args.push_front(new Item_func_eq(*ref, new Item_field(fld)));
- }
- }
- if (args.elements == 1)
- equalities= args.head();
- else
- equalities= new Item_cond_and(args);
-
- DBUG_RETURN(equalities->fix_fields(table_thd, &equalities));
-}
-
-
-/**
Field enumerator for TABLE::add_tmp_key
@param arg reference variable with current field number
@@ -166,7 +116,8 @@ void Expression_cache_tmptable::init()
if (cache_table->alloc_keys(1) ||
(cache_table->add_tmp_key(0, items.elements - 1,
&field_enumerator,
- (uchar*)&field_counter) < 0) ||
+ (uchar*)&field_counter,
+ TRUE) < 0) ||
ref.tmp_table_index_lookup_init(table_thd, cache_table->key_info, it,
TRUE))
{
@@ -193,12 +144,6 @@ void Expression_cache_tmptable::init()
goto error;
}
- if (make_equalities())
- {
- DBUG_PRINT("error", ("Creating equalities failed"));
- goto error;
- }
-
DBUG_VOID_RETURN;
error:
@@ -249,7 +194,7 @@ Expression_cache::result Expression_cache_tmptable::check_value(Item **value)
(uint)cache_table->status, (uint)ref.has_record));
if ((res= join_read_key2(table_thd, NULL, cache_table, &ref)) == 1)
DBUG_RETURN(ERROR);
- if (res || (equalities && !equalities->val_int()))
+ if (res)
{
subquery_cache_miss++;
DBUG_RETURN(MISS);
diff --git a/sql/sql_expression_cache.h b/sql/sql_expression_cache.h
index e931eca6091..d74e9f49178 100644
--- a/sql/sql_expression_cache.h
+++ b/sql/sql_expression_cache.h
@@ -60,7 +60,6 @@ public:
private:
void init();
- bool make_equalities();
/* tmp table parameters */
TMP_TABLE_PARAM cache_table_param;
@@ -78,8 +77,6 @@ private:
List<Item> items;
/* Value Item example */
Item *val;
- /* Expression to check after index lookup */
- Item *equalities;
/* Set on if the object has been succesfully initialized with init() */
bool inited;
};
diff --git a/sql/table.cc b/sql/table.cc
index 3a4ea3064be..2b1a85a74ea 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -5162,6 +5162,7 @@ bool TABLE::alloc_keys(uint key_count)
@param next_field_no the call-back function that returns the number of
the field used as the next component of the key
@param arg the argument for the above function
+ @param unique Is it unique index
@details
The function adds a new key to the table that is assumed to be
@@ -5173,7 +5174,8 @@ bool TABLE::alloc_keys(uint key_count)
*/
bool TABLE::add_tmp_key(uint key, uint key_parts,
- uint (*next_field_no) (uchar *), uchar *arg)
+ uint (*next_field_no) (uchar *), uchar *arg,
+ bool unique)
{
DBUG_ASSERT(key < max_keys);
@@ -5192,6 +5194,8 @@ bool TABLE::add_tmp_key(uint key, uint key_parts,
keyinfo->key_length=0;
keyinfo->algorithm= HA_KEY_ALG_UNDEF;
keyinfo->flags= HA_GENERATED_KEY;
+ if (unique)
+ keyinfo->flags|= HA_NOSAME;
sprintf(buf, "key%i", key);
if (!(keyinfo->name= strdup_root(&mem_root, buf)))
return TRUE;
@@ -5230,6 +5234,8 @@ bool TABLE::add_tmp_key(uint key, uint key_parts,
{
key_part_info->store_length+= HA_KEY_NULL_LENGTH;
keyinfo->key_length+= HA_KEY_NULL_LENGTH;
+ if (unique)
+ keyinfo->flags|= HA_NULL_ARE_EQUAL; // def. that NULL == NULL
}
if ((*reg_field)->type() == MYSQL_TYPE_BLOB ||
(*reg_field)->real_type() == MYSQL_TYPE_VARCHAR)
diff --git a/sql/table.h b/sql/table.h
index 5102955e2ad..3922e1dd6bd 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -920,7 +920,8 @@ struct st_table {
{ return s->version != refresh_version; }
bool alloc_keys(uint key_count);
bool add_tmp_key(uint key, uint key_parts,
- uint (*next_field_no) (uchar *), uchar *arg);
+ uint (*next_field_no) (uchar *), uchar *arg,
+ bool unique);
bool is_children_attached(void);
inline void enable_keyread()
{