Commit ee0a516c authored by sergefp@mysql.com's avatar sergefp@mysql.com

Manual merge

parents 078f7178 2e93dfaf
......@@ -146,7 +146,13 @@ enum ha_extra_function {
On-the-fly switching between unique and non-unique key inserting.
*/
HA_EXTRA_CHANGE_KEY_TO_UNIQUE,
HA_EXTRA_CHANGE_KEY_TO_DUP
HA_EXTRA_CHANGE_KEY_TO_DUP,
/*
When using HA_EXTRA_KEYREAD, overwrite only key member fields and keep
other fields intact. When this is off (by default) InnoDB will use memcpy
to overwrite entire row.
*/
HA_EXTRA_KEYREAD_PRESERVE_FIELDS
};
/* The following is parameter to ha_panic() */
......
......@@ -46,6 +46,8 @@ extern my_bool bitmap_is_set(const MY_BITMAP *map, uint bitmap_bit);
extern my_bool bitmap_is_set_all(const MY_BITMAP *map);
extern my_bool bitmap_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2);
extern uint bitmap_set_next(MY_BITMAP *map);
extern uint bitmap_get_first(const MY_BITMAP *map);
extern uint bitmap_bits_set(const MY_BITMAP *map);
extern void bitmap_clear_all(MY_BITMAP *map);
extern void bitmap_clear_bit(MY_BITMAP *map, uint bitmap_bit);
extern void bitmap_free(MY_BITMAP *map);
......
......@@ -748,6 +748,7 @@ extern byte *my_compress_alloc(const byte *packet, ulong *len, ulong *complen);
extern ha_checksum my_checksum(ha_checksum crc, const byte *mem, uint count);
extern uint my_bit_log2(ulong value);
extern uint my_count_bits(ulonglong v);
extern uint my_count_bits_ushort(ushort v);
extern void my_sleep(ulong m_seconds);
extern ulong crc32(ulong crc, const uchar *buf, uint len);
extern uint my_set_max_open_files(uint files);
......
......@@ -573,6 +573,10 @@ struct row_prebuilt_struct {
allocated mem buf start, because
there is a 4 byte magic number at the
start and at the end */
ibool keep_other_fields_on_keyread; /* when using fetch
cache with HA_EXTRA_KEYREAD, don't
overwrite other fields in mysql row
row buffer.*/
ulint fetch_cache_first;/* position of the first not yet
fetched row in fetch_cache */
ulint n_fetch_cached; /* number of not yet fetched rows
......
......@@ -2571,10 +2571,35 @@ row_sel_pop_cached_row_for_mysql(
row */
row_prebuilt_t* prebuilt) /* in: prebuilt struct */
{
ut_ad(prebuilt->n_fetch_cached > 0);
ulint i;
mysql_row_templ_t* templ;
byte* cached_rec;
ut_ad(prebuilt->n_fetch_cached > 0);
if (prebuilt->keep_other_fields_on_keyread)
{
/* Copy cache record field by field, don't touch fields that
are not covered by current key */
cached_rec =
prebuilt->fetch_cache[prebuilt->fetch_cache_first];
for (i = 0; i < prebuilt->n_template; i++) {
templ = prebuilt->mysql_template + i;
ut_memcpy(
buf + templ->mysql_col_offset,
cached_rec + templ->mysql_col_offset,
templ->mysql_col_len);
ut_memcpy(buf, prebuilt->fetch_cache[prebuilt->fetch_cache_first],
prebuilt->mysql_row_len);
if (templ->mysql_null_bit_mask)
buf[templ->mysql_null_byte_offset] &=
cached_rec[templ->mysql_null_byte_offset];
}
}
else
{
ut_memcpy(buf, prebuilt->fetch_cache[prebuilt->fetch_cache_first],
prebuilt->mysql_row_len);
}
prebuilt->n_fetch_cached--;
prebuilt->fetch_cache_first++;
......
......@@ -21,7 +21,7 @@ id select_type table type possible_keys key key_len ref rows Extra
explain
select * from t0 where key1 < 3 or key2 > 1020;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 31 Using where
1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 31 Using sort_union(i1,i2); Using where
select * from t0 where key1 < 3 or key2 > 1020;
key1 key2 key3 key4 key5 key6 key7 key8
1 1 1 1 1 1 1 1023
......@@ -32,11 +32,11 @@ key1 key2 key3 key4 key5 key6 key7 key8
1024 1024 1024 1024 1024 1024 1024 0
explain select * from t0 where key1 < 3 or key2 <4;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 7 Using where
1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 7 Using sort_union(i1,i2); Using where
explain
select * from t0 where (key1 > 30 and key1<35) or (key2 >32 and key2 < 40);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 9 Using where
1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 9 Using sort_union(i1,i2); Using where
select * from t0 where (key1 > 30 and key1<35) or (key2 >32 and key2 < 40);
key1 key2 key3 key4 key5 key6 key7 key8
31 31 31 31 31 31 31 993
......@@ -56,18 +56,18 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 ref i1,i2,i3 i3 4 const 1 Using where
explain select * from t0 use index (i1,i2) where (key1 < 3 or key2 <4) and key3 = 50;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 7 Using where
1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 7 Using sort_union(i1,i2); Using where
explain select * from t0 where (key1 > 1 or key2 > 2);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 ALL i1,i2 NULL NULL NULL 1024 Using where
explain select * from t0 force index (i1,i2) where (key1 > 1 or key2 > 2);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 1024 Using where
1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 1024 Using sort_union(i1,i2); Using where
explain
select * from t0 where key1<3 or key2<3 or (key1>5 and key1<8) or
(key1>10 and key1<12) or (key2>100 and key2<110);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 17 Using where
1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 17 Using sort_union(i1,i2); Using where
explain select * from t0 where key2 = 45 or key1 <=> null;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 range i1,i2 i2 4 NULL 1 Using where
......@@ -79,26 +79,26 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 range i1,i2 i2 4 NULL 1 Using where
explain select * from t0 where key2=10 or key3=3 or key4 <=> null;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 index_merge i2,i3,i4 i2,i3 4,4 NULL 2 Using where
1 SIMPLE t0 index_merge i2,i3,i4 i2,i3 4,4 NULL 2 Using union(i2,i3); Using where
explain select * from t0 where key2=10 or key3=3 or key4 is null;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 index_merge i2,i3,i4 i2,i3 4,4 NULL 2 Using where
1 SIMPLE t0 index_merge i2,i3,i4 i2,i3 4,4 NULL 2 Using union(i2,i3); Using where
explain select key1 from t0 where (key1 <=> null) or (key2 < 5) or
(key3=10) or (key4 <=> null);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 index_merge i1,i2,i3,i4 i2,i3 4,4 NULL 6 Using where
1 SIMPLE t0 index_merge i1,i2,i3,i4 i2,i3 4,4 NULL 6 Using sort_union(i2,i3); Using where
explain select key1 from t0 where (key1 <=> null) or (key1 < 5) or
(key3=10) or (key4 <=> null);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 index_merge i1,i3,i4 i1,i3 4,4 NULL 5 Using where
1 SIMPLE t0 index_merge i1,i3,i4 i1,i3 4,4 NULL 5 Using sort_union(i1,i3); Using where
explain select * from t0 where
(key1 < 3 or key2 < 3) and (key3 < 4 or key4 < 4) and (key5 < 5 or key6 < 5);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 index_merge i1,i2,i3,i4,i5,i6 i1,i2 4,4 NULL 6 Using where
1 SIMPLE t0 index_merge i1,i2,i3,i4,i5,i6 i1,i2 4,4 NULL 6 Using sort_union(i1,i2); Using where
explain
select * from t0 where (key1 < 3 or key2 < 6) and (key1 < 7 or key3 < 4);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 index_merge i1,i2,i3 i1,i2 4,4 NULL 9 Using where
1 SIMPLE t0 index_merge i1,i2,i3 i1,i2 4,4 NULL 9 Using sort_union(i1,i2); Using where
select * from t0 where (key1 < 3 or key2 < 6) and (key1 < 7 or key3 < 4);
key1 key2 key3 key4 key5 key6 key7 key8
1 1 1 1 1 1 1 1023
......@@ -109,7 +109,7 @@ key1 key2 key3 key4 key5 key6 key7 key8
explain select * from t0 where
(key1 < 3 or key2 < 3) and (key3 < 4 or key4 < 4) and (key5 < 2 or key6 < 2);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 index_merge i1,i2,i3,i4,i5,i6 i1,i2 4,4 NULL 6 Using where
1 SIMPLE t0 index_merge i1,i2,i3,i4,i5,i6 i1,i2 4,4 NULL 6 Using sort_union(i1,i2); Using where
explain select * from t0 where
(key1 < 3 or key2 < 3) and (key3 < 100);
id select_type table type possible_keys key key_len ref rows Extra
......@@ -129,7 +129,7 @@ explain select * from t0 where
or
key1 < 7;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 index_merge i1,i2,i3 i1,i2 4,4 NULL 10 Using where
1 SIMPLE t0 index_merge i1,i2,i3 i1,i2 4,4 NULL 10 Using sort_union(i1,i2); Using where
select * from t0 where
((key1 < 4 or key2 < 4) and (key2 <5 or key3 < 4))
or
......@@ -146,25 +146,25 @@ explain select * from t0 where
or
((key5 < 5 or key6 < 6) and (key7 <7 or key8 < 4));
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 index_merge i1,i2,i3,i5,i6,i7,i8 i1,i2,i5,i6 4,4,4,4 NULL 19 Using where
1 SIMPLE t0 index_merge i1,i2,i3,i5,i6,i7,i8 i1,i2,i5,i6 4,4,4,4 NULL 19 Using sort_union(i1,i2,i5,i6); Using where
explain select * from t0 where
((key3 <5 or key5 < 4) and (key1 < 4 or key2 < 4))
or
((key7 <7 or key8 < 4) and (key5 < 5 or key6 < 6));
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 index_merge i1,i2,i3,i5,i6,i7,i8 i3,i5,i7,i8 4,4,4,4 NULL 21 Using where
1 SIMPLE t0 index_merge i1,i2,i3,i5,i6,i7,i8 i3,i5,i7,i8 4,4,4,4 NULL 21 Using sort_union(i3,i5,i7,i8); Using where
explain select * from t0 where
((key3 <5 or key5 < 4) and (key1 < 4 or key2 < 4))
or
((key3 <7 or key5 < 2) and (key5 < 5 or key6 < 6));
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 index_merge i1,i2,i3,i5,i6 i3,i5 4,4 NULL 11 Using where
1 SIMPLE t0 index_merge i1,i2,i3,i5,i6 i3,i5 4,4 NULL 11 Using sort_union(i3,i5); Using where
explain select * from t0 where
((key3 <5 or key5 < 4) and (key1 < 4 or key2 < 4))
or
(((key3 <7 and key7 < 6) or key5 < 2) and (key5 < 5 or key6 < 6));
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 index_merge i1,i2,i3,i5,i6,i7 i3,i5 4,4 NULL 11 Using where
1 SIMPLE t0 index_merge i1,i2,i3,i5,i6,i7 i3,i5 4,4 NULL 11 Using sort_union(i3,i5); Using where
explain select * from t0 where
((key3 <5 or key5 < 4) and (key1 < 4 or key2 < 4))
or
......@@ -176,7 +176,7 @@ explain select * from t0 force index(i1, i2, i3, i4, i5, i6 ) where
or
((key3 >=5 or key5 < 2) and (key5 < 5 or key6 < 6));
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 index_merge i1,i2,i3,i5,i6 i3,i5 0,4 NULL 1024 Using where
1 SIMPLE t0 index_merge i1,i2,i3,i5,i6 i3,i5 0,4 NULL 1024 Using sort_union(i3,i5); Using where
select * from t0 where key1 < 5 or key8 < 4 order by key1;
key1 key2 key3 key4 key5 key6 key7 key8
1 1 1 1 1 1 1 1023
......@@ -190,7 +190,7 @@ key1 key2 key3 key4 key5 key6 key7 key8
explain
select * from t0 where key1 < 5 or key8 < 4 order by key1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 index_merge i1,i8 i1,i8 4,4 NULL 9 Using where; Using filesort
1 SIMPLE t0 index_merge i1,i8 i1,i8 4,4 NULL 9 Using sort_union(i1,i8); Using where; Using filesort
create table t2 like t0;
insert into t2 select * from t0;
alter table t2 add index i1_3(key1, key3);
......@@ -200,7 +200,7 @@ alter table t2 drop index i2;
alter table t2 add index i321(key3, key2, key1);
explain select key3 from t2 where key1 = 100 or key2 = 100;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 index_merge i1_3,i2_3 i1_3,i2_3 4,4 NULL 2 Using where
1 SIMPLE t2 index_merge i1_3,i2_3 i1_3,i2_3 4,4 NULL 2 Using sort_union(i1_3,i2_3); Using where
explain select key3 from t2 where key1 <100 or key2 < 100;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 index i1_3,i2_3 i321 12 NULL 1024 Using where; Using index
......@@ -226,7 +226,7 @@ key1a key1b key2 key2_1 key2_2 key3
4 4 0 4 4 4
explain select * from t4 where key1a = 3 or key1b = 4;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t4 index_merge i1a,i1b i1a,i1b 4,4 NULL 2 Using where
1 SIMPLE t4 index_merge i1a,i1b i1a,i1b 4,4 NULL 2 Using sort_union(i1a,i1b); Using where
explain select * from t4 where key2 = 1 and (key2_1 = 1 or key3 = 5);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t4 ref i2_1,i2_2 i2_1 4 const 10 Using where
......@@ -241,7 +241,7 @@ insert into t1 select * from t0;
explain select * from t0 left join t1 on (t0.key1=t1.key1)
where t0.key1=3 or t0.key2=4;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 2 Using where
1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 2 Using union(i1,i2); Using where
1 SIMPLE t1 ref i1 i1 4 test.t0.key1 1
select * from t0 left join t1 on (t0.key1=t1.key1)
where t0.key1=3 or t0.key2=4;
......@@ -251,13 +251,13 @@ key1 key2 key3 key4 key5 key6 key7 key8 key1 key2 key3 key4 key5 key6 key7 key8
explain
select * from t0,t1 where (t0.key1=t1.key1) and ( t0.key1=3 or t0.key2=4);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 2 Using where
1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 2 Using union(i1,i2); Using where
1 SIMPLE t1 ref i1 i1 4 test.t0.key1 1
explain
select * from t0,t1 where (t0.key1=t1.key1) and
(t0.key1=3 or t0.key2=4) and t1.key1<200;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 2 Using where
1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 2 Using union(i1,i2); Using where
1 SIMPLE t1 ref i1 i1 4 test.t0.key1 1 Using where
explain
select * from t0,t1 where (t0.key1=t1.key1) and
......@@ -269,7 +269,7 @@ explain select * from t0,t1 where t0.key1 = 5 and
(t1.key1 = t0.key1 or t1.key8 = t0.key1);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 ref i1 i1 4 const 1 Using where
1 SIMPLE t1 index_merge i1,i8 i1,i8 4,4 NULL 2 Using where
1 SIMPLE t1 index_merge i1,i8 i1,i8 4,4 NULL 2 Using union(i1,i8); Using where
explain select * from t0,t1 where t0.key1 < 3 and
(t1.key1 = t0.key1 or t1.key8 = t0.key1);
id select_type table type possible_keys key key_len ref rows Extra
......@@ -278,13 +278,13 @@ id select_type table type possible_keys key key_len ref rows Extra
explain select * from t1 where key1=3 or key2=4
union select * from t1 where key1<4 or key3=5;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 index_merge i1,i2 i1,i2 4,4 NULL 2 Using where
2 UNION t1 index_merge i1,i3 i1,i3 4,4 NULL 5 Using where
1 PRIMARY t1 index_merge i1,i2 i1,i2 4,4 NULL 2 Using union(i1,i2); Using where
2 UNION t1 index_merge i1,i3 i1,i3 4,4 NULL 5 Using sort_union(i1,i3); Using where
NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL
explain select * from (select * from t1 where key1 = 3 or key2 =3) as Z where key8 >5;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 1
2 DERIVED t1 index_merge i1,i2 i1,i2 4,4 NULL 2 Using where
2 DERIVED t1 index_merge i1,i2 i1,i2 4,4 NULL 2 Using union(i1,i2); Using where
create table t3 like t0;
insert into t3 select * from t0;
alter table t3 add key9 int not null, add index i9(key9);
......@@ -297,7 +297,7 @@ key1=1 or key2=2 or key3=3 or key4=4 or
key5=5 or key6=6 or key7=7 or key8=8 or
key9=9 or keyA=10 or keyB=11 or keyC=12;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t3 index_merge i1,i2,i3,i4,i5,i6,i7,i8,i9,iA,iB,iC i1,i2,i3,i4,i5,i6,i7,i8,i9,iA,iB,iC 4,4,4,4,4,4,4,4,4,4,4,4 NULL 12 Using where
1 SIMPLE t3 index_merge i1,i2,i3,i4,i5,i6,i7,i8,i9,iA,iB,iC i1,i2,i3,i4,i5,i6,i7,i8,i9,iA,iB,iC 4,4,4,4,4,4,4,4,4,4,4,4 NULL 12 Using union(i1,i2,i3,i4,i5,i6,i7,i8,i9,iA,iB,iC); Using where
select * from t3 where
key1=1 or key2=2 or key3=3 or key4=4 or
key5=5 or key6=6 or key7=7 or key8=8 or
......@@ -317,7 +317,7 @@ key1 key2 key3 key4 key5 key6 key7 key8 key9 keyA keyB keyC
1016 1016 1016 1016 1016 1016 1016 8 1016 1016 1016 1016
explain select * from t0 where key1 < 3 or key2 < 4;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 7 Using where
1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 7 Using sort_union(i1,i2); Using where
select * from t0 where key1 < 3 or key2 < 4;
key1 key2 key3 key4 key5 key6 key7 key8
1 1 1 1 1 1 1 1023
......
......@@ -8,7 +8,7 @@ INDEX i2(key2)
) engine=innodb;
explain select * from t1 where key1 < 5 or key2 > 197;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge i1,i2 i1,i2 4,4 NULL 8 Using where
1 SIMPLE t1 index_merge i1,i2 i1,i2 4,4 NULL 8 Using sort_union(i1,i2); Using where
select * from t1 where key1 < 5 or key2 > 197;
key1 key2
0 200
......@@ -18,7 +18,7 @@ key1 key2
4 196
explain select * from t1 where key1 < 3 or key2 > 195;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge i1,i2 i1,i2 4,4 NULL 8 Using where
1 SIMPLE t1 index_merge i1,i2 i1,i2 4,4 NULL 8 Using sort_union(i1,i2); Using where
select * from t1 where key1 < 3 or key2 > 195;
key1 key2
0 200
......@@ -34,7 +34,7 @@ update t1 set str1='aaa', str2='bbb', str3=concat(key2, '-', key1 div 2, '_' ,if
alter table t1 add primary key (str1, zeroval, str2, str3);
explain select * from t1 where key1 < 5 or key2 > 197;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge i1,i2 i1,i2 4,4 NULL 8 Using where
1 SIMPLE t1 index_merge i1,i2 i1,i2 4,4 NULL 8 Using sort_union(i1,i2); Using where
select * from t1 where key1 < 5 or key2 > 197;
key1 key2 str1 zeroval str2 str3
4 196 aaa 0 bbb 196-2_a
......@@ -44,7 +44,7 @@ key1 key2 str1 zeroval str2 str3
0 200 aaa 0 bbb 200-0_a
explain select * from t1 where key1 < 3 or key2 > 195;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge i1,i2 i1,i2 4,4 NULL 8 Using where
1 SIMPLE t1 index_merge i1,i2 i1,i2 4,4 NULL 8 Using sort_union(i1,i2); Using where
select * from t1 where key1 < 3 or key2 > 195;
key1 key2 str1 zeroval str2 str3
4 196 aaa 0 bbb 196-2_a
......
drop table if exists t0,t1,t2;
select count(*) from t1;
count(*)
64801
explain select key1,key2 from t1 where key1=100 and key2=100;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge key1,key2 key1,key2 5,5 NULL 3 Using intersect(key1,key2); Using where; Using index
select key1,key2 from t1 where key1=100 and key2=100;
key1 key2
100 100
explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge key1,key2,key3,key4 key1,key2,key3,key4 5,5,5,5 NULL 8 Using union(intersect(key1,key2),intersect(key3,key4)); Using where
select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
key1 key2 key3 key4 filler1
100 100 100 100 key1-key2-key3-key4
insert into t1 (key1, key2, key3, key4, filler1) values (100, 100, -1, -1, 'key1-key2');
insert into t1 (key1, key2, key3, key4, filler1) values (-1, -1, 100, 100, 'key4-key3');
explain select key1,key2,filler1 from t1 where key1=100 and key2=100;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge key1,key2 key1,key2 5,5 NULL 3 Using intersect(key1,key2); Using where
select key1,key2,filler1 from t1 where key1=100 and key2=100;
key1 key2 filler1
100 100 key1-key2-key3-key4
100 100 key1-key2
explain select key1,key2 from t1 where key1=100 and key2=100;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge key1,key2 key1,key2 5,5 NULL 3 Using intersect(key1,key2); Using where; Using index
select key1,key2 from t1 where key1=100 and key2=100;
key1 key2
100 100
100 100
explain select key1,key2,key3,key4 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge key1,key2,key3,key4 key1,key2,key3,key4 5,5,5,5 NULL 8 Using union(intersect(key1,key2),intersect(key3,key4)); Using where
select key1,key2,key3,key4 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
key1 key2 key3 key4
100 100 100 100
100 100 -1 -1
-1 -1 100 100
explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge key1,key2,key3,key4 key1,key2,key3,key4 5,5,5,5 NULL 8 Using union(intersect(key1,key2),intersect(key3,key4)); Using where
select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
key1 key2 key3 key4 filler1
100 100 100 100 key1-key2-key3-key4
100 100 -1 -1 key1-key2
-1 -1 100 100 key4-key3
explain select key1,key2,key3 from t1 where key1=100 and key2=100 and key3=100;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge key1,key2,key3 key1,key2,key3 5,5,5 NULL 1 Using intersect(key1,key2,key3); Using where; Using index
select key1,key2,key3 from t1 where key1=100 and key2=100 and key3=100;
key1 key2 key3
100 100 100
insert into t1 (key1,key2,key3,key4,filler1) values (101,101,101,101, 'key1234-101');
explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=101;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge key1,key2,key3 key1,key2,key3 5,5,5 NULL 5 Using union(intersect(key1,key2),key3); Using where
select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=101;
key1 key2 key3 key4 filler1
100 100 100 100 key1-key2-key3-key4
100 100 -1 -1 key1-key2
101 101 101 101 key1234-101
select key1,key2, filler1 from t1 where key1=100 and key2=100;
key1 key2 filler1
100 100 key1-key2-key3-key4
100 100 key1-key2
update t1 set filler1='to be deleted' where key1=100 and key2=100;
update t1 set key1=200,key2=200 where key1=100 and key2=100;
delete from t1 where key1=200 and key2=200;
select key1,key2,filler1 from t1 where key2=100 and key2=200;
key1 key2 filler1
explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge key1,key2,key3,key4 key1,key2,key3,key4 5,5,5,5 NULL 8 Using union(intersect(key1,key2),intersect(key3,key4)); Using where
select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
key1 key2 key3 key4 filler1
-1 -1 100 100 key4-key3
delete from t1 where key3=100 and key4=100;
explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge key1,key2,key3,key4 key1,key2,key3,key4 5,5,5,5 NULL 8 Using union(intersect(key1,key2),intersect(key3,key4)); Using where
select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
key1 key2 key3 key4 filler1
explain select key1,key2 from t1 where key1=100 and key2=100;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge key1,key2 key1,key2 5,5 NULL 3 Using intersect(key1,key2); Using where; Using index
select key1,key2 from t1 where key1=100 and key2=100;
key1 key2
insert into t1 (key1, key2, key3, key4, filler1) values (100, 100, 200, 200,'key1-key2-key3-key4-1');
insert into t1 (key1, key2, key3, key4, filler1) values (100, 100, 200, 200,'key1-key2-key3-key4-2');
insert into t1 (key1, key2, key3, key4, filler1) values (100, 100, 200, 200,'key1-key2-key3-key4-3');
explain select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge key1,key2,key3,key4 key3,key1,key2,key4 5,5,5,5 NULL 16 Using union(key3,intersect(key1,key2),key4); Using where
select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200;
key1 key2 key3 key4 filler1
100 100 200 200 key1-key2-key3-key4-3
100 100 200 200 key1-key2-key3-key4-2
100 100 200 200 key1-key2-key3-key4-1
insert into t1 (key1, key2, key3, key4, filler1) values (-1, -1, -1, 200,'key4');
explain select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge key1,key2,key3,key4 key3,key1,key2,key4 5,5,5,5 NULL 18 Using union(key3,intersect(key1,key2),key4); Using where
select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200;
key1 key2 key3 key4 filler1
100 100 200 200 key1-key2-key3-key4-3
100 100 200 200 key1-key2-key3-key4-2
100 100 200 200 key1-key2-key3-key4-1
-1 -1 -1 200 key4
insert into t1 (key1, key2, key3, key4, filler1) values (-1, -1, 200, -1,'key3');
explain select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge key1,key2,key3,key4 key3,key1,key2,key4 5,5,5,5 NULL 20 Using union(key3,intersect(key1,key2),key4); Using where
select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200;
key1 key2 key3 key4 filler1
100 100 200 200 key1-key2-key3-key4-3
100 100 200 200 key1-key2-key3-key4-2
100 100 200 200 key1-key2-key3-key4-1
-1 -1 -1 200 key4
-1 -1 200 -1 key3
explain select * from t1 where st_a=1 and st_b=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,st_a,stb_swt1a_2b,stb_swt1b,st_b st_a,st_b 4,4 NULL 2508 Using intersect(st_a,st_b); Using where
explain select st_a,st_b from t1 where st_a=1 and st_b=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,st_a,stb_swt1a_2b,stb_swt1b,st_b st_a,st_b 4,4 NULL 2508 Using intersect(st_a,st_b); Using where; Using index
explain select st_a from t1 ignore index (st_a) where st_a=1 and st_b=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,stb_swt1a_2b,stb_swt1b,st_b st_b 4 const 14720 Using where
explain select * from t1 where st_a=1 and swt1a=1 and swt2a=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,st_a sta_swt12a 12 const,const,const 958 Using where
explain select * from t1 where st_b=1 and swt1b=1 and swt2b=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref stb_swt1a_2b,stb_swt1b,st_b stb_swt1b 8 const,const 3757 Using where
explain select * from t1 where st_a=1 and swt1a=1 and swt2a=1 and st_b=1 and swt1b=1 and swt2b=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,st_a,stb_swt1a_2b,stb_swt1b,st_b sta_swt12a,stb_swt1a_2b 12,12 NULL 42 Using intersect(sta_swt12a,stb_swt1a_2b); Using where
explain select * from t1 ignore index (sta_swt21a, stb_swt1a_2b)
where st_a=1 and swt1a=1 and swt2a=1 and st_b=1 and swt1b=1 and swt2b=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge sta_swt12a,sta_swt1a,sta_swt2a,st_a,stb_swt1b,st_b sta_swt12a,stb_swt1b 12,8 NULL 42 Using intersect(sta_swt12a,stb_swt1b); Using where
explain select * from t1 ignore index (sta_swt21a, sta_swt12a, stb_swt1a_2b)
where st_a=1 and swt1a=1 and swt2a=1 and st_b=1 and swt1b=1 and swt2b=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge sta_swt1a,sta_swt2a,st_a,stb_swt1b,st_b sta_swt1a,sta_swt2a,stb_swt1b 8,8,8 NULL 41 Using intersect(sta_swt1a,sta_swt2a,stb_swt1b); Using where
explain select * from t1 ignore index (sta_swt21a, sta_swt12a, stb_swt1a_2b, stb_swt1b)
where st_a=1 and swt1a=1 and swt2a=1 and st_b=1 and swt1b=1 and swt2b=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge sta_swt1a,sta_swt2a,st_a,st_b sta_swt1a,sta_swt2a,st_b 8,8,4 NULL 159 Using intersect(sta_swt1a,sta_swt2a,st_b); Using where
explain select * from t1
where st_a=1 and swt1a=1 and swt2a=1 and st_b=1 and swt1b=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,st_a,stb_swt1a_2b,stb_swt1b,st_b sta_swt12a,stb_swt1a_2b 12,12 NULL 42 Using intersect(sta_swt12a,stb_swt1a_2b); Using where
explain select * from t1
where st_a=1 and swt1a=1 and st_b=1 and swt1b=1 and swt1b=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,st_a,stb_swt1a_2b,stb_swt1b,st_b sta_swt1a,stb_swt1b 8,8 NULL 163 Using intersect(sta_swt1a,stb_swt1b); Using where
explain select st_a from t1
where st_a=1 and swt1a=1 and st_b=1 and swt1b=1 and swt1b=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,st_a,stb_swt1a_2b,stb_swt1b,st_b sta_swt1a,stb_swt1b 8,8 NULL 163 Using intersect(sta_swt1a,stb_swt1b); Using where; Using index
explain select st_a from t1
where st_a=1 and swt1a=1 and st_b=1 and swt1b=1 and swt1b=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,st_a,stb_swt1a_2b,stb_swt1b,st_b sta_swt1a,stb_swt1b 8,8 NULL 163 Using intersect(sta_swt1a,stb_swt1b); Using where; Using index
drop table t0,t1;
create table t2 (
a char(10),
b char(10),
filler1 char(255),
filler2 char(255),
key(a(5)),
key(b(5))
);
select count(a) from t2 where a='BBBBBBBB';
count(a)
4
select count(a) from t2 where b='BBBBBBBB';
count(a)
4
explain select count(a) from t2 where a='AAAAAAAA' and b='AAAAAAAA';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ref a,b a 6 const 4 Using where
select count(a) from t2 where a='AAAAAAAA' and b='AAAAAAAA';
count(a)
4
select count(a) from t2 ignore index(a,b) where a='AAAAAAAA' and b='AAAAAAAA';
count(a)
4
insert into t2 values ('ab', 'ab', 'uh', 'oh');
explain select a from t2 where a='ab';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ref a a 6 const 1 Using where
drop table t2;
drop table if exists t1;
create table t1
(
pk1 int not null,
pk2 int not null,
key1 int not null,
key2 int not null,
pktail1ok int not null,
pktail2ok int not null,
pktail3bad int not null,
pktail4bad int not null,
pktail5bad int not null,
pk2copy int not null,
badkey int not null,
filler1 char (200),
filler2 char (200),
key (key1),
key (key2),
/* keys with tails from CPK members */
key (pktail1ok, pk1),
key (pktail2ok, pk1, pk2),
key (pktail3bad, pk2, pk1),
key (pktail4bad, pk1, pk2copy),
key (pktail5bad, pk1, pk2, pk2copy),
primary key (pk1, pk2)
) engine=innodb;
explain select * from t1 where pk1 = 1 and pk2 < 80 and key1=0;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref PRIMARY,key1 PRIMARY 4 const 1 Using where
select * from t1 where pk1 = 1 and pk2 < 80 and key1=0;
pk1 pk2 key1 key2 pktail1ok pktail2ok pktail3bad pktail4bad pktail5bad pk2copy badkey filler1 filler2
1 10 0 0 0 0 0 0 0 10 0 filler-data-10 filler2
1 11 0 0 0 0 0 0 0 11 0 filler-data-11 filler2
1 12 0 0 0 0 0 0 0 12 0 filler-data-12 filler2
1 13 0 0 0 0 0 0 0 13 0 filler-data-13 filler2
1 14 0 0 0 0 0 0 0 14 0 filler-data-14 filler2
1 15 0 0 0 0 0 0 0 15 0 filler-data-15 filler2
1 16 0 0 0 0 0 0 0 16 0 filler-data-16 filler2
1 17 0 0 0 0 0 0 0 17 0 filler-data-17 filler2
1 18 0 0 0 0 0 0 0 18 0 filler-data-18 filler2
1 19 0 0 0 0 0 0 0 19 0 filler-data-19 filler2
explain select pk1,pk2 from t1 where key1 = 10 and key2=10 and 2*pk1+1 < 2*96+1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge key1,key2 key1,key2 4,4 NULL 1 Using intersect(key1,key2); Using where; Using index
select pk1,pk2 from t1 where key1 = 10 and key2=10 and 2*pk1+1 < 2*96+1;
pk1 pk2
95 50
95 51
95 52
95 53
95 54
95 55
95 56
95 57
95 58
95 59
explain select * from t1 where badkey=1 and key1=10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref key1 key1 4 const 101 Using where
explain select * from t1 where pk1 < 7500 and key1 = 10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge PRIMARY,key1 key1,PRIMARY 4,4 NULL 38 Using intersect(key1,PRIMARY); Using where
explain select * from t1 where pktail1ok=1 and key1=10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge key1,pktail1ok key1,pktail1ok 4,4 NULL 1 Using intersect(key1,pktail1ok); Using where
explain select * from t1 where pktail2ok=1 and key1=10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge key1,pktail2ok key1,pktail2ok 4,4 NULL 1 Using intersect(key1,pktail2ok); Using where
select ' The following is actually a deficiency, it uses sort_union currently:' as 'note:';
note:
The following is actually a deficiency, it uses sort_union currently:
explain select * from t1 where (pktail2ok=1 and pk1< 50000) or key1=10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge PRIMARY,key1,pktail2ok pktail2ok,key1 8,4 NULL 199 Using sort_union(pktail2ok,key1); Using where
explain select * from t1 where pktail3bad=1 and key1=10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref key1,pktail3bad pktail3bad 4 const 98 Using where
explain select * from t1 where pktail4bad=1 and key1=10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref key1,pktail4bad pktail4bad 4 const 99 Using where
explain select * from t1 where pktail5bad=1 and key1=10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref key1,pktail5bad pktail5bad 4 const 99 Using where
explain select pk1,pk2,key1,key2 from t1 where key1 = 10 and key2=10 limit 10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge key1,key2 key1,key2 4,4 NULL 1 Using intersect(key1,key2); Using where; Using index
select pk1,pk2,key1,key2 from t1 where key1 = 10 and key2=10 limit 10;
pk1 pk2 key1 key2
95 50 10 10
95 51 10 10
95 52 10 10
95 53 10 10
95 54 10 10
95 55 10 10
95 56 10 10
95 57 10 10
95 58 10 10
95 59 10 10
drop table t1;
drop table if exists t1, t2, t3,t4;
create table t1 (
pk1 int not NULL,
key1 int(11),
key2 int(11),
PRIMARY KEY (pk1),
KEY key1 (key1),
KEY key2 (key2)
) engine=bdb;
insert into t1 values (-5, 1, 1),
(-100, 1, 1),
(3, 1, 1),
(0, 1, 1),
(10, 1, 1);
explain select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge key1,key2 key1,key2 5,5 NULL 5 Using sort_union(key1,key2); Using where
select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
pk1 key1 key2
-100 1 1
-5 1 1
0 1 1
3 1 1
10 1 1
drop table t1;
create table t1 (
pk1 int unsigned not NULL,
key1 int(11),
key2 int(11),
PRIMARY KEY (pk1),
KEY key1 (key1),
KEY key2 (key2)
) engine=bdb;
insert into t1 values (0, 1, 1),
(0xFFFFFFFF, 1, 1),
(0xFFFFFFFE, 1, 1),
(1, 1, 1),
(2, 1, 1);
select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
pk1 key1 key2
0 1 1
1 1 1
2 1 1
4294967294 1 1
4294967295 1 1
drop table t1;
create table t1 (
pk1 char(4) not NULL,
key1 int(11),
key2 int(11),
PRIMARY KEY (pk1),
KEY key1 (key1),
KEY key2 (key2)
) engine=bdb collate latin2_general_ci;
insert into t1 values ('a1', 1, 1),
('b2', 1, 1),
('A3', 1, 1),
('B4', 1, 1);
select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
pk1 key1 key2
a1 1 1
A3 1 1
b2 1 1
B4 1 1
drop table t1;
create table t1 (
pk1 int not NULL,
pk2 char(4) not NULL collate latin1_german1_ci,
pk3 char(4) not NULL collate latin1_bin,
key1 int(11),
key2 int(11),
PRIMARY KEY (pk1,pk2,pk3),
KEY key1 (key1),
KEY key2 (key2)
) engine=bdb;
insert into t1 values
(1, 'u', 'u', 1, 1),
(1, 'u', char(0xEC), 1, 1),
(1, 'u', 'x', 1, 1);
insert ignore into t1 select pk1, char(0xEC), pk3, key1, key2 from t1;
insert ignore into t1 select pk1, 'x', pk3, key1, key2 from t1 where pk2='u';
insert ignore into t1 select 2, pk2, pk3, key1, key2 from t1;
select * from t1;
pk1 pk2 pk3 key1 key2
1 u 1 1
1 x 1 1
1 1 1
1 u u 1 1
1 u x 1 1
1 u 1 1
1 x u 1 1
1 x x 1 1
1 x 1 1
2 u 1 1
2 x 1 1
2 1 1
2 u u 1 1
2 u x 1 1
2 u 1 1
2 x u 1 1
2 x x 1 1
2 x 1 1
select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
pk1 pk2 pk3 key1 key2
1 u 1 1
1 x 1 1
1 1 1
1 u u 1 1
1 u x 1 1
1 u 1 1
1 x u 1 1
1 x x 1 1
1 x 1 1
2 u 1 1
2 x 1 1
2 1 1
2 u u 1 1
2 u x 1 1
2 u 1 1
2 x u 1 1
2 x x 1 1
2 x 1 1
alter table t1 drop primary key;
select * from t1;
pk1 pk2 pk3 key1 key2
1 u 1 1
1 x 1 1
1 1 1
1 u u 1 1
1 u x 1 1
1 u 1 1
1 x u 1 1
1 x x 1 1
1 x 1 1
2 u 1 1
2 x 1 1
2 1 1
2 u u 1 1
2 u x 1 1
2 u 1 1
2 x u 1 1
2 x x 1 1
2 x 1 1
select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
pk1 pk2 pk3 key1 key2
1 u 1 1
1 x 1 1
1 1 1
1 u u 1 1
1 u x 1 1
1 u 1 1
1 x u 1 1
1 x x 1 1
1 x 1 1
2 u 1 1
2 x 1 1
2 1 1
2 u u 1 1
2 u x 1 1
2 u 1 1
2 x u 1 1
2 x x 1 1
2 x 1 1
drop table t1;
create table t1 (
pk1 varchar(8) NOT NULL default '',
pk2 varchar(4) NOT NULL default '',
key1 int(11),
key2 int(11),
primary key(pk1, pk2),
KEY key1 (key1),
KEY key2 (key2)
) engine=bdb;
insert into t1 values ('','empt',2,2),
('a','a--a',2,2),
('bb','b--b',2,2),
('ccc','c--c',2,2),
('dddd','d--d',2,2);
select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
pk1 pk2 key1 key2
empt 2 2
a a--a 2 2
bb b--b 2 2
ccc c--c 2 2
dddd d--d 2 2
drop table t1;
drop table if exists t1, t2, t3,t4;
create table t1 (
pk1 int not NULL,
key1 int(11),
key2 int(11),
PRIMARY KEY (pk1),
KEY key1 (key1),
KEY key2 (key2)
) engine=innodb;
insert into t1 values (-5, 1, 1),
(-100, 1, 1),
(3, 1, 1),
(0, 1, 1),
(10, 1, 1);
explain select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge key1,key2 key1,key2 5,5 NULL 6 Using sort_union(key1,key2); Using where
select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
pk1 key1 key2
-100 1 1
-5 1 1
0 1 1
3 1 1
10 1 1
drop table t1;
create table t1 (
pk1 int unsigned not NULL,
key1 int(11),
key2 int(11),
PRIMARY KEY (pk1),
KEY key1 (key1),
KEY key2 (key2)
) engine=innodb;
insert into t1 values (0, 1, 1),
(0xFFFFFFFF, 1, 1),
(0xFFFFFFFE, 1, 1),
(1, 1, 1),
(2, 1, 1);
select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
pk1 key1 key2
0 1 1
1 1 1
2 1 1
4294967294 1 1
4294967295 1 1
drop table t1;
create table t1 (
pk1 char(4) not NULL,
key1 int(11),
key2 int(11),
PRIMARY KEY (pk1),
KEY key1 (key1),
KEY key2 (key2)
) engine=innodb collate latin2_general_ci;
insert into t1 values ('a1', 1, 1),
('b2', 1, 1),
('A3', 1, 1),
('B4', 1, 1);
select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
pk1 key1 key2
a1 1 1
A3 1 1
b2 1 1
B4 1 1
drop table t1;
create table t1 (
pk1 int not NULL,
pk2 char(4) not NULL collate latin1_german1_ci,
pk3 char(4) not NULL collate latin1_bin,
key1 int(11),
key2 int(11),
PRIMARY KEY (pk1,pk2,pk3),
KEY key1 (key1),
KEY key2 (key2)
) engine=innodb;
insert into t1 values
(1, 'u', 'u', 1, 1),
(1, 'u', char(0xEC), 1, 1),
(1, 'u', 'x', 1, 1);
insert ignore into t1 select pk1, char(0xEC), pk3, key1, key2 from t1;
insert ignore into t1 select pk1, 'x', pk3, key1, key2 from t1 where pk2='u';
insert ignore into t1 select 2, pk2, pk3, key1, key2 from t1;
select * from t1;
pk1 pk2 pk3 key1 key2
1 u 1 1
1 x 1 1
1 1 1
1 u u 1 1
1 u x 1 1
1 u 1 1
1 x u 1 1
1 x x 1 1
1 x 1 1
2 u 1 1
2 x 1 1
2 1 1
2 u u 1 1
2 u x 1 1
2 u 1 1
2 x u 1 1
2 x x 1 1
2 x 1 1
select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
pk1 pk2 pk3 key1 key2
1 u 1 1
1 x 1 1
1 1 1
1 u u 1 1
1 u x 1 1
1 u 1 1
1 x u 1 1
1 x x 1 1
1 x 1 1
2 u 1 1
2 x 1 1
2 1 1
2 u u 1 1
2 u x 1 1
2 u 1 1
2 x u 1 1
2 x x 1 1
2 x 1 1
alter table t1 drop primary key;
select * from t1;
pk1 pk2 pk3 key1 key2
1 u 1 1
1 x 1 1
1 1 1
1 u u 1 1
1 u x 1 1
1 u 1 1
1 x u 1 1
1 x x 1 1
1 x 1 1
2 u 1 1
2 x 1 1
2 1 1
2 u u 1 1
2 u x 1 1
2 u 1 1
2 x u 1 1
2 x x 1 1
2 x 1 1
select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
pk1 pk2 pk3 key1 key2
1 u 1 1
1 x 1 1
1 1 1
1 u u 1 1
1 u x 1 1
1 u 1 1
1 x u 1 1
1 x x 1 1
1 x 1 1
2 u 1 1
2 x 1 1
2 1 1
2 u u 1 1
2 u x 1 1
2 u 1 1
2 x u 1 1
2 x x 1 1
2 x 1 1
drop table t1;
create table t1 (
pk1 varchar(8) NOT NULL default '',
pk2 varchar(4) NOT NULL default '',
key1 int(11),
key2 int(11),
primary key(pk1, pk2),
KEY key1 (key1),
KEY key2 (key2)
) engine=innodb;
insert into t1 values ('','empt',2,2),
('a','a--a',2,2),
('bb','b--b',2,2),
('ccc','c--c',2,2),
('dddd','d--d',2,2);
select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
pk1 pk2 key1 key2
empt 2 2
a a--a 2 2
bb b--b 2 2
ccc c--c 2 2
dddd d--d 2 2
drop table t1;
#
# ROR-index_merge tests.
#
--disable_warnings
drop table if exists t0,t1,t2;
--enable_warnings
--disable_query_log
create table t1
(
/* Field names reflect value(rowid) distribution, st=STairs, swt= SaWTooth */
st_a int not null,
swt1a int not null,
swt2a int not null,
st_b int not null,
swt1b int not null,
swt2b int not null,
/* fields/keys for row retrieval tests */
key1 int,
key2 int,
key3 int,
key4 int,
/* make rows much bigger then keys */
filler1 char (200),
filler2 char (200),
filler3 char (200),
filler4 char (200),
filler5 char (200),
filler6 char (200),
/* order of keys is important */
key sta_swt12a(st_a,swt1a,swt2a),
key sta_swt1a(st_a,swt1a),
key sta_swt2a(st_a,swt2a),
key sta_swt21a(st_a,swt2a,swt1a),
key st_a(st_a),
key stb_swt1a_2b(st_b,swt1b,swt2a),
key stb_swt1b(st_b,swt1b),
key st_b(st_b),
key(key1),
key(key2),
key(key3),
key(key4)
) ;
# Fill table
create table t0 as select * from t1;
let $cnt=1000;
while ($cnt)
{
eval insert into t0 values (1, 2, 3, 1, 2, 3, 0, 0, 0, 0, 'data1', 'data2', 'data3', 'data4', 'data5', 'data6');
dec $cnt;
}
alter table t1 disable keys;
let $1=4;
while ($1)
{
let $2=4;
while ($2)
{
let $3=4;
while ($3)
{
eval insert into t1 select $1, $2, $3, $1 ,$2, $3, key1, key2, key3, key4, filler1, filler2, filler3, filler4, filler5, filler6 from t0;
dec $3;
}
dec $2;
}
dec $1;
}
# Row retrieval tests
# -1 is used for values 'out of any range we are using'
# insert enough rows for index intersection to be used for (key1,key2)
insert into t1 (key1, key2, key3, key4, filler1) values (100, 100, 100, 100,'key1-key2-key3-key4');
let $cnt=400;
while ($cnt)
{
eval insert into t1 (key1, key2, key3, key4, filler1) values (100, -1, 100, -1,'key1-key3');
dec $cnt;
}
let $cnt=400;
while ($cnt)
{
eval insert into t1 (key1, key2, key3, key4, filler1) values (-1, 100, -1, 100,'key2-key4');
dec $cnt;
}
alter table t1 enable keys;
--enable_query_log
select count(*) from t1;
# One row results tests for cases where a single row matches all conditions
explain select key1,key2 from t1 where key1=100 and key2=100;
select key1,key2 from t1 where key1=100 and key2=100;
explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
# Several-rows results
insert into t1 (key1, key2, key3, key4, filler1) values (100, 100, -1, -1, 'key1-key2');
insert into t1 (key1, key2, key3, key4, filler1) values (-1, -1, 100, 100, 'key4-key3');
# ROR-intersection, not covering
explain select key1,key2,filler1 from t1 where key1=100 and key2=100;
select key1,key2,filler1 from t1 where key1=100 and key2=100;
# ROR-intersection, covering
explain select key1,key2 from t1 where key1=100 and key2=100;
select key1,key2 from t1 where key1=100 and key2=100;
# ROR-union of ROR-intersections
explain select key1,key2,key3,key4 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
select key1,key2,key3,key4 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
# 3-way ROR-intersection
explain select key1,key2,key3 from t1 where key1=100 and key2=100 and key3=100;
select key1,key2,key3 from t1 where key1=100 and key2=100 and key3=100;
# ROR-union(ROR-intersection, ROR-range)
insert into t1 (key1,key2,key3,key4,filler1) values (101,101,101,101, 'key1234-101');
explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=101;
select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=101;
# Run some ROR updates/deletes
select key1,key2, filler1 from t1 where key1=100 and key2=100;
update t1 set filler1='to be deleted' where key1=100 and key2=100;
update t1 set key1=200,key2=200 where key1=100 and key2=100;
delete from t1 where key1=200 and key2=200;
select key1,key2,filler1 from t1 where key2=100 and key2=200;
# ROR-union(ROR-intersection) with one of ROR-intersection giving empty
# results
explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
delete from t1 where key3=100 and key4=100;
# ROR-union with all ROR-intersections giving empty results
explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
# ROR-intersection with empty result
explain select key1,key2 from t1 where key1=100 and key2=100;
select key1,key2 from t1 where key1=100 and key2=100;
# ROR-union tests with various cases.
# All scans returning duplicate rows:
insert into t1 (key1, key2, key3, key4, filler1) values (100, 100, 200, 200,'key1-key2-key3-key4-1');
insert into t1 (key1, key2, key3, key4, filler1) values (100, 100, 200, 200,'key1-key2-key3-key4-2');
insert into t1 (key1, key2, key3, key4, filler1) values (100, 100, 200, 200,'key1-key2-key3-key4-3');
explain select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200;
select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200;
insert into t1 (key1, key2, key3, key4, filler1) values (-1, -1, -1, 200,'key4');
explain select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200;
select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200;
insert into t1 (key1, key2, key3, key4, filler1) values (-1, -1, 200, -1,'key3');
explain select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200;
select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200;
##
## Optimizer tests
##
# Check that the shortest key is used for ROR-intersection, covering and non-covering.
explain select * from t1 where st_a=1 and st_b=1;
explain select st_a,st_b from t1 where st_a=1 and st_b=1;
# Check if "ingore index" syntax works
explain select st_a from t1 ignore index (st_a) where st_a=1 and st_b=1;
# Do many tests
# Check that keys that don't improve selectivity are skipped.
#
explain select * from t1 where st_a=1 and swt1a=1 and swt2a=1;
explain select * from t1 where st_b=1 and swt1b=1 and swt2b=1;
explain select * from t1 where st_a=1 and swt1a=1 and swt2a=1 and st_b=1 and swt1b=1 and swt2b=1;
explain select * from t1 ignore index (sta_swt21a, stb_swt1a_2b)
where st_a=1 and swt1a=1 and swt2a=1 and st_b=1 and swt1b=1 and swt2b=1;
explain select * from t1 ignore index (sta_swt21a, sta_swt12a, stb_swt1a_2b)
where st_a=1 and swt1a=1 and swt2a=1 and st_b=1 and swt1b=1 and swt2b=1;
explain select * from t1 ignore index (sta_swt21a, sta_swt12a, stb_swt1a_2b, stb_swt1b)
where st_a=1 and swt1a=1 and swt2a=1 and st_b=1 and swt1b=1 and swt2b=1;
explain select * from t1
where st_a=1 and swt1a=1 and swt2a=1 and st_b=1 and swt1b=1;
explain select * from t1
where st_a=1 and swt1a=1 and st_b=1 and swt1b=1 and swt1b=1;
explain select st_a from t1
where st_a=1 and swt1a=1 and st_b=1 and swt1b=1 and swt1b=1;
explain select st_a from t1
where st_a=1 and swt1a=1 and st_b=1 and swt1b=1 and swt1b=1;
drop table t0,t1;
# 'Partially' covered fields test
create table t2 (
a char(10),
b char(10),
filler1 char(255),
filler2 char(255),
key(a(5)),
key(b(5))
);
--disable_query_log
let $1=8;
while ($1)
{
eval insert into t2 values (repeat(char($1+64), 8),repeat(char($1+64), 8),'filler1', 'filler2');
dec $1;
}
insert into t2 select * from t2;
insert into t2 select * from t2;
--enable_query_log
# The table row buffer is reused. Fill it with rows that don't match.
select count(a) from t2 where a='BBBBBBBB';
select count(a) from t2 where b='BBBBBBBB';
# BUG#1:
explain select count(a) from t2 where a='AAAAAAAA' and b='AAAAAAAA';
select count(a) from t2 where a='AAAAAAAA' and b='AAAAAAAA';
select count(a) from t2 ignore index(a,b) where a='AAAAAAAA' and b='AAAAAAAA';
insert into t2 values ('ab', 'ab', 'uh', 'oh');
explain select a from t2 where a='ab';
drop table t2;
#
# Clustered PK ROR-index_merge tests
#
-- source include/have_innodb.inc
--disable_warnings
drop table if exists t1;
--enable_warnings
create table t1
(
pk1 int not null,
pk2 int not null,
key1 int not null,
key2 int not null,
pktail1ok int not null,
pktail2ok int not null,
pktail3bad int not null,
pktail4bad int not null,
pktail5bad int not null,
pk2copy int not null,
badkey int not null,
filler1 char (200),
filler2 char (200),
key (key1),
key (key2),
/* keys with tails from CPK members */
key (pktail1ok, pk1),
key (pktail2ok, pk1, pk2),
key (pktail3bad, pk2, pk1),
key (pktail4bad, pk1, pk2copy),
key (pktail5bad, pk1, pk2, pk2copy),
primary key (pk1, pk2)
) engine=innodb;
--disable_query_log
set autocommit=0;
let $1=10000;
while ($1)
{
eval insert into t1 values ($1 div 10,$1 mod 100, $1/100,$1/100, $1/100,$1/100,$1/100,$1/100,$1/100, $1 mod 100, $1/1000,'filler-data-$1','filler2');
dec $1;
}
set autocommit=1;
--enable_query_log
# Verify that range scan on CPK is ROR
# (use index_intersection because it is impossible to check that for index union)
explain select * from t1 where pk1 = 1 and pk2 < 80 and key1=0;
# CPK scan + 1 ROR range scan is a special case
select * from t1 where pk1 = 1 and pk2 < 80 and key1=0;
# Verify that CPK fields are considered to be covered by index scans
explain select pk1,pk2 from t1 where key1 = 10 and key2=10 and 2*pk1+1 < 2*96+1;
select pk1,pk2 from t1 where key1 = 10 and key2=10 and 2*pk1+1 < 2*96+1;
# Verify that CPK is always used for index intersection scans
# (this is because it is used as a filter, not for retrieval)
explain select * from t1 where badkey=1 and key1=10;
explain select * from t1 where pk1 < 7500 and key1 = 10;
# Verify that keys with 'tails' of PK members are ok.
explain select * from t1 where pktail1ok=1 and key1=10;
explain select * from t1 where pktail2ok=1 and key1=10;
select ' The following is actually a deficiency, it uses sort_union currently:' as 'note:';
explain select * from t1 where (pktail2ok=1 and pk1< 50000) or key1=10;
explain select * from t1 where pktail3bad=1 and key1=10;
explain select * from t1 where pktail4bad=1 and key1=10;
explain select * from t1 where pktail5bad=1 and key1=10;
# Test for problem with innodb key values prefetch buffer:
explain select pk1,pk2,key1,key2 from t1 where key1 = 10 and key2=10 limit 10;
select pk1,pk2,key1,key2 from t1 where key1 = 10 and key2=10 limit 10;
drop table t1;
#
# Test for rowid ordering (and comparison) functions.
# do index_merge select for tables with PK of various types.
#
--disable_warnings
drop table if exists t1, t2, t3,t4;
--enable_warnings
-- source include/have_bdb.inc
# Signed number as rowid
create table t1 (
pk1 int not NULL,
key1 int(11),
key2 int(11),
PRIMARY KEY (pk1),
KEY key1 (key1),
KEY key2 (key2)
) engine=bdb;
insert into t1 values (-5, 1, 1),
(-100, 1, 1),
(3, 1, 1),
(0, 1, 1),
(10, 1, 1);
explain select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
drop table t1;
# Unsigned numbers as rowids
create table t1 (
pk1 int unsigned not NULL,
key1 int(11),
key2 int(11),
PRIMARY KEY (pk1),
KEY key1 (key1),
KEY key2 (key2)
) engine=bdb;
insert into t1 values (0, 1, 1),
(0xFFFFFFFF, 1, 1),
(0xFFFFFFFE, 1, 1),
(1, 1, 1),
(2, 1, 1);
select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
drop table t1;
# Case-insensitive char(N)
create table t1 (
pk1 char(4) not NULL,
key1 int(11),
key2 int(11),
PRIMARY KEY (pk1),
KEY key1 (key1),
KEY key2 (key2)
) engine=bdb collate latin2_general_ci;
insert into t1 values ('a1', 1, 1),
('b2', 1, 1),
('A3', 1, 1),
('B4', 1, 1);
select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
drop table t1;
# Multi-part PK
create table t1 (
pk1 int not NULL,
pk2 char(4) not NULL collate latin1_german1_ci,
pk3 char(4) not NULL collate latin1_bin,
key1 int(11),
key2 int(11),
PRIMARY KEY (pk1,pk2,pk3),
KEY key1 (key1),
KEY key2 (key2)
) engine=bdb;
insert into t1 values
(1, 'u', 'u', 1, 1),
(1, 'u', char(0xEC), 1, 1),
(1, 'u', 'x', 1, 1);
insert ignore into t1 select pk1, char(0xEC), pk3, key1, key2 from t1;
insert ignore into t1 select pk1, 'x', pk3, key1, key2 from t1 where pk2='u';
insert ignore into t1 select 2, pk2, pk3, key1, key2 from t1;
select * from t1;
select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
# Hidden PK
alter table t1 drop primary key;
select * from t1;
select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
drop table t1;
# Variable-length PK
# this is also test for Bug#2688
create table t1 (
pk1 varchar(8) NOT NULL default '',
pk2 varchar(4) NOT NULL default '',
key1 int(11),
key2 int(11),
primary key(pk1, pk2),
KEY key1 (key1),
KEY key2 (key2)
) engine=bdb;
insert into t1 values ('','empt',2,2),
('a','a--a',2,2),
('bb','b--b',2,2),
('ccc','c--c',2,2),
('dddd','d--d',2,2);
select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
drop table t1;
#
# Test for rowid ordering (and comparison) functions.
# do index_merge select for tables with PK of various types.
#
--disable_warnings
drop table if exists t1, t2, t3,t4;
--enable_warnings
-- source include/have_innodb.inc
# Signed number as rowid
create table t1 (
pk1 int not NULL,
key1 int(11),
key2 int(11),
PRIMARY KEY (pk1),
KEY key1 (key1),
KEY key2 (key2)
) engine=innodb;
insert into t1 values (-5, 1, 1),
(-100, 1, 1),
(3, 1, 1),
(0, 1, 1),
(10, 1, 1);
explain select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
drop table t1;
# Unsigned numbers as rowids
create table t1 (
pk1 int unsigned not NULL,
key1 int(11),
key2 int(11),
PRIMARY KEY (pk1),
KEY key1 (key1),
KEY key2 (key2)
) engine=innodb;
insert into t1 values (0, 1, 1),
(0xFFFFFFFF, 1, 1),
(0xFFFFFFFE, 1, 1),
(1, 1, 1),
(2, 1, 1);
select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
drop table t1;
# Case-insensitive char(N)
create table t1 (
pk1 char(4) not NULL,
key1 int(11),
key2 int(11),
PRIMARY KEY (pk1),
KEY key1 (key1),
KEY key2 (key2)
) engine=innodb collate latin2_general_ci;
insert into t1 values ('a1', 1, 1),
('b2', 1, 1),
('A3', 1, 1),
('B4', 1, 1);
select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
drop table t1;
# Multi-part PK
create table t1 (
pk1 int not NULL,
pk2 char(4) not NULL collate latin1_german1_ci,
pk3 char(4) not NULL collate latin1_bin,
key1 int(11),
key2 int(11),
PRIMARY KEY (pk1,pk2,pk3),
KEY key1 (key1),
KEY key2 (key2)
) engine=innodb;
insert into t1 values
(1, 'u', 'u', 1, 1),
(1, 'u', char(0xEC), 1, 1),
(1, 'u', 'x', 1, 1);
insert ignore into t1 select pk1, char(0xEC), pk3, key1, key2 from t1;
insert ignore into t1 select pk1, 'x', pk3, key1, key2 from t1 where pk2='u';
insert ignore into t1 select 2, pk2, pk3, key1, key2 from t1;
select * from t1;
select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
# Hidden PK
alter table t1 drop primary key;
select * from t1;
select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
drop table t1;
# Variable-length PK
# this is also test for Bug#2688
create table t1 (
pk1 varchar(8) NOT NULL default '',
pk2 varchar(4) NOT NULL default '',
key1 int(11),
key2 int(11),
primary key(pk1, pk2),
KEY key1 (key1),
KEY key2 (key2)
) engine=innodb;
insert into t1 values ('','empt',2,2),
('a','a--a',2,2),
('bb','b--b',2,2),
('ccc','c--c',2,2),
('dddd','d--d',2,2);
select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
drop table t1;
......@@ -71,3 +71,8 @@ uint my_count_bits(ulonglong v)
#endif
}
uint my_count_bits_ushort(ushort v)
{
return nbits[v];
}
......@@ -28,6 +28,9 @@
* when both arguments are bitmaps, they must be of the same size
* bitmap_intersect() is an exception :)
(for for Bitmap::intersect(ulonglong map2buff))
If THREAD is defined all bitmap operations except bitmap_init/bitmap_free
are thread-safe.
TODO:
Make assembler THREAD safe versions of these using test-and-set instructions
......@@ -330,3 +333,66 @@ void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2)
bitmap_unlock(map);
}
/*
SYNOPSIS
bitmap_bits_set()
map
RETURN
Number of set bits in the bitmap.
*/
uint bitmap_bits_set(const MY_BITMAP *map)
{
uchar *m= map->bitmap;
uchar *end= m + map->bitmap_size;
uint res= 0;
DBUG_ASSERT(map->bitmap);
bitmap_lock((MY_BITMAP *)map);
while (m < end)
{
res+= my_count_bits_ushort(*m++);
}
bitmap_unlock((MY_BITMAP *)map);
return res;
}
/*
SYNOPSIS
bitmap_get_first()
map
RETURN
Number of first unset bit in the bitmap or MY_BIT_NONE if all bits are set.
*/
uint bitmap_get_first(const MY_BITMAP *map)
{
uchar *bitmap=map->bitmap;
uint bit_found = MY_BIT_NONE;
uint bitmap_size=map->bitmap_size*8;
uint i;
DBUG_ASSERT(map->bitmap);
bitmap_lock((MY_BITMAP *)map);
for (i=0; i < bitmap_size ; i++, bitmap++)
{
if (*bitmap != 0xff)
{ /* Found slot with free bit */
uint b;
for (b=0; ; b++)
{
if (!(*bitmap & (1 << b)))
{
bit_found = (i*8)+b;
break;
}
}
break; /* Found bit */
}
}
bitmap_unlock((MY_BITMAP *)map);
return bit_found;
}
......@@ -2499,4 +2499,29 @@ ha_rows ha_berkeley::estimate_number_of_rows()
return share->rows + HA_BERKELEY_EXTRA_ROWS;
}
int ha_berkeley::cmp_ref(const byte *ref1, const byte *ref2)
{
if (hidden_primary_key)
return memcmp(ref1, ref2, BDB_HIDDEN_PRIMARY_KEY_LENGTH);
int result;
Field *field;
KEY *key_info=table->key_info+table->primary_key;
KEY_PART_INFO *key_part=key_info->key_part;
KEY_PART_INFO *end=key_part+key_info->key_parts;
for (; key_part != end; key_part++)
{
field= key_part->field;
result= field->pack_cmp((const char*)ref1, (const char*)ref2,
key_part->length);
if (result)
return result;
ref1 += field->packed_col_length((const char*)ref1, key_part->length);
ref2 += field->packed_col_length((const char*)ref2, key_part->length);
}
return 0;
}
#endif /* HAVE_BERKELEY_DB */
......@@ -163,6 +163,7 @@ class ha_berkeley: public handler
void print_error(int error, myf errflag);
uint8 table_cache_type() { return HA_CACHE_TBL_TRANSACT; }
bool primary_key_is_clustered() { return true; }
int cmp_ref(const byte *ref1, const byte *ref2);
};
extern bool berkeley_shared_data;
......
......@@ -94,5 +94,10 @@ class ha_heap: public handler
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
enum thr_lock_type lock_type);
int cmp_ref(const byte *ref1, const byte *ref2)
{
HEAP_PTR ptr1=*(HEAP_PTR*)ref1;
HEAP_PTR ptr2=*(HEAP_PTR*)ref2;
return ptr1 < ptr2? -1 : (ptr1 > ptr2? 1 : 0);
}
};
......@@ -749,6 +749,8 @@ ha_innobase::init_table_handle_for_HANDLER(void)
prebuilt->read_just_key = FALSE;
prebuilt->used_in_HANDLER = TRUE;
prebuilt->keep_other_fields_on_keyread = FALSE;
}
/*************************************************************************
......@@ -4579,9 +4581,11 @@ ha_innobase::extra(
if (prebuilt->blob_heap) {
row_mysql_prebuilt_free_blob_heap(prebuilt);
}
prebuilt->keep_other_fields_on_keyread = 0;
prebuilt->read_just_key = 0;
break;
case HA_EXTRA_RESET_STATE:
prebuilt->keep_other_fields_on_keyread = 0;
prebuilt->read_just_key = 0;
break;
case HA_EXTRA_NO_KEYREAD:
......@@ -4600,6 +4604,9 @@ ha_innobase::extra(
case HA_EXTRA_KEYREAD:
prebuilt->read_just_key = 1;
break;
case HA_EXTRA_KEYREAD_PRESERVE_FIELDS:
prebuilt->keep_other_fields_on_keyread = 1;
break;
default:/* Do nothing */
;
}
......@@ -4648,6 +4655,7 @@ ha_innobase::start_stmt(
prebuilt->sql_stat_start = TRUE;
prebuilt->hint_need_to_fetch_extra_cols = 0;
prebuilt->read_just_key = 0;
prebuilt->keep_other_fields_on_keyread = FALSE;
if (!prebuilt->mysql_has_locked) {
/* This handle is for a temporary table created inside
......@@ -4725,6 +4733,7 @@ ha_innobase::external_lock(
prebuilt->hint_need_to_fetch_extra_cols = 0;
prebuilt->read_just_key = 0;
prebuilt->keep_other_fields_on_keyread = FALSE;
if (lock_type == F_WRLCK) {
......@@ -5161,4 +5170,52 @@ ha_innobase::get_auto_increment()
return(nr);
}
int
ha_innobase::cmp_ref(
const mysql_byte *ref1,
const mysql_byte *ref2)
{
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
enum_field_types mysql_type;
Field* field;
int result;
if (prebuilt->clust_index_was_generated)
return memcmp(ref1, ref2, DATA_ROW_ID_LEN);
/* Do type-aware comparison of Primary Key members. PK members
are always NOT NULL, so no checks for NULL are performed */
KEY_PART_INFO *key_part= table->key_info[table->primary_key].key_part;
KEY_PART_INFO *key_part_end=
key_part + table->key_info[table->primary_key].key_parts;
for (; key_part != key_part_end; ++key_part) {
field = key_part->field;
mysql_type = field->type();
if (mysql_type == FIELD_TYPE_TINY_BLOB
|| mysql_type == FIELD_TYPE_MEDIUM_BLOB
|| mysql_type == FIELD_TYPE_BLOB
|| mysql_type == FIELD_TYPE_LONG_BLOB) {
ut_a(!ref1[1]);
ut_a(!ref2[1]);
byte len1= *ref1;
byte len2= *ref2;
ref1 += 2;
ref2 += 2;
result =
((Field_blob*)field)->cmp((const char*)ref1, len1,
(const char*)ref2, len2);
} else {
result =
field->cmp((const char*)ref1, (const char*)ref2);
}
if (result)
return result;
ref1 += key_part->length;
ref2 += key_part->length;
}
return 0;
}
#endif /* HAVE_INNOBASE_DB */
......@@ -184,6 +184,7 @@ class ha_innobase: public handler
longlong get_auto_increment();
uint8 table_cache_type() { return HA_CACHE_TBL_ASKTRANSACT; }
bool primary_key_is_clustered() { return true; }
int cmp_ref(const byte *ref1, const byte *ref2);
};
extern uint innobase_init_flags, innobase_lock_type;
......
......@@ -446,6 +446,11 @@ public:
false otherwise
*/
virtual bool primary_key_is_clustered() { return false; }
virtual int cmp_ref(const byte *ref1, const byte *ref2)
{
return memcmp(ref1, ref2, ref_length);
}
};
/* Some extern variables used with handlers */
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -78,25 +78,59 @@ public:
ha_rows records; /* estimate of # of records to be retrieved */
double read_time; /* time to perform this retrieval */
TABLE *head;
/*
Index this quick select uses, or MAX_KEY for quick selects
that use several indexes
*/
uint index;
/*
the only index this quick select uses, or MAX_KEY for
QUICK_INDEX_MERGE_SELECT
Total length of first used_key_parts parts of the key.
Applicable if index!= MAX_KEY.
*/
uint index;
uint max_used_key_length, used_key_parts;
uint max_used_key_length;
/*
Max. number of (first) key parts this quick select uses for retrieval.
eg. for "(key1p1=c1 AND key1p2=c2) OR key1p1=c2" used_key_parts == 2.
Applicable if index!= MAX_KEY.
*/
uint used_key_parts;
QUICK_SELECT_I();
virtual ~QUICK_SELECT_I(){};
/*
Call init() immediately after creation of quick select. if init() call
fails, reset() or get_next() must not be called.
/*
Do post-constructor initialization.
SYNOPSIS
init()
init() performs initializations that should have been in constructor if
it was possible to return errors from constructors. The join optimizer may
create and then delete quick selects without retrieving any rows so init()
must not contain any IO or CPU intensive code.
If init() call fails the only valid action is to delete this quick select,
reset() and get_next() must not be called.
RETURN
0 OK
other Error code
*/
virtual int init() = 0;
/*
Call reset() before first get_next call. get_next must not be called if
reset() call fails.
Initialize quick select for row retrieval.
SYNOPSIS
reset()
reset() should be called when it is certain that row retrieval will be
necessary. This call may do heavyweight initialization like buffering first
N records etc. If reset() call fails get_next() must not be called.
RETURN
0 OK
other Error code
*/
virtual int reset(void) = 0;
virtual int get_next() = 0; /* get next record to retrieve */
......@@ -107,27 +141,98 @@ public:
QS_TYPE_RANGE = 0,
QS_TYPE_INDEX_MERGE = 1,
QS_TYPE_RANGE_DESC = 2,
QS_TYPE_FULLTEXT = 3
QS_TYPE_FULLTEXT = 3,
QS_TYPE_ROR_INTERSECT = 4,
QS_TYPE_ROR_UNION = 5,
};
/* Get type of this quick select - one of the QS_* values */
virtual int get_type() = 0;
/* Get type of this quick select - one of the QS_TYPE_* values */
virtual int get_type() = 0;
/*
Initialize this quick select as a merged scan inside a ROR-union or a ROR-
intersection scan. The caller must not additionally call init() if this
function is called.
SYNOPSIS
init_ror_merged_scan()
reuse_handler If true, the quick select may use table->handler, otherwise
it must create and use a separate handler object.
RETURN
0 Ok
other Error
*/
virtual int init_ror_merged_scan(bool reuse_handler)
{ DBUG_ASSERT(0); return 1; }
/*
Save ROWID of last retrieved row in file->ref. This used in ROR-merging.
*/
virtual void save_last_pos(){};
/*
Append comma-separated list of keys this quick select uses to key_names;
append comma-separated list of corresponding used lengths to used_lengths.
This is used by select_describe.
*/
virtual void add_keys_and_lengths(String *key_names,
String *used_lengths)=0;
/*
Append text representation of quick select structure (what and how is
merged) to str. The result is added to "Extra" field in EXPLAIN output.
This function is implemented only by quick selects that merge other quick
selects output and/or can produce output suitable for merging.
*/
virtual void add_info_string(String *str) {};
/*
Return 1 if any index used by this quick select
a) uses field that is listed in passed field list or
b) is automatically updated (like a timestamp)
*/
virtual bool check_if_keys_used(List<Item> *fields);
/*
rowid of last row retrieved by this quick select. This is used only when
doing ROR-index_merge selects
*/
byte *last_rowid;
/*
Table record buffer used by this quick select.
*/
byte *record;
#ifndef DBUG_OFF
/*
Print quick select information to DBUG_FILE. Caller is responsible
for locking DBUG_FILE before this call and unlocking it afterwards.
*/
virtual void dbug_dump(int indent, bool verbose)= 0;
#endif
};
struct st_qsel_param;
class SEL_ARG;
class QUICK_RANGE_SELECT : public QUICK_SELECT_I
/*
Quick select that does a range scan on a single key. The records are
returned in key order.
*/
class QUICK_RANGE_SELECT : public QUICK_SELECT_I
{
protected:
bool next,dont_free;
public:
int error;
protected:
handler *file;
byte *record;
/*
If true, this quick select has its "own" handler object which should be
closed no later then this quick select is deleted.
*/
bool free_file;
protected:
friend void print_quick_sel_range(QUICK_RANGE_SELECT *quick,
const key_map* needed_reg);
friend
QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
struct st_table_ref *ref);
......@@ -141,18 +246,20 @@ protected:
MEM_ROOT *alloc);
friend class QUICK_SELECT_DESC;
friend class QUICK_INDEX_MERGE_SELECT;
friend class QUICK_ROR_INTERSECT_SELECT;
DYNAMIC_ARRAY ranges; /* ordered array of range ptrs */
QUICK_RANGE **cur_range; /* current element in ranges */
QUICK_RANGE *range;
MEM_ROOT alloc;
KEY_PART *key_parts;
KEY_PART_INFO *key_part_info;
int cmp_next(QUICK_RANGE *range);
int cmp_prev(QUICK_RANGE *range);
bool row_in_ranges();
public:
MEM_ROOT alloc;
QUICK_RANGE_SELECT(THD *thd, TABLE *table,uint index_arg,bool no_alloc=0,
MEM_ROOT *parent_alloc=NULL);
~QUICK_RANGE_SELECT();
......@@ -168,7 +275,17 @@ public:
int get_next();
bool reverse_sorted() { return 0; }
bool unique_key_range();
int init_ror_merged_scan(bool reuse_handler);
void save_last_pos()
{
file->position(record);
};
int get_type() { return QS_TYPE_RANGE; }
void add_keys_and_lengths(String *key_names, String *used_lengths);
void add_info_string(String *str);
#ifndef DBUG_OFF
void dbug_dump(int indent, bool verbose);
#endif
};
......@@ -254,6 +371,12 @@ public:
bool reverse_sorted() { return false; }
bool unique_key_range() { return false; }
int get_type() { return QS_TYPE_INDEX_MERGE; }
void add_keys_and_lengths(String *key_names, String *used_lengths);
void add_info_string(String *str);
bool check_if_keys_used(List<Item> *fields);
#ifndef DBUG_OFF
void dbug_dump(int indent, bool verbose);
#endif
bool push_quick_back(QUICK_RANGE_SELECT *quick_sel_range);
......@@ -264,9 +387,6 @@ public:
List_iterator_fast<QUICK_RANGE_SELECT> cur_quick_it;
QUICK_RANGE_SELECT* cur_quick_select;
/* last element in quick_selects list */
QUICK_RANGE_SELECT* last_quick_select;
/* quick select that uses clustered primary key (NULL if none) */
QUICK_RANGE_SELECT* pk_quick_select;
......@@ -278,12 +398,120 @@ public:
THD *thd;
int prepare_unique();
bool reset_called;
/* used to get rows collected in Unique */
READ_RECORD read_record;
};
/*
Rowid-Ordered Retrieval (ROR) index intersection quick select.
This quick select produces intersection of row sequences returned
by several QUICK_RANGE_SELECTs it "merges".
All merged QUICK_RANGE_SELECTs must return rowids in rowid order.
QUICK_ROR_INTERSECT_SELECT will return rows in rowid order, too.
All merged quick selects retrieve {rowid, covered_fields} tuples (not full
table records).
QUICK_ROR_INTERSECT_SELECT retrieves full records if it is not being used
by QUICK_ROR_INTERSECT_SELECT and all merged quick selects together don't
cover needed all fields.
If one of the merged quick selects is a Clustered PK range scan, it is
used only to filter rowid sequence produced by other merged quick selects.
*/
class QUICK_ROR_INTERSECT_SELECT : public QUICK_SELECT_I
{
public:
QUICK_ROR_INTERSECT_SELECT(THD *thd, TABLE *table,
bool retrieve_full_rows,
MEM_ROOT *parent_alloc);
~QUICK_ROR_INTERSECT_SELECT();
int init();
int reset(void);
int get_next();
bool reverse_sorted() { return false; }
bool unique_key_range() { return false; }
int get_type() { return QS_TYPE_ROR_INTERSECT; }
void add_keys_and_lengths(String *key_names, String *used_lengths);
void add_info_string(String *str);
bool check_if_keys_used(List<Item> *fields);
#ifndef DBUG_OFF
void dbug_dump(int indent, bool verbose);
#endif
int init_ror_merged_scan(bool reuse_handler);
bool push_quick_back(QUICK_RANGE_SELECT *quick_sel_range);
/*
Range quick selects this intersection consists of, not including
cpk_quick.
*/
List<QUICK_RANGE_SELECT> quick_selects;
/*
Merged quick select that uses Clustered PK, if there is one. This quick
select is not used for row retrieval, it is used for row retrieval.
*/
QUICK_RANGE_SELECT *cpk_quick;
MEM_ROOT alloc; /* Memory pool for this and merged quick selects data. */
THD *thd; /* current thread */
bool need_to_fetch_row; /* if true, do retrieve full table records. */
};
/*
Rowid-Ordered Retrieval index union select.
This quick select produces union of row sequences returned by several
quick select it "merges".
All merged quick selects must return rowids in rowid order.
QUICK_ROR_UNION_SELECT will return rows in rowid order, too.
All merged quick selects are set not to retrieve full table records.
ROR-union quick select always retrieves full records.
*/
class QUICK_ROR_UNION_SELECT : public QUICK_SELECT_I
{
public:
QUICK_ROR_UNION_SELECT(THD *thd, TABLE *table);
~QUICK_ROR_UNION_SELECT();
int init();
int reset(void);
int get_next();
bool reverse_sorted() { return false; }
bool unique_key_range() { return false; }
int get_type() { return QS_TYPE_ROR_UNION; }
void add_keys_and_lengths(String *key_names, String *used_lengths);
void add_info_string(String *str);
bool check_if_keys_used(List<Item> *fields);
#ifndef DBUG_OFF
void dbug_dump(int indent, bool verbose);
#endif
bool push_quick_back(QUICK_SELECT_I *quick_sel_range);
List<QUICK_SELECT_I> quick_selects; /* Merged quick selects */
QUEUE queue; /* Priority queue for merge operation */
MEM_ROOT alloc; /* Memory pool for this and merged quick selects data. */
THD *thd; /* current thread */
byte *cur_rowid; /* buffer used in get_next() */
byte *prev_rowid; /* rowid of last row returned by get_next() */
bool have_prev_rowid; /* true if prev_rowid has valid data */
uint rowid_length; /* table rowid length */
private:
static int queue_cmp(void *arg, byte *val1, byte *val2);
};
class QUICK_SELECT_DESC: public QUICK_RANGE_SELECT
{
public:
......
......@@ -291,10 +291,10 @@ int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds)
#define MEM_STRIP_BUF_SIZE current_thd->variables.sortbuff_size
extern "C" int refposcmp2(void* arg, const void *a,const void *b)
extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b)
{
/* arg is a pointer to file->ref_length */
return memcmp(a,b, *(int*) arg);
handler *file= (handler*)arg;
return file->cmp_ref((const byte*)a, (const byte*)b);
}
multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt,
......@@ -358,8 +358,8 @@ multi_delete::initialize_tables(JOIN *join)
for (walk=walk->next ; walk ; walk=walk->next)
{
TABLE *table=walk->table;
*tempfiles_ptr++= new Unique (refposcmp2,
(void *) &table->file->ref_length,
*tempfiles_ptr++= new Unique (refpos_order_cmp,
(void *) table->file,
table->file->ref_length,
MEM_STRIP_BUF_SIZE);
}
......
......@@ -8061,8 +8061,16 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
}
else if (select && select->quick) // Range found by opt_range
{
/* assume results are not ordered when index merge is used */
if (select->quick->get_type() == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE)
int quick_type= select->quick->get_type();
/*
assume results are not ordered when index merge is used
TODO: sergeyp: Results of all index merge selects actually are ordered
by clustered PK values.
*/
if (quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE ||
quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION ||
quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT)
DBUG_RETURN(0);
ref_key= select->quick->index;
ref_key_parts= select->quick->used_key_parts;
......@@ -8123,9 +8131,11 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
*/
if (!select->quick->reverse_sorted())
{
int quick_type= select->quick->get_type();
if (table->file->index_flags(ref_key) & HA_NOT_READ_PREFIX_LAST ||
(select->quick->get_type() ==
QUICK_SELECT_I::QS_TYPE_INDEX_MERGE))
quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE ||
quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT ||
quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION)
DBUG_RETURN(0); // Use filesort
// ORDER BY range_key DESC
......@@ -10105,6 +10115,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
select_result *result=join->result;
Item *item_null= new Item_null();
CHARSET_INFO *cs= system_charset_info;
int quick_type;
DBUG_ENTER("select_describe");
DBUG_PRINT("info", ("Select 0x%lx, type %s, message %s",
(ulong)join->select_lex, join->select_lex->type,
......@@ -10196,17 +10207,20 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
{
JOIN_TAB *tab=join->join_tab+i;
TABLE *table=tab->table;
char buff[512],*buff_ptr=buff;
char buff[512];
char buff1[512], buff2[512], buff3[512];
char keylen_str_buf[64];
String extra(buff, sizeof(buff),cs);
char table_name_buffer[NAME_LEN];
String tmp1(buff1,sizeof(buff1),cs);
String tmp2(buff2,sizeof(buff2),cs);
String tmp3(buff3,sizeof(buff3),cs);
extra.length(0);
tmp1.length(0);
tmp2.length(0);
tmp3.length(0);
quick_type= -1;
item_list.empty();
/* id */
item_list.push_back(new Item_uint((uint32)
......@@ -10217,8 +10231,10 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
cs));
if (tab->type == JT_ALL && tab->select && tab->select->quick)
{
if (tab->select->quick->get_type() ==
QUICK_SELECT_I::QS_TYPE_INDEX_MERGE)
quick_type= tab->select->quick->get_type();
if ((quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE) ||
(quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT) ||
(quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION))
tab->type = JT_INDEX_MERGE;
else
tab->type = JT_RANGE;
......@@ -10241,7 +10257,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
strlen(join_type_str[tab->type]),
cs));
uint j;
/* possible_keys */
/* Build "possible_keys" value and add it to item_list */
if (!tab->keys.is_clear_all())
{
for (j=0 ; j < table->keys ; j++)
......@@ -10260,7 +10276,8 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
item_list.push_back(new Item_string(tmp1.ptr(),tmp1.length(),cs));
else
item_list.push_back(item_null);
/* key key_len ref */
/* Build "key", "key_len", and "ref" values and add them to item_list */
if (tab->ref.key_parts)
{
KEY *key_info=table->key_info+ tab->ref.key;
......@@ -10296,48 +10313,9 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
}
else if (tab->select && tab->select->quick)
{
if (tab->select->quick->get_type() ==
QUICK_SELECT_I::QS_TYPE_INDEX_MERGE)
{
QUICK_INDEX_MERGE_SELECT *quick_imerge=
(QUICK_INDEX_MERGE_SELECT*)tab->select->quick;
QUICK_RANGE_SELECT *quick;
List_iterator_fast<QUICK_RANGE_SELECT> it(quick_imerge->
quick_selects);
while ((quick= it++))
{
KEY *key_info= table->key_info + quick->index;
register uint length;
if (tmp3.length())
tmp3.append(',');
tmp3.append(key_info->name);
if (tmp2.length())
tmp2.append(',');
length= longlong2str(quick->max_used_key_length, keylen_str_buf,
10) -
keylen_str_buf;
tmp2.append(keylen_str_buf, length);
}
}
else
{
KEY *key_info= table->key_info + tab->select->quick->index;
register uint length;
tmp3.append(key_info->name);
length= longlong2str(tab->select->quick->max_used_key_length,
keylen_str_buf, 10) -
keylen_str_buf;
tmp2.append(keylen_str_buf, length);
}
item_list.push_back(new Item_string(tmp3.ptr(),tmp3.length(),cs));
tab->select->quick->add_keys_and_lengths(&tmp2, &tmp3);
item_list.push_back(new Item_string(tmp2.ptr(),tmp2.length(),cs));
item_list.push_back(new Item_string(tmp3.ptr(),tmp3.length(),cs));
item_list.push_back(item_null);
}
else
......@@ -10346,52 +10324,68 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
item_list.push_back(item_null);
item_list.push_back(item_null);
}
/* rows */
/* Add "rows" field to item_list. */
item_list.push_back(new Item_int((longlong) (ulonglong)
join->best_positions[i]. records_read,
21));
/* extra */
/* Build "Extra" field and add it to item_list. */
my_bool key_read=table->key_read;
if ((tab->type == JT_NEXT || tab->type == JT_CONST) &&
table->used_keys.is_set(tab->index))
key_read=1;
if (quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT &&
!((QUICK_ROR_INTERSECT_SELECT*)tab->select->quick)->need_to_fetch_row)
key_read=1;
if (tab->info)
item_list.push_back(new Item_string(tab->info,strlen(tab->info),cs));
else
{
if (quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION ||
quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT ||
quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE)
{
extra.append("; Using ");
tab->select->quick->add_info_string(&extra);
}
if (tab->select)
{
if (tab->use_quick == 2)
{
char buf[MAX_KEY/8+1];
sprintf(buff_ptr,"; Range checked for each record (index map: 0x%s)",
tab->keys.print(buf));
buff_ptr=strend(buff_ptr);
extra.append("; Range checked for each record (index map: 0x");
extra.append(tab->keys.print(buf));
extra.append(')');
}
else
buff_ptr=strmov(buff_ptr,"; Using where");
extra.append("; Using where");
}
if (key_read)
buff_ptr= strmov(buff_ptr,"; Using index");
extra.append("; Using index");
if (table->reginfo.not_exists_optimize)
buff_ptr= strmov(buff_ptr,"; Not exists");
extra.append("; Not exists");
if (need_tmp_table)
{
need_tmp_table=0;
buff_ptr= strmov(buff_ptr,"; Using temporary");
extra.append("; Using temporary");
}
if (need_order)
{
need_order=0;
buff_ptr= strmov(buff_ptr,"; Using filesort");
extra.append("; Using filesort");
}
if (distinct & test_all_bits(used_tables,thd->used_tables))
buff_ptr= strmov(buff_ptr,"; Distinct");
if (buff_ptr == buff)
buff_ptr+= 2; // Skip inital "; "
item_list.push_back(new Item_string(buff+2,(uint) (buff_ptr - buff)-2,
cs));
extra.append("; Distinct");
/* Skip initial "; "*/
const char *str= extra.ptr();
uint32 len= extra.length();
if (len)
{
str += 2;
len -= 2;
}
item_list.push_back(new Item_string(str, len, cs));
}
// For next iteration
used_tables|=table->map;
......
......@@ -340,7 +340,7 @@ uint find_shortest_key(TABLE *table, const key_map *usable_keys);
int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds);
/* from sql_delete.cc, used by opt_range.cc */
extern "C" int refposcmp2(void* arg, const void *a,const void *b);
extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b);
/* class to copying an field/item to a key struct */
......
......@@ -182,37 +182,8 @@ TEST_join(JOIN *join)
tab->select->quick_keys.print(buf));
else if (tab->select->quick)
{
int quick_type= tab->select->quick->get_type();
if ((quick_type == QUICK_SELECT_I::QS_TYPE_RANGE) ||
(quick_type == QUICK_SELECT_I::QS_TYPE_RANGE_DESC))
{
fprintf(DBUG_FILE,
" quick select used on key %s, length: %d\n",
form->key_info[tab->select->quick->index].name,
tab->select->quick->max_used_key_length);
}
else if (quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE)
{
QUICK_INDEX_MERGE_SELECT *quick_imerge=
(QUICK_INDEX_MERGE_SELECT*)tab->select->quick;
QUICK_RANGE_SELECT *quick;
fprintf(DBUG_FILE,
" index_merge quick select used\n");
List_iterator_fast<QUICK_RANGE_SELECT> it(quick_imerge->quick_selects);
while ((quick = it++))
{
fprintf(DBUG_FILE,
" range quick select: key %s, length: %d\n",
form->key_info[quick->index].name,
quick->max_used_key_length);
}
}
else
{
fprintf(DBUG_FILE,
" quick select of unknown nature used\n");
}
fprintf(DBUG_FILE, " quick select used:\n");
tab->select->quick->dbug_dump(18, false);
}
else
VOID(fputs(" select used\n",DBUG_FILE));
......
......@@ -156,18 +156,12 @@ int mysql_update(THD *thd,
}
init_ftfuncs(thd, &thd->lex->select_lex, 1);
/* Check if we are modifying a key that we are used to search with */
if (select && select->quick)
{
if (select->quick->get_type() != QUICK_SELECT_I::QS_TYPE_INDEX_MERGE)
{
used_index= select->quick->index;
used_key_is_modified= (!select->quick->unique_key_range() &&
check_if_key_used(table,used_index,fields));
}
else
{
used_key_is_modified= true;
}
used_index= select->quick->index;
used_key_is_modified= (!select->quick->unique_key_range() &&
select->quick->check_if_keys_used(&fields));
}
else if ((used_index=table->file->key_used_on_scan) < MAX_KEY)
used_key_is_modified=check_if_key_used(table, used_index, fields);
......@@ -180,7 +174,7 @@ int mysql_update(THD *thd,
matching rows before updating the table!
*/
table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
if (old_used_keys.is_set(used_index))
if ( (used_index != MAX_KEY) && old_used_keys.is_set(used_index))
{
table->key_read=1;
table->file->extra(HA_EXTRA_KEYREAD);
......@@ -226,7 +220,7 @@ int mysql_update(THD *thd,
if (open_cached_file(&tempfile, mysql_tmpdir,TEMP_PREFIX,
DISK_BUFFER_SIZE, MYF(MY_WME)))
goto err;
/* If quick select is used, initialize it before retrieving rows. */
if (select && select->quick && select->quick->reset())
goto err;
......@@ -286,6 +280,9 @@ int mysql_update(THD *thd,
if (handle_duplicates == DUP_IGNORE)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
if (select && select->quick && select->quick->reset())
goto err;
init_read_record(&info,thd,table,select,0,1);
updated= found= 0;
......@@ -833,26 +830,7 @@ static bool safe_update_on_fly(JOIN_TAB *join_tab, List<Item> *fields)
case JT_ALL:
/* If range search on index */
if (join_tab->quick)
{
if (join_tab->quick->get_type() != QUICK_SELECT_I::QS_TYPE_INDEX_MERGE)
{
return !check_if_key_used(table,join_tab->quick->index,*fields);
}
else
{
QUICK_INDEX_MERGE_SELECT *qsel_imerge=
(QUICK_INDEX_MERGE_SELECT*)(join_tab->quick);
List_iterator_fast<QUICK_RANGE_SELECT> it(qsel_imerge->quick_selects);
QUICK_RANGE_SELECT *quick;
while ((quick= it++))
{
if (check_if_key_used(table, quick->index, *fields))
return 0;
}
return 1;
}
}
return !join_tab->quick->check_if_keys_used(fields);
/* If scanning in clustered key */
if ((table->file->table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX) &&
table->primary_key < MAX_KEY)
......
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