diff --git a/mysql-test/r/percona_range_optimizer.result b/mysql-test/r/percona_range_optimizer.result new file mode 100644 index 00000000000..7e4f4b9081d --- /dev/null +++ b/mysql-test/r/percona_range_optimizer.result @@ -0,0 +1,13 @@ +CREATE TABLE t1 (a INTEGER, b INTEGER, PRIMARY KEY (a)); +CREATE TABLE t2 (a INTEGER, b INTEGER, PRIMARY KEY (a, b)); +INSERT INTO t1 VALUES (1, 1), (2, 2); +ANALYZE TABLE t1, t2; +Table Op Msg_type Msg_text +test.t1 analyze status OK +test.t2 analyze status OK +EXPLAIN FORMAT=TREE SELECT t1.b FROM t1 JOIN t2 WHERE t1.a = t2.a AND t2.a = 2 AND t2.b >= t1.b AND t2.b <= t1.b+2; +EXPLAIN +-> Filter: ((t2.a = 2) and (t2.b >= '2') and (t2.b <= (('2' + 2)))) (cost=COST rows=3) + -> Covering index range scan on t2 using PRIMARY over (a = 2 AND 2 <= b <= 4) (cost=COST rows=3) + +DROP TABLE t1, t2; diff --git a/mysql-test/t/percona_range_optimizer.test b/mysql-test/t/percona_range_optimizer.test new file mode 100644 index 00000000000..bd59e5ee8d4 --- /dev/null +++ b/mysql-test/t/percona_range_optimizer.test @@ -0,0 +1,28 @@ +# +# In the following test, t1 evaluates to const table. +# Ensure that range optimzer sets the upper scan boundary accordingly. +# (ensure that b<=4 boundary is set) +# + +CREATE TABLE t1 (a INTEGER, b INTEGER, PRIMARY KEY (a)); +CREATE TABLE t2 (a INTEGER, b INTEGER, PRIMARY KEY (a, b)); +INSERT INTO t1 VALUES (1, 1), (2, 2); + +--let $n = 1000 +--disable_query_log +BEGIN; +while($n) { + --eval INSERT INTO t2 VALUES (2, $n) + --dec $n +} +COMMIT; +--enable_query_log + +ANALYZE TABLE t1, t2; + +--replace_regex /cost=[0-9]*\.[0-9]*/cost=COST/ +EXPLAIN FORMAT=TREE SELECT t1.b FROM t1 JOIN t2 WHERE t1.a = t2.a AND t2.a = 2 AND t2.b >= t1.b AND t2.b <= t1.b+2; + + +# cleanup +DROP TABLE t1, t2; diff --git a/sql/sql_optimizer.cc b/sql/sql_optimizer.cc index 809975e3ed3..338ef344b36 100644 --- a/sql/sql_optimizer.cc +++ b/sql/sql_optimizer.cc @@ -6268,9 +6268,13 @@ static ha_rows get_quick_record_count(THD *thd, JOIN_TAB *tab, ha_rows limit, keys_to_use.merge(tab->skip_scan_keys); MEM_ROOT temp_mem_root(key_memory_test_quick_select_exec, thd->variables.range_alloc_block_size); + table_map const_tables = tab->join()->found_const_table_map; + table_map read_tables = tab->join()->is_executed() + ? (tab->prefix_tables() & ~tab->added_tables()) + : const_tables; int error = test_quick_select( - thd, thd->mem_root, &temp_mem_root, keys_to_use, 0, - 0, // empty table_map + thd, thd->mem_root, &temp_mem_root, keys_to_use, const_tables, + read_tables, limit, false, // don't force quick range ORDER_NOT_RELEVANT, tab->table(), tab->skip_records_in_range(),