Ensure that test_quick_select doesn't return more rows than in the table

Other changes:
- In test_quick_select(), assume that if table->used_stats_records is 0
  then the table has 0 rows.
- Fixed prepare_simple_select() to populate table->used_stat_records
- Enusre that set_statistics_for_tables() doesn't cause used_stats_records
  to be 0 when using stat_tables.
- To get blackhole to work with replication, set stats.records to 2 so
  that test_quick_select() doesn't assume the table is empty.
This commit is contained in:
Monty 2021-10-05 17:08:16 +03:00 committed by Sergei Petrunia
parent 8b977a6c3a
commit c443dbff0e
16 changed files with 85 additions and 50 deletions

View file

@ -1445,10 +1445,10 @@ id select_type table type possible_keys key key_len ref rows r_rows filtered r_f
DELETE FROM t1 WHERE a = 10; DELETE FROM t1 WHERE a = 10;
EXPLAIN DELETE FROM t1 WHERE a = 10; EXPLAIN DELETE FROM t1 WHERE a = 10;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 1 Using where 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
ANALYZE DELETE FROM t1 WHERE a = 10; ANALYZE DELETE FROM t1 WHERE a = 10;
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 t1 ALL NULL NULL NULL NULL 1 0.00 100.00 100.00 Using where 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
DELETE FROM t1 USING t1, t2; DELETE FROM t1 USING t1, t2;
EXPLAIN DELETE FROM t1 USING t1, t2; EXPLAIN DELETE FROM t1 USING t1, t2;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
@ -1790,10 +1790,10 @@ id select_type table type possible_keys key key_len ref rows r_rows filtered r_f
DELETE FROM t1 WHERE a = 10; DELETE FROM t1 WHERE a = 10;
EXPLAIN DELETE FROM t1 WHERE a = 10; EXPLAIN DELETE FROM t1 WHERE a = 10;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 1 Using where 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
ANALYZE DELETE FROM t1 WHERE a = 10; ANALYZE DELETE FROM t1 WHERE a = 10;
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 t1 ALL NULL NULL NULL NULL 1 0.00 100.00 100.00 Using where 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
DELETE FROM t1 USING t1, t2; DELETE FROM t1 USING t1, t2;
EXPLAIN DELETE FROM t1 USING t1, t2; EXPLAIN DELETE FROM t1 USING t1, t2;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra

View file

@ -19281,7 +19281,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables 1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table 3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings: Warnings:
Note 1003 /* select#1 */ select NULL AS `f`,`v2`.`f` AS `f` from `test`.`t1` `a` straight_join `test`.`t1` `b` join `test`.`v2` where 0 Note 1003 /* select#1 */ select NULL AS `f`,NULL AS `f` from `test`.`t1` `a` straight_join `test`.`t1` `b` join `test`.`v2` where 0
DROP VIEW v1,v2; DROP VIEW v1,v2;
DROP TABLE t1; DROP TABLE t1;
# #
@ -19749,7 +19749,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1 1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1
1 PRIMARY <derived2> ref key0 key0 5 test.t3.id 2 1 PRIMARY <derived2> ref key0 key0 5 test.t3.id 2
3 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
2 DERIVED cp2 range NULL a 5 NULL 8 Using index for group-by 2 DERIVED cp2 range NULL a 5 NULL 7 Using index for group-by
explain format=json select * from t1, (select a from t1 cp2 group by a) dt, t3 explain format=json select * from t1, (select a from t1 cp2 group by a) dt, t3
where dt.a = t1.a and t1.a = t3.id and t1.a in (select a from t2); where dt.a = t1.a and t1.a = t3.id and t1.a in (select a from t2);
EXPLAIN EXPLAIN
@ -19830,7 +19830,7 @@ EXPLAIN
"key": "a", "key": "a",
"key_length": "5", "key_length": "5",
"used_key_parts": ["a"], "used_key_parts": ["a"],
"rows": 8, "rows": 7,
"filtered": 100, "filtered": 100,
"using_index_for_group_by": true "using_index_for_group_by": true
} }

View file

@ -11,7 +11,7 @@ table_name t1
table_type BASE TABLE table_type BASE TABLE
engine BLACKHOLE engine BLACKHOLE
row_format Fixed row_format Fixed
table_rows 0 table_rows 2
data_length 0 data_length 0
table_comment table_comment
select table_catalog, table_schema, table_name, table_type, engine, row_format, table_rows, data_length, table_comment from information_schema.tables where table_schema='test' and table_name='t2'; select table_catalog, table_schema, table_name, table_type, engine, row_format, table_rows, data_length, table_comment from information_schema.tables where table_schema='test' and table_name='t2';
@ -610,7 +610,7 @@ table_name t1
table_type BASE TABLE table_type BASE TABLE
engine BLACKHOLE engine BLACKHOLE
row_format Fixed row_format Fixed
table_rows 0 table_rows 2
data_length 0 data_length 0
table_comment table_comment
select table_catalog, table_schema, table_name, table_type, engine, row_format, table_rows, data_length, table_comment from information_schema.tables where table_schema='test' and table_name='t2'; select table_catalog, table_schema, table_name, table_type, engine, row_format, table_rows, data_length, table_comment from information_schema.tables where table_schema='test' and table_name='t2';

View file

@ -946,7 +946,7 @@ set optimizer_switch='index_condition_pushdown=off';
EXPLAIN EXTENDED EXPLAIN EXTENDED
SELECT * FROM t1, t2 WHERE a > 9; SELECT * FROM t1, t2 WHERE a > 9;
id select_type table type possible_keys key key_len ref rows filtered Extra id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 range a a 5 NULL 1 0.00 Using where 1 SIMPLE t1 range a a 5 NULL 1 100.00 Using where
1 SIMPLE t2 ALL NULL NULL NULL NULL 8 100.00 Using join buffer (flat, BNL join) 1 SIMPLE t2 ALL NULL NULL NULL NULL 8 100.00 Using join buffer (flat, BNL join)
Warnings: Warnings:
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a` > 9 Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a` > 9

View file

@ -9,18 +9,23 @@ select @@sql_safe_updates;
# #
create table t1 (a int, b int, primary key (a), key (b)); create table t1 (a int, b int, primary key (a), key (b));
update t1 set b=2 where a=1 or b=2; update t1 set b=2 where a=1 or b=2;
ERROR HY000: You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
explain update t1 set b=2 where a=1 or b=2; explain update t1 set b=2 where a=1 or b=2;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 1 Using where 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
delete from t1 where a=1 or b=2; delete from t1 where a=1 or b=2;
ERROR HY000: You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
explain delete from t1 where a=1 or b=2; explain delete from t1 where a=1 or b=2;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 1 Using where 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
insert into t1 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8); insert into t1 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8);
explain update t1 set b=2 where a=1 or b=2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge PRIMARY,b PRIMARY,b 4,5 NULL 2 Using union(PRIMARY,b); Using where; Using buffer
update t1 set b=2 where a=1 or b=2; update t1 set b=2 where a=1 or b=2;
set @@optimizer_switch="index_merge=off";
update t1 set b=2 where a=1 or b=2;
ERROR HY000: You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
delete from t1 where a=1 or b=2; delete from t1 where a=1 or b=2;
ERROR HY000: You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
drop table t1; drop table t1;
# #
# End of 10.3 tests # End of 10.3 tests

View file

@ -7,14 +7,17 @@ select @@sql_safe_updates;
--echo # MDEV-18304 sql_safe_updates does not work with OR clauses --echo # MDEV-18304 sql_safe_updates does not work with OR clauses
--echo # --echo #
create table t1 (a int, b int, primary key (a), key (b)); create table t1 (a int, b int, primary key (a), key (b));
--error ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE
update t1 set b=2 where a=1 or b=2; update t1 set b=2 where a=1 or b=2;
explain update t1 set b=2 where a=1 or b=2; explain update t1 set b=2 where a=1 or b=2;
--error ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE
delete from t1 where a=1 or b=2; delete from t1 where a=1 or b=2;
explain delete from t1 where a=1 or b=2; explain delete from t1 where a=1 or b=2;
insert into t1 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8); insert into t1 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8);
explain update t1 set b=2 where a=1 or b=2;
update t1 set b=2 where a=1 or b=2; update t1 set b=2 where a=1 or b=2;
set @@optimizer_switch="index_merge=off";
--error ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE
update t1 set b=2 where a=1 or b=2;
--error ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE
delete from t1 where a=1 or b=2; delete from t1 where a=1 or b=2;
drop table t1; drop table t1;

View file

@ -412,7 +412,7 @@ EXPLAIN
SELECT * FROM t1 STRAIGHT_JOIN t2 WHERE name IN ( 'AUS','YEM' ) AND id = 1; SELECT * FROM t1 STRAIGHT_JOIN t2 WHERE name IN ( 'AUS','YEM' ) AND id = 1;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 Using index 1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 Using index
1 SIMPLE t2 ALL NULL NULL NULL NULL 0 Using where 1 SIMPLE t2 ALL NULL NULL NULL NULL 1 Using where
ANALYZE TABLE t2; ANALYZE TABLE t2;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.t2 analyze status Engine-independent statistics collected test.t2 analyze status Engine-independent statistics collected

View file

@ -444,7 +444,7 @@ EXPLAIN
SELECT * FROM t1 STRAIGHT_JOIN t2 WHERE name IN ( 'AUS','YEM' ) AND id = 1; SELECT * FROM t1 STRAIGHT_JOIN t2 WHERE name IN ( 'AUS','YEM' ) AND id = 1;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 Using index 1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 Using index
1 SIMPLE t2 ALL NULL NULL NULL NULL 0 Using where 1 SIMPLE t2 ALL NULL NULL NULL NULL 1 Using where
ANALYZE TABLE t2; ANALYZE TABLE t2;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.t2 analyze status Engine-independent statistics collected test.t2 analyze status Engine-independent statistics collected

View file

@ -638,10 +638,10 @@ DEFAULT SUBSTRING_INDEX(USER(),'@',1)
); );
EXPLAIN UPDATE gafld SET nuigafld = 0 WHERE nuigafld = 10; EXPLAIN UPDATE gafld SET nuigafld = 0 WHERE nuigafld = 10;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE gafld ALL NULL NULL NULL NULL 1 Using where 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
EXPLAIN UPDATE gafld SET nuigafld = 0 WHERE nuigafld = 10; EXPLAIN UPDATE gafld SET nuigafld = 0 WHERE nuigafld = 10;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE gafld ALL NULL NULL NULL NULL 1 Using where 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
DROP TABLE gafld; DROP TABLE gafld;
# (duplicate) MDEV-17653 replace into generated columns is unstable # (duplicate) MDEV-17653 replace into generated columns is unstable
# Some columns are snipped from the MDEV test # Some columns are snipped from the MDEV test

View file

@ -191,8 +191,8 @@ min(7)
7 7
explain select min(7) from t2i join t1i; explain select min(7) from t2i join t1i;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1i ALL NULL NULL NULL NULL 0 1 SIMPLE t2i ALL NULL NULL NULL NULL 1
1 SIMPLE t2i ALL NULL NULL NULL NULL 1 Using join buffer (flat, BNL join) 1 SIMPLE t1i ALL NULL NULL NULL NULL 1 Using join buffer (flat, BNL join)
select min(7) from t2i join t1i; select min(7) from t2i join t1i;
min(7) min(7)
NULL NULL
@ -207,8 +207,8 @@ max(7)
7 7
explain select max(7) from t2i join t1i; explain select max(7) from t2i join t1i;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1i ALL NULL NULL NULL NULL 0 1 SIMPLE t2i ALL NULL NULL NULL NULL 1
1 SIMPLE t2i ALL NULL NULL NULL NULL 1 Using join buffer (flat, BNL join) 1 SIMPLE t1i ALL NULL NULL NULL NULL 1 Using join buffer (flat, BNL join)
select max(7) from t2i join t1i; select max(7) from t2i join t1i;
max(7) max(7)
NULL NULL
@ -239,7 +239,7 @@ select 1, max(1) from t1i where 1=99;
explain select count(*), min(7), max(7) from t1m, t1i; explain select count(*), min(7), max(7) from t1m, t1i;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1m system NULL NULL NULL NULL 0 Const row not found 1 SIMPLE t1m system NULL NULL NULL NULL 0 Const row not found
1 SIMPLE t1i ALL NULL NULL NULL NULL 0 1 SIMPLE t1i ALL NULL NULL NULL NULL 1
select count(*), min(7), max(7) from t1m, t1i; select count(*), min(7), max(7) from t1m, t1i;
count(*) min(7) max(7) count(*) min(7) max(7)
0 NULL NULL 0 NULL NULL
@ -253,7 +253,7 @@ count(*) min(7) max(7)
explain select count(*), min(7), max(7) from t2m, t1i; explain select count(*), min(7), max(7) from t2m, t1i;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2m system NULL NULL NULL NULL 1 1 SIMPLE t2m system NULL NULL NULL NULL 1
1 SIMPLE t1i ALL NULL NULL NULL NULL 0 1 SIMPLE t1i ALL NULL NULL NULL NULL 1
select count(*), min(7), max(7) from t2m, t1i; select count(*), min(7), max(7) from t2m, t1i;
count(*) min(7) max(7) count(*) min(7) max(7)
0 NULL NULL 0 NULL NULL

View file

@ -24,7 +24,7 @@ FROM information_schema.statistics WHERE table_name = 'test_ps_fetch_corrupted'
ORDER BY index_name, seq_in_index; ORDER BY index_name, seq_in_index;
seq_in_index 1 seq_in_index 1
column_name a column_name a
cardinality 0 cardinality 1
SELECT table_rows, avg_row_length, max_data_length, index_length SELECT table_rows, avg_row_length, max_data_length, index_length
FROM information_schema.tables WHERE table_name = 'test_ps_fetch_corrupted'; FROM information_schema.tables WHERE table_name = 'test_ps_fetch_corrupted';
table_rows 0 table_rows 0
@ -38,7 +38,7 @@ FROM information_schema.statistics WHERE table_name = 'test_ps_fetch_corrupted'
ORDER BY index_name, seq_in_index; ORDER BY index_name, seq_in_index;
seq_in_index 1 seq_in_index 1
column_name a column_name a
cardinality 0 cardinality 1
SELECT table_rows, avg_row_length, max_data_length, index_length SELECT table_rows, avg_row_length, max_data_length, index_length
FROM information_schema.tables WHERE table_name = 'test_ps_fetch_corrupted'; FROM information_schema.tables WHERE table_name = 'test_ps_fetch_corrupted';
table_rows 0 table_rows 0

View file

@ -22,7 +22,7 @@ FROM information_schema.statistics WHERE table_name = 'test_ps_fetch_nonexistent
ORDER BY index_name, seq_in_index; ORDER BY index_name, seq_in_index;
seq_in_index 1 seq_in_index 1
column_name a column_name a
cardinality 0 cardinality 1
SELECT table_rows, avg_row_length, max_data_length, index_length SELECT table_rows, avg_row_length, max_data_length, index_length
FROM information_schema.tables WHERE table_name = 'test_ps_fetch_nonexistent'; FROM information_schema.tables WHERE table_name = 'test_ps_fetch_nonexistent';
table_rows 0 table_rows 0

View file

@ -2683,11 +2683,16 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
Item *notnull_cond= NULL; Item *notnull_cond= NULL;
TABLE_READ_PLAN *best_trp= NULL; TABLE_READ_PLAN *best_trp= NULL;
SEL_ARG **backup_keys= 0; SEL_ARG **backup_keys= 0;
ha_rows table_records= head->stat_records();
/* We trust that if stat_records() is 0 the table is really empty! */
bool impossible_range= table_records == 0;
DBUG_ENTER("SQL_SELECT::test_quick_select"); DBUG_ENTER("SQL_SELECT::test_quick_select");
DBUG_PRINT("enter",("keys_to_use: %lu prev_tables: %lu const_tables: %lu", DBUG_PRINT("enter",("keys_to_use: %lu prev_tables: %lu const_tables: %lu",
(ulong) keys_to_use.to_ulonglong(), (ulong) prev_tables, (ulong) keys_to_use.to_ulonglong(), (ulong) prev_tables,
(ulong) const_tables)); (ulong) const_tables));
DBUG_PRINT("info", ("records: %lu", (ulong) head->stat_records())); DBUG_PRINT("info", ("records: %llu", (ulonglong) table_records));
DBUG_ASSERT(table_records || !head->file->stats.records);
delete quick; delete quick;
quick=0; quick=0;
needed_reg.clear_all(); needed_reg.clear_all();
@ -2696,10 +2701,8 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
DBUG_ASSERT(!head->is_filled_at_execution()); DBUG_ASSERT(!head->is_filled_at_execution());
if (keys_to_use.is_clear_all() || head->is_filled_at_execution()) if (keys_to_use.is_clear_all() || head->is_filled_at_execution())
DBUG_RETURN(0); DBUG_RETURN(0);
records= head->stat_records(); records= table_records;
notnull_cond= head->notnull_cond; notnull_cond= head->notnull_cond;
if (!records)
records++; /* purecov: inspected */
if (head->file->ha_table_flags() & HA_NON_COMPARABLE_ROWID) if (head->file->ha_table_flags() & HA_NON_COMPARABLE_ROWID)
only_single_index_range_scan= 1; only_single_index_range_scan= 1;
@ -2726,8 +2729,8 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
DBUG_PRINT("info",("Time to scan table: %g", read_time)); DBUG_PRINT("info",("Time to scan table: %g", read_time));
Json_writer_object table_records(thd); Json_writer_object table_info(thd);
table_records.add_table_name(head); table_info.add_table_name(head);
Json_writer_object trace_range(thd, "range_analysis"); Json_writer_object trace_range(thd, "range_analysis");
{ {
@ -2893,7 +2896,8 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
{ {
if (tree->type == SEL_TREE::IMPOSSIBLE) if (tree->type == SEL_TREE::IMPOSSIBLE)
{ {
records=0L; /* Return -1 from this function. */ records= 0;
impossible_range= 1; /* Return -1 from this function. */
read_time= (double) HA_POS_ERROR; read_time= (double) HA_POS_ERROR;
trace_range.add("impossible_range", true); trace_range.add("impossible_range", true);
goto free_mem; goto free_mem;
@ -2992,7 +2996,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
} }
if (optimizer_flag(thd, OPTIMIZER_SWITCH_INDEX_MERGE) && if (optimizer_flag(thd, OPTIMIZER_SWITCH_INDEX_MERGE) &&
head->stat_records() != 0 && !only_single_index_range_scan) table_records != 0 && !only_single_index_range_scan)
{ {
/* Try creating index_merge/ROR-union scan. */ /* Try creating index_merge/ROR-union scan. */
SEL_IMERGE *imerge; SEL_IMERGE *imerge;
@ -3034,7 +3038,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
if ((group_trp= get_best_group_min_max(&param, tree, read_time))) if ((group_trp= get_best_group_min_max(&param, tree, read_time)))
{ {
param.table->opt_range_condition_rows= MY_MIN(group_trp->records, param.table->opt_range_condition_rows= MY_MIN(group_trp->records,
head->stat_records()); table_records);
Json_writer_object grp_summary(thd, "best_group_range_summary"); Json_writer_object grp_summary(thd, "best_group_range_summary");
if (unlikely(thd->trace_started())) if (unlikely(thd->trace_started()))
@ -3059,6 +3063,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
if (best_trp) if (best_trp)
{ {
records= best_trp->records; records= best_trp->records;
impossible_range= records == 0; // No matching rows
if (!(quick= best_trp->make_quick(&param, TRUE)) || quick->init()) if (!(quick= best_trp->make_quick(&param, TRUE)) || quick->init())
{ {
delete quick; delete quick;
@ -3092,7 +3097,8 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
Assume that if the user is using 'limit' we will only need to scan Assume that if the user is using 'limit' we will only need to scan
limit rows if we are using a key limit rows if we are using a key
*/ */
DBUG_RETURN(records ? MY_TEST(quick) : -1); set_if_smaller(records, table_records);
DBUG_RETURN(impossible_range ? -1 : MY_TEST(quick));
} }
/**************************************************************************** /****************************************************************************

View file

@ -664,16 +664,19 @@ SQL_SELECT *prepare_simple_select(THD *thd, Item *cond,
/* Assume that no indexes cover all required fields */ /* Assume that no indexes cover all required fields */
table->covering_keys.clear_all(); table->covering_keys.clear_all();
table->file->info(HA_STATUS_VARIABLE);
table->used_stat_records= table->file->stats.records;
SQL_SELECT *res= make_select(table, 0, 0, cond, 0, 0, error); SQL_SELECT *res= make_select(table, 0, 0, cond, 0, 0, error);
if (unlikely(*error) || if (unlikely(!res) || unlikely(*error))
(likely(res) && unlikely(res->check_quick(thd, 0, HA_POS_ERROR))) || goto error;
(likely(res) && res->quick && unlikely(res->quick->reset()))) (void) res->check_quick(thd, 0, HA_POS_ERROR);
{ if (!res->quick || res->quick->reset() == 0)
delete res; return res;
res=0;
} error:
return res; delete res;
return 0;
} }
/* /*
@ -1076,7 +1079,9 @@ error:
new_trans.restore_old_transaction(); new_trans.restore_old_transaction();
error2: error2:
DBUG_RETURN(TRUE); if (!thd->is_error())
my_eof(thd);
DBUG_RETURN(thd->is_error());
} }

View file

@ -3741,10 +3741,15 @@ void set_statistics_for_table(THD *thd, TABLE *table)
{ {
TABLE_STATISTICS_CB *stats_cb= &table->s->stats_cb; TABLE_STATISTICS_CB *stats_cb= &table->s->stats_cb;
Table_statistics *read_stats= stats_cb->table_stats; Table_statistics *read_stats= stats_cb->table_stats;
table->used_stat_records=
/*
The MAX below is to ensure that we don't return 0 rows for a table if it
not guaranteed to be empty.
*/
table->used_stat_records=
(!check_eits_preferred(thd) || (!check_eits_preferred(thd) ||
!table->stats_is_read || read_stats->cardinality_is_null) ? !table->stats_is_read || read_stats->cardinality_is_null) ?
table->file->stats.records : read_stats->cardinality; table->file->stats.records : MY_MAX(read_stats->cardinality, 1);
/* /*
For partitioned table, EITS statistics is based on data from all partitions. For partitioned table, EITS statistics is based on data from all partitions.

View file

@ -182,6 +182,17 @@ int ha_blackhole::info(uint flag)
DBUG_ENTER("ha_blackhole::info"); DBUG_ENTER("ha_blackhole::info");
bzero((char*) &stats, sizeof(stats)); bzero((char*) &stats, sizeof(stats));
/*
The following is required to get replication to work as otherwise
test_quick_select() will think the table is empty and thus any
update/delete will not have any rows to update.
*/
stats.records= 2;
/*
Block size should not be 0 as this will cause division by zero
in scan_time()
*/
stats.block_size= 8192;
if (flag & HA_STATUS_AUTO) if (flag & HA_STATUS_AUTO)
stats.auto_increment_value= 1; stats.auto_increment_value= 1;
DBUG_RETURN(0); DBUG_RETURN(0);