mirror of
https://github.com/MariaDB/server.git
synced 2025-01-15 19:42:28 +01:00
This is first cset for WL#1394 "Optimize index merge when all involved index ranges include only values with equal keys"
The main idea is to exploit the fact that key scans for "key=const" return ordered sequences of rowids. include/my_base.h: Added HA_EXTRA_KEYREAD_PRESERVE_FIELDS flag include/my_bitmap.h: Added a couple of utility functions include/my_sys.h: Added my_conunt_bits_ushort function innobase/include/row0mysql.h: Added support for HA_EXTRA_KEYREAD_PRESERVE_FIELDS innobase/row/row0sel.c: Added support for HA_EXTRA_KEYREAD_PRESERVE_FIELDS mysys/my_bit.c: Added my_count_bits_ushort function mysys/my_bitmap.c: Added a couple of utility functions sql/ha_berkeley.cc: Added cmp_ref rowid comparison function. sql/ha_berkeley.h: Added cmp_ref rowid comparison function. sql/ha_heap.h: Added cmp_ref rowid comparison function. sql/ha_innodb.cc: Added cmp_ref rowid comparison function and support from HA_EXTRA_KEYREAD_PRESERVE_FIELDS sql/ha_innodb.h: Added cmp_ref rowid comparison function. sql/handler.h: Added cmp_ref rowid comparison function. sql/opt_range.cc: Added QUICK_ROR_{INTERSECT,UNION}_SELECT classes and related optimizer code sql/opt_range.h: Added QUICK_ROR_{INTERSECT,UNION}_SELECT classes sql/sql_delete.cc: Changed to use new ROWID comparison function also always call quick->reset() for quick selects sql/sql_select.cc: Account for new quick select types sql/sql_select.h: New, proper rowid ordering/comparison function to be used with Unique class etc. sql/sql_test.cc: Account for new quick select types sql/sql_update.cc: Account for new quick select types
This commit is contained in:
parent
7e95a257e0
commit
3600d09ab4
28 changed files with 3720 additions and 500 deletions
|
@ -132,7 +132,13 @@ enum ha_extra_function {
|
|||
HA_EXTRA_RETRIEVE_ALL_COLS,
|
||||
HA_EXTRA_PREPARE_FOR_DELETE,
|
||||
HA_EXTRA_PREPARE_FOR_UPDATE, /* Remove read cache if problems */
|
||||
HA_EXTRA_PRELOAD_BUFFER_SIZE /* Set buffer size for preloading */
|
||||
HA_EXTRA_PRELOAD_BUFFER_SIZE, /* Set buffer size for preloading */
|
||||
/*
|
||||
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);
|
||||
|
|
|
@ -744,6 +744,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);
|
||||
|
||||
|
|
|
@ -552,6 +552,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
|
||||
|
|
|
@ -2577,10 +2577,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];
|
||||
|
||||
ut_memcpy(buf, prebuilt->fetch_cache[prebuilt->fetch_cache_first],
|
||||
prebuilt->mysql_row_len);
|
||||
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);
|
||||
|
||||
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++;
|
||||
|
||||
|
|
168
mysql-test/r/index_merge_ror.result
Normal file
168
mysql-test/r/index_merge_ror.result
Normal file
|
@ -0,0 +1,168 @@
|
|||
drop table if exists t1,t0;
|
||||
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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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,stb_swt1b 8,8 NULL 163 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,st_b 8,4 NULL 640 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 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 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 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 where; Using index
|
||||
drop table t0,t1;
|
93
mysql-test/r/index_merge_ror_cpk.result
Normal file
93
mysql-test/r/index_merge_ror_cpk.result
Normal file
|
@ -0,0 +1,93 @@
|
|||
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 intr(key1,key2) 4,4 NULL 1 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 intr(key1:PRIMARY) 4:4 NULL 38 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 intr(key1,pktail1ok) 4,4 NULL 1 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 intr(key1,pktail2ok) 4,4 NULL 1 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 intr(key1,key2) 4,4 NULL 1 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;
|
186
mysql-test/r/rowid_order_bdb.result
Normal file
186
mysql-test/r/rowid_order_bdb.result
Normal file
|
@ -0,0 +1,186 @@
|
|||
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 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;
|
186
mysql-test/r/rowid_order_innodb.result
Normal file
186
mysql-test/r/rowid_order_innodb.result
Normal file
|
@ -0,0 +1,186 @@
|
|||
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 4 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;
|
215
mysql-test/t/index_merge_ror.test
Normal file
215
mysql-test/t/index_merge_ror.test
Normal file
|
@ -0,0 +1,215 @@
|
|||
#
|
||||
# ROR-index_merge tests.
|
||||
#
|
||||
--disable_warnings
|
||||
drop table if exists t1,t0;
|
||||
--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;
|
||||
|
81
mysql-test/t/index_merge_ror_cpk.test
Normal file
81
mysql-test/t/index_merge_ror_cpk.test
Normal file
|
@ -0,0 +1,81 @@
|
|||
#
|
||||
# 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;
|
||||
|
||||
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;
|
||||
|
108
mysql-test/t/rowid_order_bdb.test
Normal file
108
mysql-test/t/rowid_order_bdb.test
Normal file
|
@ -0,0 +1,108 @@
|
|||
#
|
||||
# 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;
|
||||
|
108
mysql-test/t/rowid_order_innodb.test
Normal file
108
mysql-test/t/rowid_order_innodb.test
Normal file
|
@ -0,0 +1,108 @@
|
|||
#
|
||||
# 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];
|
||||
}
|
||||
|
||||
|
|
|
@ -330,3 +330,59 @@ void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2)
|
|||
bitmap_unlock(map);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Get number of set bits in the bitmap
|
||||
*/
|
||||
uint bitmap_bits_set(const MY_BITMAP *map)
|
||||
{
|
||||
uchar *m= map->bitmap,
|
||||
*end= map->bitmap+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;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Return number of first zero bit 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -2457,4 +2457,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 */
|
||||
|
|
|
@ -168,6 +168,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_skip, berkeley_shared_data;
|
||||
|
|
|
@ -93,5 +93,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);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -711,6 +711,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;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
|
@ -4454,9 +4456,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:
|
||||
|
@ -4468,6 +4472,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 */
|
||||
;
|
||||
}
|
||||
|
@ -4526,6 +4533,7 @@ ha_innobase::start_stmt(
|
|||
prebuilt->sql_stat_start = TRUE;
|
||||
prebuilt->hint_no_need_to_fetch_extra_cols = TRUE;
|
||||
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
|
||||
|
@ -4604,6 +4612,7 @@ ha_innobase::external_lock(
|
|||
prebuilt->hint_no_need_to_fetch_extra_cols = TRUE;
|
||||
|
||||
prebuilt->read_just_key = 0;
|
||||
prebuilt->keep_other_fields_on_keyread = FALSE;
|
||||
|
||||
if (lock_type == F_WRLCK) {
|
||||
|
||||
|
@ -5000,4 +5009,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 */
|
||||
|
|
|
@ -188,6 +188,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 bool innodb_skip;
|
||||
|
|
|
@ -382,6 +382,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 */
|
||||
|
|
2539
sql/opt_range.cc
2539
sql/opt_range.cc
File diff suppressed because it is too large
Load diff
165
sql/opt_range.h
165
sql/opt_range.h
|
@ -79,14 +79,18 @@ public:
|
|||
TABLE *head;
|
||||
|
||||
/*
|
||||
the only index this quick select uses, or MAX_KEY for
|
||||
QUICK_INDEX_MERGE_SELECT
|
||||
index this quick select uses, or MAX_KEY for quick selects
|
||||
that use several indexes
|
||||
*/
|
||||
uint index;
|
||||
uint index;
|
||||
|
||||
/* applicable iff index!= MAX_KEY */
|
||||
uint max_used_key_length, used_key_parts;
|
||||
|
||||
QUICK_SELECT_I();
|
||||
virtual ~QUICK_SELECT_I(){};
|
||||
|
||||
/**/
|
||||
virtual int init() = 0;
|
||||
virtual int reset(void) = 0;
|
||||
virtual int get_next() = 0; /* get next record to retrieve */
|
||||
|
@ -97,27 +101,64 @@ 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 child of a index union or intersection
|
||||
scan. This call replaces init() call.
|
||||
*/
|
||||
virtual int init_ror_child_scan(bool reuse_handler)
|
||||
{ DBUG_ASSERT(0); return 1; }
|
||||
|
||||
virtual void cleanup_ror_child_scan() { DBUG_ASSERT(0); }
|
||||
virtual void save_last_pos(){};
|
||||
|
||||
/*
|
||||
Fill key_names with list of keys this quick select used;
|
||||
fill used_lenghth with correponding used lengths.
|
||||
This is used by select_describe.
|
||||
*/
|
||||
virtual void fill_keys_and_lengths(String *key_names,
|
||||
String *used_lengths)=0;
|
||||
|
||||
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;
|
||||
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
|
||||
class QUICK_RANGE_SELECT : public QUICK_SELECT_I
|
||||
{
|
||||
protected:
|
||||
bool next,dont_free;
|
||||
public:
|
||||
int error;
|
||||
handler *file;
|
||||
byte *record;
|
||||
protected:
|
||||
friend void print_quick_sel_range(QUICK_RANGE_SELECT *quick,
|
||||
const key_map* needed_reg);
|
||||
handler *file;
|
||||
bool free_file; /* if true, this quick select "owns" file and will free it */
|
||||
|
||||
protected:
|
||||
friend
|
||||
QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
|
||||
struct st_table_ref *ref);
|
||||
|
@ -131,17 +172,19 @@ 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;
|
||||
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();
|
||||
|
@ -157,7 +200,16 @@ public:
|
|||
int get_next();
|
||||
bool reverse_sorted() { return 0; }
|
||||
bool unique_key_range();
|
||||
int init_ror_child_scan(bool reuse_handler);
|
||||
void save_last_pos()
|
||||
{
|
||||
file->position(record);
|
||||
};
|
||||
int get_type() { return QS_TYPE_RANGE; }
|
||||
void fill_keys_and_lengths(String *key_names, String *used_lengths);
|
||||
#ifndef DBUG_OFF
|
||||
virtual void dbug_dump(int indent, bool verbose);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
@ -232,6 +284,11 @@ public:
|
|||
bool reverse_sorted() { return false; }
|
||||
bool unique_key_range() { return false; }
|
||||
int get_type() { return QS_TYPE_INDEX_MERGE; }
|
||||
void fill_keys_and_lengths(String *key_names, String *used_lengths);
|
||||
bool check_if_keys_used(List<Item> *fields);
|
||||
#ifndef DBUG_OFF
|
||||
virtual void dbug_dump(int indent, bool verbose);
|
||||
#endif
|
||||
|
||||
bool push_quick_back(QUICK_RANGE_SELECT *quick_sel_range);
|
||||
|
||||
|
@ -242,9 +299,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;
|
||||
|
||||
|
@ -262,6 +316,87 @@ public:
|
|||
READ_RECORD read_record;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
Rowid-Ordered Retrieval (ROR) index intersection quick select.
|
||||
This quick select produces an intersection of records returned by several
|
||||
QUICK_RANGE_SELECTs that return data ordered by rowid.
|
||||
*/
|
||||
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 fill_keys_and_lengths(String *key_names, String *used_lengths);
|
||||
bool check_if_keys_used(List<Item> *fields);
|
||||
#ifndef DBUG_OFF
|
||||
virtual void dbug_dump(int indent, bool verbose);
|
||||
#endif
|
||||
int init_ror_child_scan(bool reuse_handler);
|
||||
bool push_quick_back(QUICK_RANGE_SELECT *quick_sel_range);
|
||||
|
||||
/* range quick selects this intersection consists of */
|
||||
List<QUICK_RANGE_SELECT> quick_selects;
|
||||
|
||||
QUICK_RANGE_SELECT *cpk_quick;
|
||||
MEM_ROOT alloc;
|
||||
THD *thd;
|
||||
bool reset_called;
|
||||
bool need_to_fetch_row;
|
||||
};
|
||||
|
||||
/*
|
||||
Rowid-Ordered Retrieval index union select.
|
||||
|
||||
*/
|
||||
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 fill_keys_and_lengths(String *key_names, String *used_lengths);
|
||||
bool check_if_keys_used(List<Item> *fields);
|
||||
#ifndef DBUG_OFF
|
||||
virtual void dbug_dump(int indent, bool verbose);
|
||||
#endif
|
||||
|
||||
bool push_quick_back(QUICK_SELECT_I *quick_sel_range);
|
||||
|
||||
/* range quick selects this index_merge read consists of */
|
||||
List<QUICK_SELECT_I> quick_selects;
|
||||
|
||||
QUEUE queue;
|
||||
MEM_ROOT alloc;
|
||||
|
||||
THD *thd;
|
||||
byte *cur_rowid;
|
||||
byte *prev_rowid;
|
||||
uint rowid_length;
|
||||
bool reset_called;
|
||||
bool have_prev_rowid;
|
||||
|
||||
private:
|
||||
static int queue_cmp(void *arg, byte *val1, byte *val2);
|
||||
};
|
||||
|
||||
|
||||
|
||||
class QUICK_SELECT_DESC: public QUICK_RANGE_SELECT
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -151,6 +151,12 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order,
|
|||
select= 0;
|
||||
}
|
||||
|
||||
if (select && select->quick && select->quick->reset())
|
||||
{
|
||||
delete select;
|
||||
free_underlaid_joins(thd, &thd->lex->select_lex);
|
||||
DBUG_RETURN(-1); // This will force out message
|
||||
}
|
||||
init_read_record(&info,thd,table,select,1,1);
|
||||
deleted=0L;
|
||||
init_ftfuncs(thd, &thd->lex->select_lex, 1);
|
||||
|
@ -250,10 +256,10 @@ cleanup:
|
|||
|
||||
#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,
|
||||
|
@ -317,8 +323,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);
|
||||
}
|
||||
|
|
|
@ -6976,8 +6976,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;
|
||||
|
@ -7038,9 +7046,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
|
||||
|
@ -8961,6 +8971,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= &my_charset_latin1;
|
||||
int quick_type= -1;
|
||||
DBUG_ENTER("select_describe");
|
||||
DBUG_PRINT("info", ("Select 0x%lx, type %s, message %s",
|
||||
(ulong)join->select_lex, join->select_lex->type,
|
||||
|
@ -9006,8 +9017,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;
|
||||
|
@ -9028,6 +9041,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
|
|||
strlen(join_type_str[tab->type]),
|
||||
cs));
|
||||
uint j;
|
||||
/* Build "possible_keys" value and add it to item_list */
|
||||
if (!tab->keys.is_clear_all())
|
||||
{
|
||||
for (j=0 ; j < table->keys ; j++)
|
||||
|
@ -9044,6 +9058,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);
|
||||
|
||||
/* 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;
|
||||
|
@ -9078,48 +9094,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->fill_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
|
||||
|
@ -9134,7 +9111,10 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
|
|||
my_bool key_read=table->key_read;
|
||||
if (tab->type == JT_NEXT && 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
|
||||
|
|
|
@ -329,7 +329,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));
|
||||
|
|
|
@ -176,18 +176,11 @@ 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_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);
|
||||
|
@ -246,7 +239,9 @@ int mysql_update(THD *thd,
|
|||
if (open_cached_file(&tempfile, mysql_tmpdir,TEMP_PREFIX,
|
||||
DISK_BUFFER_SIZE, MYF(MY_WME)))
|
||||
goto err;
|
||||
|
||||
|
||||
if (select && select->quick && select->quick->reset())
|
||||
goto err;
|
||||
init_read_record(&info,thd,table,select,0,1);
|
||||
thd->proc_info="Searching rows for update";
|
||||
uint tmp_limit= limit;
|
||||
|
@ -300,6 +295,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;
|
||||
|
@ -732,26 +730,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)
|
||||
|
|
Loading…
Reference in a new issue