Commit 47c1b040 authored by Sergey Petrunya's avatar Sergey Petrunya

MDEV-4778: Incorrect results from Aria/MyISAM SELECT using index with prefix length on TEXT column

Backport the fix olav.sandstaa@sun.com-20101102184747-qfuntqwj021imy9r:
"Fix for Bug#52660 Perf. regr. using ICP for MyISAM on range queries on an index containing TEXT" 
(together with further fixes in that code) into MyISAM and Aria.
parent 9651a6f5
......@@ -892,3 +892,24 @@ insert into t1 values ('',1);
select 1 from t1 where b <= 1 and a <> '';
drop table t1;
--echo #
--echo # MDEV-4778: Incorrect results from Aria/MyISAM SELECT using index with prefix length on TEXT column
--echo #
CREATE TABLE t1 (
c1 TEXT ,
c2 VARCHAR(2) ,
INDEX idx1 (c2,c1(2)),
INDEX idx2 (c2,c1(1))
);
INSERT INTO t1 (c1,c2) VALUES ('aa','x'), ('a' ,'y');
SELECT * FROM t1 IGNORE INDEX(idx1,idx2) WHERE (c1='aa' AND c2='x') OR (c1='a' AND c2='y');
EXPLAIN
SELECT * FROM t1 FORCE INDEX(idx1) WHERE (c1='aa' AND c2='x') OR (c1='a' AND c2='y');
SELECT * FROM t1 FORCE INDEX(idx1) WHERE (c1='aa' AND c2='x') OR (c1='a' AND c2='y');
SELECT * FROM t1 FORCE INDEX(idx2) WHERE (c1='aa' AND c2='x') OR (c1='a' AND c2='y');
DROP TABLE t1;
......@@ -852,6 +852,33 @@ select 1 from t1 where b <= 1 and a <> '';
1
drop table t1;
#
# MDEV-4778: Incorrect results from Aria/MyISAM SELECT using index with prefix length on TEXT column
#
CREATE TABLE t1 (
c1 TEXT ,
c2 VARCHAR(2) ,
INDEX idx1 (c2,c1(2)),
INDEX idx2 (c2,c1(1))
);
INSERT INTO t1 (c1,c2) VALUES ('aa','x'), ('a' ,'y');
SELECT * FROM t1 IGNORE INDEX(idx1,idx2) WHERE (c1='aa' AND c2='x') OR (c1='a' AND c2='y');
c1 c2
aa x
a y
EXPLAIN
SELECT * FROM t1 FORCE INDEX(idx1) WHERE (c1='aa' AND c2='x') OR (c1='a' AND c2='y');
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range idx1 idx1 10 NULL 2 Using index condition; Using where
SELECT * FROM t1 FORCE INDEX(idx1) WHERE (c1='aa' AND c2='x') OR (c1='a' AND c2='y');
c1 c2
aa x
a y
SELECT * FROM t1 FORCE INDEX(idx2) WHERE (c1='aa' AND c2='x') OR (c1='a' AND c2='y');
c1 c2
aa x
a y
DROP TABLE t1;
#
# BUG#920132: Assert trx->n_active_thrs == 1 failed at que0que.c line 1050
#
CREATE TABLE t1 ( a INT )
......
......@@ -105,7 +105,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range FieldKey FieldKey 38 NULL 4 Using index condition; Rowid-ordered scan; Using filesort
EXPLAIN SELECT * FROM t1 IGNORE INDEX (FieldKey, LongField) WHERE FieldKey > '2' ORDER BY LongVal;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range StringField StringField 38 NULL 4 Using index condition; Using filesort
1 SIMPLE t1 range StringField StringField 38 NULL 4 Using where; Using filesort
SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY LongVal;
FieldKey LongVal StringVal
3 1 2
......
......@@ -211,7 +211,7 @@ c-1006=w
EXPLAIN
SELECT c1 FROM t3 WHERE c1 >= 'c-1004=w' and c1 <= 'c-1006=w' and i1 > 2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t3 range c1 c1 12 NULL 2 Using index condition; Using where
1 SIMPLE t3 range c1 c1 12 NULL 2 Using where
SELECT c1 FROM t3 WHERE c1 >= 'c-1004=w' and c1 <= 'c-1006=w' and i1 > 2;
c1
EXPLAIN
......@@ -855,6 +855,33 @@ insert into t1 values ('',1);
select 1 from t1 where b <= 1 and a <> '';
1
drop table t1;
#
# MDEV-4778: Incorrect results from Aria/MyISAM SELECT using index with prefix length on TEXT column
#
CREATE TABLE t1 (
c1 TEXT ,
c2 VARCHAR(2) ,
INDEX idx1 (c2,c1(2)),
INDEX idx2 (c2,c1(1))
);
INSERT INTO t1 (c1,c2) VALUES ('aa','x'), ('a' ,'y');
SELECT * FROM t1 IGNORE INDEX(idx1,idx2) WHERE (c1='aa' AND c2='x') OR (c1='a' AND c2='y');
c1 c2
aa x
a y
EXPLAIN
SELECT * FROM t1 FORCE INDEX(idx1) WHERE (c1='aa' AND c2='x') OR (c1='a' AND c2='y');
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range idx1 idx1 10 NULL 2 Using where
SELECT * FROM t1 FORCE INDEX(idx1) WHERE (c1='aa' AND c2='x') OR (c1='a' AND c2='y');
c1 c2
aa x
a y
SELECT * FROM t1 FORCE INDEX(idx2) WHERE (c1='aa' AND c2='x') OR (c1='a' AND c2='y');
c1 c2
aa x
a y
DROP TABLE t1;
drop table if exists t0, t1, t1i, t1m;
#
# BUG#826935 Assertion `!table || (!table->read_set || bitmap_is_set(table->read_set, field_index))' failed
......
......@@ -78,13 +78,13 @@ insert into t2 select * from t1;
alter table t1 modify b blob not null, add c int not null, drop key a, add unique key (a,b(20),c), drop key b, add key (b(10));
explain select * from t1 where a is null and b = 2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref a,b a 5 const 3 Using index condition; Using where
1 SIMPLE t1 ref a,b a 5 const 3 Using where
explain select * from t1 where a is null and b = 2 and c=0;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref a,b a 5 const 3 Using index condition; Using where
1 SIMPLE t1 ref a,b a 5 const 3 Using where
explain select * from t1 where a is null and b = 7 and c=0;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref a,b a 5 const 3 Using index condition; Using where
1 SIMPLE t1 ref a,b a 5 const 3 Using where
explain select * from t1 where a=2 and b = 2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref a,b a 5 const 1 Using where
......@@ -93,25 +93,25 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 12 Using where
explain select * from t1 where (a is null or a > 0 and a < 3) and b < 5 and c=0 limit 3;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range a,b a 5 NULL 5 Using index condition; Using where
1 SIMPLE t1 range a,b a 5 NULL 5 Using where
explain select * from t1 where (a is null or a = 7) and b=7 and c=0;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref_or_null a,b a 5 const 4 Using index condition; Using where
1 SIMPLE t1 ref_or_null a,b a 5 const 4 Using where
explain select * from t1 where (a is null and b>a) or a is null and b=7 limit 2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref a,b a 5 const 3 Using index condition; Using where
1 SIMPLE t1 ref a,b a 5 const 3 Using where
explain select * from t1 where a is null and b=9 or a is null and b=7 limit 3;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref a,b a 5 const 3 Using index condition; Using where
1 SIMPLE t1 ref a,b a 5 const 3 Using where
explain select * from t1 where a > 1 and a < 3 limit 1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range a a 5 NULL 1 Using index condition
1 SIMPLE t1 range a a 5 NULL 1 Using where
explain select * from t1 where a is null and b=7 or a > 1 and a < 3 limit 1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range a,b a 5 NULL 4 Using index condition; Using where
1 SIMPLE t1 range a,b a 5 NULL 4 Using where
explain select * from t1 where a > 8 and a < 9;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range a a 5 NULL 1 Using index condition
1 SIMPLE t1 range a a 5 NULL 1 Using where
explain select * from t1 where b like "6%";
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range b b 12 NULL 1 Using where
......
......@@ -618,7 +618,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range FieldKey FieldKey 38 NULL 4 Using index condition; Using filesort
EXPLAIN SELECT * FROM t1 IGNORE INDEX (FieldKey, LongField) WHERE FieldKey > '2' ORDER BY LongVal;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range StringField StringField 38 NULL 4 Using index condition; Using filesort
1 SIMPLE t1 range StringField StringField 38 NULL 4 Using where; Using filesort
SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY LongVal;
FieldKey LongVal StringVal
3 1 2
......
......@@ -213,7 +213,7 @@ c-1006=w
EXPLAIN
SELECT c1 FROM t3 WHERE c1 >= 'c-1004=w' and c1 <= 'c-1006=w' and i1 > 2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t3 range c1 c1 12 NULL 2 Using index condition; Using where
1 SIMPLE t3 range c1 c1 12 NULL 2 Using where
SELECT c1 FROM t3 WHERE c1 >= 'c-1004=w' and c1 <= 'c-1006=w' and i1 > 2;
c1
EXPLAIN
......@@ -857,5 +857,32 @@ insert into t1 values ('',1);
select 1 from t1 where b <= 1 and a <> '';
1
drop table t1;
#
# MDEV-4778: Incorrect results from Aria/MyISAM SELECT using index with prefix length on TEXT column
#
CREATE TABLE t1 (
c1 TEXT ,
c2 VARCHAR(2) ,
INDEX idx1 (c2,c1(2)),
INDEX idx2 (c2,c1(1))
);
INSERT INTO t1 (c1,c2) VALUES ('aa','x'), ('a' ,'y');
SELECT * FROM t1 IGNORE INDEX(idx1,idx2) WHERE (c1='aa' AND c2='x') OR (c1='a' AND c2='y');
c1 c2
aa x
a y
EXPLAIN
SELECT * FROM t1 FORCE INDEX(idx1) WHERE (c1='aa' AND c2='x') OR (c1='a' AND c2='y');
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range idx1 idx1 10 NULL 2 Using where
SELECT * FROM t1 FORCE INDEX(idx1) WHERE (c1='aa' AND c2='x') OR (c1='a' AND c2='y');
c1 c2
aa x
a y
SELECT * FROM t1 FORCE INDEX(idx2) WHERE (c1='aa' AND c2='x') OR (c1='a' AND c2='y');
c1 c2
aa x
a y
DROP TABLE t1;
set storage_engine= @save_storage_engine;
set optimizer_switch=@maria_icp_tmp;
......@@ -2637,7 +2637,33 @@ public:
Pops the top if condition stack, if stack is not empty.
*/
virtual void cond_pop() { return; };
/**
Push down an index condition to the handler.
The server will use this method to push down a condition it wants
the handler to evaluate when retrieving records using a specified
index. The pushed index condition will only refer to fields from
this handler that is contained in the index (but it may also refer
to fields in other handlers). Before the handler evaluates the
condition it must read the content of the index entry into the
record buffer.
The handler is free to decide if and how much of the condition it
will take responsibility for evaluating. Based on this evaluation
it should return the part of the condition it will not evaluate.
If it decides to evaluate the entire condition it should return
NULL. If it decides not to evaluate any part of the condition it
should return a pointer to the same condition as given as argument.
@param keyno the index number to evaluate the condition on
@param idx_cond the condition to be evaluated by the handler
@return The part of the pushed condition that the handler decides
not to evaluate
*/
virtual Item *idx_cond_push(uint keyno, Item* idx_cond) { return idx_cond; }
/** Reset information about pushed index conditions */
virtual void cancel_pushed_idx_cond()
{
......
......@@ -3802,6 +3802,25 @@ int ha_maria::multi_range_read_explain_info(uint mrr_mode, char *str,
Item *ha_maria::idx_cond_push(uint keyno_arg, Item* idx_cond_arg)
{
/*
Check if the key contains a blob field. If it does then MyISAM
should not accept the pushed index condition since MyISAM will not
read the blob field from the index entry during evaluation of the
pushed index condition and the BLOB field might be part of the
range evaluation done by the ICP code.
*/
const KEY *key= &table_share->key_info[keyno_arg];
for (uint k= 0; k < key->key_parts; ++k)
{
const KEY_PART_INFO *key_part= &key->key_part[k];
if (key_part->key_part_flag & HA_BLOB_PART)
{
/* Let the server handle the index condition */
return idx_cond_arg;
}
}
pushed_idx_cond_keyno= keyno_arg;
pushed_idx_cond= idx_cond_arg;
in_range_check_pushed_down= TRUE;
......
......@@ -2274,6 +2274,25 @@ int ha_myisam::multi_range_read_explain_info(uint mrr_mode, char *str,
Item *ha_myisam::idx_cond_push(uint keyno_arg, Item* idx_cond_arg)
{
/*
Check if the key contains a blob field. If it does then MyISAM
should not accept the pushed index condition since MyISAM will not
read the blob field from the index entry during evaluation of the
pushed index condition and the BLOB field might be part of the
range evaluation done by the ICP code.
*/
const KEY *key= &table_share->key_info[keyno_arg];
for (uint k= 0; k < key->key_parts; ++k)
{
const KEY_PART_INFO *key_part= &key->key_part[k];
if (key_part->key_part_flag & HA_BLOB_PART)
{
/* Let the server handle the index condition */
return idx_cond_arg;
}
}
pushed_idx_cond_keyno= keyno_arg;
pushed_idx_cond= idx_cond_arg;
in_range_check_pushed_down= TRUE;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment