MDEV-21794: Optimizer flag rowid_filter leads to long query
Rowid Filter check is just like Index Condition Pushdown check: before we check the filter, we must check if we have walked out of the range we are scanning. (If we did, we should return, and not continue the scan). Consequences of this: - Rowid filtering doesn't work for keys that have partially-covered blob columns (just like Index Condition Pushdown) - The rowid filter function has three return values: CHECK_POS (passed) CHECK_NEG (filtered out), CHECK_OUT_OF_RANGE. All of the above is implemented in this patch
This commit is contained in:
parent
0253ea7f22
commit
8d85715d50
@ -127,31 +127,32 @@ extern HA_KEYSEG *ha_find_null(HA_KEYSEG *keyseg, const uchar *a);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Return values of index_cond_func_xxx functions.
|
Return values for pushed index condition or rowid filter check functions.
|
||||||
|
|
||||||
0=ICP_NO_MATCH - index tuple doesn't satisfy the pushed index condition (the
|
0=CHECK_NEG - The filter is not satisfied. The engine should discard this
|
||||||
engine should discard the tuple and go to the next one)
|
index tuple and continue the scan.
|
||||||
1=ICP_MATCH - index tuple satisfies the pushed index condition (the
|
1=CHECK_POS - The filter is statisfied. Current index tuple should be
|
||||||
engine should fetch and return the record)
|
returned to the SQL layer.
|
||||||
2=ICP_OUT_OF_RANGE - index tuple is out range that we're scanning, e.g. this
|
2=CHECK_OUT_OF_RANGE - the index tuple is outside of the range that we're
|
||||||
if we're scanning "t.key BETWEEN 10 AND 20" and got a
|
scanning. (Example: if we're scanning "t.key BETWEEN 10 AND
|
||||||
"t.key=21" tuple (the engine should stop scanning and
|
20" and got a "t.key=21" tuple) Tthe engine should stop
|
||||||
return HA_ERR_END_OF_FILE right away).
|
scanning and return HA_ERR_END_OF_FILE right away).
|
||||||
3=ICP_ABORTED_BY_USER - engine must stop scanning and should return
|
3=CHECK_ABORTED_BY_USER - the engine must stop scanning and should return
|
||||||
HA_ERR_ABORTED_BY_USER right away
|
HA_ERR_ABORTED_BY_USER right away
|
||||||
-1= ICP_ERROR - Reserved for internal errors in engines. Should not be
|
-1=CHECK_ERROR - Reserved for internal errors in engines. Should not be
|
||||||
returned by index_cond_func_xxx
|
returned by ICP or rowid filter check functions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef enum icp_result {
|
typedef enum check_result {
|
||||||
ICP_ERROR=-1,
|
CHECK_ERROR=-1,
|
||||||
ICP_NO_MATCH=0,
|
CHECK_NEG=0,
|
||||||
ICP_MATCH=1,
|
CHECK_POS=1,
|
||||||
ICP_OUT_OF_RANGE=2,
|
CHECK_OUT_OF_RANGE=2,
|
||||||
ICP_ABORTED_BY_USER=3
|
CHECK_ABORTED_BY_USER=3
|
||||||
} ICP_RESULT;
|
} check_result_t;
|
||||||
|
|
||||||
typedef ICP_RESULT (*index_cond_func_t)(void *param);
|
typedef check_result_t (*index_cond_func_t)(void *param);
|
||||||
typedef int (*rowid_filter_func_t)(void *param);
|
typedef check_result_t (*rowid_filter_func_t)(void *param);
|
||||||
|
typedef int (*rowid_filter_is_active_func_t)(void *param);
|
||||||
|
|
||||||
#endif /* _my_compare_h */
|
#endif /* _my_compare_h */
|
||||||
|
@ -54,6 +54,17 @@ orders CREATE TABLE `orders` (
|
|||||||
KEY `i_o_totalprice` (`o_totalprice`)
|
KEY `i_o_totalprice` (`o_totalprice`)
|
||||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
set optimizer_use_condition_selectivity=2;
|
set optimizer_use_condition_selectivity=2;
|
||||||
|
select
|
||||||
|
100 *
|
||||||
|
(select count(*) from lineitem
|
||||||
|
WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND l_quantity > 45
|
||||||
|
)
|
||||||
|
/
|
||||||
|
(select count(*) from lineitem
|
||||||
|
where l_shipdate BETWEEN '1997-01-01' AND '1997-06-30')
|
||||||
|
as correct_r_filtered_when_using_l_shipdate;
|
||||||
|
correct_r_filtered_when_using_l_shipdate
|
||||||
|
11.7647
|
||||||
set statement optimizer_switch='rowid_filter=on' for EXPLAIN SELECT l_orderkey, l_linenumber, l_shipdate, l_quantity FROM lineitem
|
set statement optimizer_switch='rowid_filter=on' for EXPLAIN SELECT l_orderkey, l_linenumber, l_shipdate, l_quantity FROM lineitem
|
||||||
WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND
|
WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND
|
||||||
l_quantity > 45;
|
l_quantity > 45;
|
||||||
@ -92,7 +103,7 @@ set statement optimizer_switch='rowid_filter=on' for ANALYZE SELECT l_orderkey,
|
|||||||
WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND
|
WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND
|
||||||
l_quantity > 45;
|
l_quantity > 45;
|
||||||
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
|
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
|
||||||
1 SIMPLE lineitem range|filter i_l_shipdate,i_l_quantity i_l_shipdate|i_l_quantity 4|9 NULL 509 (12%) 60.00 (3%) 11.69 100.00 Using index condition; Using where; Using rowid filter
|
1 SIMPLE lineitem range|filter i_l_shipdate,i_l_quantity i_l_shipdate|i_l_quantity 4|9 NULL 509 (12%) 60.00 (11%) 11.69 100.00 Using index condition; Using where; Using rowid filter
|
||||||
set statement optimizer_switch='rowid_filter=on' for ANALYZE FORMAT=JSON SELECT l_orderkey, l_linenumber, l_shipdate, l_quantity FROM lineitem
|
set statement optimizer_switch='rowid_filter=on' for ANALYZE FORMAT=JSON SELECT l_orderkey, l_linenumber, l_shipdate, l_quantity FROM lineitem
|
||||||
WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND
|
WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND
|
||||||
l_quantity > 45;
|
l_quantity > 45;
|
||||||
@ -117,7 +128,7 @@ ANALYZE
|
|||||||
"rows": 702,
|
"rows": 702,
|
||||||
"selectivity_pct": 11.69,
|
"selectivity_pct": 11.69,
|
||||||
"r_rows": 605,
|
"r_rows": 605,
|
||||||
"r_selectivity_pct": 3.6855,
|
"r_selectivity_pct": 11.765,
|
||||||
"r_buffer_size": "REPLACED",
|
"r_buffer_size": "REPLACED",
|
||||||
"r_filling_time_ms": "REPLACED"
|
"r_filling_time_ms": "REPLACED"
|
||||||
},
|
},
|
||||||
@ -641,7 +652,7 @@ WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND
|
|||||||
l_quantity > 45 AND
|
l_quantity > 45 AND
|
||||||
o_totalprice between 180000 and 230000;
|
o_totalprice between 180000 and 230000;
|
||||||
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
|
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
|
||||||
1 SIMPLE lineitem range|filter PRIMARY,i_l_shipdate,i_l_orderkey,i_l_orderkey_quantity,i_l_quantity i_l_shipdate|i_l_quantity 4|9 NULL 509 (12%) 60.00 (3%) 11.69 100.00 Using index condition; Using where; Using rowid filter
|
1 SIMPLE lineitem range|filter PRIMARY,i_l_shipdate,i_l_orderkey,i_l_orderkey_quantity,i_l_quantity i_l_shipdate|i_l_quantity 4|9 NULL 509 (12%) 60.00 (11%) 11.69 100.00 Using index condition; Using where; Using rowid filter
|
||||||
1 SIMPLE orders eq_ref|filter PRIMARY,i_o_totalprice PRIMARY|i_o_totalprice 4|9 dbt3_s001.lineitem.l_orderkey 1 (9%) 0.27 (25%) 9.27 100.00 Using where; Using rowid filter
|
1 SIMPLE orders eq_ref|filter PRIMARY,i_o_totalprice PRIMARY|i_o_totalprice 4|9 dbt3_s001.lineitem.l_orderkey 1 (9%) 0.27 (25%) 9.27 100.00 Using where; Using rowid filter
|
||||||
set statement optimizer_switch='rowid_filter=on' for ANALYZE FORMAT=JSON SELECT o_orderkey, l_linenumber, l_shipdate, l_quantity, o_totalprice
|
set statement optimizer_switch='rowid_filter=on' for ANALYZE FORMAT=JSON SELECT o_orderkey, l_linenumber, l_shipdate, l_quantity, o_totalprice
|
||||||
FROM orders JOIN lineitem ON o_orderkey=l_orderkey
|
FROM orders JOIN lineitem ON o_orderkey=l_orderkey
|
||||||
@ -675,7 +686,7 @@ ANALYZE
|
|||||||
"rows": 702,
|
"rows": 702,
|
||||||
"selectivity_pct": 11.69,
|
"selectivity_pct": 11.69,
|
||||||
"r_rows": 605,
|
"r_rows": 605,
|
||||||
"r_selectivity_pct": 3.6855,
|
"r_selectivity_pct": 11.765,
|
||||||
"r_buffer_size": "REPLACED",
|
"r_buffer_size": "REPLACED",
|
||||||
"r_filling_time_ms": "REPLACED"
|
"r_filling_time_ms": "REPLACED"
|
||||||
},
|
},
|
||||||
@ -2105,6 +2116,37 @@ EXPLAIN
|
|||||||
}
|
}
|
||||||
DROP TABLE t1,t2;
|
DROP TABLE t1,t2;
|
||||||
#
|
#
|
||||||
|
# MDEV-21794: Optimizer flag rowid_filter leads to long query
|
||||||
|
#
|
||||||
|
create table t10(a int);
|
||||||
|
insert into t10 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
|
||||||
|
create table t11(a int);
|
||||||
|
insert into t11 select A.a + B.a* 10 + C.a * 100 from t10 A, t10 B, t10 C;
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
el_id int(10) unsigned NOT NULL ,
|
||||||
|
el_index blob NOT NULL,
|
||||||
|
el_index_60 varbinary(60) NOT NULL,
|
||||||
|
filler blob,
|
||||||
|
PRIMARY KEY (el_id),
|
||||||
|
KEY el_index (el_index(60)),
|
||||||
|
KEY el_index_60 (el_index_60,el_id)
|
||||||
|
);
|
||||||
|
insert into t1
|
||||||
|
select
|
||||||
|
A.a+1000*B.a,
|
||||||
|
A.a+1000*B.a + 10000,
|
||||||
|
A.a+1000*B.a + 10000,
|
||||||
|
'filler-data-filler-data'
|
||||||
|
from
|
||||||
|
t11 A, t10 B;
|
||||||
|
# This must not use rowid_filter with key=el_index|el_index_60:
|
||||||
|
explain
|
||||||
|
select * from t1
|
||||||
|
where el_index like '10%' and (el_index_60 like '10%' or el_index_60 like '20%');
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 range el_index,el_index_60 el_index 62 NULL 645 Using where
|
||||||
|
drop table t10, t11, t1;
|
||||||
|
#
|
||||||
# MDEV-22160: SIGSEGV in st_join_table::save_explain_data on SELECT
|
# MDEV-22160: SIGSEGV in st_join_table::save_explain_data on SELECT
|
||||||
#
|
#
|
||||||
set @save_optimizer_switch= @@optimizer_switch;
|
set @save_optimizer_switch= @@optimizer_switch;
|
||||||
|
@ -39,6 +39,16 @@ set statement optimizer_switch='rowid_filter=on' for;
|
|||||||
let $without_filter=
|
let $without_filter=
|
||||||
set statement optimizer_switch='rowid_filter=off' for;
|
set statement optimizer_switch='rowid_filter=off' for;
|
||||||
|
|
||||||
|
select
|
||||||
|
100 *
|
||||||
|
(select count(*) from lineitem
|
||||||
|
WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND l_quantity > 45
|
||||||
|
)
|
||||||
|
/
|
||||||
|
(select count(*) from lineitem
|
||||||
|
where l_shipdate BETWEEN '1997-01-01' AND '1997-06-30')
|
||||||
|
as correct_r_filtered_when_using_l_shipdate;
|
||||||
|
|
||||||
let $q1=
|
let $q1=
|
||||||
SELECT l_orderkey, l_linenumber, l_shipdate, l_quantity FROM lineitem
|
SELECT l_orderkey, l_linenumber, l_shipdate, l_quantity FROM lineitem
|
||||||
WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND
|
WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND
|
||||||
@ -339,6 +349,42 @@ eval EXPLAIN FORMAT=JSON $q;
|
|||||||
|
|
||||||
DROP TABLE t1,t2;
|
DROP TABLE t1,t2;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-21794: Optimizer flag rowid_filter leads to long query
|
||||||
|
--echo #
|
||||||
|
create table t10(a int);
|
||||||
|
insert into t10 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
|
||||||
|
|
||||||
|
create table t11(a int);
|
||||||
|
insert into t11 select A.a + B.a* 10 + C.a * 100 from t10 A, t10 B, t10 C;
|
||||||
|
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
el_id int(10) unsigned NOT NULL ,
|
||||||
|
el_index blob NOT NULL,
|
||||||
|
el_index_60 varbinary(60) NOT NULL,
|
||||||
|
filler blob,
|
||||||
|
|
||||||
|
PRIMARY KEY (el_id),
|
||||||
|
KEY el_index (el_index(60)),
|
||||||
|
KEY el_index_60 (el_index_60,el_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
insert into t1
|
||||||
|
select
|
||||||
|
A.a+1000*B.a,
|
||||||
|
A.a+1000*B.a + 10000,
|
||||||
|
A.a+1000*B.a + 10000,
|
||||||
|
'filler-data-filler-data'
|
||||||
|
from
|
||||||
|
t11 A, t10 B;
|
||||||
|
|
||||||
|
--echo # This must not use rowid_filter with key=el_index|el_index_60:
|
||||||
|
explain
|
||||||
|
select * from t1
|
||||||
|
where el_index like '10%' and (el_index_60 like '10%' or el_index_60 like '20%');
|
||||||
|
|
||||||
|
drop table t10, t11, t1;
|
||||||
|
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
--echo # MDEV-22160: SIGSEGV in st_join_table::save_explain_data on SELECT
|
--echo # MDEV-22160: SIGSEGV in st_join_table::save_explain_data on SELECT
|
||||||
|
@ -55,6 +55,17 @@ orders CREATE TABLE `orders` (
|
|||||||
KEY `i_o_totalprice` (`o_totalprice`)
|
KEY `i_o_totalprice` (`o_totalprice`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||||
set optimizer_use_condition_selectivity=2;
|
set optimizer_use_condition_selectivity=2;
|
||||||
|
select
|
||||||
|
100 *
|
||||||
|
(select count(*) from lineitem
|
||||||
|
WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND l_quantity > 45
|
||||||
|
)
|
||||||
|
/
|
||||||
|
(select count(*) from lineitem
|
||||||
|
where l_shipdate BETWEEN '1997-01-01' AND '1997-06-30')
|
||||||
|
as correct_r_filtered_when_using_l_shipdate;
|
||||||
|
correct_r_filtered_when_using_l_shipdate
|
||||||
|
11.7647
|
||||||
set statement optimizer_switch='rowid_filter=on' for EXPLAIN SELECT l_orderkey, l_linenumber, l_shipdate, l_quantity FROM lineitem
|
set statement optimizer_switch='rowid_filter=on' for EXPLAIN SELECT l_orderkey, l_linenumber, l_shipdate, l_quantity FROM lineitem
|
||||||
WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND
|
WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND
|
||||||
l_quantity > 45;
|
l_quantity > 45;
|
||||||
@ -2034,6 +2045,37 @@ EXPLAIN
|
|||||||
}
|
}
|
||||||
DROP TABLE t1,t2;
|
DROP TABLE t1,t2;
|
||||||
#
|
#
|
||||||
|
# MDEV-21794: Optimizer flag rowid_filter leads to long query
|
||||||
|
#
|
||||||
|
create table t10(a int);
|
||||||
|
insert into t10 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
|
||||||
|
create table t11(a int);
|
||||||
|
insert into t11 select A.a + B.a* 10 + C.a * 100 from t10 A, t10 B, t10 C;
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
el_id int(10) unsigned NOT NULL ,
|
||||||
|
el_index blob NOT NULL,
|
||||||
|
el_index_60 varbinary(60) NOT NULL,
|
||||||
|
filler blob,
|
||||||
|
PRIMARY KEY (el_id),
|
||||||
|
KEY el_index (el_index(60)),
|
||||||
|
KEY el_index_60 (el_index_60,el_id)
|
||||||
|
);
|
||||||
|
insert into t1
|
||||||
|
select
|
||||||
|
A.a+1000*B.a,
|
||||||
|
A.a+1000*B.a + 10000,
|
||||||
|
A.a+1000*B.a + 10000,
|
||||||
|
'filler-data-filler-data'
|
||||||
|
from
|
||||||
|
t11 A, t10 B;
|
||||||
|
# This must not use rowid_filter with key=el_index|el_index_60:
|
||||||
|
explain
|
||||||
|
select * from t1
|
||||||
|
where el_index like '10%' and (el_index_60 like '10%' or el_index_60 like '20%');
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 range el_index,el_index_60 el_index 62 NULL 1000 Using where
|
||||||
|
drop table t10, t11, t1;
|
||||||
|
#
|
||||||
# MDEV-22160: SIGSEGV in st_join_table::save_explain_data on SELECT
|
# MDEV-22160: SIGSEGV in st_join_table::save_explain_data on SELECT
|
||||||
#
|
#
|
||||||
set @save_optimizer_switch= @@optimizer_switch;
|
set @save_optimizer_switch= @@optimizer_switch;
|
||||||
|
@ -5970,22 +5970,22 @@ int handler::compare_key2(key_range *range) const
|
|||||||
/**
|
/**
|
||||||
ICP callback - to be called by an engine to check the pushed condition
|
ICP callback - to be called by an engine to check the pushed condition
|
||||||
*/
|
*/
|
||||||
extern "C" enum icp_result handler_index_cond_check(void* h_arg)
|
extern "C" check_result_t handler_index_cond_check(void* h_arg)
|
||||||
{
|
{
|
||||||
handler *h= (handler*)h_arg;
|
handler *h= (handler*)h_arg;
|
||||||
THD *thd= h->table->in_use;
|
THD *thd= h->table->in_use;
|
||||||
enum icp_result res;
|
check_result_t res;
|
||||||
|
|
||||||
enum thd_kill_levels abort_at= h->has_transactions() ?
|
enum thd_kill_levels abort_at= h->has_transactions() ?
|
||||||
THD_ABORT_SOFTLY : THD_ABORT_ASAP;
|
THD_ABORT_SOFTLY : THD_ABORT_ASAP;
|
||||||
if (thd_kill_level(thd) > abort_at)
|
if (thd_kill_level(thd) > abort_at)
|
||||||
return ICP_ABORTED_BY_USER;
|
return CHECK_ABORTED_BY_USER;
|
||||||
|
|
||||||
if (h->end_range && h->compare_key2(h->end_range) > 0)
|
if (h->end_range && h->compare_key2(h->end_range) > 0)
|
||||||
return ICP_OUT_OF_RANGE;
|
return CHECK_OUT_OF_RANGE;
|
||||||
h->increment_statistics(&SSV::ha_icp_attempts);
|
h->increment_statistics(&SSV::ha_icp_attempts);
|
||||||
if ((res= h->pushed_idx_cond->val_int()? ICP_MATCH : ICP_NO_MATCH) ==
|
if ((res= h->pushed_idx_cond->val_int()? CHECK_POS : CHECK_NEG) ==
|
||||||
ICP_MATCH)
|
CHECK_POS)
|
||||||
h->increment_statistics(&SSV::ha_icp_match);
|
h->increment_statistics(&SSV::ha_icp_match);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -5996,12 +5996,30 @@ extern "C" enum icp_result handler_index_cond_check(void* h_arg)
|
|||||||
keys of the rows whose data is to be fetched against the used rowid filter
|
keys of the rows whose data is to be fetched against the used rowid filter
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern "C" int handler_rowid_filter_check(void *h_arg)
|
extern "C"
|
||||||
|
check_result_t handler_rowid_filter_check(void *h_arg)
|
||||||
{
|
{
|
||||||
handler *h= (handler*) h_arg;
|
handler *h= (handler*) h_arg;
|
||||||
TABLE *tab= h->get_table();
|
TABLE *tab= h->get_table();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Check for out-of-range and killed conditions only if we haven't done it
|
||||||
|
already in the pushed index condition check
|
||||||
|
*/
|
||||||
|
if (!h->pushed_idx_cond)
|
||||||
|
{
|
||||||
|
THD *thd= h->table->in_use;
|
||||||
|
enum thd_kill_levels abort_at= h->has_transactions() ?
|
||||||
|
THD_ABORT_SOFTLY : THD_ABORT_ASAP;
|
||||||
|
if (thd_kill_level(thd) > abort_at)
|
||||||
|
return CHECK_ABORTED_BY_USER;
|
||||||
|
|
||||||
|
if (h->end_range && h->compare_key2(h->end_range) > 0)
|
||||||
|
return CHECK_OUT_OF_RANGE;
|
||||||
|
}
|
||||||
|
|
||||||
h->position(tab->record[0]);
|
h->position(tab->record[0]);
|
||||||
return h->pushed_rowid_filter->check((char *) h->ref);
|
return h->pushed_rowid_filter->check((char*)h->ref)? CHECK_POS: CHECK_NEG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2913,9 +2913,9 @@ public:
|
|||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
extern "C" enum icp_result handler_index_cond_check(void* h_arg);
|
extern "C" check_result_t handler_index_cond_check(void* h_arg);
|
||||||
|
|
||||||
extern "C" int handler_rowid_filter_check(void* h_arg);
|
extern "C" check_result_t handler_rowid_filter_check(void* h_arg);
|
||||||
extern "C" int handler_rowid_filter_is_active(void* h_arg);
|
extern "C" int handler_rowid_filter_is_active(void* h_arg);
|
||||||
|
|
||||||
uint calculate_key_len(TABLE *, uint, const uchar *, key_part_map);
|
uint calculate_key_len(TABLE *, uint, const uchar *, key_part_map);
|
||||||
@ -4837,7 +4837,8 @@ public:
|
|||||||
|
|
||||||
virtual void set_lock_type(enum thr_lock_type lock);
|
virtual void set_lock_type(enum thr_lock_type lock);
|
||||||
|
|
||||||
friend enum icp_result handler_index_cond_check(void* h_arg);
|
friend check_result_t handler_index_cond_check(void* h_arg);
|
||||||
|
friend check_result_t handler_rowid_filter_check(void *h_arg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Find unique record by index or unique constrain
|
Find unique record by index or unique constrain
|
||||||
|
@ -469,6 +469,14 @@ TABLE::best_range_rowid_filter_for_partial_join(uint access_key_no,
|
|||||||
covering_keys.is_set(access_key_no))
|
covering_keys.is_set(access_key_no))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
// Disallow use of range filter if the key contains partially-covered
|
||||||
|
// columns.
|
||||||
|
for (uint i= 0; i < key_info[access_key_no].usable_key_parts; i++)
|
||||||
|
{
|
||||||
|
if (key_info[access_key_no].key_part[i].field->type() == MYSQL_TYPE_BLOB)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Currently we do not support usage of range filters if the table
|
Currently we do not support usage of range filters if the table
|
||||||
is accessed by the clustered primary key. It does not make sense
|
is accessed by the clustered primary key. It does not make sense
|
||||||
|
@ -3877,9 +3877,9 @@ exhausted:
|
|||||||
|
|
||||||
/*********************************************************************//**
|
/*********************************************************************//**
|
||||||
Check a pushed-down index condition.
|
Check a pushed-down index condition.
|
||||||
@return ICP_NO_MATCH, ICP_MATCH, or ICP_OUT_OF_RANGE */
|
@return CHECK_NEG, CHECK_POS, or CHECK_OUT_OF_RANGE */
|
||||||
static
|
static
|
||||||
ICP_RESULT
|
check_result_t
|
||||||
row_search_idx_cond_check(
|
row_search_idx_cond_check(
|
||||||
/*======================*/
|
/*======================*/
|
||||||
byte* mysql_rec, /*!< out: record
|
byte* mysql_rec, /*!< out: record
|
||||||
@ -3897,7 +3897,7 @@ row_search_idx_cond_check(
|
|||||||
|
|
||||||
if (!prebuilt->idx_cond) {
|
if (!prebuilt->idx_cond) {
|
||||||
if (!handler_rowid_filter_is_active(prebuilt->pk_filter)) {
|
if (!handler_rowid_filter_is_active(prebuilt->pk_filter)) {
|
||||||
return(ICP_MATCH);
|
return(CHECK_POS);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
MONITOR_INC(MONITOR_ICP_ATTEMPTS);
|
MONITOR_INC(MONITOR_ICP_ATTEMPTS);
|
||||||
@ -3922,7 +3922,7 @@ row_search_idx_cond_check(
|
|||||||
rec, prebuilt->index, offsets,
|
rec, prebuilt->index, offsets,
|
||||||
templ->icp_rec_field_no,
|
templ->icp_rec_field_no,
|
||||||
templ)) {
|
templ)) {
|
||||||
return(ICP_NO_MATCH);
|
return(CHECK_NEG);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3932,12 +3932,12 @@ row_search_idx_cond_check(
|
|||||||
index, if the case of the column has been updated in
|
index, if the case of the column has been updated in
|
||||||
the past, or a record has been deleted and a record
|
the past, or a record has been deleted and a record
|
||||||
inserted in a different case. */
|
inserted in a different case. */
|
||||||
ICP_RESULT result = prebuilt->idx_cond
|
check_result_t result = prebuilt->idx_cond
|
||||||
? handler_index_cond_check(prebuilt->idx_cond)
|
? handler_index_cond_check(prebuilt->idx_cond)
|
||||||
: ICP_MATCH;
|
: CHECK_POS;
|
||||||
|
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case ICP_MATCH:
|
case CHECK_POS:
|
||||||
if (handler_rowid_filter_is_active(prebuilt->pk_filter)) {
|
if (handler_rowid_filter_is_active(prebuilt->pk_filter)) {
|
||||||
ut_ad(!prebuilt->index->is_primary());
|
ut_ad(!prebuilt->index->is_primary());
|
||||||
if (prebuilt->clust_index_was_generated) {
|
if (prebuilt->clust_index_was_generated) {
|
||||||
@ -3952,9 +3952,18 @@ row_search_idx_cond_check(
|
|||||||
ut_ad(len == DATA_ROW_ID_LEN);
|
ut_ad(len == DATA_ROW_ID_LEN);
|
||||||
memcpy(prebuilt->row_id, data, DATA_ROW_ID_LEN);
|
memcpy(prebuilt->row_id, data, DATA_ROW_ID_LEN);
|
||||||
}
|
}
|
||||||
if (!handler_rowid_filter_check(prebuilt->pk_filter)) {
|
result = handler_rowid_filter_check(prebuilt->pk_filter);
|
||||||
MONITOR_INC(MONITOR_ICP_MATCH);
|
switch (result) {
|
||||||
return(ICP_NO_MATCH);
|
case CHECK_NEG:
|
||||||
|
MONITOR_INC(MONITOR_ICP_NO_MATCH);
|
||||||
|
return(result);
|
||||||
|
case CHECK_OUT_OF_RANGE:
|
||||||
|
MONITOR_INC(MONITOR_ICP_OUT_OF_RANGE);
|
||||||
|
return(result);
|
||||||
|
case CHECK_POS:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ut_error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Convert the remaining fields to MySQL format.
|
/* Convert the remaining fields to MySQL format.
|
||||||
@ -3966,19 +3975,19 @@ row_search_idx_cond_check(
|
|||||||
mysql_rec, prebuilt, rec, NULL, false,
|
mysql_rec, prebuilt, rec, NULL, false,
|
||||||
prebuilt->index, offsets)) {
|
prebuilt->index, offsets)) {
|
||||||
ut_ad(dict_index_is_clust(prebuilt->index));
|
ut_ad(dict_index_is_clust(prebuilt->index));
|
||||||
return(ICP_NO_MATCH);
|
return(CHECK_NEG);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MONITOR_INC(MONITOR_ICP_MATCH);
|
MONITOR_INC(MONITOR_ICP_MATCH);
|
||||||
return(result);
|
return(result);
|
||||||
case ICP_NO_MATCH:
|
case CHECK_NEG:
|
||||||
MONITOR_INC(MONITOR_ICP_NO_MATCH);
|
MONITOR_INC(MONITOR_ICP_NO_MATCH);
|
||||||
return(result);
|
return(result);
|
||||||
case ICP_OUT_OF_RANGE:
|
case CHECK_OUT_OF_RANGE:
|
||||||
MONITOR_INC(MONITOR_ICP_OUT_OF_RANGE);
|
MONITOR_INC(MONITOR_ICP_OUT_OF_RANGE);
|
||||||
return(result);
|
return(result);
|
||||||
case ICP_ERROR:
|
case CHECK_ERROR:
|
||||||
case ICP_ABORTED_BY_USER:
|
case CHECK_ABORTED_BY_USER:
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4414,12 +4423,12 @@ row_search_mvcc(
|
|||||||
switch (row_search_idx_cond_check(
|
switch (row_search_idx_cond_check(
|
||||||
buf, prebuilt,
|
buf, prebuilt,
|
||||||
rec, offsets)) {
|
rec, offsets)) {
|
||||||
case ICP_NO_MATCH:
|
case CHECK_NEG:
|
||||||
case ICP_OUT_OF_RANGE:
|
case CHECK_OUT_OF_RANGE:
|
||||||
case ICP_ABORTED_BY_USER:
|
case CHECK_ABORTED_BY_USER:
|
||||||
case ICP_ERROR:
|
case CHECK_ERROR:
|
||||||
goto shortcut_mismatch;
|
goto shortcut_mismatch;
|
||||||
case ICP_MATCH:
|
case CHECK_POS:
|
||||||
goto shortcut_match;
|
goto shortcut_match;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5198,14 +5207,14 @@ no_gap_lock:
|
|||||||
index entry. */
|
index entry. */
|
||||||
switch (row_search_idx_cond_check(
|
switch (row_search_idx_cond_check(
|
||||||
buf, prebuilt, rec, offsets)) {
|
buf, prebuilt, rec, offsets)) {
|
||||||
case ICP_NO_MATCH:
|
case CHECK_NEG:
|
||||||
goto next_rec;
|
goto next_rec;
|
||||||
case ICP_OUT_OF_RANGE:
|
case CHECK_OUT_OF_RANGE:
|
||||||
case ICP_ABORTED_BY_USER:
|
case CHECK_ABORTED_BY_USER:
|
||||||
case ICP_ERROR:
|
case CHECK_ERROR:
|
||||||
err = DB_RECORD_NOT_FOUND;
|
err = DB_RECORD_NOT_FOUND;
|
||||||
goto idx_cond_failed;
|
goto idx_cond_failed;
|
||||||
case ICP_MATCH:
|
case CHECK_POS:
|
||||||
goto requires_clust_rec;
|
goto requires_clust_rec;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5255,17 +5264,17 @@ locks_ok_del_marked:
|
|||||||
|
|
||||||
/* Check if the record matches the index condition. */
|
/* Check if the record matches the index condition. */
|
||||||
switch (row_search_idx_cond_check(buf, prebuilt, rec, offsets)) {
|
switch (row_search_idx_cond_check(buf, prebuilt, rec, offsets)) {
|
||||||
case ICP_NO_MATCH:
|
case CHECK_NEG:
|
||||||
if (did_semi_consistent_read) {
|
if (did_semi_consistent_read) {
|
||||||
row_unlock_for_mysql(prebuilt, TRUE);
|
row_unlock_for_mysql(prebuilt, TRUE);
|
||||||
}
|
}
|
||||||
goto next_rec;
|
goto next_rec;
|
||||||
case ICP_OUT_OF_RANGE:
|
case CHECK_OUT_OF_RANGE:
|
||||||
case ICP_ABORTED_BY_USER:
|
case CHECK_ABORTED_BY_USER:
|
||||||
case ICP_ERROR:
|
case CHECK_ERROR:
|
||||||
err = DB_RECORD_NOT_FOUND;
|
err = DB_RECORD_NOT_FOUND;
|
||||||
goto idx_cond_failed;
|
goto idx_cond_failed;
|
||||||
case ICP_MATCH:
|
case CHECK_POS:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
#define HA_RECOVER_QUICK 8 /* Don't check rows in data file */
|
#define HA_RECOVER_QUICK 8 /* Don't check rows in data file */
|
||||||
|
|
||||||
C_MODE_START
|
C_MODE_START
|
||||||
ICP_RESULT index_cond_func_maria(void *arg);
|
check_result_t index_cond_func_maria(void *arg);
|
||||||
C_MODE_END
|
C_MODE_END
|
||||||
|
|
||||||
extern TYPELIB maria_recover_typelib;
|
extern TYPELIB maria_recover_typelib;
|
||||||
@ -187,7 +187,7 @@ public:
|
|||||||
int find_unique_row(uchar *record, uint unique_idx);
|
int find_unique_row(uchar *record, uint unique_idx);
|
||||||
private:
|
private:
|
||||||
DsMrr_impl ds_mrr;
|
DsMrr_impl ds_mrr;
|
||||||
friend ICP_RESULT index_cond_func_maria(void *arg);
|
friend check_result_t index_cond_func_maria(void *arg);
|
||||||
friend void reset_thd_trn(THD *thd);
|
friend void reset_thd_trn(THD *thd);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -666,20 +666,20 @@ int _ma_read_key_record(MARIA_HA *info, uchar *buf, MARIA_RECORD_POS filepos)
|
|||||||
will look for column values there)
|
will look for column values there)
|
||||||
|
|
||||||
RETURN
|
RETURN
|
||||||
ICP_ERROR Error ; my_errno set to HA_ERR_CRASHED
|
CHECK_ERROR Error ; my_errno set to HA_ERR_CRASHED
|
||||||
ICP_NO_MATCH Index condition is not satisfied, continue scanning
|
CHECK_NEG Index condition is not satisfied, continue scanning
|
||||||
ICP_MATCH Index condition is satisfied
|
CHECK_POS Index condition is satisfied
|
||||||
ICP_OUT_OF_RANGE Index condition is not satisfied, end the scan.
|
CHECK_OUT_OF_RANGE Index condition is not satisfied, end the scan.
|
||||||
my_errno set to HA_ERR_END_OF_FILE
|
my_errno set to HA_ERR_END_OF_FILE
|
||||||
|
|
||||||
info->cur_row.lastpos is set to HA_OFFSET_ERROR in case of ICP_ERROR or
|
info->cur_row.lastpos is set to HA_OFFSET_ERROR in case of CHECK_ERROR or
|
||||||
ICP_OUT_OF_RANGE to indicate that we don't have any active row.
|
CHECK_OUT_OF_RANGE to indicate that we don't have any active row.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ICP_RESULT ma_check_index_cond(register MARIA_HA *info, uint keynr,
|
check_result_t ma_check_index_cond(register MARIA_HA *info, uint keynr,
|
||||||
uchar *record)
|
uchar *record)
|
||||||
{
|
{
|
||||||
ICP_RESULT res= ICP_MATCH;
|
check_result_t res= CHECK_POS;
|
||||||
if (info->index_cond_func)
|
if (info->index_cond_func)
|
||||||
{
|
{
|
||||||
if (_ma_put_key_in_record(info, keynr, FALSE, record))
|
if (_ma_put_key_in_record(info, keynr, FALSE, record))
|
||||||
@ -688,10 +688,10 @@ ICP_RESULT ma_check_index_cond(register MARIA_HA *info, uint keynr,
|
|||||||
maria_print_error(info->s, HA_ERR_CRASHED);
|
maria_print_error(info->s, HA_ERR_CRASHED);
|
||||||
info->cur_row.lastpos= HA_OFFSET_ERROR; /* No active record */
|
info->cur_row.lastpos= HA_OFFSET_ERROR; /* No active record */
|
||||||
my_errno= HA_ERR_CRASHED;
|
my_errno= HA_ERR_CRASHED;
|
||||||
res= ICP_ERROR;
|
res= CHECK_ERROR;
|
||||||
}
|
}
|
||||||
else if ((res= info->index_cond_func(info->index_cond_func_arg)) ==
|
else if ((res= info->index_cond_func(info->index_cond_func_arg)) ==
|
||||||
ICP_OUT_OF_RANGE)
|
CHECK_OUT_OF_RANGE)
|
||||||
{
|
{
|
||||||
/* We got beyond the end of scanned range */
|
/* We got beyond the end of scanned range */
|
||||||
info->cur_row.lastpos= HA_OFFSET_ERROR; /* No active record */
|
info->cur_row.lastpos= HA_OFFSET_ERROR; /* No active record */
|
||||||
|
@ -34,7 +34,7 @@ int maria_rkey(MARIA_HA *info, uchar *buf, int inx, const uchar *key_data,
|
|||||||
HA_KEYSEG *last_used_keyseg;
|
HA_KEYSEG *last_used_keyseg;
|
||||||
uint32 nextflag;
|
uint32 nextflag;
|
||||||
MARIA_KEY key;
|
MARIA_KEY key;
|
||||||
ICP_RESULT icp_res= ICP_MATCH;
|
check_result_t check= CHECK_POS;
|
||||||
DBUG_ENTER("maria_rkey");
|
DBUG_ENTER("maria_rkey");
|
||||||
DBUG_PRINT("enter", ("base:%p buf:%p inx: %d search_flag: %d",
|
DBUG_PRINT("enter", ("base:%p buf:%p inx: %d search_flag: %d",
|
||||||
info, buf, inx, search_flag));
|
info, buf, inx, search_flag));
|
||||||
@ -115,7 +115,7 @@ int maria_rkey(MARIA_HA *info, uchar *buf, int inx, const uchar *key_data,
|
|||||||
not satisfied with an out-of-range condition.
|
not satisfied with an out-of-range condition.
|
||||||
*/
|
*/
|
||||||
if ((*share->row_is_visible)(info) &&
|
if ((*share->row_is_visible)(info) &&
|
||||||
((icp_res= ma_check_index_cond(info, inx, buf)) != ICP_NO_MATCH))
|
((check= ma_check_index_cond(info, inx, buf)) != CHECK_NEG))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* The key references a concurrently inserted record. */
|
/* The key references a concurrently inserted record. */
|
||||||
@ -174,7 +174,7 @@ int maria_rkey(MARIA_HA *info, uchar *buf, int inx, const uchar *key_data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
} while (!(*share->row_is_visible)(info) ||
|
} while (!(*share->row_is_visible)(info) ||
|
||||||
((icp_res= ma_check_index_cond(info, inx, buf)) == 0));
|
((check= ma_check_index_cond(info, inx, buf)) == 0));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -186,7 +186,7 @@ int maria_rkey(MARIA_HA *info, uchar *buf, int inx, const uchar *key_data,
|
|||||||
|
|
||||||
if (info->cur_row.lastpos == HA_OFFSET_ERROR)
|
if (info->cur_row.lastpos == HA_OFFSET_ERROR)
|
||||||
{
|
{
|
||||||
if (icp_res == ICP_OUT_OF_RANGE)
|
if (check == CHECK_OUT_OF_RANGE)
|
||||||
{
|
{
|
||||||
/* We don't want HA_ERR_END_OF_FILE in this particular case */
|
/* We don't want HA_ERR_END_OF_FILE in this particular case */
|
||||||
my_errno= HA_ERR_KEY_NOT_FOUND;
|
my_errno= HA_ERR_KEY_NOT_FOUND;
|
||||||
|
@ -30,7 +30,7 @@ int maria_rnext(MARIA_HA *info, uchar *buf, int inx)
|
|||||||
uint flag;
|
uint flag;
|
||||||
MARIA_SHARE *share= info->s;
|
MARIA_SHARE *share= info->s;
|
||||||
MARIA_KEYDEF *keyinfo;
|
MARIA_KEYDEF *keyinfo;
|
||||||
ICP_RESULT icp_res= ICP_MATCH;
|
check_result_t check= CHECK_POS;
|
||||||
uint update_mask= HA_STATE_NEXT_FOUND;
|
uint update_mask= HA_STATE_NEXT_FOUND;
|
||||||
DBUG_ENTER("maria_rnext");
|
DBUG_ENTER("maria_rnext");
|
||||||
|
|
||||||
@ -107,7 +107,7 @@ int maria_rnext(MARIA_HA *info, uchar *buf, int inx)
|
|||||||
if (!error)
|
if (!error)
|
||||||
{
|
{
|
||||||
while (!(*share->row_is_visible)(info) ||
|
while (!(*share->row_is_visible)(info) ||
|
||||||
((icp_res= ma_check_index_cond(info, inx, buf)) == ICP_NO_MATCH))
|
((check= ma_check_index_cond(info, inx, buf)) == CHECK_NEG))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
If we are at the last key on the key page, allow writers to
|
If we are at the last key on the key page, allow writers to
|
||||||
@ -135,7 +135,7 @@ int maria_rnext(MARIA_HA *info, uchar *buf, int inx)
|
|||||||
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
|
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
|
||||||
info->update|= update_mask;
|
info->update|= update_mask;
|
||||||
|
|
||||||
if (error || icp_res != ICP_MATCH)
|
if (error || check != CHECK_POS)
|
||||||
{
|
{
|
||||||
fast_ma_writeinfo(info);
|
fast_ma_writeinfo(info);
|
||||||
if (my_errno == HA_ERR_KEY_NOT_FOUND)
|
if (my_errno == HA_ERR_KEY_NOT_FOUND)
|
||||||
|
@ -30,7 +30,7 @@ int maria_rnext_same(MARIA_HA *info, uchar *buf)
|
|||||||
int error;
|
int error;
|
||||||
uint inx,not_used[2];
|
uint inx,not_used[2];
|
||||||
MARIA_KEYDEF *keyinfo;
|
MARIA_KEYDEF *keyinfo;
|
||||||
ICP_RESULT icp_res= ICP_MATCH;
|
check_result_t check= CHECK_POS;
|
||||||
DBUG_ENTER("maria_rnext_same");
|
DBUG_ENTER("maria_rnext_same");
|
||||||
|
|
||||||
if ((int) (inx= info->lastinx) < 0 ||
|
if ((int) (inx= info->lastinx) < 0 ||
|
||||||
@ -92,7 +92,7 @@ int maria_rnext_same(MARIA_HA *info, uchar *buf)
|
|||||||
}
|
}
|
||||||
/* Skip rows that are inserted by other threads since we got a lock */
|
/* Skip rows that are inserted by other threads since we got a lock */
|
||||||
if ((info->s->row_is_visible)(info) &&
|
if ((info->s->row_is_visible)(info) &&
|
||||||
((icp_res= ma_check_index_cond(info, inx, buf)) != ICP_NO_MATCH))
|
((check= ma_check_index_cond(info, inx, buf)) != CHECK_NEG))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -102,7 +102,7 @@ int maria_rnext_same(MARIA_HA *info, uchar *buf)
|
|||||||
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
|
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
|
||||||
info->update|= HA_STATE_NEXT_FOUND | HA_STATE_RNEXT_SAME;
|
info->update|= HA_STATE_NEXT_FOUND | HA_STATE_RNEXT_SAME;
|
||||||
|
|
||||||
if (error || icp_res != ICP_MATCH)
|
if (error || check != CHECK_POS)
|
||||||
{
|
{
|
||||||
fast_ma_writeinfo(info);
|
fast_ma_writeinfo(info);
|
||||||
if (my_errno == HA_ERR_KEY_NOT_FOUND)
|
if (my_errno == HA_ERR_KEY_NOT_FOUND)
|
||||||
|
@ -28,7 +28,7 @@ int maria_rprev(MARIA_HA *info, uchar *buf, int inx)
|
|||||||
register uint flag;
|
register uint flag;
|
||||||
MARIA_SHARE *share= info->s;
|
MARIA_SHARE *share= info->s;
|
||||||
MARIA_KEYDEF *keyinfo;
|
MARIA_KEYDEF *keyinfo;
|
||||||
ICP_RESULT icp_res= ICP_MATCH;
|
check_result_t check= CHECK_POS;
|
||||||
DBUG_ENTER("maria_rprev");
|
DBUG_ENTER("maria_rprev");
|
||||||
|
|
||||||
if ((inx = _ma_check_index(info,inx)) < 0)
|
if ((inx = _ma_check_index(info,inx)) < 0)
|
||||||
@ -58,7 +58,7 @@ int maria_rprev(MARIA_HA *info, uchar *buf, int inx)
|
|||||||
{
|
{
|
||||||
my_off_t cur_keypage= info->last_keypage;
|
my_off_t cur_keypage= info->last_keypage;
|
||||||
while (!(*share->row_is_visible)(info) ||
|
while (!(*share->row_is_visible)(info) ||
|
||||||
((icp_res= ma_check_index_cond(info, inx, buf)) == ICP_NO_MATCH))
|
((check= ma_check_index_cond(info, inx, buf)) == CHECK_NEG))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
If we are at the last (i.e. first?) key on the key page,
|
If we are at the last (i.e. first?) key on the key page,
|
||||||
@ -86,7 +86,7 @@ int maria_rprev(MARIA_HA *info, uchar *buf, int inx)
|
|||||||
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
|
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
|
||||||
info->update|= HA_STATE_PREV_FOUND;
|
info->update|= HA_STATE_PREV_FOUND;
|
||||||
|
|
||||||
if (error || icp_res != ICP_MATCH)
|
if (error || check != CHECK_POS)
|
||||||
{
|
{
|
||||||
fast_ma_writeinfo(info);
|
fast_ma_writeinfo(info);
|
||||||
if (my_errno == HA_ERR_KEY_NOT_FOUND)
|
if (my_errno == HA_ERR_KEY_NOT_FOUND)
|
||||||
|
@ -1433,7 +1433,7 @@ extern my_bool maria_flush_log_for_page_none(PAGECACHE_IO_HOOK_ARGS *args);
|
|||||||
extern PAGECACHE *maria_log_pagecache;
|
extern PAGECACHE *maria_log_pagecache;
|
||||||
extern void ma_set_index_cond_func(MARIA_HA *info, index_cond_func_t func,
|
extern void ma_set_index_cond_func(MARIA_HA *info, index_cond_func_t func,
|
||||||
void *func_arg);
|
void *func_arg);
|
||||||
ICP_RESULT ma_check_index_cond(MARIA_HA *info, uint keynr, uchar *record);
|
check_result_t ma_check_index_cond(MARIA_HA *info, uint keynr, uchar *record);
|
||||||
|
|
||||||
extern my_bool ma_yield_and_check_if_killed(MARIA_HA *info, int inx);
|
extern my_bool ma_yield_and_check_if_killed(MARIA_HA *info, int inx);
|
||||||
extern my_bool ma_killed_standalone(MARIA_HA *);
|
extern my_bool ma_killed_standalone(MARIA_HA *);
|
||||||
|
@ -38,7 +38,7 @@ extern const char *myisam_recover_names[];
|
|||||||
extern ulonglong myisam_recover_options;
|
extern ulonglong myisam_recover_options;
|
||||||
|
|
||||||
C_MODE_START
|
C_MODE_START
|
||||||
ICP_RESULT index_cond_func_myisam(void *arg);
|
check_result_t index_cond_func_myisam(void *arg);
|
||||||
C_MODE_END
|
C_MODE_END
|
||||||
|
|
||||||
class ha_myisam: public handler
|
class ha_myisam: public handler
|
||||||
@ -175,5 +175,5 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
DsMrr_impl ds_mrr;
|
DsMrr_impl ds_mrr;
|
||||||
friend ICP_RESULT index_cond_func_myisam(void *arg);
|
friend check_result_t index_cond_func_myisam(void *arg);
|
||||||
};
|
};
|
||||||
|
@ -424,7 +424,7 @@ void mi_set_index_cond_func(MI_INFO *info, index_cond_func_t func,
|
|||||||
|
|
||||||
void mi_set_rowid_filter_func(MI_INFO *info,
|
void mi_set_rowid_filter_func(MI_INFO *info,
|
||||||
rowid_filter_func_t check_func,
|
rowid_filter_func_t check_func,
|
||||||
rowid_filter_func_t is_active_func,
|
rowid_filter_is_active_func_t is_active_func,
|
||||||
void *func_arg)
|
void *func_arg)
|
||||||
{
|
{
|
||||||
info->rowid_filter_func= check_func;
|
info->rowid_filter_func= check_func;
|
||||||
|
@ -490,58 +490,83 @@ int _mi_read_key_record(MI_INFO *info, my_off_t filepos, uchar *buf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
static
|
||||||
Save current key tuple to record and call index condition check function
|
int mi_unpack_index_tuple(MI_INFO *info, uint keynr, uchar *record)
|
||||||
|
|
||||||
SYNOPSIS
|
|
||||||
mi_check_index_cond()
|
|
||||||
info MyISAM handler
|
|
||||||
keynr Index we're running a scan on
|
|
||||||
record Record buffer to use (it is assumed that index check function
|
|
||||||
will look for column values there)
|
|
||||||
|
|
||||||
RETURN
|
|
||||||
ICP_ERROR Error
|
|
||||||
ICP_NO_MATCH Index condition is not satisfied, continue scanning
|
|
||||||
ICP_MATCH Index condition is satisfied
|
|
||||||
ICP_OUT_OF_RANGE Index condition is not satisfied, end the scan.
|
|
||||||
*/
|
|
||||||
|
|
||||||
ICP_RESULT mi_check_index_cond(register MI_INFO *info, uint keynr,
|
|
||||||
uchar *record)
|
|
||||||
{
|
{
|
||||||
ICP_RESULT res;
|
|
||||||
if (_mi_put_key_in_record(info, keynr, FALSE, record))
|
if (_mi_put_key_in_record(info, keynr, FALSE, record))
|
||||||
{
|
{
|
||||||
/* Impossible case; Can only happen if bug in code */
|
/* Impossible case; Can only happen if bug in code */
|
||||||
mi_print_error(info->s, HA_ERR_CRASHED);
|
mi_print_error(info->s, HA_ERR_CRASHED);
|
||||||
info->lastpos= HA_OFFSET_ERROR; /* No active record */
|
info->lastpos= HA_OFFSET_ERROR; /* No active record */
|
||||||
my_errno= HA_ERR_CRASHED;
|
my_errno= HA_ERR_CRASHED;
|
||||||
res= ICP_ERROR;
|
return 1;
|
||||||
}
|
}
|
||||||
else if ((res= info->index_cond_func(info->index_cond_func_arg)) ==
|
return 0;
|
||||||
ICP_OUT_OF_RANGE)
|
|
||||||
{
|
|
||||||
/* We got beyond the end of scanned range */
|
|
||||||
info->lastpos= HA_OFFSET_ERROR; /* No active record */
|
|
||||||
my_errno= HA_ERR_END_OF_FILE;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int mi_check_rowid_filter(MI_INFO *info)
|
static int mi_check_rowid_filter_is_active(MI_INFO *info)
|
||||||
{
|
|
||||||
return info->rowid_filter_func(info->rowid_filter_func_arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
int mi_check_rowid_filter_is_active(MI_INFO *info)
|
|
||||||
{
|
{
|
||||||
if (info->rowid_filter_is_active_func == NULL)
|
if (info->rowid_filter_is_active_func == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
return info->rowid_filter_is_active_func(info->rowid_filter_func_arg);
|
return info->rowid_filter_is_active_func(info->rowid_filter_func_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Check the current index tuple: Check ICP condition and/or Rowid Filter
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
mi_check_index_tuple()
|
||||||
|
info MyISAM handler
|
||||||
|
keynr Index we're running a scan on
|
||||||
|
record Record buffer to use (it is assumed that index check function
|
||||||
|
will look for column values there)
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
Check result according to check_result_t definition
|
||||||
|
*/
|
||||||
|
|
||||||
|
check_result_t mi_check_index_tuple(MI_INFO *info, uint keynr, uchar *record)
|
||||||
|
{
|
||||||
|
int need_unpack= TRUE;
|
||||||
|
check_result_t res= CHECK_POS;
|
||||||
|
|
||||||
|
if (info->index_cond_func)
|
||||||
|
{
|
||||||
|
if (mi_unpack_index_tuple(info, keynr, record))
|
||||||
|
res= CHECK_ERROR;
|
||||||
|
else if ((res= info->index_cond_func(info->index_cond_func_arg)) ==
|
||||||
|
CHECK_OUT_OF_RANGE)
|
||||||
|
{
|
||||||
|
/* We got beyond the end of scanned range */
|
||||||
|
info->lastpos= HA_OFFSET_ERROR; /* No active record */
|
||||||
|
my_errno= HA_ERR_END_OF_FILE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
If we got an error, out-of-range condition, or ICP condition computed to
|
||||||
|
FALSE - we don't need to check the Rowid Filter.
|
||||||
|
*/
|
||||||
|
if (res != CHECK_POS)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
need_unpack= FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check the Rowid Filter, if present */
|
||||||
|
if (mi_check_rowid_filter_is_active(info))
|
||||||
|
{
|
||||||
|
/* Unpack the index tuple if we haven't done it already */
|
||||||
|
if (need_unpack && mi_unpack_index_tuple(info, keynr, record))
|
||||||
|
res= CHECK_ERROR;
|
||||||
|
else
|
||||||
|
res= info->rowid_filter_func(info->rowid_filter_func_arg);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Retrieve auto_increment info
|
Retrieve auto_increment info
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ int mi_rkey(MI_INFO *info, uchar *buf, int inx, const uchar *key,
|
|||||||
MI_KEYDEF *keyinfo;
|
MI_KEYDEF *keyinfo;
|
||||||
HA_KEYSEG *last_used_keyseg;
|
HA_KEYSEG *last_used_keyseg;
|
||||||
uint pack_key_length, use_key_length, nextflag;
|
uint pack_key_length, use_key_length, nextflag;
|
||||||
ICP_RESULT res= ICP_NO_MATCH;
|
check_result_t res= CHECK_NEG;
|
||||||
DBUG_ENTER("mi_rkey");
|
DBUG_ENTER("mi_rkey");
|
||||||
DBUG_PRINT("enter", ("base: %p buf: %p inx: %d search_flag: %d",
|
DBUG_PRINT("enter", ("base: %p buf: %p inx: %d search_flag: %d",
|
||||||
info, buf, inx, search_flag));
|
info, buf, inx, search_flag));
|
||||||
@ -119,10 +119,7 @@ int mi_rkey(MI_INFO *info, uchar *buf, int inx, const uchar *key,
|
|||||||
while ((info->lastpos >= info->state->data_file_length &&
|
while ((info->lastpos >= info->state->data_file_length &&
|
||||||
(search_flag != HA_READ_KEY_EXACT ||
|
(search_flag != HA_READ_KEY_EXACT ||
|
||||||
last_used_keyseg != keyinfo->seg + keyinfo->keysegs)) ||
|
last_used_keyseg != keyinfo->seg + keyinfo->keysegs)) ||
|
||||||
(info->index_cond_func &&
|
(res= mi_check_index_tuple(info, inx, buf)) == CHECK_NEG)
|
||||||
(res= mi_check_index_cond(info, inx, buf)) == ICP_NO_MATCH) ||
|
|
||||||
(mi_check_rowid_filter_is_active(info) &&
|
|
||||||
!mi_check_rowid_filter(info)))
|
|
||||||
{
|
{
|
||||||
uint not_used[2];
|
uint not_used[2];
|
||||||
/*
|
/*
|
||||||
@ -162,12 +159,12 @@ int mi_rkey(MI_INFO *info, uchar *buf, int inx, const uchar *key,
|
|||||||
/* Aborted by user */
|
/* Aborted by user */
|
||||||
DBUG_ASSERT(info->lastpos == HA_OFFSET_ERROR &&
|
DBUG_ASSERT(info->lastpos == HA_OFFSET_ERROR &&
|
||||||
my_errno == HA_ERR_ABORTED_BY_USER);
|
my_errno == HA_ERR_ABORTED_BY_USER);
|
||||||
res= ICP_ERROR;
|
res= CHECK_ERROR;
|
||||||
buf= 0; /* Fast abort */
|
buf= 0; /* Fast abort */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (res == ICP_OUT_OF_RANGE)
|
if (res == CHECK_OUT_OF_RANGE)
|
||||||
{
|
{
|
||||||
/* Change error from HA_ERR_END_OF_FILE */
|
/* Change error from HA_ERR_END_OF_FILE */
|
||||||
DBUG_ASSERT(info->lastpos == HA_OFFSET_ERROR);
|
DBUG_ASSERT(info->lastpos == HA_OFFSET_ERROR);
|
||||||
|
@ -28,7 +28,7 @@ int mi_rnext(MI_INFO *info, uchar *buf, int inx)
|
|||||||
{
|
{
|
||||||
int error,changed;
|
int error,changed;
|
||||||
uint flag;
|
uint flag;
|
||||||
ICP_RESULT icp_res= ICP_MATCH;
|
check_result_t check= CHECK_POS;
|
||||||
uint update_mask= HA_STATE_NEXT_FOUND;
|
uint update_mask= HA_STATE_NEXT_FOUND;
|
||||||
DBUG_ENTER("mi_rnext");
|
DBUG_ENTER("mi_rnext");
|
||||||
|
|
||||||
@ -101,10 +101,7 @@ int mi_rnext(MI_INFO *info, uchar *buf, int inx)
|
|||||||
{
|
{
|
||||||
while ((info->s->concurrent_insert &&
|
while ((info->s->concurrent_insert &&
|
||||||
info->lastpos >= info->state->data_file_length) ||
|
info->lastpos >= info->state->data_file_length) ||
|
||||||
(info->index_cond_func &&
|
(check= mi_check_index_tuple(info, inx, buf)) == CHECK_NEG)
|
||||||
(icp_res= mi_check_index_cond(info, inx, buf)) == ICP_NO_MATCH) ||
|
|
||||||
(mi_check_rowid_filter_is_active(info) &&
|
|
||||||
!mi_check_rowid_filter(info)))
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
If we are at the last key on the key page, allow writers to
|
If we are at the last key on the key page, allow writers to
|
||||||
@ -137,7 +134,7 @@ int mi_rnext(MI_INFO *info, uchar *buf, int inx)
|
|||||||
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
|
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
|
||||||
info->update|= update_mask;
|
info->update|= update_mask;
|
||||||
|
|
||||||
if (error || icp_res != ICP_MATCH)
|
if (error || check != CHECK_POS)
|
||||||
{
|
{
|
||||||
fast_mi_writeinfo(info);
|
fast_mi_writeinfo(info);
|
||||||
if (my_errno == HA_ERR_KEY_NOT_FOUND)
|
if (my_errno == HA_ERR_KEY_NOT_FOUND)
|
||||||
|
@ -30,7 +30,7 @@ int mi_rnext_same(MI_INFO *info, uchar *buf)
|
|||||||
int error;
|
int error;
|
||||||
uint inx,not_used[2];
|
uint inx,not_used[2];
|
||||||
MI_KEYDEF *keyinfo;
|
MI_KEYDEF *keyinfo;
|
||||||
ICP_RESULT icp_res= ICP_MATCH;
|
check_result_t check= CHECK_POS;
|
||||||
DBUG_ENTER("mi_rnext_same");
|
DBUG_ENTER("mi_rnext_same");
|
||||||
|
|
||||||
if ((int) (inx=info->lastinx) < 0 || info->lastpos == HA_OFFSET_ERROR)
|
if ((int) (inx=info->lastinx) < 0 || info->lastpos == HA_OFFSET_ERROR)
|
||||||
@ -94,10 +94,7 @@ int mi_rnext_same(MI_INFO *info, uchar *buf)
|
|||||||
- rows that don't match index condition
|
- rows that don't match index condition
|
||||||
*/
|
*/
|
||||||
if (info->lastpos < info->state->data_file_length &&
|
if (info->lastpos < info->state->data_file_length &&
|
||||||
(!info->index_cond_func ||
|
(check= mi_check_index_tuple(info, inx, buf)) != CHECK_NEG)
|
||||||
(icp_res= mi_check_index_cond(info, inx, buf)) != ICP_NO_MATCH) &&
|
|
||||||
(!mi_check_rowid_filter_is_active(info) ||
|
|
||||||
mi_check_rowid_filter(info)))
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -109,7 +106,7 @@ int mi_rnext_same(MI_INFO *info, uchar *buf)
|
|||||||
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
|
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
|
||||||
info->update|= HA_STATE_NEXT_FOUND | HA_STATE_RNEXT_SAME;
|
info->update|= HA_STATE_NEXT_FOUND | HA_STATE_RNEXT_SAME;
|
||||||
|
|
||||||
if (error || icp_res != ICP_MATCH)
|
if (error || check != CHECK_POS)
|
||||||
{
|
{
|
||||||
fast_mi_writeinfo(info);
|
fast_mi_writeinfo(info);
|
||||||
if (my_errno == HA_ERR_KEY_NOT_FOUND)
|
if (my_errno == HA_ERR_KEY_NOT_FOUND)
|
||||||
|
@ -28,7 +28,7 @@ int mi_rprev(MI_INFO *info, uchar *buf, int inx)
|
|||||||
int error,changed;
|
int error,changed;
|
||||||
register uint flag;
|
register uint flag;
|
||||||
MYISAM_SHARE *share=info->s;
|
MYISAM_SHARE *share=info->s;
|
||||||
ICP_RESULT icp_res= ICP_MATCH;
|
check_result_t check= CHECK_POS;
|
||||||
DBUG_ENTER("mi_rprev");
|
DBUG_ENTER("mi_rprev");
|
||||||
|
|
||||||
if ((inx = _mi_check_index(info,inx)) < 0)
|
if ((inx = _mi_check_index(info,inx)) < 0)
|
||||||
@ -58,10 +58,7 @@ int mi_rprev(MI_INFO *info, uchar *buf, int inx)
|
|||||||
my_off_t cur_keypage= info->last_keypage;
|
my_off_t cur_keypage= info->last_keypage;
|
||||||
while ((share->concurrent_insert &&
|
while ((share->concurrent_insert &&
|
||||||
info->lastpos >= info->state->data_file_length) ||
|
info->lastpos >= info->state->data_file_length) ||
|
||||||
(info->index_cond_func &&
|
(check= mi_check_index_tuple(info, inx, buf)) == CHECK_NEG)
|
||||||
(icp_res= mi_check_index_cond(info, inx, buf)) == ICP_NO_MATCH) ||
|
|
||||||
(mi_check_rowid_filter_is_active(info) &&
|
|
||||||
!mi_check_rowid_filter(info)))
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
If we are at the last (i.e. first?) key on the key page,
|
If we are at the last (i.e. first?) key on the key page,
|
||||||
@ -95,7 +92,7 @@ int mi_rprev(MI_INFO *info, uchar *buf, int inx)
|
|||||||
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
|
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
|
||||||
info->update|= HA_STATE_PREV_FOUND;
|
info->update|= HA_STATE_PREV_FOUND;
|
||||||
|
|
||||||
if (error || icp_res != ICP_MATCH)
|
if (error || check != CHECK_POS)
|
||||||
{
|
{
|
||||||
fast_mi_writeinfo(info);
|
fast_mi_writeinfo(info);
|
||||||
if (my_errno == HA_ERR_KEY_NOT_FOUND)
|
if (my_errno == HA_ERR_KEY_NOT_FOUND)
|
||||||
|
@ -307,7 +307,7 @@ struct st_myisam_info
|
|||||||
index_cond_func_t index_cond_func; /* Index condition function */
|
index_cond_func_t index_cond_func; /* Index condition function */
|
||||||
void *index_cond_func_arg; /* parameter for the func */
|
void *index_cond_func_arg; /* parameter for the func */
|
||||||
rowid_filter_func_t rowid_filter_func; /* rowid filter check function */
|
rowid_filter_func_t rowid_filter_func; /* rowid filter check function */
|
||||||
rowid_filter_func_t rowid_filter_is_active_func; /* is activefunction */
|
rowid_filter_is_active_func_t rowid_filter_is_active_func; /* is activefunction */
|
||||||
void *rowid_filter_func_arg; /* parameter for the func */
|
void *rowid_filter_func_arg; /* parameter for the func */
|
||||||
THR_LOCK_DATA lock;
|
THR_LOCK_DATA lock;
|
||||||
uchar *rtree_recursion_state; /* For RTREE */
|
uchar *rtree_recursion_state; /* For RTREE */
|
||||||
@ -725,9 +725,8 @@ my_bool mi_dynmap_file(MI_INFO *info, my_off_t size);
|
|||||||
int mi_munmap_file(MI_INFO *info);
|
int mi_munmap_file(MI_INFO *info);
|
||||||
void mi_remap_file(MI_INFO *info, my_off_t size);
|
void mi_remap_file(MI_INFO *info, my_off_t size);
|
||||||
|
|
||||||
ICP_RESULT mi_check_index_cond(MI_INFO *info, uint keynr, uchar *record);
|
check_result_t mi_check_index_tuple(MI_INFO *info, uint keynr, uchar *record);
|
||||||
int mi_check_rowid_filter(MI_INFO *info);
|
|
||||||
int mi_check_rowid_filter_is_active(MI_INFO *info);
|
|
||||||
/* Functions needed by mi_check */
|
/* Functions needed by mi_check */
|
||||||
int killed_ptr(HA_CHECK *param);
|
int killed_ptr(HA_CHECK *param);
|
||||||
void mi_check_print_error(HA_CHECK *param, const char *fmt, ...);
|
void mi_check_print_error(HA_CHECK *param, const char *fmt, ...);
|
||||||
@ -738,7 +737,7 @@ extern void mi_set_index_cond_func(MI_INFO *info, index_cond_func_t check_func,
|
|||||||
void *func_arg);
|
void *func_arg);
|
||||||
extern void mi_set_rowid_filter_func(MI_INFO *info,
|
extern void mi_set_rowid_filter_func(MI_INFO *info,
|
||||||
rowid_filter_func_t check_func,
|
rowid_filter_func_t check_func,
|
||||||
rowid_filter_func_t is_active_func,
|
rowid_filter_is_active_func_t is_active_func,
|
||||||
void *func_arg);
|
void *func_arg);
|
||||||
int flush_blocks(HA_CHECK *param, KEY_CACHE *key_cache, File file,
|
int flush_blocks(HA_CHECK *param, KEY_CACHE *key_cache, File file,
|
||||||
ulonglong *dirty_part_map);
|
ulonglong *dirty_part_map);
|
||||||
|
@ -8680,17 +8680,18 @@ int ha_rocksdb::find_icp_matching_index_rec(const bool move_forward,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
const enum icp_result icp_status= handler_index_cond_check(this);
|
const check_result_t icp_status= handler_index_cond_check(this);
|
||||||
if (icp_status == ICP_NO_MATCH) {
|
if (icp_status == CHECK_NEG) {
|
||||||
rocksdb_smart_next(!move_forward, m_scan_it);
|
rocksdb_smart_next(!move_forward, m_scan_it);
|
||||||
continue; /* Get the next (or prev) index tuple */
|
continue; /* Get the next (or prev) index tuple */
|
||||||
}
|
}
|
||||||
else if (icp_status == ICP_OUT_OF_RANGE || icp_status == ICP_ABORTED_BY_USER) {
|
else if (icp_status == CHECK_OUT_OF_RANGE ||
|
||||||
|
icp_status == CHECK_ABORTED_BY_USER) {
|
||||||
/* We have walked out of range we are scanning */
|
/* We have walked out of range we are scanning */
|
||||||
table->status = STATUS_NOT_FOUND;
|
table->status = STATUS_NOT_FOUND;
|
||||||
return HA_ERR_END_OF_FILE;
|
return HA_ERR_END_OF_FILE;
|
||||||
}
|
}
|
||||||
else /* icp_status == ICP_MATCH */
|
else /* icp_status == CHECK_POS */
|
||||||
{
|
{
|
||||||
/* Index Condition is satisfied. We have rc==0, proceed to fetch the
|
/* Index Condition is satisfied. We have rc==0, proceed to fetch the
|
||||||
* row. */
|
* row. */
|
||||||
|
@ -5223,10 +5223,10 @@ static int smart_dbt_bf_callback(
|
|||||||
info->key_to_compare);
|
info->key_to_compare);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum icp_result ha_tokudb::toku_handler_index_cond_check(
|
check_result_t ha_tokudb::toku_handler_index_cond_check(
|
||||||
Item* pushed_idx_cond) {
|
Item* pushed_idx_cond) {
|
||||||
|
|
||||||
enum icp_result res;
|
check_result_t res;
|
||||||
if (end_range) {
|
if (end_range) {
|
||||||
int cmp;
|
int cmp;
|
||||||
#ifdef MARIADB_BASE_VERSION
|
#ifdef MARIADB_BASE_VERSION
|
||||||
@ -5235,10 +5235,10 @@ enum icp_result ha_tokudb::toku_handler_index_cond_check(
|
|||||||
cmp = compare_key_icp(end_range);
|
cmp = compare_key_icp(end_range);
|
||||||
#endif
|
#endif
|
||||||
if (cmp > 0) {
|
if (cmp > 0) {
|
||||||
return ICP_OUT_OF_RANGE;
|
return CHECK_OUT_OF_RANGE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res = pushed_idx_cond->val_int() ? ICP_MATCH : ICP_NO_MATCH;
|
res = pushed_idx_cond->val_int() ? CHECK_POS : CHECK_NEG;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5278,19 +5278,19 @@ int ha_tokudb::fill_range_query_buf(
|
|||||||
if (toku_pushed_idx_cond &&
|
if (toku_pushed_idx_cond &&
|
||||||
(tokudb_active_index == toku_pushed_idx_cond_keyno)) {
|
(tokudb_active_index == toku_pushed_idx_cond_keyno)) {
|
||||||
unpack_key(buf, key, tokudb_active_index);
|
unpack_key(buf, key, tokudb_active_index);
|
||||||
enum icp_result result =
|
check_result_t result =
|
||||||
toku_handler_index_cond_check(toku_pushed_idx_cond);
|
toku_handler_index_cond_check(toku_pushed_idx_cond);
|
||||||
|
|
||||||
// If we have reason to stop, we set icp_went_out_of_range and get out
|
// If we have reason to stop, we set icp_went_out_of_range and get out
|
||||||
// otherwise, if we simply see that the current key is no match,
|
// otherwise, if we simply see that the current key is no match,
|
||||||
// we tell the cursor to continue and don't store
|
// we tell the cursor to continue and don't store
|
||||||
// the key locally
|
// the key locally
|
||||||
if (result == ICP_OUT_OF_RANGE || thd_kill_level(thd)) {
|
if (result == CHECK_OUT_OF_RANGE || thd_kill_level(thd)) {
|
||||||
icp_went_out_of_range = true;
|
icp_went_out_of_range = true;
|
||||||
error = 0;
|
error = 0;
|
||||||
DEBUG_SYNC(ha_thd(), "tokudb_icp_asc_scan_out_of_range");
|
DEBUG_SYNC(ha_thd(), "tokudb_icp_asc_scan_out_of_range");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
} else if (result == ICP_NO_MATCH) {
|
} else if (result == CHECK_NEG) {
|
||||||
// Optimizer change for MyRocks also benefits us here in TokuDB as
|
// Optimizer change for MyRocks also benefits us here in TokuDB as
|
||||||
// opt_range.cc QUICK_SELECT::get_next now sets end_range during
|
// opt_range.cc QUICK_SELECT::get_next now sets end_range during
|
||||||
// descending scan. We should not ever hit this condition, but
|
// descending scan. We should not ever hit this condition, but
|
||||||
|
@ -1027,7 +1027,7 @@ private:
|
|||||||
int get_next(uchar* buf, int direction, DBT* key_to_compare, bool do_key_read);
|
int get_next(uchar* buf, int direction, DBT* key_to_compare, bool do_key_read);
|
||||||
int read_data_from_range_query_buff(uchar* buf, bool need_val, bool do_key_read);
|
int read_data_from_range_query_buff(uchar* buf, bool need_val, bool do_key_read);
|
||||||
// for ICP, only in MariaDB and MySQL 5.6
|
// for ICP, only in MariaDB and MySQL 5.6
|
||||||
enum icp_result toku_handler_index_cond_check(Item* pushed_idx_cond);
|
check_result_t toku_handler_index_cond_check(Item* pushed_idx_cond);
|
||||||
void invalidate_bulk_fetch();
|
void invalidate_bulk_fetch();
|
||||||
void invalidate_icp();
|
void invalidate_icp();
|
||||||
int delete_all_rows_internal();
|
int delete_all_rows_internal();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user