[Commits] 988ff90256d: MDEV-20227: rocksdb.rocksdb_concurrent_delete fails on windows
by Sergei Petrunia 04 Aug '19
by Sergei Petrunia 04 Aug '19
04 Aug '19
revision-id: 988ff90256d2aacbcb6aaf57fc8984dc60ae74ff (mariadb-10.2.26-3-g988ff90256d)
parent(s): 09a85692a65634cda40214b6693f34bec2f5b73b
author: Sergei Petrunia
committer: Sergei Petrunia
timestamp: 2019-08-04 23:37:47 +0300
message:
MDEV-20227: rocksdb.rocksdb_concurrent_delete fails on windows
A combination of:
* lots of include'd test files where each has "--source
include/have_rocksdb.inc"
* for each such occurrence, MTR adds testsuite's arguments into server
arguments
* which hits some limit on the length of argv array on Windows, causing
the server to get garbage data in the last argument.
Work around this by commenting out one of the totally redundant
"source include/have_rocksdb.inc" lines.
---
storage/rocksdb/mysql-test/rocksdb/t/rocksdb_concurrent_delete.inc | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/storage/rocksdb/mysql-test/rocksdb/t/rocksdb_concurrent_delete.inc b/storage/rocksdb/mysql-test/rocksdb/t/rocksdb_concurrent_delete.inc
index 55f466a4d31..5336c77ee83 100644
--- a/storage/rocksdb/mysql-test/rocksdb/t/rocksdb_concurrent_delete.inc
+++ b/storage/rocksdb/mysql-test/rocksdb/t/rocksdb_concurrent_delete.inc
@@ -1,4 +1,7 @@
---source include/have_rocksdb.inc
+# MariaDB: including the below too many times causes really long argv list
+# in win_main()'s argument which blows up some limit on Windows.
+# Comment it out:
+#--source include/have_rocksdb.inc
--source include/have_debug_sync.inc
--source include/count_sessions.inc
1
0
[Commits] 638fa95e6b4: Post-merge fixes for rocksdb.group_min_max test
by Sergei Petrunia 03 Aug '19
by Sergei Petrunia 03 Aug '19
03 Aug '19
revision-id: 638fa95e6b4a3ea4ffd6d776f49096b61c84ab0f (mariadb-10.2.25-87-g638fa95e6b4)
parent(s): 731ef751758e3267745bfce582a3692115753289
author: Sergei Petrunia
committer: Sergei Petrunia
timestamp: 2019-08-03 23:15:44 +0300
message:
Post-merge fixes for rocksdb.group_min_max test
- Fix the LooseScan code to support storage engines that return
HA_ERR_END_OF_FILE if the index scan goes out of provided range
bounds
- Add a DBUG_EXECUTE_IF("force_group_by",...) to allow a test to
force a LooseScan
- Adjust rocksdb.group_min_max test not to use features not present
in MariaDB 10.2 (e.g. optimizer_trace. In MariaDB 10.4 it's present
but it doesn't meet the assumptions that the test makes about it
- Adjust the test result file:
= MariaDB doesn't support "Enhanced Loose Scan" that FB/MySQL has
= MariaDB has different cost calculations.
---
sql/opt_range.cc | 38 +-
.../mysql-test/rocksdb/include/group_min_max.inc | 49 +-
.../mysql-test/rocksdb/r/group_min_max.result | 663 +++++++++++----------
.../mysql-test/rocksdb/t/group_min_max.test | 5 +-
4 files changed, 395 insertions(+), 360 deletions(-)
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 3ba8c44d790..3f6c18dca5c 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -2428,6 +2428,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
KEY_PART *key_parts;
KEY *key_info;
PARAM param;
+ bool force_group_by = false;
if (check_stack_overrun(thd, 2*STACK_MIN_SIZE + sizeof(PARAM), buff))
DBUG_RETURN(0); // Fatal error flag is set
@@ -2555,15 +2556,20 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
Try to construct a QUICK_GROUP_MIN_MAX_SELECT.
Notice that it can be constructed no matter if there is a range tree.
*/
+ DBUG_EXECUTE_IF("force_group_by", force_group_by = true; );
group_trp= get_best_group_min_max(¶m, tree, best_read_time);
if (group_trp)
{
param.table->quick_condition_rows= MY_MIN(group_trp->records,
head->stat_records());
- if (group_trp->read_cost < best_read_time)
+ if (group_trp->read_cost < best_read_time || force_group_by)
{
best_trp= group_trp;
best_read_time= best_trp->read_cost;
+ if (force_group_by)
+ {
+ goto force_plan;
+ }
}
}
@@ -2663,6 +2669,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
}
}
+force_plan:
thd->mem_root= param.old_root;
/* If we got a read plan, create a quick select from it. */
@@ -11509,13 +11516,28 @@ int QUICK_RANGE_SELECT::get_next_prefix(uint prefix_length,
DBUG_ASSERT(cur_prefix != NULL);
result= file->ha_index_read_map(record, cur_prefix, keypart_map,
HA_READ_AFTER_KEY);
- if (result || last_range->max_keypart_map == 0)
- DBUG_RETURN(result);
-
- key_range previous_endpoint;
- last_range->make_max_endpoint(&previous_endpoint, prefix_length, keypart_map);
- if (file->compare_key(&previous_endpoint) <= 0)
- DBUG_RETURN(0);
+ if (result || last_range->max_keypart_map == 0) {
+ /*
+ Only return if actual failure occurred. For HA_ERR_KEY_NOT_FOUND
+ or HA_ERR_END_OF_FILE, we just want to continue to reach the next
+ set of ranges. It is possible for the storage engine to return
+ HA_ERR_KEY_NOT_FOUND/HA_ERR_END_OF_FILE even when there are more
+ keys if it respects the end range set by the read_range_first call
+ below.
+ */
+ if (result != HA_ERR_KEY_NOT_FOUND && result != HA_ERR_END_OF_FILE)
+ DBUG_RETURN(result);
+ } else {
+ /*
+ For storage engines that don't respect end range, check if we've
+ moved past the current range.
+ */
+ key_range previous_endpoint;
+ last_range->make_max_endpoint(&previous_endpoint, prefix_length,
+ keypart_map);
+ if (file->compare_key(&previous_endpoint) <= 0)
+ DBUG_RETURN(0);
+ }
}
uint count= ranges.elements - (uint)(cur_range - (QUICK_RANGE**) ranges.buffer);
diff --git a/storage/rocksdb/mysql-test/rocksdb/include/group_min_max.inc b/storage/rocksdb/mysql-test/rocksdb/include/group_min_max.inc
index 79ac367a73b..6c3e29537b1 100644
--- a/storage/rocksdb/mysql-test/rocksdb/include/group_min_max.inc
+++ b/storage/rocksdb/mysql-test/rocksdb/include/group_min_max.inc
@@ -266,6 +266,17 @@ select a1, max(c) from t2 where a1 in ('a','b','d') group by a1,a2,b;
# B) Equalities only over the non-group 'B' attributes
# plans
+--echo #
+--echo # MariaDB: we dont have the following patch:
+--echo #
+--echo # commit 60a92a79a3b7fde3c6efe91799e344b977c8e5c3
+--echo # Author: Manuel Ung <mung(a)fb.com>
+--echo # Date: Thu Apr 19 23:06:27 2018 -0700
+--echo #
+--echo # Enhance group-by loose index scan
+--echo #
+--echo # So the following results are not very meaningful, but are still kept here
+
explain select a1,a2,b,max(c),min(c) from t1 where (a2 = 'a') and (b = 'b') group by a1;
explain select a1,a2,b,max(c),min(c) from t1 where (a2 = 'a' or a2 = 'b') and (b = 'b') group by a1;
explain select a1,a2,b,max(c),min(c) from t1 where (a2 = 'a') and (b = 'b' or b = 'a') group by a1;
@@ -730,9 +741,9 @@ explain extended select a1,a2,count(a2) from t1 where (a1 > 'a') group by a1,a2,
explain extended select sum(ord(a1)) from t1 where (a1 > 'a') group by a1,a2,b;
# test multi_range_groupby flag
-set optimizer_switch = 'multi_range_groupby=off';
+#MariaDB: no support: set optimizer_switch = 'multi_range_groupby=off';
explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b = 'a' or b = 'b') group by a1;
-set optimizer_switch = 'default';
+#set optimizer_switch = 'default';
explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b = 'a' or b = 'b') group by a1;
@@ -1361,41 +1372,41 @@ drop table t1;
eval CREATE TABLE t (a INT, b INT, KEY(a,b)) engine=$engine;
INSERT INTO t VALUES (1,1), (2,2), (3,3), (4,4), (1,0), (3,2), (4,5);
ANALYZE TABLE t;
-let $DEFAULT_TRACE_MEM_SIZE=1048576; # 1MB
-eval set optimizer_trace_max_mem_size=$DEFAULT_TRACE_MEM_SIZE;
-set @@session.optimizer_trace='enabled=on';
-set end_markers_in_json=on;
+# MariaDB: 10.2 doesn't have trace, yet: let $DEFAULT_TRACE_MEM_SIZE=1048576; # 1MB
+# eval set optimizer_trace_max_mem_size=$DEFAULT_TRACE_MEM_SIZE;
+# set @@session.optimizer_trace='enabled=on';
+# set end_markers_in_json=on;
ANALYZE TABLE t;
SELECT a, SUM(DISTINCT a), MIN(b) FROM t GROUP BY a;
EXPLAIN SELECT a, SUM(DISTINCT a), MIN(b) FROM t GROUP BY a;
-SELECT TRACE RLIKE 'have_both_agg_distinct_and_min_max' AS OK
- FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+#SELECT TRACE RLIKE 'have_both_agg_distinct_and_min_max' AS OK
+# FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
SELECT a, SUM(DISTINCT a), MAX(b) FROM t GROUP BY a;
EXPLAIN SELECT a, SUM(DISTINCT a), MAX(b) FROM t GROUP BY a;
-SELECT TRACE RLIKE 'have_both_agg_distinct_and_min_max' AS OK
- FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+#SELECT TRACE RLIKE 'have_both_agg_distinct_and_min_max' AS OK
+# FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
SELECT a, MAX(b) FROM t GROUP BY a HAVING SUM(DISTINCT a);
EXPLAIN SELECT a, MAX(b) FROM t GROUP BY a HAVING SUM(DISTINCT a);
-SELECT TRACE RLIKE 'have_both_agg_distinct_and_min_max' AS OK
- FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+#SELECT TRACE RLIKE 'have_both_agg_distinct_and_min_max' AS OK
+# FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
SELECT SUM(DISTINCT a), MIN(b), MAX(b) FROM t;
EXPLAIN SELECT SUM(DISTINCT a), MIN(b), MAX(b) FROM t;
-SELECT TRACE RLIKE 'have_both_agg_distinct_and_min_max' AS OK
- FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+#SELECT TRACE RLIKE 'have_both_agg_distinct_and_min_max' AS OK
+# FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
SELECT a, SUM(DISTINCT a), MIN(b), MAX(b) FROM t GROUP BY a;
EXPLAIN SELECT a, SUM(DISTINCT a), MIN(b), MAX(b) FROM t GROUP BY a;
-SELECT TRACE RLIKE 'have_both_agg_distinct_and_min_max' AS OK
- FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+#SELECT TRACE RLIKE 'have_both_agg_distinct_and_min_max' AS OK
+# FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
-SET optimizer_trace_max_mem_size=DEFAULT;
-SET optimizer_trace=DEFAULT;
-SET end_markers_in_json=DEFAULT;
+#SET optimizer_trace_max_mem_size=DEFAULT;
+#SET optimizer_trace=DEFAULT;
+#SET end_markers_in_json=DEFAULT;
DROP TABLE t;
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/group_min_max.result b/storage/rocksdb/mysql-test/rocksdb/r/group_min_max.result
index 7fede0ac603..a1031f518e0 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/group_min_max.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/group_min_max.result
@@ -1,4 +1,5 @@
-set global debug="+d,force_group_by";
+set @debug_tmp= @@debug_dbug;
+set global debug_dbug="+d,force_group_by";
drop table if exists t1;
create table t1 (
a1 char(64), a2 char(64), b char(16), c char(16) not null, d char(16), dummy char(248) default ' '
@@ -134,34 +135,34 @@ Table Op Msg_type Msg_text
test.t3 analyze status OK
explain select a1, min(a2) from t1 group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 126 Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 130 NULL 63 Using index for group-by
explain select a1, max(a2) from t1 group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 65 NULL 126 Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 65 NULL 63 Using index for group-by
explain select a1, min(a2), max(a2) from t1 group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 126 Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 130 NULL 63 Using index for group-by
explain select a1, a2, b, min(c), max(c) from t1 group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 501 Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 251 Using index for group-by
explain select a1,a2,b,max(c),min(c) from t1 group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 501 Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 251 Using index for group-by
explain select a1,a2,b,max(c),min(c) from t2 group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_1,idx_t2_2 idx_t2_1 # NULL # Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 # NULL # Using index for group-by
explain select min(a2), a1, max(a2), min(a2), a1 from t1 group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 126 Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 130 NULL 63 Using index for group-by
explain select a1, b, min(c), a1, max(c), b, a2, max(c), max(c) from t1 group by a1, a2, b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 501 Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 251 Using index for group-by
explain select min(a2) from t1 group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 126 Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 130 NULL 63 Using index for group-by
explain select a2, min(c), max(c) from t1 group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 501 Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 251 Using index for group-by
select a1, min(a2) from t1 group by a1;
a1 min(a2)
a a
@@ -288,37 +289,37 @@ b i421 l421
b m422 p422
explain select a1,a2,b,min(c),max(c) from t1 where a1 < 'd' group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t1 where a1 >= 'b' group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
explain select a1,a2,b, max(c) from t1 where a1 >= 'c' or a1 < 'b' group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 1002 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 502 Using where; Using index for group-by
explain select a1, max(c) from t1 where a1 >= 'c' or a1 < 'b' group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 1002 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 502 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t1 where a1 >= 'c' or a2 < 'b' group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
explain select a1,a2,b, max(c) from t1 where a1 = 'z' or a1 = 'b' or a1 = 'd' group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 1503 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 753 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t1 where a1 = 'z' or a1 = 'b' or a1 = 'd' group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 1503 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 753 Using where; Using index for group-by
explain select a1,a2,b, max(c) from t1 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 2004 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 1004 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t1 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 2004 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 1004 Using where; Using index for group-by
explain select a1,min(c),max(c) from t1 where a1 >= 'b' group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
explain select a1, max(c) from t1 where a1 in ('a','b','d') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 1503 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 753 Using where; Using index for group-by
explain select a1,a2,b, max(c) from t2 where a1 < 'd' group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL # Using where; Using index for group-by
@@ -668,99 +669,109 @@ d d411
d h412
d l421
d p422
+#
+# MariaDB: we dont have the following patch:
+#
+# commit 60a92a79a3b7fde3c6efe91799e344b977c8e5c3
+# Author: Manuel Ung <mung(a)fb.com>
+# Date: Thu Apr 19 23:06:27 2018 -0700
+#
+# Enhance group-by loose index scan
+#
+# So the following results are not very meaningful, but are still kept here
explain select a1,a2,b,max(c),min(c) from t1 where (a2 = 'a') and (b = 'b') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 126 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 63 Using where; Using index for group-by
explain select a1,a2,b,max(c),min(c) from t1 where (a2 = 'a' or a2 = 'b') and (b = 'b') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 126 Using where; Using index for group-by
+1 SIMPLE t1 index NULL idx_t1_1 163 NULL 1000 Using where; Using index
explain select a1,a2,b,max(c),min(c) from t1 where (a2 = 'a') and (b = 'b' or b = 'a') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 126 Using where; Using index for group-by
+1 SIMPLE t1 index NULL idx_t1_1 163 NULL 1000 Using where; Using index
explain select a1,a2,b,max(c),min(c) from t1 where (a2 = 'a' or a2 = 'b') and (b = 'b' or b = 'a') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 126 Using where; Using index for group-by
+1 SIMPLE t1 index NULL idx_t1_1 163 NULL 1000 Using where; Using index
explain select a1,max(c),min(c) from t1 where (a2 = 'a') and (b = 'b') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 126 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 63 Using where; Using index for group-by
explain select a1,max(c),min(c) from t1 where (a2 = 'a' or a2 = 'b') and (b = 'b') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 126 Using where; Using index for group-by
+1 SIMPLE t1 index NULL idx_t1_1 163 NULL 1000 Using where; Using index
explain select a1,max(c),min(c) from t1 where (a2 = 'a') and (b = 'b' or b = 'a') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 126 Using where; Using index for group-by
+1 SIMPLE t1 index NULL idx_t1_1 163 NULL 1000 Using where; Using index
explain select a1,a2,b, max(c) from t1 where (b = 'b') group by a1,a2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 126 Using where; Using index for group-by
explain select a1,a2,b, max(c) from t1 where (b = 'b' or b = 'a') group by a1,a2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 index NULL idx_t1_1 163 NULL 1000 Using where; Using index
explain select a1,a2,b,min(c),max(c) from t1 where (b = 'b') group by a1,a2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 126 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t1 where (b = 'b' or b = 'a') group by a1,a2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 index NULL idx_t1_1 163 NULL 1000 Using where; Using index
explain select a1,a2, max(c) from t1 where (b = 'b') group by a1,a2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 126 Using where; Using index for group-by
explain select a1,a2, max(c) from t1 where (b = 'b' or b = 'a') group by a1,a2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 index NULL idx_t1_1 163 NULL 1000 Using where; Using index
explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL 126 Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL 63 Using where; Using index for group-by
explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a' or a2 = 'b') and (b = 'b') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL 126 Using where; Using index for group-by
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b' or b = 'a') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL 126 Using where; Using index for group-by
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
explain select a1,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL 126 Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL 63 Using where; Using index for group-by
explain select a1,max(c),min(c) from t2 where (a2 = 'a' or a2 = 'b') and (b = 'b') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL 126 Using where; Using index for group-by
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
explain select a1,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b' or b = 'a') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL 126 Using where; Using index for group-by
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
explain select a1,a2,b, max(c) from t2 where (b = 'b') group by a1,a2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_1,idx_t2_2 idx_t2_1 146 NULL 251 Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 146 NULL 126 Using where; Using index for group-by
explain select a1,a2,b, max(c) from t2 where (b = 'b' or b = 'a') group by a1,a2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_1,idx_t2_2 idx_t2_1 146 NULL 251 Using where; Using index for group-by
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
explain select a1,a2,b,min(c),max(c) from t2 where (b = 'b') group by a1,a2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_1,idx_t2_2 idx_t2_1 163 NULL 251 Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL 126 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t2 where (b = 'b' or b = 'a') group by a1,a2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_1,idx_t2_2 idx_t2_1 163 NULL 251 Using where; Using index for group-by
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
explain select a1,a2, max(c) from t2 where (b = 'b') group by a1,a2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_1,idx_t2_2 idx_t2_1 146 NULL 251 Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 146 NULL 126 Using where; Using index for group-by
explain select a1,a2, max(c) from t2 where (b = 'b' or b = 'a') group by a1,a2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_1,idx_t2_2 idx_t2_1 146 NULL 251 Using where; Using index for group-by
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
explain select a1,a2,b,max(c),min(c) from t3 where (a2 = 'a') and (b = 'b') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 range idx_t3_0,idx_t3_1,idx_t3_2 idx_t3_1 6 NULL 126 Using where; Using index for group-by
+1 SIMPLE t3 range NULL idx_t3_1 6 NULL 63 Using where; Using index for group-by
explain select a1,a2,b,max(c),min(c) from t3 where (a2 = 'a' or a2 = 'b') and (b = 'b') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 range idx_t3_0,idx_t3_1,idx_t3_2 idx_t3_1 6 NULL 126 Using where; Using index for group-by
+1 SIMPLE t3 index NULL idx_t3_1 10 NULL 1000 Using where; Using index
explain select a1,a2,b,max(c),min(c) from t3 where (a2 = 'a') and (b = 'b' or b = 'a') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 range idx_t3_0,idx_t3_1,idx_t3_2 idx_t3_1 6 NULL 126 Using where; Using index for group-by
+1 SIMPLE t3 index NULL idx_t3_1 10 NULL 1000 Using where; Using index
explain select a1,max(c),min(c) from t3 where (a2 = 'a') and (b = 'b') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 range idx_t3_0,idx_t3_1,idx_t3_2 idx_t3_1 6 NULL 126 Using where; Using index for group-by
+1 SIMPLE t3 range NULL idx_t3_1 6 NULL 63 Using where; Using index for group-by
explain select a1,max(c),min(c) from t3 where (a2 = 'a' or a2 = 'b') and (b = 'b') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 range idx_t3_0,idx_t3_1,idx_t3_2 idx_t3_1 6 NULL 126 Using where; Using index for group-by
+1 SIMPLE t3 index NULL idx_t3_1 10 NULL 1000 Using where; Using index
explain select a1,max(c),min(c) from t3 where (a2 = 'a') and (b = 'b' or b = 'a') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 range idx_t3_0,idx_t3_1,idx_t3_2 idx_t3_1 6 NULL 126 Using where; Using index for group-by
+1 SIMPLE t3 index NULL idx_t3_1 10 NULL 1000 Using where; Using index
select a1,a2,b,max(c),min(c) from t1 where (a2 = 'a') and (b = 'b') group by a1;
a1 a2 b max(c) min(c)
a a b h112 e112
@@ -769,22 +780,22 @@ c a b h312 e312
d a b h412 e412
select a1,a2,b,max(c),min(c) from t1 where (a2 = 'a' or a2 = 'b') and (b = 'b') group by a1;
a1 a2 b max(c) min(c)
-a b b p122 e112
-b b b p222 e212
-c b b p322 e312
-d b b p422 e412
+a a b p122 e112
+b a b p222 e212
+c a b p322 e312
+d a b p422 e412
select a1,a2,b,max(c),min(c) from t1 where (a2 = 'a') and (b = 'b' or b = 'a') group by a1;
a1 a2 b max(c) min(c)
-a a b h112 a111
-b a b h212 a211
-c a b h312 a311
-d a b h412 a411
+a a a h112 a111
+b a a h212 a211
+c a a h312 a311
+d a a h412 a411
select a1,a2,b,max(c),min(c) from t1 where (a2 = 'a' or a2 = 'b') and (b = 'b' or b = 'a') group by a1;
a1 a2 b max(c) min(c)
-a b b p122 a111
-b b b p222 a211
-c b b p322 a311
-d b b p422 a411
+a a a p122 a111
+b a a p222 a211
+c a a p322 a311
+d a a p422 a411
select a1,max(c),min(c) from t1 where (a2 = 'a') and (b = 'b') group by a1;
a1 max(c) min(c)
a h112 e112
@@ -815,14 +826,14 @@ d a b h412
d b b p422
select a1,a2,b, max(c) from t1 where (b = 'b' or b = 'a') group by a1,a2;
a1 a2 b max(c)
-a a b h112
-a b b p122
-b a b h212
-b b b p222
-c a b h312
-c b b p322
-d a b h412
-d b b p422
+a a a h112
+a b a p122
+b a a h212
+b b a p222
+c a a h312
+c b a p322
+d a a h412
+d b a p422
select a1,a2,b,min(c),max(c) from t1 where (b = 'b') group by a1,a2;
a1 a2 b min(c) max(c)
a a b e112 h112
@@ -835,14 +846,14 @@ d a b e412 h412
d b b m422 p422
select a1,a2,b,min(c),max(c) from t1 where (b = 'b' or b = 'a') group by a1,a2;
a1 a2 b min(c) max(c)
-a a b a111 h112
-a b b i121 p122
-b a b a211 h212
-b b b i221 p222
-c a b a311 h312
-c b b i321 p322
-d a b a411 h412
-d b b i421 p422
+a a a a111 h112
+a b a i121 p122
+b a a a211 h212
+b b a i221 p222
+c a a a311 h312
+c b a i321 p322
+d a a a411 h412
+d b a i421 p422
select a1,a2, max(c) from t1 where (b = 'b') group by a1,a2;
a1 a2 max(c)
a a h112
@@ -872,17 +883,18 @@ d a b h412 e412
e a b NULL NULL
select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a' or a2 = 'b') and (b = 'b') group by a1;
a1 a2 b max(c) min(c)
-a b b p122 e112
-b b b p222 e212
-c b b p322 e312
-d b b p422 e412
+a a b p122 e112
+b a b p222 e212
+c a b p322 e312
+d a b p422 e412
+e a b NULL NULL
select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b' or b = 'a') group by a1;
a1 a2 b max(c) min(c)
-a a b h112 a111
-b a b h212 a211
-c a b h312 a311
-d a b h412 a411
-e a b NULL NULL
+a a a h112 a111
+b a a h212 a211
+c a a h312 a311
+d a a h412 a411
+e a a NULL NULL
select a1,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b') group by a1;
a1 max(c) min(c)
a h112 e112
@@ -896,6 +908,7 @@ a p122 e112
b p222 e212
c p322 e312
d p422 e412
+e NULL NULL
select a1,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b' or b = 'a') group by a1;
a1 max(c) min(c)
a h112 a111
@@ -916,15 +929,15 @@ d b b p422
e a b NULL
select a1,a2,b, max(c) from t2 where (b = 'b' or b = 'a') group by a1,a2;
a1 a2 b max(c)
-a a b h112
-a b b p122
-b a b h212
-b b b p222
-c a b h312
-c b b p322
-d a b h412
-d b b p422
-e a b NULL
+a a a h112
+a b a p122
+b a a h212
+b b a p222
+c a a h312
+c b a p322
+d a a h412
+d b a p422
+e a a NULL
select a1,a2,b,min(c),max(c) from t2 where (b = 'b') group by a1,a2;
a1 a2 b min(c) max(c)
a a b e112 h112
@@ -938,15 +951,15 @@ d b b m422 p422
e a b NULL NULL
select a1,a2,b,min(c),max(c) from t2 where (b = 'b' or b = 'a') group by a1,a2;
a1 a2 b min(c) max(c)
-a a b a111 h112
-a b b i121 p122
-b a b a211 h212
-b b b i221 p222
-c a b a311 h312
-c b b i321 p322
-d a b a411 h412
-d b b i421 p422
-e a b NULL NULL
+a a a a111 h112
+a b a i121 p122
+b a a a211 h212
+b b a i221 p222
+c a a a311 h312
+c b a i321 p322
+d a a a411 h412
+d b a i421 p422
+e a a NULL NULL
select a1,a2, max(c) from t2 where (b = 'b') group by a1,a2;
a1 a2 max(c)
a a h112
@@ -976,14 +989,14 @@ b a b h212 e212
c a b h312 e312
select a1,a2,b,max(c),min(c) from t3 where (a2 = 'a' or a2 = 'b') and (b = 'b') group by a1;
a1 a2 b max(c) min(c)
-a b b p122 e112
-b b b p222 e212
-c b b p322 e312
+a a b p122 e112
+b a b p222 e212
+c a b p322 e312
select a1,a2,b,max(c),min(c) from t3 where (a2 = 'a') and (b = 'b' or b = 'a') group by a1;
a1 a2 b max(c) min(c)
-a a b h112 a111
-b a b h212 a211
-c a b h312 a311
+a a a h112 a111
+b a a h212 a211
+c a a h312 a311
select a1,max(c),min(c) from t3 where (a2 = 'a') and (b = 'b') group by a1;
a1 max(c) min(c)
a h112 e112
@@ -1001,37 +1014,41 @@ b h212 a211
c h312 a311
explain select a1,a2,b,min(c) from t2 where (a2 = 'a') and b is NULL group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL 126 Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL 63 Using where; Using index for group-by
explain select a1,a2,b,min(c) from t2 where (a2 = 'a' or a2 = 'b') and b is NULL group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL 126 Using where; Using index for group-by
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
explain select a1,a2,b,max(c) from t2 where (a2 = 'a') and b is NULL group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL 126 Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 146 NULL 63 Using where; Using index for group-by
explain select a1,a2,b,max(c) from t2 where (a2 = 'a' or a2 = 'b') and b is NULL group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL 126 Using where; Using index for group-by
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
explain select a1,a2,b,min(c) from t2 where b is NULL group by a1,a2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_1,idx_t2_2 idx_t2_1 163 NULL 251 Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL 126 Using where; Using index for group-by
explain select a1,a2,b,max(c) from t2 where b is NULL group by a1,a2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_1,idx_t2_2 idx_t2_1 146 NULL 251 Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 146 NULL 126 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t2 where b is NULL group by a1,a2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_1,idx_t2_2 idx_t2_1 163 NULL 251 Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL 126 Using where; Using index for group-by
select a1,a2,b,min(c) from t2 where (a2 = 'a') and b is NULL group by a1;
a1 a2 b min(c)
a a NULL a777
c a NULL c777
select a1,a2,b,min(c) from t2 where (a2 = 'a' or a2 = 'b') and b is NULL group by a1;
a1 a2 b min(c)
+a a NULL a777
+c a NULL c777
select a1,a2,b,max(c) from t2 where (a2 = 'a') and b is NULL group by a1;
a1 a2 b max(c)
a a NULL a999
c a NULL c999
select a1,a2,b,max(c) from t2 where (a2 = 'a' or a2 = 'b') and b is NULL group by a1;
a1 a2 b max(c)
+a a NULL a999
+c a NULL c999
select a1,a2,b,min(c) from t2 where b is NULL group by a1,a2;
a1 a2 b min(c)
a a NULL a777
@@ -1050,97 +1067,97 @@ a a NULL a777 a999
c a NULL c777 c999
explain select a1,a2,b, max(c) from t1 where (c > 'b1') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 147 NULL # Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL # Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t1 where (c > 'b1') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 251 Using where; Using index for group-by
explain select a1,a2,b, max(c) from t1 where (c > 'f123') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 251 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t1 where (c > 'f123') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 251 Using where; Using index for group-by
explain select a1,a2,b, max(c) from t1 where (c < 'a0') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 251 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t1 where (c < 'a0') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 251 Using where; Using index for group-by
explain select a1,a2,b, max(c) from t1 where (c < 'k321') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 251 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t1 where (c < 'k321') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 251 Using where; Using index for group-by
explain select a1,a2,b, max(c) from t1 where (c < 'a0') or (c > 'b1') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 251 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t1 where (c < 'a0') or (c > 'b1') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 251 Using where; Using index for group-by
explain select a1,a2,b, max(c) from t1 where (c > 'b1') or (c <= 'g1') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 251 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t1 where (c > 'b1') or (c <= 'g1') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 251 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t1 where (c > 'b111') and (c <= 'g112') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 251 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t1 where (c < 'c5') or (c = 'g412') or (c = 'k421') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 251 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t1 where ((c > 'b111') and (c <= 'g112')) or ((c > 'd000') and (c <= 'i110')) group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 251 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t1 where (c between 'b111' and 'g112') or (c between 'd000' and 'i110') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 251 Using where; Using index for group-by
explain select a1,a2,b, max(c) from t2 where (c > 'b1') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_1,idx_t2_2 idx_t2_1 146 NULL # Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 146 NULL # Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t2 where (c > 'b1') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
explain select a1,a2,b, max(c) from t2 where (c > 'f123') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_1,idx_t2_2 idx_t2_1 146 NULL # Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 146 NULL # Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t2 where (c > 'f123') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
explain select a1,a2,b, max(c) from t2 where (c < 'a0') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t2 where (c < 'a0') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
explain select a1,a2,b, max(c) from t2 where (c < 'k321') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t2 where (c < 'k321') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
explain select a1,a2,b, max(c) from t2 where (c < 'a0') or (c > 'b1') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t2 where (c < 'a0') or (c > 'b1') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
explain select a1,a2,b, max(c) from t2 where (c > 'b1') or (c <= 'g1') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_1,idx_t2_2 idx_t2_1 146 NULL # Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 146 NULL # Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t2 where (c > 'b1') or (c <= 'g1') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t2 where (c > 'b111') and (c <= 'g112') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t2 where (c < 'c5') or (c = 'g412') or (c = 'k421') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t2 where ((c > 'b111') and (c <= 'g112')) or ((c > 'd000') and (c <= 'i110')) group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
select a1,a2,b, max(c) from t1 where (c > 'b1') group by a1,a2,b;
a1 a2 b max(c)
a a a d111
@@ -1562,35 +1579,36 @@ explain select a1,a2,b,min(c),max(c) from t1
where exists ( select * from t2 where t2.c = t1.c )
group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 index idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 1000 Using where; Using index
-2 DEPENDENT SUBQUERY t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
+1 PRIMARY t1 index NULL idx_t1_1 163 NULL 1000 Using index
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 16 func 1
+2 MATERIALIZED t2 index NULL idx_t2_1 163 NULL 1000 Using index
explain select a1,a2,b,min(c),max(c) from t1
where exists ( select * from t2 where t2.c > 'b1' )
group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 range idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 501 Using index for group-by
+1 PRIMARY t1 index NULL idx_t1_1 163 NULL 1000 Using index
2 SUBQUERY t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
explain select a1,a2,b,min(c),max(c) from t1 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t1 where (a1 >= 'c' or a2 < 'b') and (c > 'b111') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 251 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t1 where (a2 >= 'b') and (b = 'a') and (c > 'b111') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 251 Using where; Using index for group-by
explain select a1,a2,b,min(c) from t1 where ((a1 > 'a') or (a1 < '9')) and ((a2 >= 'b') and (a2 < 'z')) and (b = 'a') and ((c < 'h112') or (c = 'j121') or (c > 'k121' and c < 'm122') or (c > 'o122')) group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 1002 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 502 Using where; Using index for group-by
explain select a1,a2,b,min(c) from t1 where ((a1 > 'a') or (a1 < '9')) and ((a2 >= 'b') and (a2 < 'z')) and (b = 'a') and ((c = 'j121') or (c > 'k121' and c < 'm122') or (c > 'o122') or (c < 'h112') or (c = 'c111')) group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 1002 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 502 Using where; Using index for group-by
explain select a1,a2,b,min(c) from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
explain select a1,a2,b,min(c) from t1 where (ord(a1) > 97) and (ord(a2) + ord(a1) > 194) and (b = 'c') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 251 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t2 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by
@@ -1599,7 +1617,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t2 where (a2 >= 'b') and (b = 'a') and (c > 'b111') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
explain select a1,a2,b,min(c) from t2 where ((a1 > 'a') or (a1 < '9')) and ((a2 >= 'b') and (a2 < 'z')) and (b = 'a') and ((c < 'h112') or (c = 'j121') or (c > 'k121' and c < 'm122') or (c > 'o122')) group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by
@@ -1695,31 +1713,31 @@ select a1,a2,b,min(c) from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') grou
a1 a2 b min(c)
explain select a1,a2,b from t1 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
explain select a1,a2,b from t1 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 251 Using where; Using index for group-by
explain select a1,a2,b,c from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 251 Using where; Using index for group-by
explain select a1,a2,b,c from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121' or c = 'i121') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 251 Using where; Using index for group-by
explain select a1,a2,b from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
explain select a1,a2,b from t2 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL # Using where; Using index for group-by
explain select a1,a2,b from t2 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_1,idx_t2_2 idx_t2_1 146 NULL # Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 146 NULL # Using where; Using index for group-by
explain select a1,a2,b,c from t2 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
explain select a1,a2,b,c from t2 where (a2 >= 'b') and (b = 'a') and (c = 'i121' or c = 'i121') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
explain select a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL # Using where; Using index for group-by
@@ -1770,50 +1788,50 @@ select a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1
a1 a2 b
explain select distinct a1,a2,b from t1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 501 Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 251 Using index for group-by
explain select distinct a1,a2,b from t1 where (a2 >= 'b') and (b = 'a');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 251 Using where; Using index for group-by
explain extended select distinct a1,a2,b,c from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121');
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t1 range idx_t1_1 idx_t1_1 163 NULL 1001 99.90 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 501 100.00 Using where; Using index for group-by
Warnings:
-Note 1003 /* select#1 */ select distinct `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where ((`test`.`t1`.`c` = 'i121') and (`test`.`t1`.`b` = 'a') and (`test`.`t1`.`a2` >= 'b'))
+Note 1003 select distinct `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`b` = 'a' and `test`.`t1`.`c` = 'i121' and `test`.`t1`.`a2` >= 'b'
explain select distinct a1,a2,b from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
explain select distinct b from t1 where (a2 >= 'b') and (b = 'a');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index idx_t1_1,idx_t1_2 idx_t1_2 147 NULL 1000 Using where; Using index
+1 SIMPLE t1 index NULL idx_t1_2 147 NULL 1000 Using where; Using index
explain select distinct a1 from t1 where a1 in ('a', 'd') and a2 = 'b';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 252 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 126 Using where; Using index for group-by
explain select distinct a1 from t1 where a1 in ('a', 'd') and a2 = 'e';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 252 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 126 Using where; Using index for group-by
explain select distinct a1,a2,b from t2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_1,idx_t2_2 idx_t2_1 146 NULL # Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 146 NULL # Using index for group-by
explain select distinct a1,a2,b from t2 where (a2 >= 'b') and (b = 'a');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_1,idx_t2_2 idx_t2_1 146 NULL # Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 146 NULL # Using where; Using index for group-by
explain extended select distinct a1,a2,b,c from t2 where (a2 >= 'b') and (b = 'a') and (c = 'i121');
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t2 range idx_t2_1 idx_t2_1 163 NULL 1001 99.90 Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL 501 100.00 Using where; Using index for group-by
Warnings:
-Note 1003 /* select#1 */ select distinct `test`.`t2`.`a1` AS `a1`,`test`.`t2`.`a2` AS `a2`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` where ((`test`.`t2`.`c` = 'i121') and (`test`.`t2`.`b` = 'a') and (`test`.`t2`.`a2` >= 'b'))
+Note 1003 select distinct `test`.`t2`.`a1` AS `a1`,`test`.`t2`.`a2` AS `a2`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` where `test`.`t2`.`b` = 'a' and `test`.`t2`.`c` = 'i121' and `test`.`t2`.`a2` >= 'b'
explain select distinct a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c');
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL # Using where; Using index for group-by
explain select distinct b from t2 where (a2 >= 'b') and (b = 'a');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 index idx_t2_1,idx_t2_2 idx_t2_2 146 NULL 1000 Using where; Using index
+1 SIMPLE t2 index NULL idx_t2_2 146 NULL 1000 Using where; Using index
explain select distinct a1 from t2 where a1 in ('a', 'd') and a2 = 'b';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 129 NULL 252 Using where; Using index for group-by
+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 129 NULL 126 Using where; Using index for group-by
explain select distinct a1 from t2 where a1 in ('a', 'd') and a2 = 'e';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 129 NULL 252 Using where; Using index for group-by
+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 129 NULL 126 Using where; Using index for group-by
select distinct a1,a2,b from t1;
a1 a2 b
a a a
@@ -1942,40 +1960,40 @@ c e
d e
explain select distinct a1,a2,b from t1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 501 Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 251 Using index for group-by
explain select distinct a1,a2,b from t1 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 251 Using where; Using index for group-by
explain select distinct a1,a2,b,c from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 251 Using where; Using index for group-by
explain select distinct a1,a2,b from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
explain select distinct b from t1 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 501 Using where; Using index for group-by; Using temporary; Using filesort
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 251 Using where; Using index for group-by; Using temporary; Using filesort
explain select distinct a1 from t1 where a1 in ('a', 'd') and a2 = 'b' group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 252 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 126 Using where; Using index for group-by
explain select distinct a1 from t1 where a1 in ('a', 'd') and a2 = 'e' group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 252 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 126 Using where; Using index for group-by
explain select distinct a1,a2,b from t2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_1,idx_t2_2 idx_t2_1 146 NULL # Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 146 NULL # Using index for group-by
explain select distinct a1,a2,b from t2 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_1,idx_t2_2 idx_t2_1 146 NULL # Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 146 NULL # Using where; Using index for group-by
explain select distinct a1,a2,b,c from t2 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
explain select distinct a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL # Using where; Using index for group-by
explain select distinct b from t2 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_1,idx_t2_2 idx_t2_1 146 NULL # Using where; Using index for group-by; Using temporary; Using filesort
+1 SIMPLE t2 range NULL idx_t2_1 146 NULL # Using where; Using index for group-by; Using temporary; Using filesort
explain select distinct a1 from t2 where a1 in ('a', 'd') and a2 = 'b' group by a1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 129 NULL # Using where; Using index for group-by
@@ -2064,23 +2082,23 @@ select distinct a1 from t2 where a1 in ('a', 'd') and a2 = 'e' group by a1;
a1
explain select count(distinct a1,a2,b) from t1 where (a2 >= 'b') and (b = 'a');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 501 Using where; Using index for group-by (scanning)
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 251 Using where; Using index for group-by
explain select count(distinct a1,a2,b,c) from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1 idx_t1_1 163 NULL 1001 Using where; Using index for group-by (scanning)
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 501 Using where; Using index for group-by (scanning)
explain extended select count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c');
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 501 100.00 Using where; Using index for group-by (scanning)
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 100.00 Using where; Using index for group-by
Warnings:
-Note 1003 /* select#1 */ select count(distinct `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`) AS `count(distinct a1,a2,b)` from `test`.`t1` where ((`test`.`t1`.`b` = 'c') and (`test`.`t1`.`a1` > 'a') and (`test`.`t1`.`a2` > 'a'))
+Note 1003 select count(distinct `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`) AS `count(distinct a1,a2,b)` from `test`.`t1` where `test`.`t1`.`b` = 'c' and `test`.`t1`.`a1` > 'a' and `test`.`t1`.`a2` > 'a'
explain select count(distinct b) from t1 where (a2 >= 'b') and (b = 'a');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index idx_t1_1,idx_t1_2 idx_t1_2 147 NULL 1000 Using where; Using index
+1 SIMPLE t1 index NULL idx_t1_2 147 NULL 1000 Using where; Using index
explain extended select 98 + count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a');
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 501 100.00 Using where; Using index for group-by (scanning)
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 100.00 Using where; Using index for group-by
Warnings:
-Note 1003 /* select#1 */ select (98 + count(distinct `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`)) AS `98 + count(distinct a1,a2,b)` from `test`.`t1` where ((`test`.`t1`.`a1` > 'a') and (`test`.`t1`.`a2` > 'a'))
+Note 1003 select 98 + count(distinct `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`) AS `98 + count(distinct a1,a2,b)` from `test`.`t1` where `test`.`t1`.`a1` > 'a' and `test`.`t1`.`a2` > 'a'
select count(distinct a1,a2,b) from t1 where (a2 >= 'b') and (b = 'a');
count(distinct a1,a2,b)
4
@@ -2098,19 +2116,19 @@ select 98 + count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a');
104
explain select a1,a2,b, concat(min(c), max(c)) from t1 where a1 < 'd' group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
explain select concat(a1,min(c)),b from t1 where a1 < 'd' group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
explain select concat(a1,min(c)),b,max(c) from t1 where a1 < 'd' group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
explain select concat(a1,a2),b,min(c),max(c) from t1 where a1 < 'd' group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
explain select concat(ord(min(b)),ord(max(b))),min(b),max(b) from t1 group by a1,a2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 126 Using index for group-by
select a1,a2,b, concat(min(c), max(c)) from t1 where a1 < 'd' group by a1,a2,b;
a1 a2 b concat(min(c), max(c))
a a a a111d111
@@ -2179,85 +2197,83 @@ concat(ord(min(b)),ord(max(b))) min(b) max(b)
9798 a b
explain select a1,a2,b,d,min(c),max(c) from t1 group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index idx_t1_1,idx_t1_2 idx_t1_2 147 NULL 1000 NULL
+1 SIMPLE t1 index NULL idx_t1_2 147 NULL 1000
explain select a1,a2,b,d from t1 group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index idx_t1_1,idx_t1_2 idx_t1_2 147 NULL 1000 NULL
+1 SIMPLE t1 index NULL idx_t1_2 147 NULL 1000
explain extended select a1,a2,min(b),max(b) from t1
where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (c > 'a111') group by a1,a2;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 index idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 1000 100.00 Using where; Using index
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,min(`test`.`t1`.`b`) AS `min(b)`,max(`test`.`t1`.`b`) AS `max(b)` from `test`.`t1` where (((`test`.`t1`.`a1` = 'b') or (`test`.`t1`.`a1` = 'd') or (`test`.`t1`.`a1` = 'a') or (`test`.`t1`.`a1` = 'c')) and (`test`.`t1`.`a2` > 'a') and (`test`.`t1`.`c` > 'a111')) group by `test`.`t1`.`a1`,`test`.`t1`.`a2`
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,min(`test`.`t1`.`b`) AS `min(b)`,max(`test`.`t1`.`b`) AS `max(b)` from `test`.`t1` where (`test`.`t1`.`a1` = 'b' or `test`.`t1`.`a1` = 'd' or `test`.`t1`.`a1` = 'a' or `test`.`t1`.`a1` = 'c') and `test`.`t1`.`a2` > 'a' and `test`.`t1`.`c` > 'a111' group by `test`.`t1`.`a1`,`test`.`t1`.`a2`
explain extended select a1,a2,b,min(c),max(c) from t1
where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (d > 'xy2') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 index idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 147 NULL 1000 100.00 Using where
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t1`.`b` AS `b`,min(`test`.`t1`.`c`) AS `min(c)`,max(`test`.`t1`.`c`) AS `max(c)` from `test`.`t1` where (((`test`.`t1`.`a1` = 'b') or (`test`.`t1`.`a1` = 'd') or (`test`.`t1`.`a1` = 'a') or (`test`.`t1`.`a1` = 'c')) and (`test`.`t1`.`a2` > 'a') and (`test`.`t1`.`d` > 'xy2')) group by `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t1`.`b` AS `b`,min(`test`.`t1`.`c`) AS `min(c)`,max(`test`.`t1`.`c`) AS `max(c)` from `test`.`t1` where (`test`.`t1`.`a1` = 'b' or `test`.`t1`.`a1` = 'd' or `test`.`t1`.`a1` = 'a' or `test`.`t1`.`a1` = 'c') and `test`.`t1`.`a2` > 'a' and `test`.`t1`.`d` > 'xy2' group by `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`
explain extended select a1,a2,b,c from t1
where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (d > 'xy2') group by a1,a2,b,c;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 index idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 1000 100.00 Using where
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where (((`test`.`t1`.`a1` = 'b') or (`test`.`t1`.`a1` = 'd') or (`test`.`t1`.`a1` = 'a') or (`test`.`t1`.`a1` = 'c')) and (`test`.`t1`.`a2` > 'a') and (`test`.`t1`.`d` > 'xy2')) group by `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`,`test`.`t1`.`c`
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where (`test`.`t1`.`a1` = 'b' or `test`.`t1`.`a1` = 'd' or `test`.`t1`.`a1` = 'a' or `test`.`t1`.`a1` = 'c') and `test`.`t1`.`a2` > 'a' and `test`.`t1`.`d` > 'xy2' group by `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`,`test`.`t1`.`c`
explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b') or (b < 'b') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 index idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_0 65 NULL 1000 Using where
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b < 'b') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 index idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_0 65 NULL 1000 Using where
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b <= 'b') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 index idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_0 65 NULL 1000 Using where
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b <= 'b' and b >= 'a') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 index idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_0 65 NULL 1000 Using where
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
explain extended select a1,a2,b from t1 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (c > 'a111') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 index idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 1000 100.00 Using where; Using index
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t1`.`b` AS `b` from `test`.`t1` where (((`test`.`t1`.`a1` = 'b') or (`test`.`t1`.`a1` = 'd') or (`test`.`t1`.`a1` = 'a') or (`test`.`t1`.`a1` = 'c')) and (`test`.`t1`.`a2` > 'a') and (`test`.`t1`.`c` > 'a111')) group by `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t1`.`b` AS `b` from `test`.`t1` where (`test`.`t1`.`a1` = 'b' or `test`.`t1`.`a1` = 'd' or `test`.`t1`.`a1` = 'a' or `test`.`t1`.`a1` = 'c') and `test`.`t1`.`a2` > 'a' and `test`.`t1`.`c` > 'a111' group by `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`
explain select a1,a2,min(b),c from t2 where (a2 = 'a') and (c = 'a111') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 index idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_0 65 NULL 1000 Using where
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
select a1,a2,min(b),c from t2 where (a2 = 'a') and (c = 'a111') group by a1;
a1 a2 min(b) c
a a a a111
explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b') or (b = 'a') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 index idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_0 65 NULL 1000 Using where
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
explain select a1,a2,b,min(c),max(c) from t2
where (c > 'a000') and (c <= 'd999') and (c like '_8__') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 index idx_t2_1,idx_t2_2 idx_t2_1 163 NULL 1000 Using where; Using index
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
explain select a1, a2, b, c, min(d), max(d) from t1 group by a1,a2,b,c;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index idx_t1_1 idx_t1_1 163 NULL 1000 NULL
+1 SIMPLE t1 index NULL idx_t1_1 163 NULL 1000
explain select a1,a2,count(a2) from t1 group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index idx_t1_1,idx_t1_2 idx_t1_2 147 NULL 1000 Using index
+1 SIMPLE t1 index NULL idx_t1_2 147 NULL 1000 Using index
explain extended select a1,a2,count(a2) from t1 where (a1 > 'a') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 index idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 147 NULL 1000 100.00 Using where; Using index
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,count(`test`.`t1`.`a2`) AS `count(a2)` from `test`.`t1` where (`test`.`t1`.`a1` > 'a') group by `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`
+Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,count(`test`.`t1`.`a2`) AS `count(a2)` from `test`.`t1` where `test`.`t1`.`a1` > 'a' group by `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`
explain extended select sum(ord(a1)) from t1 where (a1 > 'a') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 index idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 147 NULL 1000 100.00 Using where; Using index
Warnings:
-Note 1003 /* select#1 */ select sum(ord(`test`.`t1`.`a1`)) AS `sum(ord(a1))` from `test`.`t1` where (`test`.`t1`.`a1` > 'a') group by `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`
-set optimizer_switch = 'multi_range_groupby=off';
+Note 1003 select sum(ord(`test`.`t1`.`a1`)) AS `sum(ord(a1))` from `test`.`t1` where `test`.`t1`.`a1` > 'a' group by `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`
explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b = 'a' or b = 'b') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 index idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_0 65 NULL 1000 Using where
-set optimizer_switch = 'default';
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b = 'a' or b = 'b') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL 126 Using where; Using index for group-by
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
explain select distinct(a1) from t1 where ord(a2) = 98;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_0 65 NULL 1000 Using where
+1 SIMPLE t1 index NULL idx_t1_2 147 NULL 1000 Using where; Using index
select distinct(a1) from t1 where ord(a2) = 98;
a1
a
@@ -2266,7 +2282,7 @@ c
d
explain select a1 from t1 where a2 = 'b' group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 126 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 130 NULL 63 Using where; Using index for group-by
select a1 from t1 where a2 = 'b' group by a1;
a1
a
@@ -2275,7 +2291,7 @@ c
d
explain select distinct a1 from t1 where a2 = 'b';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 126 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 130 NULL 63 Using where; Using index for group-by
select distinct a1 from t1 where a2 = 'b';
a1
a
@@ -2385,7 +2401,7 @@ INSERT INTO t1 (a) VALUES
('SOUTH EAST'), ('SOUTH WEST'), ('WESTERN');
EXPLAIN SELECT DISTINCT a,a FROM t1 ORDER BY a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range PRIMARY PRIMARY 66 NULL 1001 Using index for group-by
+1 SIMPLE t1 index NULL PRIMARY 66 NULL 1000 Using index
SELECT DISTINCT a,a FROM t1 ORDER BY a;
a a
@@ -2477,7 +2493,7 @@ Table Op Msg_type Msg_text
test.t1 analyze status OK
EXPLAIN SELECT max(b), a FROM t1 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 5 NULL 501 Using index for group-by
+1 SIMPLE t1 range NULL a 5 NULL 251 Using index for group-by
FLUSH STATUS;
SELECT max(b), a FROM t1 GROUP BY a;
max(b) a
@@ -2489,15 +2505,17 @@ SHOW STATUS LIKE 'handler_read__e%';
Variable_name Value
Handler_read_key 8
Handler_read_next 0
+Handler_read_retry 0
EXPLAIN SELECT max(b), a FROM t1 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 5 NULL 501 Using index for group-by
+1 SIMPLE t1 range NULL a 5 NULL 251 Using index for group-by
FLUSH STATUS;
CREATE TABLE t2 engine=RocksDB SELECT max(b), a FROM t1 GROUP BY a;
SHOW STATUS LIKE 'handler_read__e%';
Variable_name Value
Handler_read_key 8
Handler_read_next 0
+Handler_read_retry 0
FLUSH STATUS;
SELECT * FROM (SELECT max(b), a FROM t1 GROUP BY a) b;
max(b) a
@@ -2509,6 +2527,7 @@ SHOW STATUS LIKE 'handler_read__e%';
Variable_name Value
Handler_read_key 8
Handler_read_next 0
+Handler_read_retry 0
FLUSH STATUS;
(SELECT max(b), a FROM t1 GROUP BY a) UNION
(SELECT max(b), a FROM t1 GROUP BY a);
@@ -2521,50 +2540,52 @@ SHOW STATUS LIKE 'handler_read__e%';
Variable_name Value
Handler_read_key 16
Handler_read_next 0
+Handler_read_retry 0
EXPLAIN (SELECT max(b), a FROM t1 GROUP BY a) UNION
(SELECT max(b), a FROM t1 GROUP BY a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 range a a 5 NULL 501 Using index for group-by
-2 UNION t1 range a a 5 NULL 501 Using index for group-by
-NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL Using temporary
+1 PRIMARY t1 range NULL a 5 NULL 251 Using index for group-by
+2 UNION t1 range NULL a 5 NULL 251 Using index for group-by
+NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL
EXPLAIN SELECT (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) x
FROM t1 AS t1_outer;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1_outer index NULL a 10 NULL 1000 Using index
-2 SUBQUERY t1 range a a 5 NULL 501 Using index for group-by
+2 SUBQUERY t1 range NULL a 5 NULL 251 Using index for group-by
EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE EXISTS
(SELECT max(b) FROM t1 GROUP BY a HAVING a < 2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1_outer index NULL a 10 NULL 1000 Using index
-2 SUBQUERY t1 range a a 5 NULL 501 Using index for group-by
+2 SUBQUERY t1 index NULL a 10 NULL 1000 Using index
EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE
(SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) > 12;
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 range a a 5 NULL 501 Using index for group-by
+1 PRIMARY t1_outer index NULL a 10 NULL 1000 Using index
+2 SUBQUERY t1 range NULL a 5 NULL 251 Using index for group-by
EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE
a IN (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1_outer index NULL a 10 NULL 1000 Using where; Using index
-2 SUBQUERY t1 range a a 5 NULL 501 Using index for group-by
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 251
+1 PRIMARY t1_outer ref a a 5 <subquery2>.max(b) 4 Using index
+2 MATERIALIZED t1 range NULL a 5 NULL 251 Using index for group-by
EXPLAIN SELECT 1 FROM t1 AS t1_outer GROUP BY a HAVING
a > (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1_outer range a a 5 NULL 501 Using index for group-by
-2 SUBQUERY t1 range a a 5 NULL 501 Using index for group-by
+1 PRIMARY t1_outer range NULL a 5 NULL 251 Using index for group-by
+2 SUBQUERY t1 range NULL a 5 NULL 251 Using index for group-by
EXPLAIN SELECT 1 FROM t1 AS t1_outer1 JOIN t1 AS t1_outer2
ON t1_outer1.a = (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2)
AND t1_outer1.b = t1_outer2.b;
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1_outer2 index NULL a 10 NULL 1000 Using where; Using index
-1 PRIMARY t1_outer1 ref a a 10 const,test.t1_outer2.b 1 Using where; Using index
-2 SUBQUERY t1 range a a 5 NULL 501 Using index for group-by
+1 PRIMARY t1_outer1 ref a a 5 const 4 Using where; Using index
+1 PRIMARY t1_outer2 index NULL a 10 NULL 1000 Using where; Using index; Using join buffer (flat, BNL join)
+2 SUBQUERY t1 range NULL a 5 NULL 251 Using index for group-by
EXPLAIN SELECT (SELECT (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) x
FROM t1 AS t1_outer) x2 FROM t1 AS t1_outer2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1_outer2 index NULL a 10 NULL 1000 Using index
2 SUBQUERY t1_outer index NULL a 10 NULL 1000 Using index
-3 SUBQUERY t1 range a a 5 NULL 501 Using index for group-by
+3 SUBQUERY t1 range NULL a 5 NULL 251 Using index for group-by
CREATE TABLE t3 LIKE t1;
FLUSH STATUS;
INSERT INTO t3 SELECT a,MAX(b) FROM t1 GROUP BY a;
@@ -2572,6 +2593,7 @@ SHOW STATUS LIKE 'handler_read__e%';
Variable_name Value
Handler_read_key 8
Handler_read_next 0
+Handler_read_retry 0
DELETE FROM t3;
FLUSH STATUS;
INSERT INTO t3 SELECT 1, (SELECT MAX(b) FROM t1 GROUP BY a HAVING a < 2)
@@ -2580,12 +2602,14 @@ SHOW STATUS LIKE 'handler_read__e%';
Variable_name Value
Handler_read_key 8
Handler_read_next 0
+Handler_read_retry 0
FLUSH STATUS;
DELETE FROM t3 WHERE (SELECT MAX(b) FROM t1 GROUP BY a HAVING a < 2) > 10000;
SHOW STATUS LIKE 'handler_read__e%';
Variable_name Value
Handler_read_key 8
Handler_read_next 0
+Handler_read_retry 0
FLUSH STATUS;
DELETE FROM t3 WHERE (SELECT (SELECT MAX(b) FROM t1 GROUP BY a HAVING a < 2) x
FROM t1) > 10000;
@@ -2594,6 +2618,7 @@ SHOW STATUS LIKE 'handler_read__e%';
Variable_name Value
Handler_read_key 8
Handler_read_next 1
+Handler_read_retry 0
DROP TABLE t1,t2,t3;
CREATE TABLE t1 (a int, INDEX idx(a)) engine=RocksDB;
INSERT INTO t1 VALUES
@@ -2604,7 +2629,7 @@ Table Op Msg_type Msg_text
test.t1 analyze status OK
EXPLAIN SELECT DISTINCT(a) FROM t1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx idx 5 NULL 1001 Using index for group-by
+1 SIMPLE t1 range NULL idx 5 NULL 501 Using index for group-by
SELECT DISTINCT(a) FROM t1;
a
1
@@ -2612,7 +2637,7 @@ a
4
EXPLAIN SELECT SQL_BIG_RESULT DISTINCT(a) FROM t1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx idx 5 NULL 1001 Using index for group-by
+1 SIMPLE t1 range NULL idx 5 NULL 501 Using index for group-by
SELECT SQL_BIG_RESULT DISTINCT(a) FROM t1;
a
1
@@ -2640,7 +2665,7 @@ CREATE INDEX break_it ON t1 (a, b);
EXPLAIN
SELECT a, MIN(b), MAX(b) FROM t1 GROUP BY a ORDER BY a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range break_it break_it 10 NULL 501 Using index for group-by
+1 SIMPLE t1 range NULL break_it 10 NULL 251 Using index for group-by
SELECT a, MIN(b), MAX(b) FROM t1 GROUP BY a ORDER BY a;
a MIN(b) MAX(b)
1 1 3
@@ -2650,7 +2675,7 @@ a MIN(b) MAX(b)
EXPLAIN
SELECT a, MIN(b), MAX(b) FROM t1 GROUP BY a ORDER BY a DESC;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range break_it break_it 10 NULL 501 Using index for group-by; Using temporary; Using filesort
+1 SIMPLE t1 range NULL break_it 10 NULL 251 Using index for group-by; Using temporary; Using filesort
SELECT a, MIN(b), MAX(b) FROM t1 GROUP BY a ORDER BY a DESC;
a MIN(b) MAX(b)
4 1 3
@@ -2660,7 +2685,7 @@ a MIN(b) MAX(b)
EXPLAIN
SELECT a, MIN(b), MAX(b), AVG(b) FROM t1 GROUP BY a ORDER BY a DESC;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index break_it break_it 10 NULL 1000 Using index
+1 SIMPLE t1 index NULL break_it 10 NULL 1000 Using index
SELECT a, MIN(b), MAX(b), AVG(b) FROM t1 GROUP BY a ORDER BY a DESC;
a MIN(b) MAX(b) AVG(b)
4 1 3 2.0000
@@ -2743,9 +2768,9 @@ a b
3 13
explain extended select sql_buffer_result a, max(b)+1 from t1 where a = 0 group by a;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t1 range PRIMARY,index PRIMARY 4 NULL 1 100.00 Using where; Using index for group-by; Using temporary
+1 SIMPLE t1 ref PRIMARY,index PRIMARY 4 const 15 100.00 Using index; Using temporary
Warnings:
-Note 1003 /* select#1 */ select sql_buffer_result `test`.`t1`.`a` AS `a`,(max(`test`.`t1`.`b`) + 1) AS `max(b)+1` from `test`.`t1` where (`test`.`t1`.`a` = 0) group by `test`.`t1`.`a`
+Note 1003 select sql_buffer_result `test`.`t1`.`a` AS `a`,max(`test`.`t1`.`b`) + 1 AS `max(b)+1` from `test`.`t1` where `test`.`t1`.`a` = 0 group by `test`.`t1`.`a`
drop table t1;
CREATE TABLE t1 (a int, b int, c int, d int,
KEY foo (c,d,a,b), KEY bar (c,a,b,d)) engine=RocksDB;
@@ -2758,7 +2783,7 @@ Table Op Msg_type Msg_text
test.t1 analyze status OK
EXPLAIN SELECT DISTINCT c FROM t1 WHERE d=4;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range foo,bar foo 10 NULL 126 Using where; Using index for group-by
+1 SIMPLE t1 range NULL foo 10 NULL 63 Using where; Using index for group-by
SELECT DISTINCT c FROM t1 WHERE d=4;
c
1
@@ -2780,7 +2805,7 @@ test.t analyze status OK
EXPLAIN
SELECT a, MIN(b) FROM t WHERE b <> 0 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t range a a 10 NULL 501 Using where; Using index for group-by
+1 SIMPLE t range NULL a 10 NULL 251 Using where; Using index for group-by
#should return 1 row
SELECT a, MIN(b) FROM t WHERE b <> 0 GROUP BY a;
a MIN(b)
@@ -2790,7 +2815,7 @@ a MIN(b)
EXPLAIN
SELECT a, MAX(b) FROM t WHERE b <> 1 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t range a a 10 NULL 501 Using where; Using index for group-by
+1 SIMPLE t range NULL a 10 NULL 251 Using where; Using index for group-by
#should return 1 row
SELECT a, MAX(b) FROM t WHERE b <> 1 GROUP BY a;
a MAX(b)
@@ -2801,7 +2826,7 @@ INSERT INTO t SELECT a, 2 FROM t;
EXPLAIN
SELECT a, MAX(b) FROM t WHERE b > 0 AND b < 2 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t range a a 10 NULL 501 Using where; Using index for group-by
+1 SIMPLE t range NULL a 10 NULL 251 Using where; Using index for group-by
#should return 1 row
SELECT a, MAX(b) FROM t WHERE b > 0 AND b < 2 GROUP BY a;
a MAX(b)
@@ -2915,7 +2940,7 @@ NULL
EXPLAIN
SELECT MIN( a ) FROM t1 WHERE a = (SELECT a FROM t1 WHERE a < 0);
id select_type table type possible_keys key key_len ref rows Extra
-x x x x x x x x x Impossible WHERE noticed after reading const tables
+x x x x x x x x x Using where; Using index
x x x x x x x x x Using where; Using index
SELECT MIN( a ) FROM t1 WHERE a = (SELECT a FROM t1 WHERE a < 0);
MIN( a )
@@ -2990,7 +3015,7 @@ NULL
EXPLAIN
SELECT MIN( a ) FROM t1 WHERE a = (SELECT a FROM t1 WHERE a < 0);
id select_type table type possible_keys key key_len ref rows Extra
-x x x x x x x x x Impossible WHERE noticed after reading const tables
+x x x x x x x x x Using where; Using index
x x x x x x x x x Using where; Using index
SELECT MIN( a ) FROM t1 WHERE a = (SELECT a FROM t1 WHERE a < 0);
MIN( a )
@@ -3072,7 +3097,7 @@ NULL
EXPLAIN
SELECT MIN( a ) FROM t1 WHERE a = (SELECT a FROM t1 WHERE a < 0);
id select_type table type possible_keys key key_len ref rows Extra
-x x x x x x x x x Impossible WHERE noticed after reading const tables
+x x x x x x x x x Using where; Using index
x x x x x x x x x Using where; Using index
SELECT MIN( a ) FROM t1 WHERE a = (SELECT a FROM t1 WHERE a < 0);
MIN( a )
@@ -3119,45 +3144,45 @@ Table Op Msg_type Msg_text
test.t2 analyze status OK
EXPLAIN SELECT COUNT(DISTINCT a) FROM t1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 5 NULL 501 Using index for group-by
+1 SIMPLE t1 range NULL a 5 NULL 251 Using index for group-by
SELECT COUNT(DISTINCT a) FROM t1;
COUNT(DISTINCT a)
2
EXPLAIN SELECT COUNT(DISTINCT a,b) FROM t1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 10 NULL 1001 Using index for group-by (scanning)
+1 SIMPLE t1 range NULL a 10 NULL 501 Using index for group-by
SELECT COUNT(DISTINCT a,b) FROM t1;
COUNT(DISTINCT a,b)
16
EXPLAIN SELECT COUNT(DISTINCT b,a) FROM t1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 10 NULL 1001 Using index for group-by (scanning)
+1 SIMPLE t1 range NULL a 10 NULL 501 Using index for group-by
SELECT COUNT(DISTINCT b,a) FROM t1;
COUNT(DISTINCT b,a)
16
EXPLAIN SELECT COUNT(DISTINCT b) FROM t1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index a a 10 NULL 1000 Using index
+1 SIMPLE t1 index NULL a 10 NULL 1000 Using index
SELECT COUNT(DISTINCT b) FROM t1;
COUNT(DISTINCT b)
8
EXPLAIN SELECT COUNT(DISTINCT a) FROM t1 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 5 NULL 501 Using index for group-by
+1 SIMPLE t1 range NULL a 5 NULL 251 Using index for group-by
SELECT COUNT(DISTINCT a) FROM t1 GROUP BY a;
COUNT(DISTINCT a)
1
1
EXPLAIN SELECT COUNT(DISTINCT b) FROM t1 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 10 NULL 1001 Using index for group-by (scanning)
+1 SIMPLE t1 range NULL a 10 NULL 501 Using index for group-by
SELECT COUNT(DISTINCT b) FROM t1 GROUP BY a;
COUNT(DISTINCT b)
8
8
EXPLAIN SELECT COUNT(DISTINCT a) FROM t1 GROUP BY b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index a a 10 NULL 1000 Using index; Using filesort
+1 SIMPLE t1 index NULL a 10 NULL 1000 Using index; Using filesort
SELECT COUNT(DISTINCT a) FROM t1 GROUP BY b;
COUNT(DISTINCT a)
2
@@ -3170,7 +3195,7 @@ COUNT(DISTINCT a)
2
EXPLAIN SELECT DISTINCT COUNT(DISTINCT a) FROM t1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index a a 10 NULL 1000 Using index
+1 SIMPLE t1 index NULL a 10 NULL 1000 Using index
SELECT DISTINCT COUNT(DISTINCT a) FROM t1;
COUNT(DISTINCT a)
2
@@ -3188,76 +3213,76 @@ COUNT(DISTINCT a)
2
EXPLAIN SELECT COUNT(DISTINCT a) FROM t1 HAVING COUNT(DISTINCT c) < 10;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ALL NULL NULL NULL NULL 1000 NULL
+1 SIMPLE t1 ALL NULL NULL NULL NULL 1000
SELECT COUNT(DISTINCT a) FROM t1 HAVING COUNT(DISTINCT c) < 10;
COUNT(DISTINCT a)
2
EXPLAIN SELECT 1 FROM t1 HAVING COUNT(DISTINCT a) < 10;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 5 NULL 501 Using index for group-by
+1 SIMPLE t1 range NULL a 5 NULL 251 Using index for group-by
SELECT 1 FROM t1 HAVING COUNT(DISTINCT a) < 10;
1
1
EXPLAIN SELECT 1 FROM t1 GROUP BY a HAVING COUNT(DISTINCT b) > 1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 10 NULL 1001 Using index for group-by (scanning)
+1 SIMPLE t1 range NULL a 10 NULL 501 Using index for group-by
SELECT 1 FROM t1 GROUP BY a HAVING COUNT(DISTINCT b) > 1;
1
1
1
EXPLAIN SELECT COUNT(DISTINCT t1_1.a) FROM t1 t1_1, t1 t1_2 GROUP BY t1_1.a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1_1 index a a 10 NULL 1000 Using index; Using temporary; Using filesort
-1 SIMPLE t1_2 index NULL a 10 NULL 1000 Using index; Using join buffer (Block Nested Loop)
+1 SIMPLE t1_1 index NULL a 10 NULL 1000 Using index; Using temporary; Using filesort
+1 SIMPLE t1_2 index NULL a 10 NULL 1000 Using index; Using join buffer (flat, BNL join)
SELECT COUNT(DISTINCT t1_1.a) FROM t1 t1_1, t1 t1_2 GROUP BY t1_1.a;
COUNT(DISTINCT t1_1.a)
1
1
EXPLAIN SELECT COUNT(DISTINCT a), 12 FROM t1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 5 NULL 501 Using index for group-by
+1 SIMPLE t1 range NULL a 5 NULL 251 Using index for group-by
SELECT COUNT(DISTINCT a), 12 FROM t1;
COUNT(DISTINCT a) 12
2 12
EXPLAIN SELECT COUNT(DISTINCT a, b, c) FROM t2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range a a 15 NULL 1001 Using index for group-by (scanning)
+1 SIMPLE t2 range NULL a 15 NULL 501 Using index for group-by
SELECT COUNT(DISTINCT a, b, c) FROM t2;
COUNT(DISTINCT a, b, c)
16
EXPLAIN SELECT COUNT(DISTINCT a), SUM(DISTINCT a), AVG(DISTINCT a) FROM t2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range a a 5 NULL 251 Using index for group-by
+1 SIMPLE t2 range NULL a 5 NULL 126 Using index for group-by
SELECT COUNT(DISTINCT a), SUM(DISTINCT a), AVG(DISTINCT a) FROM t2;
COUNT(DISTINCT a) SUM(DISTINCT a) AVG(DISTINCT a)
2 3 1.5000
EXPLAIN SELECT COUNT(DISTINCT a), SUM(DISTINCT a), AVG(DISTINCT f) FROM t2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 ALL NULL NULL NULL NULL 1000 NULL
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1000
SELECT COUNT(DISTINCT a), SUM(DISTINCT a), AVG(DISTINCT f) FROM t2;
COUNT(DISTINCT a) SUM(DISTINCT a) AVG(DISTINCT f)
2 3 1.0000
EXPLAIN SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, a) FROM t2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range a a 10 NULL 501 Using index for group-by (scanning)
+1 SIMPLE t2 range NULL a 10 NULL 251 Using index for group-by
SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, a) FROM t2;
COUNT(DISTINCT a, b) COUNT(DISTINCT b, a)
16 16
EXPLAIN SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, f) FROM t2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 ALL NULL NULL NULL NULL 1000 NULL
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1000
SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, f) FROM t2;
COUNT(DISTINCT a, b) COUNT(DISTINCT b, f)
16 8
EXPLAIN SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, d) FROM t2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 ALL NULL NULL NULL NULL 1000 NULL
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1000
SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, d) FROM t2;
COUNT(DISTINCT a, b) COUNT(DISTINCT b, d)
16 8
EXPLAIN SELECT a, c, COUNT(DISTINCT c, a, b) FROM t2 GROUP BY a, b, c;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range a a 15 NULL 1001 Using index for group-by (scanning)
+1 SIMPLE t2 range NULL a 15 NULL 501 Using index for group-by
SELECT a, c, COUNT(DISTINCT c, a, b) FROM t2 GROUP BY a, b, c;
a c COUNT(DISTINCT c, a, b)
1 1 1
@@ -3279,7 +3304,7 @@ a c COUNT(DISTINCT c, a, b)
EXPLAIN SELECT COUNT(DISTINCT c, a, b) FROM t2
WHERE a > 5 AND b BETWEEN 10 AND 20 GROUP BY a, b, c;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range a a 15 NULL 1001 Using where; Using index for group-by (scanning)
+1 SIMPLE t2 range a a 15 NULL 501 Using where; Using index for group-by
SELECT COUNT(DISTINCT c, a, b) FROM t2
WHERE a > 5 AND b BETWEEN 10 AND 20 GROUP BY a, b, c;
COUNT(DISTINCT c, a, b)
@@ -3292,28 +3317,28 @@ GROUP BY b;
COUNT(DISTINCT b) SUM(DISTINCT b)
EXPLAIN SELECT a, COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range a a 10 NULL 501 Using index for group-by (scanning)
+1 SIMPLE t2 range NULL a 10 NULL 251 Using index for group-by
SELECT a, COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 GROUP BY a;
a COUNT(DISTINCT b) SUM(DISTINCT b)
1 8 36
2 8 36
EXPLAIN SELECT COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range a a 10 NULL 501 Using index for group-by (scanning)
+1 SIMPLE t2 range NULL a 10 NULL 251 Using index for group-by
SELECT COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 GROUP BY a;
COUNT(DISTINCT b) SUM(DISTINCT b)
8 36
8 36
EXPLAIN SELECT COUNT(DISTINCT a, b) FROM t2 WHERE c = 13 AND d = 42;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 ALL a NULL NULL NULL 1000 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1000 Using where
SELECT COUNT(DISTINCT a, b) FROM t2 WHERE c = 13 AND d = 42;
COUNT(DISTINCT a, b)
0
EXPLAIN SELECT a, COUNT(DISTINCT a), SUM(DISTINCT a) FROM t2
WHERE b = 13 AND c = 42 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range a a 15 NULL 251 Using where; Using index for group-by
+1 SIMPLE t2 range NULL a 15 NULL 126 Using where; Using index for group-by
SELECT a, COUNT(DISTINCT a), SUM(DISTINCT a) FROM t2
WHERE b = 13 AND c = 42 GROUP BY a;
a COUNT(DISTINCT a) SUM(DISTINCT a)
@@ -3327,14 +3352,14 @@ COUNT(DISTINCT a, b) SUM(DISTINCT a)
0 NULL
EXPLAIN SELECT SUM(DISTINCT a), MAX(b) FROM t2 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 index a a 15 NULL 1000 Using index
+1 SIMPLE t2 index NULL a 15 NULL 1000 Using index
SELECT SUM(DISTINCT a), MAX(b) FROM t2 GROUP BY a;
SUM(DISTINCT a) MAX(b)
1 8
2 8
EXPLAIN SELECT 42 * (a + c + COUNT(DISTINCT c, a, b)) FROM t2 GROUP BY a, b, c;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range a a 15 NULL 1001 Using index for group-by (scanning)
+1 SIMPLE t2 range NULL a 15 NULL 501 Using index for group-by
SELECT 42 * (a + c + COUNT(DISTINCT c, a, b)) FROM t2 GROUP BY a, b, c;
42 * (a + c + COUNT(DISTINCT c, a, b))
126
@@ -3355,7 +3380,7 @@ SELECT 42 * (a + c + COUNT(DISTINCT c, a, b)) FROM t2 GROUP BY a, b, c;
168
EXPLAIN SELECT (SUM(DISTINCT a) + MAX(b)) FROM t2 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 index a a 15 NULL 1000 Using index
+1 SIMPLE t2 index NULL a 15 NULL 1000 Using index
SELECT (SUM(DISTINCT a) + MAX(b)) FROM t2 GROUP BY a;
(SUM(DISTINCT a) + MAX(b))
9
@@ -3383,7 +3408,7 @@ f1 COUNT(DISTINCT f2)
3 4
explain SELECT f1, COUNT(DISTINCT f2) FROM t1 GROUP BY f1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index PRIMARY PRIMARY 5 NULL 1000 Using index
+1 SIMPLE t1 index NULL PRIMARY 5 NULL 1000 Using index
drop table t1;
# End of test#50539.
#
@@ -3395,9 +3420,6 @@ INSERT INTO t VALUES (1,1), (2,2), (3,3), (4,4), (1,0), (3,2), (4,5);
ANALYZE TABLE t;
Table Op Msg_type Msg_text
test.t analyze status OK
-set optimizer_trace_max_mem_size=1048576;
-set @@session.optimizer_trace='enabled=on';
-set end_markers_in_json=on;
ANALYZE TABLE t;
Table Op Msg_type Msg_text
test.t analyze status OK
@@ -3409,11 +3431,7 @@ a SUM(DISTINCT a) MIN(b)
4 4 4
EXPLAIN SELECT a, SUM(DISTINCT a), MIN(b) FROM t GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t index a a 10 NULL 1000 Using index
-SELECT TRACE RLIKE 'have_both_agg_distinct_and_min_max' AS OK
-FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
-OK
-1
+1 SIMPLE t index NULL a 10 NULL 1000 Using index
SELECT a, SUM(DISTINCT a), MAX(b) FROM t GROUP BY a;
a SUM(DISTINCT a) MAX(b)
1 1 1
@@ -3422,11 +3440,7 @@ a SUM(DISTINCT a) MAX(b)
4 4 5
EXPLAIN SELECT a, SUM(DISTINCT a), MAX(b) FROM t GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t index a a 10 NULL 1000 Using index
-SELECT TRACE RLIKE 'have_both_agg_distinct_and_min_max' AS OK
-FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
-OK
-1
+1 SIMPLE t index NULL a 10 NULL 1000 Using index
SELECT a, MAX(b) FROM t GROUP BY a HAVING SUM(DISTINCT a);
a MAX(b)
1 1
@@ -3435,21 +3449,13 @@ a MAX(b)
4 5
EXPLAIN SELECT a, MAX(b) FROM t GROUP BY a HAVING SUM(DISTINCT a);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t index a a 10 NULL 1000 Using index
-SELECT TRACE RLIKE 'have_both_agg_distinct_and_min_max' AS OK
-FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
-OK
-1
+1 SIMPLE t index NULL a 10 NULL 1000 Using index
SELECT SUM(DISTINCT a), MIN(b), MAX(b) FROM t;
SUM(DISTINCT a) MIN(b) MAX(b)
10 0 5
EXPLAIN SELECT SUM(DISTINCT a), MIN(b), MAX(b) FROM t;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t index a a 10 NULL 1000 Using index
-SELECT TRACE RLIKE 'have_both_agg_distinct_and_min_max' AS OK
-FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
-OK
-1
+1 SIMPLE t index NULL a 10 NULL 1000 Using index
SELECT a, SUM(DISTINCT a), MIN(b), MAX(b) FROM t GROUP BY a;
a SUM(DISTINCT a) MIN(b) MAX(b)
1 1 0 1
@@ -3458,14 +3464,7 @@ a SUM(DISTINCT a) MIN(b) MAX(b)
4 4 4 5
EXPLAIN SELECT a, SUM(DISTINCT a), MIN(b), MAX(b) FROM t GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t index a a 10 NULL 1000 Using index
-SELECT TRACE RLIKE 'have_both_agg_distinct_and_min_max' AS OK
-FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
-OK
-1
-SET optimizer_trace_max_mem_size=DEFAULT;
-SET optimizer_trace=DEFAULT;
-SET end_markers_in_json=DEFAULT;
+1 SIMPLE t index NULL a 10 NULL 1000 Using index
DROP TABLE t;
#
# Bug#18109609: LOOSE INDEX SCAN IS NOT USED WHEN IT SHOULD
@@ -3484,7 +3483,7 @@ Table Op Msg_type Msg_text
test.t1 analyze status OK
EXPLAIN SELECT MAX(c2), c1 FROM t1 WHERE c1 = 4 GROUP BY c1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range c1 c1 5 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 ref c1 c1 5 const 1000 Using index
FLUSH STATUS;
SELECT MAX(c2), c1 FROM t1 WHERE c1 = 4 GROUP BY c1;
MAX(c2) c1
@@ -3492,12 +3491,14 @@ MAX(c2) c1
SHOW SESSION STATUS LIKE 'Handler_read%';
Variable_name Value
Handler_read_first 0
-Handler_read_key 3
-Handler_read_last 1
-Handler_read_next 0
+Handler_read_key 1
+Handler_read_last 0
+Handler_read_next 20
Handler_read_prev 0
+Handler_read_retry 0
Handler_read_rnd 0
+Handler_read_rnd_deleted 0
Handler_read_rnd_next 0
DROP TABLE t1;
# End of test for Bug#18109609
-set global debug="-d,force_group_by";
+set global debug_dbug=@debug_tmp;
diff --git a/storage/rocksdb/mysql-test/rocksdb/t/group_min_max.test b/storage/rocksdb/mysql-test/rocksdb/t/group_min_max.test
index a9c44a71edd..eb66bd0e972 100644
--- a/storage/rocksdb/mysql-test/rocksdb/t/group_min_max.test
+++ b/storage/rocksdb/mysql-test/rocksdb/t/group_min_max.test
@@ -1,8 +1,9 @@
--source include/have_debug.inc
-set global debug="+d,force_group_by";
+set @debug_tmp= @@debug_dbug;
+set global debug_dbug="+d,force_group_by";
let $engine=RocksDB;
--source include/group_min_max.inc
-set global debug="-d,force_group_by";
+set global debug_dbug=@debug_tmp;
1
0
[Commits] 1e58c579f5b: MDEV-18930: Failed CREATE OR REPLACE TEMPORARY not written into binary log makes data on master and slave diverge
by sujatha 02 Aug '19
by sujatha 02 Aug '19
02 Aug '19
revision-id: 1e58c579f5b61644a74045a0470d2c62b343eb75 (mariadb-10.1.41-3-g1e58c579f5b)
parent(s): 0bb8f33b55cc016d0ede86b97990a3ee30dcb069
author: Sujatha
committer: Sujatha
timestamp: 2019-08-01 16:16:05 +0530
message:
MDEV-18930: Failed CREATE OR REPLACE TEMPORARY not written into binary log makes data on master and slave diverge
Problem:
=======
Failed CREATE OR REPLACE TEMPORARY TABLE statement which dropped the table but
failed at a later stage of creation of temporary table is not written to
binarylog in row based replication. This causes the slave to diverge.
Analysis:
========
CREATE OR REPLACE statements work as shown below.
CREATE OR REPLACE TABLE table_name (a int);
is basically the same as:
DROP TABLE IF EXISTS table_name;
CREATE TABLE table_name (a int);
Hence every CREATE OR REPLACE TABLE command which dropped the table should be
written to binary log, even when following CREATE TABLE part fails. In order
to achieve this, during the execution of CREATE OR REPLACE command, when a
table is dropped 'thd->log_current_statement' flag is set. When table creation
results in an error within 'mysql_create_table' code, the error handling part
looks for this flag. If it is set the failed CREATE OR REPLACE statement is
written into the binary log inspite of error. This ensure that slave doesn't
diverge from the master. In case of row based replication the error handling
code returns very early, if the table is of type temporary. This is done based
on the assumption that temporary tables are not replicated in row based
replication.
It fails to handle the cases where a temporary table was created as part of
statement based replication at an earlier stage and the binary log format was
changed to row because of an unsafe statement. In this case when a CREATE OR
REPLACE statement is executed on this temporary table it will dropped but the
query will not be written to binary log. Hence slave diverges.
Fix:
===
In error handling code check the return status of create table operation. If
it is successful and replication mode is row based and table is of type
temporary then return. Other wise proceed further to the code which checks for
thd->log_current_statement flag and does appropriate logging.
---
.../suite/rpl/r/rpl_create_or_replace_fail.result | 18 +++++++
.../suite/rpl/t/rpl_create_or_replace_fail.test | 56 ++++++++++++++++++++++
sql/sql_table.cc | 2 +-
3 files changed, 75 insertions(+), 1 deletion(-)
diff --git a/mysql-test/suite/rpl/r/rpl_create_or_replace_fail.result b/mysql-test/suite/rpl/r/rpl_create_or_replace_fail.result
new file mode 100644
index 00000000000..57178f0efbe
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_create_or_replace_fail.result
@@ -0,0 +1,18 @@
+include/master-slave.inc
+[connection master]
+CREATE TEMPORARY TABLE t1 (a INT NOT NULL);
+LOAD DATA INFILE 'x' INTO TABLE x;
+ERROR 42S02: Table 'test.x' doesn't exist
+CREATE OR REPLACE TEMPORARY TABLE t1 (x INT) PARTITION BY HASH(x);
+ERROR HY000: Cannot create temporary table with partitions
+"************** DROP TEMPORARY TABLE Should be present in Binary log **************"
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; CREATE TEMPORARY TABLE t1 (a INT NOT NULL)
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; CREATE OR REPLACE TEMPORARY TABLE t1 (x INT) PARTITION BY HASH(x)
+CREATE TABLE t1 (b INT);
+INSERT INTO t1 VALUES (NULL);
+DROP TABLE t1;
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_create_or_replace_fail.test b/mysql-test/suite/rpl/t/rpl_create_or_replace_fail.test
new file mode 100644
index 00000000000..e75f34b0b56
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_create_or_replace_fail.test
@@ -0,0 +1,56 @@
+# ==== Purpose ====
+#
+# Test verifies that failed CREATE OR REPLACE TEMPORARY TABLE statement which
+# dropped the table but failed at a later stage of creation of temporary table
+# is written to binarylog in row based replication.
+#
+# ==== Implementation ====
+#
+# Steps:
+# 0 - Have mixed based replication mode.
+# 1 - Create a temporary table. It will be replicated as mixed replication
+# mode is in use.
+# 2 - Execute an unsafe statement which will switch current statement
+# binlog format to 'ROW'. i.e If binlog_format=MIXED, there are open
+# temporary tables, and an unsafe statement is executed, then subsequent
+# statements are logged in row format.
+# 3 - Execute a CREATE OR REPLACE TEMPORARY TABLE statement which tries to
+# create partitions on temporary table. Since it is not supported it will
+# fail.
+# 4 - Check the binary log output to ensure that the failed statement is
+# written to the binary log.
+# 5 - Slave should be up and running and in sync with master.
+#
+# ==== References ====
+#
+# MDEV-18930: Failed CREATE OR REPLACE TEMPORARY not written into binary log
+# makes data on master and slave diverge
+#
+
+--source include/have_partition.inc
+--source include/have_binlog_format_mixed.inc
+--source include/master-slave.inc
+
+CREATE TEMPORARY TABLE t1 (a INT NOT NULL);
+
+# Execute an unsafe statement which switches replication mode internally from
+# "STATEMENT" to "ROW".
+--error ER_NO_SUCH_TABLE
+LOAD DATA INFILE 'x' INTO TABLE x;
+
+--error ER_PARTITION_NO_TEMPORARY
+CREATE OR REPLACE TEMPORARY TABLE t1 (x INT) PARTITION BY HASH(x);
+
+--echo "************** DROP TEMPORARY TABLE Should be present in Binary log **************"
+--source include/show_binlog_events.inc
+
+CREATE TABLE t1 (b INT);
+INSERT INTO t1 VALUES (NULL);
+--sync_slave_with_master
+
+# Cleanup
+--connection master
+DROP TABLE t1;
+
+--source include/rpl_end.inc
+
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 656834c7852..fe923d73200 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -5092,7 +5092,7 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
err:
/* In RBR we don't need to log CREATE TEMPORARY TABLE */
- if (thd->is_current_stmt_binlog_format_row() && create_info->tmp_table())
+ if (!result && thd->is_current_stmt_binlog_format_row() && create_info->tmp_table())
DBUG_RETURN(result);
if (create_info->tmp_table())
2
2
[Commits] 0dd2d7d91d2: MDEV-20224: main.derived crashes with ASAN with error use-after-poison
by Varun 01 Aug '19
by Varun 01 Aug '19
01 Aug '19
revision-id: 0dd2d7d91d23bcfc035de8a024af40dc36f543ff (mariadb-10.4.4-258-g0dd2d7d91d2)
parent(s): 46553c250808f0cc21e91f7e13439add2903aea0
author: Varun Gupta
committer: Varun Gupta
timestamp: 2019-08-01 11:16:06 +0530
message:
MDEV-20224: main.derived crashes with ASAN with error use-after-poison
Make sure that the references in the GROUP BY clause that need to be considered for
pushdown from having to where are of Item_field objects
---
sql/sql_lex.cc | 1 +
1 file changed, 1 insertion(+)
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index feda4cd23fb..eceef9a7097 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -7893,6 +7893,7 @@ bool st_select_lex::collect_grouping_fields(THD *thd)
Item *item= *ord->item;
if (item->type() != Item::FIELD_ITEM &&
!(item->type() == Item::REF_ITEM &&
+ ((Item_ref*)item)->real_type() == Item::FIELD_ITEM &&
((((Item_ref *) item)->ref_type() == Item_ref::VIEW_REF) ||
(((Item_ref *) item)->ref_type() == Item_ref::REF))))
continue;
1
0
[Commits] c776ed4d6ec: MDEV-19848 Server crashes in check_vcol_forward_refs upon INSERT DELAYED into table with long blob key
by sachin.setiyaï¼ mariadb.com 29 Jul '19
by sachin.setiyaï¼ mariadb.com 29 Jul '19
29 Jul '19
revision-id: c776ed4d6ecf9a0393a8eb53cd6660ff3eb63758 (mariadb-10.4.5-153-gc776ed4d6ec)
parent(s): 4ca016237f1a1813c9e1ce9e4227c056c53896bb
author: Sachin
committer: Sachin
timestamp: 2019-07-30 03:42:21 +0530
message:
MDEV-19848 Server crashes in check_vcol_forward_refs upon INSERT DELAYED into table with long blob key
There are 2 issues
1st:- in make_new_field when we & into new field flag we forget
LONG_UNIQUE_HASH_FIELD Flag.
2nd:- We are calling parse_vcol_defs on keyinfo , but they are not in right
form. We should call setup_keyinfo_hash_all before calling parse_vcol_defs
---
mysql-test/main/long_unique_bugs.result | 3 +++
mysql-test/main/long_unique_bugs.test | 8 ++++++++
sql/field.cc | 2 +-
sql/sql_insert.cc | 1 +
sql/table.cc | 20 ++++++++++++++++++++
sql/table.h | 2 ++
6 files changed, 35 insertions(+), 1 deletion(-)
diff --git a/mysql-test/main/long_unique_bugs.result b/mysql-test/main/long_unique_bugs.result
index 910e5e592e1..4e831bcff92 100644
--- a/mysql-test/main/long_unique_bugs.result
+++ b/mysql-test/main/long_unique_bugs.result
@@ -268,3 +268,6 @@ DROP TABLE t1, t2;
create table t1(a int, unique(a) using hash);
#BULK insert > 100 rows (MI_MIN_ROWS_TO_DISABLE_INDEXES)
drop table t1;
+CREATE TABLE t1 (a BLOB, UNIQUE(a)) ENGINE=MyISAM;
+INSERT DELAYED t1 () VALUES ();
+DROP TABLE t1;
diff --git a/mysql-test/main/long_unique_bugs.test b/mysql-test/main/long_unique_bugs.test
index da054e59f34..b9b10b3d6cd 100644
--- a/mysql-test/main/long_unique_bugs.test
+++ b/mysql-test/main/long_unique_bugs.test
@@ -334,3 +334,11 @@ while ($count)
--eval $insert_stmt
--enable_query_log
drop table t1;
+
+#
+# MDEV-19848 Server crashes in check_vcol_forward_refs upon INSERT DELAYED into table with long blob key
+#
+CREATE TABLE t1 (a BLOB, UNIQUE(a)) ENGINE=MyISAM;
+INSERT DELAYED t1 () VALUES ();
+# Cleanup
+DROP TABLE t1;
diff --git a/sql/field.cc b/sql/field.cc
index 621f0136bea..caae3bca430 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -2326,7 +2326,7 @@ Field *Field::make_new_field(MEM_ROOT *root, TABLE *new_table,
tmp->flags&= (NOT_NULL_FLAG | BLOB_FLAG | UNSIGNED_FLAG |
ZEROFILL_FLAG | BINARY_FLAG | ENUM_FLAG | SET_FLAG |
VERS_SYS_START_FLAG | VERS_SYS_END_FLAG |
- VERS_UPDATE_UNVERSIONED_FLAG);
+ VERS_UPDATE_UNVERSIONED_FLAG | LONG_UNIQUE_HASH_FIELD);
tmp->reset_fields();
tmp->invisible= VISIBLE;
return tmp;
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index f3a548d7265..a05bc934553 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -2623,6 +2623,7 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
if (share->virtual_fields || share->default_expressions ||
share->default_fields)
{
+ table->setup_keyinfo_hash_all();
bool error_reported= FALSE;
if (unlikely(parse_vcol_defs(client_thd, client_thd->mem_root, copy,
&error_reported)))
diff --git a/sql/table.cc b/sql/table.cc
index 48421c4051e..d859152f700 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -9039,6 +9039,26 @@ void re_setup_keyinfo_hash(KEY *key_info)
key_info->ext_key_parts= 1;
key_info->flags&= ~HA_NOSAME;
}
+
+/*
+ call setup_keyinfo_hash for all keys in table
+ */
+void TABLE::setup_keyinfo_hash_all()
+{
+ for (uint i= 0; i < s->keys; i++)
+ if (key_info[i].algorithm == HA_KEY_ALG_LONG_HASH)
+ setup_keyinfo_hash(&key_info[i]);
+}
+
+/*
+ call re_setup_keyinfo_hash for all keys in table
+ */
+void TABLE::re_setup_keyinfo_hash_all()
+{
+ for (uint i= 0; i < s->keys; i++)
+ if (key_info[i].algorithm == HA_KEY_ALG_LONG_HASH)
+ re_setup_keyinfo_hash(&key_info[i]);
+}
/**
@brief clone of current handler.
Creates a clone of handler used in update for
diff --git a/sql/table.h b/sql/table.h
index 42c017d63af..40ff7cdba29 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -1596,6 +1596,8 @@ struct TABLE
void vers_update_fields();
void vers_update_end();
void find_constraint_correlated_indexes();
+ void setup_keyinfo_hash_all();
+ void re_setup_keyinfo_hash_all();
void clone_handler_for_update();
void delete_update_handler();
1
0
[Commits] c5b7cc28b0c: MDEV-20129: Equality propagation for ORDER BY items do not work with expressions
by Varun 29 Jul '19
by Varun 29 Jul '19
29 Jul '19
revision-id: c5b7cc28b0cbc15c9bf44fe5a74e8ef363773133 (mariadb-10.4.4-255-gc5b7cc28b0c)
parent(s): ddce85907611e0533d6226de7f53e751cf173f6a
author: Varun Gupta
committer: Varun Gupta
timestamp: 2019-07-30 00:29:11 +0530
message:
MDEV-20129: Equality propagation for ORDER BY items do not work with expressions
Introduced a function equality_propagation_for_order_items, that would propagate
equalities to order by clause and will substitute them with the best field
---
mysql-test/main/order_by.result | 110 ++++++++++++++++++++++++++++++++++++++++
mysql-test/main/order_by.test | 54 ++++++++++++++++++++
sql/item.cc | 50 ++++++++++++++++++
sql/item.h | 20 ++++++++
sql/item_func.cc | 11 ++++
sql/item_func.h | 5 ++
sql/sql_select.cc | 23 +++------
7 files changed, 258 insertions(+), 15 deletions(-)
diff --git a/mysql-test/main/order_by.result b/mysql-test/main/order_by.result
index b059cc686cd..54190d2f608 100644
--- a/mysql-test/main/order_by.result
+++ b/mysql-test/main/order_by.result
@@ -3436,3 +3436,113 @@ Note 1003 select `test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b`,`test`.`t4`.`c` A
set histogram_size=@tmp_h, histogram_type=@tmp_ht, use_stat_tables=@tmp_u,
optimizer_use_condition_selectivity=@tmp_o;
drop table t1,t2,t3,t4;
+create table ten(a int);
+insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table one_k(a int);
+insert into one_k select A.a + B.a* 10 + C.a * 100 from ten A, ten B, ten C;
+create table t1(a int, b int);
+insert into t1 select A.a + B.a* 10, A.a + B.a* 10 from ten A, ten B;
+create table t2(a int, b int, key(a));
+insert into t2 select A.a + B.a* 10, A.a+B.a*10 from ten A, ten B;
+should have Using Filesort only
+explain select * from t1,t2 where t1.a > 95 and t1.a=t2.a order by t2.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 100 Using where; Using filesort
+1 SIMPLE t2 ref a a 5 test.t1.a 1
+should have Using Filesort only with expressions too
+explain select * from t1,t2 where t1.a > 95 and t1.a=t2.a order by t2.a+t1.b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 100 Using where; Using filesort
+1 SIMPLE t2 ref a a 5 test.t1.a 1
+drop table t1,t2,ten,one_k;
+CREATE TABLE t1(a int, b int);
+CREATE TABLE t2(a int, b int, index i(a));
+INSERT INTO t1 VALUES (1,1), (2,2);
+INSERT INTO t2 VALUES (1,5), (1,6), (2,5), (2,6);
+INSERT INTO t2 VALUES (1,5), (1,6), (2,5), (2,6);
+INSERT INTO t2 VALUES (1,5), (1,6), (2,5), (2,6);
+CREATE VIEW v1 AS
+SELECT t1.a as c, t2.a as d FROM t1,t2 WHERE t1.a=t2.a;
+CREATE VIEW v2 AS
+SELECT t1.a+t2.a as c, abs(t2.a) as d FROM t1,t2 WHERE t1.a=t2.a;
+should have Using Filesort only
+explain SELECT c,d FROM v1 ORDER BY c;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where; Using filesort
+1 SIMPLE t2 ref i i 5 test.t1.a 2 Using index
+SELECT c,d FROM v1 ORDER BY c;
+c d
+1 1
+1 1
+1 1
+1 1
+1 1
+1 1
+2 2
+2 2
+2 2
+2 2
+2 2
+2 2
+views use Item_direct_view_ref, so this shows equalities are propagated
+should have Using Filesort only
+explain SELECT c,d FROM v1 ORDER BY d;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where; Using filesort
+1 SIMPLE t2 ref i i 5 test.t1.a 2 Using index
+SELECT c,d FROM v1 ORDER BY d;
+c d
+1 1
+1 1
+1 1
+1 1
+1 1
+1 1
+2 2
+2 2
+2 2
+2 2
+2 2
+2 2
+views use Item_direct_view_ref that are expressions
+should have Using Filesort only
+explain SELECT c,d FROM v2 ORDER BY c;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where; Using filesort
+1 SIMPLE t2 ref i i 5 test.t1.a 2 Using index
+SELECT c,d FROM v2 ORDER BY c;
+c d
+2 1
+2 1
+2 1
+2 1
+2 1
+2 1
+4 2
+4 2
+4 2
+4 2
+4 2
+4 2
+views use Item_direct_view_ref that are expressions
+should have Using Filesort only
+explain SELECT c,d FROM v2 ORDER BY d;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where; Using filesort
+1 SIMPLE t2 ref i i 5 test.t1.a 2 Using index
+SELECT c,d FROM v2 ORDER BY d;
+c d
+2 1
+2 1
+2 1
+2 1
+2 1
+2 1
+4 2
+4 2
+4 2
+4 2
+4 2
+4 2
+DROP VIEW v1,v2;
+DROP TABLE t1, t2;
diff --git a/mysql-test/main/order_by.test b/mysql-test/main/order_by.test
index 934c503302f..2f39bb88329 100644
--- a/mysql-test/main/order_by.test
+++ b/mysql-test/main/order_by.test
@@ -2276,3 +2276,57 @@ set histogram_size=@tmp_h, histogram_type=@tmp_ht, use_stat_tables=@tmp_u,
optimizer_use_condition_selectivity=@tmp_o;
drop table t1,t2,t3,t4;
+
+create table ten(a int);
+insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table one_k(a int);
+insert into one_k select A.a + B.a* 10 + C.a * 100 from ten A, ten B, ten C;
+create table t1(a int, b int);
+insert into t1 select A.a + B.a* 10, A.a + B.a* 10 from ten A, ten B;
+create table t2(a int, b int, key(a));
+insert into t2 select A.a + B.a* 10, A.a+B.a*10 from ten A, ten B;
+
+--echo should have Using Filesort only
+explain select * from t1,t2 where t1.a > 95 and t1.a=t2.a order by t2.a;
+
+--echo should have Using Filesort only with expressions too
+explain select * from t1,t2 where t1.a > 95 and t1.a=t2.a order by t2.a+t1.b;
+drop table t1,t2,ten,one_k;
+
+CREATE TABLE t1(a int, b int);
+CREATE TABLE t2(a int, b int, index i(a));
+INSERT INTO t1 VALUES (1,1), (2,2);
+INSERT INTO t2 VALUES (1,5), (1,6), (2,5), (2,6);
+INSERT INTO t2 VALUES (1,5), (1,6), (2,5), (2,6);
+INSERT INTO t2 VALUES (1,5), (1,6), (2,5), (2,6);
+CREATE VIEW v1 AS
+ SELECT t1.a as c, t2.a as d FROM t1,t2 WHERE t1.a=t2.a;
+
+CREATE VIEW v2 AS
+ SELECT t1.a+t2.a as c, abs(t2.a) as d FROM t1,t2 WHERE t1.a=t2.a;
+
+
+--echo should have Using Filesort only
+let $query= SELECT c,d FROM v1 ORDER BY c;
+eval explain $query;
+eval $query;
+
+--echo views use Item_direct_view_ref, so this shows equalities are propagated
+--echo should have Using Filesort only
+let $query= SELECT c,d FROM v1 ORDER BY d;
+eval explain $query;
+eval $query;
+
+--echo views use Item_direct_view_ref that are expressions
+--echo should have Using Filesort only
+let $query= SELECT c,d FROM v2 ORDER BY c;
+eval explain $query;
+eval $query;
+
+--echo views use Item_direct_view_ref that are expressions
+--echo should have Using Filesort only
+let $query= SELECT c,d FROM v2 ORDER BY d;
+eval explain $query;
+eval $query;
+DROP VIEW v1,v2;
+DROP TABLE t1, t2;
diff --git a/sql/item.cc b/sql/item.cc
index 42bcb216935..53220453cd9 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -6096,6 +6096,23 @@ Item *Item_field::propagate_equal_fields(THD *thd,
}
+Item *Item_field::equality_propagation_for_order_items(THD *thd,
+ const Context &ctx,
+ COND_EQUAL *arg)
+{
+ Item *item= propagate_equal_fields(thd, ctx, arg);
+
+ DBUG_ASSERT(item);
+ Item_equal *item_eq;
+ if ((item_eq= item->get_item_equal()))
+ {
+ Item *first= item_eq->get_first(NO_PARTICULAR_TAB, NULL);
+ return first;
+ }
+ return item;
+}
+
+
/**
Replace an Item_field for an equal Item_field that evaluated earlier
(if any).
@@ -7110,6 +7127,18 @@ Item* Item::propagate_equal_fields_and_change_item_tree(THD *thd,
}
+Item* Item::equality_propagation_and_change_item_tree(THD *thd,
+ const Context &ctx,
+ COND_EQUAL *cond,
+ Item **place)
+{
+ Item *item= equality_propagation_for_order_items(thd, ctx, cond);
+ if (item && item != this)
+ thd->change_item_tree(place, item);
+ return item;
+}
+
+
void Item_field::update_null_value()
{
/*
@@ -9003,6 +9032,17 @@ Item *Item_direct_view_ref::propagate_equal_fields(THD *thd,
}
+Item *Item_direct_view_ref::equality_propagation_for_order_items(THD *thd,
+ const Context &ctx,
+ COND_EQUAL *arg)
+{
+ Item *item= real_item();
+ Item *res= item->equality_propagation_for_order_items(thd, ctx, arg);
+ set_item_equal(res->get_item_equal());
+ return res;
+}
+
+
Item *Item_ref::propagate_equal_fields(THD *thd, const Context &ctx,
COND_EQUAL *cond)
{
@@ -9016,6 +9056,16 @@ Item *Item_ref::propagate_equal_fields(THD *thd, const Context &ctx,
}
+Item *Item_ref::equality_propagation_for_order_items(THD *thd,
+ const Context &ctx,
+ COND_EQUAL *arg)
+{
+ Item *item= real_item();
+ Item *res= item->equality_propagation_for_order_items(thd, ctx, arg);
+ return res;
+}
+
+
/**
Replace an Item_direct_view_ref for an equal Item_field evaluated earlier
(if any).
diff --git a/sql/item.h b/sql/item.h
index 14c29fe4e6a..b6ca0d81ad0 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -2022,10 +2022,26 @@ class Item: public Value_source,
return this;
};
+ /*
+ This function would propagate the equalities to the order item and
+ return the first item of the Item_equal if the field
+ has participated in an equality
+ */
+
+ virtual Item* equality_propagation_for_order_items(THD*, const Context &, COND_EQUAL *)
+ {
+ return this;
+ };
+
+
Item* propagate_equal_fields_and_change_item_tree(THD *thd,
const Context &ctx,
COND_EQUAL *cond,
Item **place);
+ Item* equality_propagation_and_change_item_tree(THD *thd,
+ const Context &ctx,
+ COND_EQUAL *cond,
+ Item **place);
/* arg points to REPLACE_EQUAL_FIELD_ARG object */
virtual Item *replace_equal_field(THD *thd, uchar *arg) { return this; }
@@ -2448,6 +2464,7 @@ class Item_args
}
bool transform_args(THD *thd, Item_transformer transformer, uchar *arg);
void propagate_equal_fields(THD *, const Item::Context &, COND_EQUAL *);
+ void equality_propagation_for_order_items(THD *, const Item::Context &, COND_EQUAL *);
bool excl_dep_on_table(table_map tab_map)
{
for (uint i= 0; i < arg_count; i++)
@@ -3392,6 +3409,7 @@ class Item_field :public Item_ident,
void set_item_equal(Item_equal *item_eq) { item_equal= item_eq; }
Item_equal *find_item_equal(COND_EQUAL *cond_equal);
Item* propagate_equal_fields(THD *, const Context &, COND_EQUAL *);
+ Item* equality_propagation_for_order_items(THD *, const Context &, COND_EQUAL *);
Item *replace_equal_field(THD *thd, uchar *arg);
uint32 max_display_length() const { return field->max_display_length(); }
Item_field *field_for_view_update() { return this; }
@@ -5120,6 +5138,7 @@ class Item_ref :public Item_ident,
Field *create_tmp_field_ex(MEM_ROOT *root, TABLE *table, Tmp_field_src *src,
const Tmp_field_param *param);
Item* propagate_equal_fields(THD *, const Context &, COND_EQUAL *);
+ Item* equality_propagation_for_order_items(THD *, const Context &, COND_EQUAL *);
table_map used_tables() const;
void update_used_tables();
COND *build_equal_items(THD *thd, COND_EQUAL *inherited,
@@ -5554,6 +5573,7 @@ class Item_direct_view_ref :public Item_direct_ref
void set_item_equal(Item_equal *item_eq) { item_equal= item_eq; }
Item_equal *find_item_equal(COND_EQUAL *cond_equal);
Item* propagate_equal_fields(THD *, const Context &, COND_EQUAL *);
+ Item* equality_propagation_for_order_items(THD *, const Context &, COND_EQUAL *);
Item *replace_equal_field(THD *thd, uchar *arg);
table_map used_tables() const;
void update_used_tables();
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 03abe4f26fb..cdf710d9be0 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -561,6 +561,17 @@ void Item_args::propagate_equal_fields(THD *thd,
}
+void Item_args::equality_propagation_for_order_items(THD *thd,
+ const Item::Context &ctx,
+ COND_EQUAL *cond)
+{
+ uint i;
+ for (i= 0; i < arg_count; i++)
+ args[i]->equality_propagation_and_change_item_tree(thd, ctx, cond,
+ &args[i]);
+}
+
+
/**
See comments in Item_cond::split_sum_func()
*/
diff --git a/sql/item_func.h b/sql/item_func.h
index 00ed688e9e3..4e15fe2fd7e 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -326,6 +326,11 @@ class Item_func :public Item_func_or_sum,
Item_args::propagate_equal_fields(thd, Context_identity(), cond);
return this;
}
+ Item* equality_propagation_for_order_items(THD *thd, const Context &ctx, COND_EQUAL *cond)
+ {
+ Item_args::equality_propagation_for_order_items(thd, Context_identity(), cond);
+ return this;
+ }
bool has_rand_bit()
{
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 8163f5b4cf0..39ca47991eb 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -13987,7 +13987,6 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond,
*/
if (optimizer_flag(join->thd, OPTIMIZER_SWITCH_ORDERBY_EQ_PROP) &&
first_is_base_table && !first_is_in_sjm_nest &&
- order->item[0]->real_item()->type() == Item::FIELD_ITEM &&
join->cond_equal)
{
table_map first_table_bit=
@@ -14003,20 +14002,14 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond,
multiple equality the item belongs to and set item->item_equal
accordingly.
*/
- Item *res= item->propagate_equal_fields(join->thd,
- Value_source::
- Context_identity(),
- join->cond_equal);
- Item_equal *item_eq;
- if ((item_eq= res->get_item_equal()))
- {
- Item *first= item_eq->get_first(NO_PARTICULAR_TAB, NULL);
- if (first->const_item() || first->used_tables() ==
- first_table_bit)
- {
- can_subst_to_first_table= true;
- }
- }
+ Item *res= item->equality_propagation_for_order_items(join->thd,
+ Value_source::
+ Context_identity(),
+ join->cond_equal);
+ res->update_used_tables();
+ Item *real_item= res->real_item();
+ if (real_item->const_item() || real_item->used_tables() == first_table_bit)
+ can_subst_to_first_table= TRUE;
}
if (!can_subst_to_first_table)
1
0
[Commits] 4ca016237f1: MDEV-20001 Potential dangerous regression: INSERT INTO >=100 rows fail for myisam table with HASH indexes
by sachin.setiyaï¼ mariadb.com 29 Jul '19
by sachin.setiyaï¼ mariadb.com 29 Jul '19
29 Jul '19
revision-id: 4ca016237f1a1813c9e1ce9e4227c056c53896bb (mariadb-10.4.5-152-g4ca016237f1)
parent(s): 4a5cd4072894864c9f1f59675c2b8b8cd2ae40a4
author: Sachin
committer: Sachin
timestamp: 2019-07-29 19:33:05 +0530
message:
MDEV-20001 Potential dangerous regression: INSERT INTO >=100 rows fail for myisam table with HASH indexes
Dont deactivate the long unique keys on bulk insert.
---
mysql-test/main/long_unique_bugs.result | 3 +++
mysql-test/main/long_unique_bugs.test | 17 +++++++++++++++++
storage/myisam/ha_myisam.cc | 11 ++++++++++-
storage/myisam/mi_check.c | 5 +++--
storage/myisam/myisamdef.h | 2 +-
5 files changed, 34 insertions(+), 4 deletions(-)
diff --git a/mysql-test/main/long_unique_bugs.result b/mysql-test/main/long_unique_bugs.result
index 33496c4e20d..910e5e592e1 100644
--- a/mysql-test/main/long_unique_bugs.result
+++ b/mysql-test/main/long_unique_bugs.result
@@ -265,3 +265,6 @@ ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
disconnect con1;
connection default;
DROP TABLE t1, t2;
+create table t1(a int, unique(a) using hash);
+#BULK insert > 100 rows (MI_MIN_ROWS_TO_DISABLE_INDEXES)
+drop table t1;
diff --git a/mysql-test/main/long_unique_bugs.test b/mysql-test/main/long_unique_bugs.test
index dc78f6c7067..da054e59f34 100644
--- a/mysql-test/main/long_unique_bugs.test
+++ b/mysql-test/main/long_unique_bugs.test
@@ -317,3 +317,20 @@ INSERT IGNORE INTO t1 VALUES (4, 1)/*4*/;
--disconnect con1
--connection default
DROP TABLE t1, t2;
+
+#
+# MDEV-20001 Potential dangerous regression: INSERT INTO >=100 rows fail for myisam table with HASH indexes
+#
+create table t1(a int, unique(a) using hash);
+--let $count=150
+--let insert_stmt= insert into t1 values(200)
+while ($count)
+{
+ --let $insert_stmt=$insert_stmt,($count)
+ --dec $count
+}
+--disable_query_log
+--echo #BULK insert > 100 rows (MI_MIN_ROWS_TO_DISABLE_INDEXES)
+--eval $insert_stmt
+--enable_query_log
+drop table t1;
diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc
index f478e01e441..c1169737911 100644
--- a/storage/myisam/ha_myisam.cc
+++ b/storage/myisam/ha_myisam.cc
@@ -1749,7 +1749,16 @@ void ha_myisam::start_bulk_insert(ha_rows rows, uint flags)
else
{
my_bool all_keys= MY_TEST(flags & HA_CREATE_UNIQUE_INDEX_BY_SORT);
- mi_disable_indexes_for_rebuild(file, rows, all_keys);
+ if (table->s->long_unique_table)
+ {
+ ulonglong hash_key_map= 0ULL;
+ for(uint i= 0; i < table->s->keys; i++)
+ if (table->key_info[i].algorithm == HA_KEY_ALG_LONG_HASH)
+ mi_set_key_active(hash_key_map, i);
+ mi_disable_indexes_for_rebuild(file, rows, all_keys, hash_key_map);
+ }
+ else
+ mi_disable_indexes_for_rebuild(file, rows, all_keys, 0ULL);
}
}
else
diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c
index 869e86b7495..d3205b89d90 100644
--- a/storage/myisam/mi_check.c
+++ b/storage/myisam/mi_check.c
@@ -4694,7 +4694,7 @@ static my_bool mi_too_big_key_for_sort(MI_KEYDEF *key, ha_rows rows)
*/
void mi_disable_indexes_for_rebuild(MI_INFO *info, ha_rows rows,
- my_bool all_keys)
+ my_bool all_keys, ulonglong hash_key_map)
{
MYISAM_SHARE *share=info->s;
MI_KEYDEF *key=share->keyinfo;
@@ -4706,7 +4706,8 @@ void mi_disable_indexes_for_rebuild(MI_INFO *info, ha_rows rows,
{
if (!(key->flag & (HA_SPATIAL | HA_AUTO_KEY)) &&
! mi_too_big_key_for_sort(key,rows) && info->s->base.auto_key != i+1 &&
- (all_keys || !(key->flag & HA_NOSAME)))
+ (all_keys || !(key->flag & HA_NOSAME)) &&
+ !mi_is_key_active(hash_key_map, i))
{
mi_clear_key_active(share->state.key_map, i);
info->update|= HA_STATE_CHANGED;
diff --git a/storage/myisam/myisamdef.h b/storage/myisam/myisamdef.h
index 7fc8a8eba4f..a8794f76fbd 100644
--- a/storage/myisam/myisamdef.h
+++ b/storage/myisam/myisamdef.h
@@ -716,7 +716,7 @@ void mi_copy_status(void *to, void *from);
my_bool mi_check_status(void *param);
void mi_fix_status(MI_INFO *org_table, MI_INFO *new_table);
void mi_disable_indexes_for_rebuild(MI_INFO *info, ha_rows rows,
- my_bool all_keys);
+ my_bool all_keys, ulonglong hash_key_map);
extern MI_INFO *test_if_reopen(char *filename);
my_bool check_table_is_closed(const char *name, const char *where);
int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share);
1
0
revision-id: 2de94d8de7a48a4a169dae8cd2a915dcd73de22f (mariadb-10.4.4-154-g2de94d8de7a)
parent(s): c51f615bf575480b13ee542fdb3b7fe644e21098
author: Varun Gupta
committer: Varun Gupta
timestamp: 2019-07-26 23:43:04 +0530
message:
Poor optimization of JOIN and ORDER BY LIMIT
Iteration one
---
mysql-test/main/order_by_limit.result | 200 +++++++++++
mysql-test/main/order_by_limit.test | 23 ++
mysql-test/main/sort_nest.result | 524 +++++++++++++++++++++++++++
mysql-test/main/sort_nest.test | 145 ++++++++
sql/item.cc | 41 ++-
sql/item.h | 40 +++
sql/item_cmpfunc.cc | 16 +
sql/item_cmpfunc.h | 1 +
sql/item_func.h | 8 +
sql/item_row.h | 5 +
sql/opt_split.cc | 1 -
sql/opt_subselect.cc | 30 ++
sql/opt_subselect.h | 1 +
sql/opt_trace.cc | 20 ++
sql/opt_trace.h | 1 +
sql/sql_class.h | 14 +
sql/sql_const.h | 8 +
sql/sql_select.cc | 660 +++++++++++++++++++++++++++++++---
sql/sql_select.h | 40 ++-
19 files changed, 1729 insertions(+), 49 deletions(-)
diff --git a/mysql-test/main/order_by_limit.result b/mysql-test/main/order_by_limit.result
new file mode 100644
index 00000000000..5199cc88519
--- /dev/null
+++ b/mysql-test/main/order_by_limit.result
@@ -0,0 +1,200 @@
+create table ten(a int);
+insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table one_k(a int);
+insert into one_k select A.a + B.a* 10 + C.a * 100 from ten A, ten B, ten C;
+create table t1(a int, b int);
+insert into t1 select A.a + B.a* 10, A.a + B.a* 10 from ten A, ten B,ten C;
+create table t2(a int, b int);
+insert into t2(a,b) values (1,1), (2,1);
+insert into t2 select A.a + B.a* 10, -1 from ten A, ten B;
+create table t3(a int, b int);
+insert into t3 select A.a + B.a* 10 + C.a * 100, A.a + B.a* 10 + C.a * 100 from ten A, ten B, ten C;
+set optimizer_trace=1;
+the best plan would be having an order nest on (t2,t1)
+explain
+select * from t1,t2,t3 where t1.a=t2.b order by t1.b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 102 Using temporary; Using filesort
+1 SIMPLE t1 ALL NULL NULL NULL NULL 1000 Using where; Using join buffer (flat, BNL join)
+1 SIMPLE t3 ALL NULL NULL NULL NULL 1000 Using join buffer (incremental, BNL join)
+select JSON_DETAILED(JSON_EXTRACT(trace, '$**.considered_execution_plans')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+JSON_DETAILED(JSON_EXTRACT(trace, '$**.considered_execution_plans'))
+[
+
+ [
+
+ {
+ "plan_prefix":
+ [
+ ],
+ "table": "t2",
+ "best_access_path":
+ {
+ "considered_access_paths":
+ [
+
+ {
+ "access_type": "scan",
+ "resulting_rows": 102,
+ "cost": 2.2241,
+ "chosen": true
+ }
+ ]
+ },
+ "rest_of_plan":
+ [
+
+ {
+ "plan_prefix":
+ [
+ "t2"
+ ],
+ "table": "t1",
+ "best_access_path":
+ {
+ "considered_access_paths":
+ [
+
+ {
+ "access_type": "scan",
+ "resulting_rows": 1000,
+ "cost": 4.1973,
+ "chosen": true
+ }
+ ]
+ },
+ "rest_of_plan":
+ [
+
+ {
+ "plan_prefix":
+ [
+ "t2",
+ "t1"
+ ],
+ "table": "t3",
+ "best_access_path":
+ {
+ "considered_access_paths":
+ [
+
+ {
+ "access_type": "scan",
+ "resulting_rows": 1000,
+ "cost": 33.578,
+ "chosen": true
+ }
+ ]
+ },
+ "cardinality": 1.02e8,
+ "cost_of_plan": 1.22e8
+ },
+
+ {
+ "plan_prefix":
+ [
+ "t2",
+ "t1"
+ ],
+ "table": "t3",
+ "order_by_nest":
+ [
+ "t2",
+ "t1"
+ ],
+ "best_access_path":
+ {
+ "considered_access_paths":
+ [
+
+ {
+ "access_type": "scan",
+ "resulting_rows": 1000,
+ "cost": 428121,
+ "chosen": true
+ }
+ ]
+ },
+ "cost_of_plan": 2.1e7
+ }
+ ]
+ },
+
+ {
+ "plan_prefix":
+ [
+ "t2"
+ ],
+ "table": "t3",
+ "best_access_path":
+ {
+ "considered_access_paths":
+ [
+
+ {
+ "access_type": "scan",
+ "resulting_rows": 1000,
+ "cost": 4.1973,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ }
+ ]
+ },
+
+ {
+ "plan_prefix":
+ [
+ ],
+ "table": "t1",
+ "best_access_path":
+ {
+ "considered_access_paths":
+ [
+
+ {
+ "access_type": "scan",
+ "resulting_rows": 1000,
+ "cost": 4.1973,
+ "chosen": true,
+ "use_tmp_table": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ },
+
+ {
+ "plan_prefix":
+ [
+ ],
+ "table": "t3",
+ "best_access_path":
+ {
+ "considered_access_paths":
+ [
+
+ {
+ "access_type": "scan",
+ "resulting_rows": 1000,
+ "cost": 4.1973,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ }
+ ]
+]
+select JSON_DETAILED(JSON_EXTRACT(trace, '$**.order_nest')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+JSON_DETAILED(JSON_EXTRACT(trace, '$**.order_nest'))
+[
+
+ [
+ "t2",
+ "t1"
+ ]
+]
+drop table t1,t2,t3,ten,one_k;
diff --git a/mysql-test/main/order_by_limit.test b/mysql-test/main/order_by_limit.test
new file mode 100644
index 00000000000..b717e84a1a8
--- /dev/null
+++ b/mysql-test/main/order_by_limit.test
@@ -0,0 +1,23 @@
+create table ten(a int);
+insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+
+create table one_k(a int);
+insert into one_k select A.a + B.a* 10 + C.a * 100 from ten A, ten B, ten C;
+
+create table t1(a int, b int);
+insert into t1 select A.a + B.a* 10, A.a + B.a* 10 from ten A, ten B,ten C;
+create table t2(a int, b int);
+insert into t2(a,b) values (1,1), (2,1);
+insert into t2 select A.a + B.a* 10, -1 from ten A, ten B;
+create table t3(a int, b int);
+insert into t3 select A.a + B.a* 10 + C.a * 100, A.a + B.a* 10 + C.a * 100 from ten A, ten B, ten C;
+
+set optimizer_trace=1;
+
+--echo the best plan would be having an order nest on (t2,t1)
+
+explain
+select * from t1,t2,t3 where t1.a=t2.b order by t1.b;
+select JSON_DETAILED(JSON_EXTRACT(trace, '$**.considered_execution_plans')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+select JSON_DETAILED(JSON_EXTRACT(trace, '$**.order_nest')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+drop table t1,t2,t3,ten,one_k;
diff --git a/mysql-test/main/sort_nest.result b/mysql-test/main/sort_nest.result
new file mode 100644
index 00000000000..f3e10597536
--- /dev/null
+++ b/mysql-test/main/sort_nest.result
@@ -0,0 +1,524 @@
+create table ten(a int);
+insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table one_k(a int);
+insert into one_k select A.a + B.a* 10 from ten A, ten B;
+create table t1 (a int, b int);
+insert into t1 select a,a from one_k;
+create table t2 (a int, b int);
+insert into t2 select a,a from one_k;
+explain
+select t1.b from t1,t2 where t1.a=t2.a order by t2.b limit 2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 100 Using filesort
+1 SIMPLE t1 ALL NULL NULL NULL NULL 100 Using where
+select t1.b from t1,t2 where t1.a=t2.a order by t2.b limit 2;
+b
+0
+1
+analyze
+select t1.a,t2.a from t1,t2 where t1.a=t2.a order by t2.b limit 10;
+id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 100 10.00 100.00 100.00 Using filesort
+1 SIMPLE t1 ALL NULL NULL NULL NULL 100 91.00 100.00 1.10 Using where
+select t1.a,t2.a from t1,t2 where t1.a=t2.a order by t2.b limit 10;
+a a
+0 0
+1 1
+2 2
+3 3
+4 4
+5 5
+6 6
+7 7
+8 8
+9 9
+alter table t1 add key (a);
+ref should be func
+explain
+select t1.b,t2.b from t1,t2 where t1.a=t2.a+1 order by t2.b limit 2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 100 Using filesort
+1 SIMPLE t1 ref a a 5 func 1 Using index condition
+select t1.b,t2.b from t1,t2 where t1.a=t2.a+1 order by t2.b limit 2;
+b b
+1 0
+2 1
+ref should be order-nest.a
+explain
+select t1.b,t2.b from t1,t2 where t1.a=t2.a order by t2.b limit 2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 100 Using where; Using filesort
+1 SIMPLE t1 ref a a 5 test.t2.a 1
+select t1.b,t2.b from t1,t2 where t1.a=t2.a order by t2.b limit 2;
+b b
+0 0
+1 1
+drop table t1,t2,ten,one_k;
+create table ten(a int);
+insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table one_k(a int);
+insert into one_k select A.a + B.a* 10 + C.a * 100 from ten A, ten B, ten C;
+create table t1(a int, b int);
+insert into t1 select A.a + B.a* 10, A.a + B.a* 10 from ten A, ten B;
+create table t2(a int, b int);
+insert into t2(a,b) values (1,1), (2,2);
+insert into t2 select A.a + B.a* 10, A.a+B.a*10 from ten A, ten B;
+create table t3(a int, b int);
+insert into t3 select A.a + B.a* 10 + C.a * 100, A.a + B.a* 10 + C.a * 100 from ten A, ten B, ten C;
+create function f1(a int) returns int
+begin
+declare b int default 0;
+return a+b;
+end|
+Covering 3 table joins
+# {t1,t2} part of the nest
+# t1.a > 95 would be attached to table t1
+# t1.b=t2.a would be attached to table t2;
+explain select * from t1,t2,t3 where t1.a > 95 and t1.a=t2.a and t1.b = t3.a order by t2.b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 100 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 102 Using where; Using join buffer (flat, BNL join)
+1 SIMPLE <order-nest> ALL NULL NULL NULL NULL 10200 Using filesort
+1 SIMPLE t3 ALL NULL NULL NULL NULL 1000 Using where
+explain format=json select * from t1,t2,t3 where t1.a > 95 and t1.a=t2.a and t1.b = t3.a order by t2.b;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 100,
+ "filtered": 100,
+ "attached_condition": "t1.a > 95"
+ },
+ "block-nl-join": {
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 102,
+ "filtered": 100
+ },
+ "buffer_type": "flat",
+ "buffer_size": "1Kb",
+ "join_type": "BNL",
+ "attached_condition": "t2.a = t1.a"
+ },
+ "read_sorted_file": {
+ "filesort": {
+ "sort_key": "`order-nest`.b",
+ "table": {
+ "table_name": "<order-nest>",
+ "access_type": "ALL",
+ "rows": 10200,
+ "filtered": 100
+ }
+ }
+ },
+ "table": {
+ "table_name": "t3",
+ "access_type": "ALL",
+ "rows": 1000,
+ "filtered": 100,
+ "attached_condition": "t3.a = `order-nest`.b"
+ }
+ }
+}
+select * from t1,t2,t3 where t1.a > 95 and t1.a=t2.a and t1.b = t3.a order by t2.b;
+a b a b a b
+96 96 96 96 96 96
+97 97 97 97 97 97
+98 98 98 98 98 98
+99 99 99 99 99 99
+# {t1,t2} part of the sort nest
+# (t2.a < 2 or t1.b > 98) would be attached to table t2
+explain select * from t1,t2,t3 where (t3.a<2 and t2.a <2) or (t1.b > 98 and t3.b > 98)
+order by t1.a, t2.b limit 5;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 100
+1 SIMPLE t2 ALL NULL NULL NULL NULL 102 Using where; Using join buffer (flat, BNL join)
+1 SIMPLE <order-nest> ALL NULL NULL NULL NULL 10200 Using filesort
+1 SIMPLE t3 ALL NULL NULL NULL NULL 1000 Using where
+explain format=json select * from t1,t2,t3 where (t3.a<2 and t2.a <2) or (t1.b > 98 and t3.b > 98)
+order by t1.a, t2.b limit 5;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 100,
+ "filtered": 100
+ },
+ "block-nl-join": {
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 102,
+ "filtered": 100
+ },
+ "buffer_type": "flat",
+ "buffer_size": "1Kb",
+ "join_type": "BNL",
+ "attached_condition": "t2.a < 2 or t1.b > 98"
+ },
+ "read_sorted_file": {
+ "filesort": {
+ "sort_key": "`order-nest`.a, `order-nest`.b",
+ "table": {
+ "table_name": "<order-nest>",
+ "access_type": "ALL",
+ "rows": 10200,
+ "filtered": 100
+ }
+ }
+ },
+ "table": {
+ "table_name": "t3",
+ "access_type": "ALL",
+ "rows": 1000,
+ "filtered": 100,
+ "attached_condition": "t3.a < 2 and `order-nest`.a < 2 or `order-nest`.b > 98 and t3.b > 98"
+ }
+ }
+}
+select * from t1,t2,t3 where (t3.a<2 and t2.a <2) or (t1.b > 98 and t3.b > 98)
+order by t1.a, t2.b limit 5;
+a b a b a b
+0 0 1 1 0 0
+0 0 1 1 1 1
+1 1 1 1 0 0
+1 1 1 1 1 1
+2 2 1 1 0 0
+# {t1,t2} part of the nest
+# t2.a < 2 or f1(t1.b) attached to table t2
+# t1.b=t2.a would be attached to table t2;
+explain select * from t1,t2,t3 where (t3.a<2 and t2.a <2) or (f1(t1.b) > 98 and t3.b > 98)
+order by t1.a,t2.b limit 5;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 100
+1 SIMPLE t2 ALL NULL NULL NULL NULL 102 Using join buffer (flat, BNL join)
+1 SIMPLE <order-nest> ALL NULL NULL NULL NULL 10200 Using filesort
+1 SIMPLE t3 ALL NULL NULL NULL NULL 1000 Using where
+explain format=json select * from t1,t2,t3 where (t3.a<2 and t2.a <2) or (f1(t1.b) > 98 and t3.b > 98)
+order by t1.a,t2.b limit 5;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 100,
+ "filtered": 100
+ },
+ "block-nl-join": {
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 102,
+ "filtered": 100
+ },
+ "buffer_type": "flat",
+ "buffer_size": "1Kb",
+ "join_type": "BNL"
+ },
+ "read_sorted_file": {
+ "filesort": {
+ "sort_key": "`order-nest`.a, `order-nest`.b",
+ "table": {
+ "table_name": "<order-nest>",
+ "access_type": "ALL",
+ "rows": 10200,
+ "filtered": 100
+ }
+ }
+ },
+ "table": {
+ "table_name": "t3",
+ "access_type": "ALL",
+ "rows": 1000,
+ "filtered": 100,
+ "attached_condition": "t3.a < 2 and `order-nest`.a < 2 or f1(`order-nest`.b) > 98 and t3.b > 98"
+ }
+ }
+}
+select * from t1,t2,t3 where (t3.a<2 and t2.a <2) or (f1(t1.b) > 98 and t3.b > 98)
+order by t1.a,t2.b limit 5;
+a b a b a b
+0 0 0 0 0 0
+0 0 0 0 1 1
+0 0 1 1 0 0
+0 0 1 1 1 1
+0 0 1 1 0 0
+#
+# Removing constant from the order by clause
+#
+explain select * from t1,t2 where t1.a > 95 and t1.a=t2.a order by t2.a limit 4;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 100 Using where; Using filesort
+1 SIMPLE t2 ALL NULL NULL NULL NULL 102 Using where
+explain format=json select * from t1,t2 where t1.a > 95 and t1.a=t2.a order by t2.a limit 4;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "read_sorted_file": {
+ "filesort": {
+ "sort_key": "t2.a",
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 100,
+ "filtered": 100,
+ "attached_condition": "t1.a > 95"
+ }
+ }
+ },
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 102,
+ "filtered": 100,
+ "attached_condition": "t2.a = t1.a"
+ }
+ }
+}
+select * from t1,t2 where t1.a > 95 and t1.a=t2.a order by t2.a limit 4;
+a b a b
+96 96 96 96
+97 97 97 97
+98 98 98 98
+99 99 99 99
+explain select * from t1,t2 where t1.a > 95 and t1.a=t2.a order by 1+2,t2.a limit 4;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 100 Using where; Using filesort
+1 SIMPLE t2 ALL NULL NULL NULL NULL 102 Using where
+explain format=json select * from t1,t2 where t1.a > 95 and t1.a=t2.a order by 1+2,t2.a limit 4;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "read_sorted_file": {
+ "filesort": {
+ "sort_key": "t2.a",
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 100,
+ "filtered": 100,
+ "attached_condition": "t1.a > 95"
+ }
+ }
+ },
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 102,
+ "filtered": 100,
+ "attached_condition": "t2.a = t1.a"
+ }
+ }
+}
+select * from t1,t2 where t1.a > 95 and t1.a=t2.a order by 1+2,t2.a limit 4;
+a b a b
+96 96 96 96
+97 97 97 97
+98 98 98 98
+99 99 99 99
+#
+# Equality propagation, both the queries should use a sort nest on {t1,t2}
+#
+explain select t3.b, t2.a , t1.b , t1.a from t1,t2,t3 where t1.b=t3.b
+order by t1.b desc, t2.a desc limit 3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 100
+1 SIMPLE t2 ALL NULL NULL NULL NULL 102 Using join buffer (flat, BNL join)
+1 SIMPLE <order-nest> ALL NULL NULL NULL NULL 10200 Using filesort
+1 SIMPLE t3 ALL NULL NULL NULL NULL 1000 Using where
+explain format=json select t3.b, t2.a , t1.b , t1.a from t1,t2,t3 where t1.b=t3.b
+order by t1.b desc, t2.a desc limit 3;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 100,
+ "filtered": 100
+ },
+ "block-nl-join": {
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 102,
+ "filtered": 100
+ },
+ "buffer_type": "flat",
+ "buffer_size": "1Kb",
+ "join_type": "BNL"
+ },
+ "read_sorted_file": {
+ "filesort": {
+ "sort_key": "`order-nest`.b desc, `order-nest`.a desc",
+ "table": {
+ "table_name": "<order-nest>",
+ "access_type": "ALL",
+ "rows": 10200,
+ "filtered": 100
+ }
+ }
+ },
+ "table": {
+ "table_name": "t3",
+ "access_type": "ALL",
+ "rows": 1000,
+ "filtered": 100,
+ "attached_condition": "t3.b = `order-nest`.b"
+ }
+ }
+}
+select t3.b, t2.a , t1.b , t1.a from t1,t2,t3 where t1.b=t3.b
+order by t1.b desc, t2.a desc limit 3;
+b a b a
+99 99 99 99
+99 98 99 99
+99 97 99 99
+explain select t3.b, t2.a , t1.b , t1.a from t1,t2,t3 where t1.b=t3.b
+order by t3.b desc, t2.a desc limit 3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 100
+1 SIMPLE t2 ALL NULL NULL NULL NULL 102 Using join buffer (flat, BNL join)
+1 SIMPLE <order-nest> ALL NULL NULL NULL NULL 10200 Using filesort
+1 SIMPLE t3 ALL NULL NULL NULL NULL 1000 Using where
+select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
+explain format=json select t3.b, t2.a , t1.b , t1.a from t1,t2,t3 where t1.b=t3.b
+order by t3.b desc, t2.a desc limit 3;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 100,
+ "filtered": 100
+ },
+ "block-nl-join": {
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 102,
+ "filtered": 100
+ },
+ "buffer_type": "flat",
+ "buffer_size": "1Kb",
+ "join_type": "BNL"
+ },
+ "read_sorted_file": {
+ "filesort": {
+ "sort_key": "`order-nest`.b desc, `order-nest`.a desc",
+ "table": {
+ "table_name": "<order-nest>",
+ "access_type": "ALL",
+ "rows": 10200,
+ "filtered": 100
+ }
+ }
+ },
+ "table": {
+ "table_name": "t3",
+ "access_type": "ALL",
+ "rows": 1000,
+ "filtered": 100,
+ "attached_condition": "t3.b = `order-nest`.b"
+ }
+ }
+}
+select t3.b, t2.a , t1.b , t1.a from t1,t2,t3 where t1.b=t3.b
+order by t3.b desc, t2.a desc limit 3;
+b a b a
+99 99 99 99
+99 98 99 99
+99 97 99 99
+#
+# Equality propagation also for arguments of expressions,
+# the plan should use a sort nest on {t1,t2}
+#
+explain select t3.b, t2.a , t1.b , t1.a from t1,t2,t3 where t1.b=t3.b
+order by t3.b+1 desc, t2.a desc limit 3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 100
+1 SIMPLE t2 ALL NULL NULL NULL NULL 102 Using join buffer (flat, BNL join)
+1 SIMPLE <order-nest> ALL NULL NULL NULL NULL 10200 Using filesort
+1 SIMPLE t3 ALL NULL NULL NULL NULL 1000 Using where
+explain format=json select t3.b, t2.a , t1.b , t1.a from t1,t2,t3 where t1.b=t3.b
+order by t3.b+1 desc, t2.a desc limit 3;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 100,
+ "filtered": 100
+ },
+ "block-nl-join": {
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 102,
+ "filtered": 100
+ },
+ "buffer_type": "flat",
+ "buffer_size": "1Kb",
+ "join_type": "BNL"
+ },
+ "read_sorted_file": {
+ "filesort": {
+ "sort_key": "tmp_field desc, `order-nest`.a desc",
+ "table": {
+ "table_name": "<order-nest>",
+ "access_type": "ALL",
+ "rows": 10200,
+ "filtered": 100
+ }
+ }
+ },
+ "table": {
+ "table_name": "t3",
+ "access_type": "ALL",
+ "rows": 1000,
+ "filtered": 100,
+ "attached_condition": "t3.b = `order-nest`.b"
+ }
+ }
+}
+select t3.b, t2.a , t1.b , t1.a from t1,t2,t3 where t1.b=t3.b
+order by t3.b+1 desc, t2.a desc limit 3;
+b a b a
+99 99 99 99
+99 98 99 99
+99 97 99 99
+#
+# Rows for the sort-nest should be the cardinality of the join of inner tables
+# of the sort-nest
+#
+# Rows for sort nest would be 9894 here
+alter table t1 add key(a);
+explain extended select t3.b, t2.a , t1.b , t1.a from t1,t2,t3 where t1.a > 5 and t1.b=t3.b
+order by t1.b desc, t2.a desc limit 3;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 ALL a NULL NULL NULL 100 97.00 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 102 100.00 Using join buffer (flat, BNL join)
+1 SIMPLE <order-nest> ALL NULL NULL NULL NULL 9894 100.00 Using filesort
+1 SIMPLE t3 ALL NULL NULL NULL NULL 1000 100.00 Using where
+Warnings:
+Note 1003 select `test`.`t3`.`b` AS `b`,`order-nest`.`a` AS `a`,`order-nest`.`b` AS `b`,`order-nest`.`a` AS `a` from `test`.`t1` join `test`.`t2` join `test`.`t3` where `test`.`t3`.`b` = `order-nest`.`b` order by `order-nest`.`b` desc,`order-nest`.`a` desc limit 3
+alter table t1 drop key a;
+drop table t1,t2,t3,ten,one_k;
+drop function f1;
diff --git a/mysql-test/main/sort_nest.test b/mysql-test/main/sort_nest.test
new file mode 100644
index 00000000000..729a6cd9eaa
--- /dev/null
+++ b/mysql-test/main/sort_nest.test
@@ -0,0 +1,145 @@
+create table ten(a int);
+insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table one_k(a int);
+insert into one_k select A.a + B.a* 10 from ten A, ten B;
+create table t1 (a int, b int);
+insert into t1 select a,a from one_k;
+
+create table t2 (a int, b int);
+insert into t2 select a,a from one_k;
+explain
+select t1.b from t1,t2 where t1.a=t2.a order by t2.b limit 2;
+select t1.b from t1,t2 where t1.a=t2.a order by t2.b limit 2;
+
+analyze
+select t1.a,t2.a from t1,t2 where t1.a=t2.a order by t2.b limit 10;
+select t1.a,t2.a from t1,t2 where t1.a=t2.a order by t2.b limit 10;
+
+alter table t1 add key (a);
+
+--echo ref should be func
+explain
+select t1.b,t2.b from t1,t2 where t1.a=t2.a+1 order by t2.b limit 2;
+select t1.b,t2.b from t1,t2 where t1.a=t2.a+1 order by t2.b limit 2;
+
+--echo ref should be order-nest.a
+explain
+select t1.b,t2.b from t1,t2 where t1.a=t2.a order by t2.b limit 2;
+select t1.b,t2.b from t1,t2 where t1.a=t2.a order by t2.b limit 2;
+
+drop table t1,t2,ten,one_k;
+
+create table ten(a int);
+insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+
+create table one_k(a int);
+insert into one_k select A.a + B.a* 10 + C.a * 100 from ten A, ten B, ten C;
+
+create table t1(a int, b int);
+insert into t1 select A.a + B.a* 10, A.a + B.a* 10 from ten A, ten B;
+create table t2(a int, b int);
+insert into t2(a,b) values (1,1), (2,2);
+insert into t2 select A.a + B.a* 10, A.a+B.a*10 from ten A, ten B;
+create table t3(a int, b int);
+insert into t3 select A.a + B.a* 10 + C.a * 100, A.a + B.a* 10 + C.a * 100 from ten A, ten B, ten C;
+
+delimiter |;
+create function f1(a int) returns int
+begin
+ declare b int default 0;
+ return a+b;
+end|
+delimiter ;|
+
+--echo Covering 3 table joins
+
+--echo # {t1,t2} part of the nest
+--echo # t1.a > 95 would be attached to table t1
+--echo # t1.b=t2.a would be attached to table t2;
+
+let $query=
+select * from t1,t2,t3 where t1.a > 95 and t1.a=t2.a and t1.b = t3.a order by t2.b;
+eval explain $query;
+eval explain format=json $query;
+eval $query;
+
+--echo # {t1,t2} part of the sort nest
+--echo # (t2.a < 2 or t1.b > 98) would be attached to table t2
+
+let $query=
+select * from t1,t2,t3 where (t3.a<2 and t2.a <2) or (t1.b > 98 and t3.b > 98)
+order by t1.a, t2.b limit 5;
+eval explain $query;
+eval explain format=json $query;
+eval $query;
+
+--echo # {t1,t2} part of the nest
+--echo # t2.a < 2 or f1(t1.b) attached to table t2
+--echo # t1.b=t2.a would be attached to table t2;
+
+let $query=
+select * from t1,t2,t3 where (t3.a<2 and t2.a <2) or (f1(t1.b) > 98 and t3.b > 98)
+order by t1.a,t2.b limit 5;
+eval explain $query;
+eval explain format=json $query;
+eval $query;
+
+--echo #
+--echo # Removing constant from the order by clause
+--echo #
+
+let $query=
+select * from t1,t2 where t1.a > 95 and t1.a=t2.a order by t2.a limit 4;
+eval explain $query;
+eval explain format=json $query;
+eval $query;
+
+let $query=
+select * from t1,t2 where t1.a > 95 and t1.a=t2.a order by 1+2,t2.a limit 4;
+eval explain $query;
+eval explain format=json $query;
+eval $query;
+
+
+--echo #
+--echo # Equality propagation, both the queries should use a sort nest on {t1,t2}
+--echo #
+
+let $query=select t3.b, t2.a , t1.b , t1.a from t1,t2,t3 where t1.b=t3.b
+order by t1.b desc, t2.a desc limit 3;
+eval explain $query;
+eval explain format=json $query;
+eval $query;
+
+let $query=select t3.b, t2.a , t1.b , t1.a from t1,t2,t3 where t1.b=t3.b
+order by t3.b desc, t2.a desc limit 3;
+
+eval explain $query;
+select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+eval explain format=json $query;
+eval $query;
+
+--echo #
+--echo # Equality propagation also for arguments of expressions,
+--echo # the plan should use a sort nest on {t1,t2}
+--echo #
+
+let $query=select t3.b, t2.a , t1.b , t1.a from t1,t2,t3 where t1.b=t3.b
+order by t3.b+1 desc, t2.a desc limit 3;
+eval explain $query;
+eval explain format=json $query;
+eval $query;
+
+--echo #
+--echo # Rows for the sort-nest should be the cardinality of the join of inner tables
+--echo # of the sort-nest
+--echo #
+
+--echo # Rows for sort nest would be 9894 here
+alter table t1 add key(a);
+let $query=select t3.b, t2.a , t1.b , t1.a from t1,t2,t3 where t1.a > 5 and t1.b=t3.b
+order by t1.b desc, t2.a desc limit 3;
+eval explain extended $query;
+alter table t1 drop key a;
+drop table t1,t2,t3,ten,one_k;
+drop function f1;
diff --git a/sql/item.cc b/sql/item.cc
index 84fd4dc6fb7..cf71a31be10 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -6158,6 +6158,28 @@ Item *Item_field::replace_equal_field(THD *thd, uchar *arg)
}
+Item *Item_field::replace_with_nest_items(THD *thd, uchar *arg)
+{
+ REPLACE_NEST_FIELD_ARG* param= (REPLACE_NEST_FIELD_ARG*)arg;
+ JOIN *join= param->join;
+ SORT_NEST_INFO *sort_nest_info= join->sort_nest_info;
+ if (!(used_tables() & sort_nest_info->nest_tables_map))
+ return this;
+
+ List_iterator_fast<Item> li(sort_nest_info->nest_base_table_cols);
+ uint index= 0;
+ Item *item;
+ while((item= li++))
+ {
+ Item *field_item= item->real_item();
+ if (field->eq(((Item_field*)field_item)->field))
+ return sort_nest_info->nest_temp_table_cols.elem(index);
+ index++;
+ }
+ return this;
+}
+
+
void Item::init_make_send_field(Send_field *tmp_field,
const Type_handler *h)
{
@@ -9061,11 +9083,17 @@ Item *Item_direct_view_ref::replace_equal_field(THD *thd, uchar *arg)
bool Item_field::excl_dep_on_table(table_map tab_map)
{
- return used_tables() == tab_map ||
+ return !(used_tables() & ~tab_map) ||
(item_equal && (item_equal->used_tables() & tab_map));
}
+bool Item_field::excl_dep_on_nest(table_map tab_map)
+{
+ return !(used_tables() & ~tab_map);
+}
+
+
bool
Item_field::excl_dep_on_grouping_fields(st_select_lex *sel)
{
@@ -9089,6 +9117,17 @@ bool Item_direct_view_ref::excl_dep_on_table(table_map tab_map)
}
+bool Item_direct_view_ref::excl_dep_on_nest(table_map tab_map)
+{
+ table_map used= used_tables();
+ if (used & OUTER_REF_TABLE_BIT)
+ return false;
+ if (!(used & ~tab_map))
+ return true;
+ return (*ref)->excl_dep_on_nest(tab_map);
+}
+
+
bool Item_direct_view_ref::excl_dep_on_grouping_fields(st_select_lex *sel)
{
if (item_equal)
diff --git a/sql/item.h b/sql/item.h
index 3b889b08e7c..8c4d07ca5b8 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -445,6 +445,11 @@ typedef struct replace_equal_field_arg
struct st_join_table *context_tab;
} REPLACE_EQUAL_FIELD_ARG;
+typedef struct replace_nest_field_arg
+{
+ JOIN *join;
+} REPLACE_NEST_FIELD_ARG;
+
class Settable_routine_parameter
{
public:
@@ -1887,6 +1892,12 @@ class Item: public Value_source,
Not to be used for AND/OR formulas.
*/
virtual bool excl_dep_on_table(table_map tab_map) { return false; }
+
+ /*
+ TRUE if the expression depends only on the table indicated by tab_map
+ Not to be used for AND/OR formulas.
+ */
+ virtual bool excl_dep_on_nest(table_map tab_map) { return false; }
/*
TRUE if the expression depends only on grouping fields of sel
or can be converted to such an expression using equalities.
@@ -2109,6 +2120,8 @@ class Item: public Value_source,
{ return this; }
virtual Item *multiple_equality_transformer(THD *thd, uchar *arg)
{ return this; }
+ virtual Item *replace_with_nest_items(THD *thd, uchar *arg)
+ { return this; }
virtual bool expr_cache_is_needed(THD *) { return FALSE; }
virtual Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs);
bool needs_charset_converter(uint32 length, CHARSET_INFO *tocs) const
@@ -2316,6 +2329,10 @@ class Item: public Value_source,
{
return excl_dep_on_table(*((table_map *)arg));
}
+ bool pushable_cond_checker_for_nest(uchar *arg)
+ {
+ return excl_dep_on_nest(*((table_map *)arg));
+ }
bool pushable_cond_checker_for_subquery(uchar *arg)
{
return excl_dep_on_in_subq_left_part((Item_in_subselect *)arg);
@@ -2511,6 +2528,17 @@ class Item_args
}
return true;
}
+ bool excl_dep_on_nest(table_map tab_map)
+ {
+ for (uint i= 0; i < arg_count; i++)
+ {
+ if (args[i]->const_item())
+ continue;
+ if (!args[i]->excl_dep_on_nest(tab_map))
+ return false;
+ }
+ return true;
+ }
bool excl_dep_on_grouping_fields(st_select_lex *sel);
bool eq(const Item_args *other, bool binary_cmp) const
{
@@ -3451,6 +3479,7 @@ class Item_field :public Item_ident,
Item *in_subq_field_transformer_for_having(THD *thd, uchar *arg);
virtual void print(String *str, enum_query_type query_type);
bool excl_dep_on_table(table_map tab_map);
+ bool excl_dep_on_nest(table_map tab_map);
bool excl_dep_on_grouping_fields(st_select_lex *sel);
bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred);
bool cleanup_excluding_fields_processor(void *arg)
@@ -3471,6 +3500,7 @@ class Item_field :public Item_ident,
return field->get_geometry_type();
}
bool check_index_dependence(void *arg);
+ Item *replace_with_nest_items(THD *thd, uchar *arg);
friend class Item_default_value;
friend class Item_insert_value;
friend class st_select_lex_unit;
@@ -5306,6 +5336,15 @@ class Item_ref :public Item_ident,
return false;
return (used == tab_map) || (*ref)->excl_dep_on_table(tab_map);
}
+
+ bool excl_dep_on_nest(table_map tab_map)
+ {
+ table_map used= used_tables();
+ if (used & OUTER_REF_TABLE_BIT)
+ return false;
+ return (!(used & ~tab_map) || (*ref)->excl_dep_on_nest(tab_map));
+ }
+
bool excl_dep_on_grouping_fields(st_select_lex *sel)
{ return (*ref)->excl_dep_on_grouping_fields(sel); }
bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
@@ -5631,6 +5670,7 @@ class Item_direct_view_ref :public Item_direct_ref
return 0;
}
bool excl_dep_on_table(table_map tab_map);
+ bool excl_dep_on_nest(table_map tab_map);
bool excl_dep_on_grouping_fields(st_select_lex *sel);
bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred);
Item *derived_field_transformer_for_having(THD *thd, uchar *arg);
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 02fc7719fbc..48434f66f64 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -5225,6 +5225,22 @@ bool Item_cond::excl_dep_on_table(table_map tab_map)
return true;
}
+bool Item_cond::excl_dep_on_nest(table_map tab_map)
+{
+ if (used_tables() & OUTER_REF_TABLE_BIT)
+ return false;
+ if (!(used_tables() & ~tab_map))
+ return true;
+ List_iterator_fast<Item> li(list);
+ Item *item;
+ while ((item= li++))
+ {
+ if (!item->excl_dep_on_nest(tab_map))
+ return false;
+ }
+ return true;
+}
+
bool Item_cond::excl_dep_on_grouping_fields(st_select_lex *sel)
{
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 2af7ebdf231..b992ee1b676 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -3011,6 +3011,7 @@ class Item_cond :public Item_bool_func
bool eval_not_null_tables(void *opt_arg);
Item *build_clone(THD *thd);
bool excl_dep_on_table(table_map tab_map);
+ bool excl_dep_on_nest(table_map tab_map);
bool excl_dep_on_grouping_fields(st_select_lex *sel);
};
diff --git a/sql/item_func.h b/sql/item_func.h
index 610adb4bb46..350fb937957 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -340,6 +340,14 @@ class Item_func :public Item_func_or_sum,
Item_args::excl_dep_on_table(tab_map);
}
+ bool excl_dep_on_nest(table_map tab_map)
+ {
+ if (used_tables() & OUTER_REF_TABLE_BIT)
+ return false;
+ return !(used_tables() & ~tab_map) ||
+ Item_args::excl_dep_on_nest(tab_map);
+ }
+
bool excl_dep_on_grouping_fields(st_select_lex *sel)
{
if (has_rand_bit() || with_subquery())
diff --git a/sql/item_row.h b/sql/item_row.h
index ea5a0f21d8b..4698dcd8150 100644
--- a/sql/item_row.h
+++ b/sql/item_row.h
@@ -140,6 +140,11 @@ class Item_row: public Item_fixed_hybrid,
return Item_args::excl_dep_on_table(tab_map);
}
+ bool excl_dep_on_nest(table_map tab_map)
+ {
+ return Item_args::excl_dep_on_nest(tab_map);
+ }
+
bool excl_dep_on_grouping_fields(st_select_lex *sel)
{
return Item_args::excl_dep_on_grouping_fields(sel);
diff --git a/sql/opt_split.cc b/sql/opt_split.cc
index cfac0c93544..0dc8006029b 100644
--- a/sql/opt_split.cc
+++ b/sql/opt_split.cc
@@ -651,7 +651,6 @@ add_ext_keyuses_for_splitting_field(Dynamic_array<KEYUSE_EXT> *ext_keyuses,
@brief
Cost of the post join operation used in specification of splittable table
*/
-
static
double spl_postjoin_oper_cost(THD *thd, double join_record_count, uint rec_len)
{
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 02d221d13b0..ef1f6f2c6ff 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -4777,6 +4777,11 @@ int setup_semijoin_loosescan(JOIN *join)
for (i= join->const_tables ; i < join->top_join_tab_count; )
{
JOIN_TAB *tab=join->join_tab + i;
+ if (tab->is_sort_nest)
+ {
+ i++;
+ continue;
+ }
switch (pos->sj_strategy) {
case SJ_OPT_MATERIALIZE:
case SJ_OPT_MATERIALIZE_SCAN:
@@ -5517,6 +5522,31 @@ enum_nested_loop_state join_tab_execution_startup(JOIN_TAB *tab)
sjm->materialized= TRUE;
}
}
+ /*
+ This should be the place to add the sub_select call for the
+ prefix of the join order
+ */
+
+ else if (tab->is_sort_nest)
+ {
+ enum_nested_loop_state rc;
+ JOIN *join= tab->join;
+ SORT_NEST_INFO *nest_info= join->sort_nest_info;
+
+ if (!nest_info->materialized)
+ {
+ JOIN_TAB *join_tab= join->join_tab + join->const_tables;
+ JOIN_TAB *save_return_tab= join->return_tab;
+ if ((rc= sub_select(join, join_tab, FALSE)) < 0 ||
+ (rc= sub_select(join, join_tab, TRUE)) < 0)
+ {
+ join->return_tab= save_return_tab;
+ DBUG_RETURN(rc);
+ }
+ join->return_tab= save_return_tab;
+ nest_info->materialized= TRUE;
+ }
+ }
DBUG_RETURN(NESTED_LOOP_OK);
}
diff --git a/sql/opt_subselect.h b/sql/opt_subselect.h
index 65131f6bc89..dad63c5d1db 100644
--- a/sql/opt_subselect.h
+++ b/sql/opt_subselect.h
@@ -298,6 +298,7 @@ class Loose_scan_opt
pos->loosescan_picker.loosescan_key= best_loose_scan_key;
pos->loosescan_picker.loosescan_parts= best_max_loose_keypart + 1;
pos->use_join_buffer= FALSE;
+ pos->sort_nest_operation_here= FALSE;
pos->table= tab;
pos->range_rowid_filter_info= tab->range_rowid_filter_info;
// todo need ref_depend_map ?
diff --git a/sql/opt_trace.cc b/sql/opt_trace.cc
index befc7934a3a..ca75b697ec3 100644
--- a/sql/opt_trace.cc
+++ b/sql/opt_trace.cc
@@ -606,6 +606,13 @@ void Json_writer::add_table_name(const JOIN_TAB *tab)
ctab->emb_sj_nest->sj_subq_pred->get_identifier());
add_str(table_name_buffer, len);
}
+ else if (tab->is_sort_nest)
+ {
+ size_t len= my_snprintf(table_name_buffer,
+ sizeof(table_name_buffer)-1,
+ "<order-nest>");
+ add_str(table_name_buffer, len);
+ }
else
{
TABLE_LIST *real_table= tab->table->pos_in_table_list;
@@ -630,6 +637,19 @@ void add_table_scan_values_to_trace(THD *thd, JOIN_TAB *tab)
table_rec.add("rows", tab->found_records)
.add("cost", tab->read_time);
}
+
+void add_sort_nest_tables_to_trace(JOIN *join)
+{
+ JOIN_TAB *end_tab, *tab;
+ THD *thd= join->thd;
+ SORT_NEST_INFO *sort_nest_info= join->sort_nest_info;
+ end_tab= sort_nest_info->nest_tab;
+ Json_writer_object trace_wrapper(thd);
+ Json_writer_array sort_nest(thd, "sort_nest");
+ for (tab= join->join_tab + join->const_tables; tab < end_tab; tab++)
+ sort_nest.add_table_name(tab);
+}
+
/*
Introduce enum_query_type flags parameter, maybe also allow
EXPLAIN also use this function.
diff --git a/sql/opt_trace.h b/sql/opt_trace.h
index 52318bc6b7f..b2dd3dff924 100644
--- a/sql/opt_trace.h
+++ b/sql/opt_trace.h
@@ -105,6 +105,7 @@ void opt_trace_print_expanded_query(THD *thd, SELECT_LEX *select_lex,
Json_writer_object *trace_object);
void add_table_scan_values_to_trace(THD *thd, JOIN_TAB *tab);
+void add_sort_nest_tables_to_trace(JOIN *join);
/*
Security related (need to add a proper comment here)
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 63f964e96ce..73f97ba727b 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -6037,6 +6037,20 @@ class SJ_MATERIALIZATION_INFO : public Sql_alloc
Copy_field *copy_field; /* Needed for SJ_Materialization scan */
};
+class SORT_NEST_INFO : public Sql_alloc
+{
+public:
+ TMP_TABLE_PARAM tmp_table_param;
+ List<Item> nest_base_table_cols;
+ List<Item> nest_temp_table_cols;
+ TABLE *table;
+ st_join_table *nest_tab;
+ uint n_tables;
+ bool materialized; /* TRUE <=> materialization already performed */
+ table_map nest_tables_map;
+ Item *nest_cond;
+};
+
/* Structs used when sorting */
struct SORT_FIELD_ATTR
diff --git a/sql/sql_const.h b/sql/sql_const.h
index 7aa4249f5ad..96779e4dbeb 100644
--- a/sql/sql_const.h
+++ b/sql/sql_const.h
@@ -296,6 +296,14 @@
*/
#define MAX_TIME_ZONE_NAME_LENGTH (NAME_LEN + 1)
+
+/**
+ Average record length is the number of bytes for the record, it is just a rough guess, needs
+ this to calculate cost of filling and reading the temp table
+
+*/
+#define AVG_REC_LEN 50
+
#if defined(__WIN__)
#define INTERRUPT_PRIOR -2
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index e97abf3d981..2346a600c6f 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -120,8 +120,12 @@ static bool best_extension_by_limited_search(JOIN *join,
uint idx, double record_count,
double read_time, uint depth,
uint prune_level,
- uint use_cond_selectivity);
+ uint use_cond_selectivity,
+ table_map previous_tables,
+ bool nest_created,
+ double *cardinality);
void trace_plan_prefix(JOIN *join, uint idx, table_map remaining_tables);
+void trace_order_by_nest(JOIN *join, uint idx, table_map remaining_tables);
static uint determine_search_depth(JOIN* join);
C_MODE_START
static int join_tab_cmp(const void *dummy, const void* ptr1, const void* ptr2);
@@ -189,6 +193,8 @@ static enum_nested_loop_state
end_update(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
static enum_nested_loop_state
end_unique_update(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
+enum_nested_loop_state
+end_nest_materialization(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
static int join_read_const_table(THD *thd, JOIN_TAB *tab, POSITION *pos);
static int join_read_system(JOIN_TAB *tab);
@@ -304,6 +310,11 @@ void set_postjoin_aggr_write_func(JOIN_TAB *tab);
static Item **get_sargable_cond(JOIN *join, TABLE *table);
+void substitute_base_to_nest_items(JOIN *join);
+void substitute_base_to_nest_items2(JOIN *join, Item **cond);
+void check_cond_extraction_for_nest(THD *thd, Item *cond,
+ Pushdown_checker checker, uchar* arg);
+
#ifndef DBUG_OFF
/*
@@ -2463,6 +2474,10 @@ int JOIN::optimize_stage2()
if (setup_semijoin_loosescan(this))
DBUG_RETURN(1);
+ if (setup_sort_nest(this))
+ DBUG_RETURN(1);
+ substitute_base_to_nest_items(this);
+
if (make_join_select(this, select, conds))
{
zero_result_cause=
@@ -2474,22 +2489,9 @@ int JOIN::optimize_stage2()
error= -1; /* if goto err */
/* Optimize distinct away if possible */
- {
- ORDER *org_order= order;
- order=remove_const(this, order,conds,1, &simple_order);
- if (unlikely(thd->is_error()))
- {
- error= 1;
- DBUG_RETURN(1);
- }
+ if (remove_const_from_order_by())
+ DBUG_RETURN(TRUE);
- /*
- If we are using ORDER BY NULL or ORDER BY const_expression,
- return result in any order (even if we are using a GROUP BY)
- */
- if (!order && org_order)
- skip_sort_order= 1;
- }
/*
Check if we can optimize away GROUP BY/DISTINCT.
We can do that if there are no aggregate functions, the
@@ -2710,7 +2712,9 @@ int JOIN::optimize_stage2()
Yet the current implementation of FORCE INDEX hints does not
allow us to do it in a clean manner.
*/
- no_jbuf_after= 1 ? table_count : make_join_orderinfo(this);
+ no_jbuf_after= 1 ? (sort_nest_info ? const_tables + sort_nest_info->n_tables
+ : table_count)
+ : make_join_orderinfo(this);
// Don't use join buffering when we use MATCH
select_opts_for_readinfo=
@@ -3583,7 +3587,9 @@ bool JOIN::make_aggr_tables_info()
curr_tab->type != JT_EQ_REF) // Don't sort 1 row
{
// Sort either first non-const table or the last tmp table
- JOIN_TAB *sort_tab= curr_tab;
+ JOIN_TAB *sort_tab= sort_nest_info ?
+ sort_nest_info->nest_tab :
+ curr_tab;
if (add_sorting_to_table(sort_tab, order_arg))
DBUG_RETURN(true);
@@ -4421,7 +4427,7 @@ JOIN::destroy()
WITH_CONST_TABLES);
tab; tab= next_linear_tab(this, tab, WITH_BUSH_ROOTS))
{
- if (tab->aggr)
+ if (tab->aggr || tab->is_sort_nest)
{
free_tmp_table(thd, tab->table);
delete tab->tmp_table_param;
@@ -4755,6 +4761,156 @@ static Item **get_sargable_cond(JOIN *join, TABLE *table)
return retval;
}
+void substitute_base_to_nest_items(JOIN *join)
+{
+ if (!join->sort_nest_needed())
+ return;
+ SORT_NEST_INFO *sort_nest_info= join->sort_nest_info;
+ REPLACE_NEST_FIELD_ARG arg= {join};
+
+ List_iterator<Item> it(join->fields_list);
+ Item *item, *new_item;
+ while ((item= it++))
+ {
+ if ((new_item= item->transform(join->thd,
+ &Item::replace_with_nest_items,
+ (uchar *) &arg)) != item)
+ it.replace(new_item);
+ }
+ JOIN_TAB *end_tab= sort_nest_info->nest_tab;
+ uint i, j;
+ for (i= join->const_tables + sort_nest_info->n_tables, j=0;
+ i < join->top_join_tab_count; i++, j++)
+ {
+ JOIN_TAB *tab= end_tab + j;
+ if (tab->type == JT_REF || tab->type == JT_EQ_REF ||
+ tab->type == JT_REF_OR_NULL)
+ {
+ for (uint keypart= 0; keypart < tab->ref.key_parts; keypart++)
+ {
+ item= tab->ref.items[keypart]->transform(join->thd,
+ &Item::replace_with_nest_items,
+ (uchar *) &arg);
+ if (item != tab->ref.items[keypart])
+ {
+ tab->ref.items[keypart]= item;
+ Item *real_item= item->real_item();
+ store_key *key_copy= tab->ref.key_copy[keypart];
+ if (key_copy->type() == store_key::FIELD_STORE_KEY)
+ {
+ store_key_field *field_copy= ((store_key_field *)key_copy);
+ DBUG_ASSERT(real_item->type() == Item::FIELD_ITEM);
+ field_copy->change_source_field((Item_field *) real_item);
+ }
+ }
+ }
+ }
+ }
+ substitute_base_to_nest_items2(join, &join->conds);
+}
+
+void substitute_base_to_nest_items2(JOIN *join, Item **cond)
+{
+ SORT_NEST_INFO *sort_nest_info= join->sort_nest_info;
+ Item *orig_cond= *cond;
+ if (!sort_nest_info)
+ return;
+ THD *thd= join->thd;
+ Item *extracted_cond;
+ SELECT_LEX* sl= join->select_lex;
+
+ /*
+ check_cond_extraction_for_nest would set NO_EXTRACTION_FL for
+ all the items that cannot be added to the inner tables of the nest
+ */
+ check_cond_extraction_for_nest(thd, orig_cond,
+ &Item::pushable_cond_checker_for_nest,
+ (uchar *)(&sort_nest_info->nest_tables_map));
+ /*
+ build_cond_for_grouping_fields would create the entire
+ condition that would be added to the tables inside the nest.
+ This may clone some items too.
+ */
+ extracted_cond= sl->build_cond_for_grouping_fields(thd, orig_cond, TRUE);
+
+ if (extracted_cond)
+ {
+ if (extracted_cond->fix_fields_if_needed(thd, 0))
+ return;
+ /*
+ Remove from the WHERE clause all the conditions that were added
+ to the inner tables of the sort nest
+ */
+ orig_cond= remove_pushed_top_conjuncts(thd, orig_cond);
+ sort_nest_info->nest_cond= extracted_cond;
+ }
+
+ REPLACE_NEST_FIELD_ARG arg= {join};
+ if (orig_cond)
+ {
+ orig_cond= orig_cond->transform(join->thd, &Item::replace_with_nest_items,
+ (uchar *) &arg);
+ orig_cond->update_used_tables();
+ }
+ *cond= orig_cond;
+}
+
+/*
+ Add a transformer to this call so that we dont have both
+ check_cond_extraction_for_nest and check_cond_extraction_for_grouping_fields
+*/
+
+void
+check_cond_extraction_for_nest(THD *thd, Item *cond,
+ Pushdown_checker checker, uchar* arg)
+{
+ if (cond->get_extraction_flag() == NO_EXTRACTION_FL)
+ return;
+ cond->clear_extraction_flag();
+ if (cond->type() == Item::COND_ITEM)
+ {
+ Item_cond_and *and_cond=
+ (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC) ?
+ ((Item_cond_and*) cond) : 0;
+
+ List<Item> *arg_list= ((Item_cond*) cond)->argument_list();
+ List_iterator<Item> li(*arg_list);
+ uint count= 0; // to count items not containing NO_EXTRACTION_FL
+ uint count_full= 0; // to count items with FULL_EXTRACTION_FL
+ Item *item;
+ while ((item=li++))
+ {
+ check_cond_extraction_for_nest(thd, item, checker, arg);
+ if (item->get_extraction_flag() != NO_EXTRACTION_FL)
+ {
+ count++;
+ if (item->get_extraction_flag() == FULL_EXTRACTION_FL)
+ count_full++;
+ }
+ else if (!and_cond)
+ break;
+ }
+ if ((and_cond && count == 0) || item)
+ cond->set_extraction_flag(NO_EXTRACTION_FL);
+ if (count_full == arg_list->elements)
+ {
+ cond->set_extraction_flag(FULL_EXTRACTION_FL);
+ }
+ if (cond->get_extraction_flag() != 0)
+ {
+ li.rewind();
+ while ((item=li++))
+ item->clear_extraction_flag();
+ }
+ }
+ else
+ {
+ int fl= (cond->*checker)(arg) ?
+ FULL_EXTRACTION_FL : NO_EXTRACTION_FL;
+ cond->set_extraction_flag(fl);
+ }
+}
+
/**
Calculate the best possible join and initialize the join structure.
@@ -5210,6 +5366,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
join->sort_by_table= get_sort_by_table(join->order, join->group_list,
join->select_lex->leaf_tables,
join->const_table_map);
+
/*
Update info on indexes that can be used for search lookups as
reading const tables may has added new sargable predicates.
@@ -5444,12 +5601,22 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
if (pull_out_semijoin_tables(join))
DBUG_RETURN(TRUE);
- join->join_tab=stat;
join->top_join_tab_count= table_count;
- join->map2table=stat_ref;
- join->table= table_vector;
join->const_tables=const_count;
join->found_const_table_map=found_const_table_map;
+ /*
+ Here a call is made to remove the constant from the order by clause,
+ this call would only remove the basic constants. This is done for
+ the ORDER BY LIMIT optimization.
+ */
+ if (join->remove_const_from_order_by())
+ DBUG_RETURN(TRUE);
+
+ (void)propagate_equal_field_for_orderby(join, join->order);
+
+ join->join_tab=stat;
+ join->map2table=stat_ref;
+ join->table= table_vector;
if (join->const_tables != join->table_count)
optimize_keyuse(join, keyuse_array);
@@ -7075,6 +7242,7 @@ void set_position(JOIN *join,uint idx,JOIN_TAB *table,KEYUSE *key)
join->positions[idx].sj_strategy= SJ_OPT_NONE;
join->positions[idx].use_join_buffer= FALSE;
join->positions[idx].range_rowid_filter_info= 0;
+ join->positions[idx].sort_nest_operation_here= FALSE;
/* Move the const table as down as possible in best_ref */
JOIN_TAB **pos=join->best_ref+idx+1;
@@ -7922,6 +8090,7 @@ best_access_path(JOIN *join,
pos->use_join_buffer= best_uses_jbuf;
pos->spl_plan= spl_plan;
pos->range_rowid_filter_info= best_filter;
+ pos->sort_nest_operation_here= FALSE;
loose_scan_opt.save_to_position(s, loose_scan_pos);
@@ -8135,6 +8304,7 @@ choose_plan(JOIN *join, table_map join_tables)
use_cond_selectivity))
DBUG_RETURN(TRUE);
}
+ trace_plan.end();
/*
Store the cost of this query into a user variable
@@ -8440,6 +8610,7 @@ optimize_straight_join(JOIN *join, table_map join_tables)
pushdown_cond_selectivity= table_cond_selectivity(join, idx, s,
join_tables);
position->cond_selectivity= pushdown_cond_selectivity;
+ record_count= record_count*pushdown_cond_selectivity;
++idx;
}
@@ -8552,6 +8723,7 @@ greedy_search(JOIN *join,
JOIN_TAB *best_table; // the next plan node to be added to the curr QEP
// ==join->tables or # tables in the sj-mat nest we're optimizing
uint n_tables __attribute__((unused));
+ double cardinality= DBL_MAX;
DBUG_ENTER("greedy_search");
/* number of tables that remain to be optimized */
@@ -8565,9 +8737,11 @@ greedy_search(JOIN *join,
do {
/* Find the extension of the current QEP with the lowest cost */
join->best_read= DBL_MAX;
+ table_map previous_tables= 0;
if (best_extension_by_limited_search(join, remaining_tables, idx, record_count,
read_time, search_depth, prune_level,
- use_cond_selectivity))
+ use_cond_selectivity,
+ previous_tables, FALSE, &cardinality))
DBUG_RETURN(TRUE);
/*
'best_read < DBL_MAX' means that optimizer managed to find
@@ -9166,6 +9340,19 @@ void trace_plan_prefix(JOIN *join, uint idx, table_map remaining_tables)
}
}
+void trace_order_by_nest(JOIN *join, uint idx, table_map remaining_tables)
+{
+ THD *const thd= join->thd;
+ Json_writer_array plan_prefix(thd, "order_by_nest");
+ for (uint i= 0; i < idx; i++)
+ {
+ TABLE *tr= join->positions[i].table->table;
+ if (tr->map & remaining_tables)
+ plan_prefix.add_table_name(join->positions[i].table);
+ }
+
+}
+
/**
Find a good, possibly optimal, query execution plan (QEP) by a possibly
exhaustive search.
@@ -9293,7 +9480,10 @@ best_extension_by_limited_search(JOIN *join,
double read_time,
uint search_depth,
uint prune_level,
- uint use_cond_selectivity)
+ uint use_cond_selectivity,
+ table_map previous_tables,
+ bool nest_created,
+ double *cardinality)
{
DBUG_ENTER("best_extension_by_limited_search");
@@ -9319,7 +9509,16 @@ best_extension_by_limited_search(JOIN *join,
JOIN_TAB *s;
double best_record_count= DBL_MAX;
double best_read_time= DBL_MAX;
- bool disable_jbuf= join->thd->variables.join_cache_level == 0;
+ bool disable_jbuf= (join->thd->variables.join_cache_level == 0) || nest_created;
+ double fraction_output;
+
+ if (nest_created)
+ {
+ fraction_output= join->select_limit < (*cardinality) ?
+ (join->select_limit/(*cardinality)) : 1.0;
+ }
+ else
+ fraction_output= 1.0;
DBUG_EXECUTE("opt", print_plan(join, idx, record_count, read_time, read_time,
"part_plan"););
@@ -9348,6 +9547,8 @@ best_extension_by_limited_search(JOIN *join,
{
trace_plan_prefix(join, idx, remaining_tables);
trace_one_table.add_table_name(s);
+ if (nest_created)
+ trace_order_by_nest(join, idx, previous_tables);
}
/* Find the best access method from 's' to the current partial plan */
@@ -9361,10 +9562,12 @@ best_extension_by_limited_search(JOIN *join,
? position->range_rowid_filter_info->get_cmp_gain(current_record_count)
: 0;
current_read_time=COST_ADD(read_time,
- COST_ADD(position->read_time -
- filter_cmp_gain,
- current_record_count /
- (double) TIME_FOR_COMPARE));
+ COST_MULT(
+ COST_ADD(position->read_time -
+ filter_cmp_gain,
+ current_record_count /
+ (double) TIME_FOR_COMPARE), fraction_output));
+ current_record_count= COST_MULT(current_record_count, fraction_output);
advance_sj_state(join, remaining_tables, idx, ¤t_record_count,
¤t_read_time, &loose_scan_pos);
@@ -9427,9 +9630,12 @@ best_extension_by_limited_search(JOIN *join,
double partial_join_cardinality= current_record_count *
pushdown_cond_selectivity;
if ( (search_depth > 1) && (remaining_tables & ~real_table_bit) & allowed_tables )
- { /* Recursively expand the current partial plan */
+ {
+ /* Recursively expand the current partial plan */
swap_variables(JOIN_TAB*, join->best_ref[idx], *pos);
Json_writer_array trace_rest(thd, "rest_of_plan");
+ bool nest_allow= (join->cur_sj_inner_tables == 0 &&
+ join->cur_embedding_map == 0);
if (best_extension_by_limited_search(join,
remaining_tables & ~real_table_bit,
idx + 1,
@@ -9437,24 +9643,58 @@ best_extension_by_limited_search(JOIN *join,
current_read_time,
search_depth - 1,
prune_level,
- use_cond_selectivity))
+ use_cond_selectivity,
+ nest_created ? previous_tables :
+ previous_tables | real_table_bit,
+ nest_created, cardinality))
DBUG_RETURN(TRUE);
+
+ if (!nest_created && !join->emb_sjm_nest && nest_allow && !join->need_order_nest() &&
+ check_join_prefix_contains_ordering(join, s, previous_tables))
+ {
+ join->positions[idx].sort_nest_operation_here= TRUE;
+ double cost= postjoin_oper_cost(thd, partial_join_cardinality, AVG_REC_LEN, idx);
+ current_read_time= COST_ADD(current_read_time, cost);
+ if (best_extension_by_limited_search(join,
+ remaining_tables & ~real_table_bit,
+ idx + 1,
+ partial_join_cardinality,
+ current_read_time,
+ search_depth - 1,
+ 0,
+ use_cond_selectivity,
+ previous_tables | real_table_bit,
+ TRUE, cardinality))
+ DBUG_RETURN(TRUE);
+ join->positions[idx].sort_nest_operation_here= FALSE;
+ }
swap_variables(JOIN_TAB*, join->best_ref[idx], *pos);
}
else
- { /*
+ {
+ /*
'join' is either the best partial QEP with 'search_depth' relations,
or the best complete QEP so far, whichever is smaller.
*/
if (join->sort_by_table &&
join->sort_by_table !=
- join->positions[join->const_tables].table->table)
+ join->positions[join->const_tables].table->table
+ && !nest_created)
+ {
/*
We may have to make a temp table, note that this is only a
heuristic since we cannot know for sure at this point.
Hence it may be wrong.
*/
- current_read_time= COST_ADD(current_read_time, current_record_count);
+ double cost= postjoin_oper_cost(thd, partial_join_cardinality, AVG_REC_LEN, idx);
+ current_read_time= COST_ADD(current_read_time, cost);
+ }
+ if (!nest_created)
+ {
+ *cardinality= partial_join_cardinality;
+ trace_one_table.add("cardinality", partial_join_cardinality);
+ }
+ trace_one_table.add("cost_of_plan", current_read_time);
if (current_read_time < join->best_read)
{
memcpy((uchar*) join->best_positions, (uchar*) join->positions,
@@ -10145,7 +10385,7 @@ bool JOIN::get_best_combination()
JOIN_TAB_RANGE *root_range;
if (!(root_range= new (thd->mem_root) JOIN_TAB_RANGE))
DBUG_RETURN(TRUE);
- root_range->start= join_tab;
+ root_range->start= join_tab;
/* root_range->end will be set later */
join_tab_ranges.empty();
@@ -10220,7 +10460,7 @@ bool JOIN::get_best_combination()
j->type=JT_ALL;
if (best_positions[tablenr].use_join_buffer &&
tablenr != const_tables)
- full_join= 1;
+ full_join= 1;
}
/*if (best_positions[tablenr].sj_strategy == SJ_OPT_LOOSE_SCAN)
@@ -10253,12 +10493,45 @@ bool JOIN::get_best_combination()
sjm_nest_root= NULL;
sjm_nest_end= NULL;
}
+ if (cur_pos->sort_nest_operation_here)
+ {
+ /*
+ Ok, we've entered an ORDERING nest
+ 1. Put into main join order a JOIN_TAB that represents a scan
+ in the temptable.
+ */
+ JOIN_TAB *prev= j;
+ if ((prev - (join_tab + const_tables) > 0))
+ {
+ j= j+1;
+ bzero((void*)j, sizeof(JOIN_TAB));
+
+ j->join= this;
+ j->table= NULL; //temporary way to tell SJM tables from others.
+ j->ref.key = -1;
+ j->on_expr_ref= (Item**) &null_ptr;
+ j->is_sort_nest= TRUE;
+ uint tables= prev - (join_tab + const_tables)+1;
+ j->records_read= calculate_record_count_for_sort_nest(this, tables);
+ j->records= (ha_rows) j->records_read;
+ j->cond_selectivity= 1.0;
+ }
+ SORT_NEST_INFO *sort_nest_info;
+ if (!(sort_nest_info= new SORT_NEST_INFO()))
+ return TRUE;
+ sort_nest_info->n_tables= prev - (join_tab + const_tables)+1;
+ sort_nest_info->nest_tab= j;
+ this->sort_nest_info= sort_nest_info;
+ DBUG_ASSERT(sort_nest_info->n_tables != 0);
+ }
}
root_range->end= j;
used_tables= OUTER_REF_TABLE_BIT; // Outer row is already read
for (j=join_tab, tablenr=0 ; tablenr < table_count ; tablenr++,j++)
{
+ if (j->is_sort_nest)
+ j++;
if (j->bush_children)
j= j->bush_children->start;
@@ -10952,6 +11225,8 @@ make_outerjoin_info(JOIN *join)
tab;
tab= next_linear_tab(join, tab, WITH_BUSH_ROOTS))
{
+ if (tab->is_sort_nest)
+ continue;
TABLE *table= tab->table;
TABLE_LIST *tbl= table->pos_in_table_list;
TABLE_LIST *embedding= tbl->embedding;
@@ -11127,10 +11402,20 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
JOIN_TAB *tab;
table_map current_map;
i= join->const_tables;
+ Item *saved_cond= cond;
+ SORT_NEST_INFO *sort_nest_info= join->sort_nest_info;
+ if (join->sort_nest_needed())
+ cond= sort_nest_info->nest_cond;
+
for (tab= first_depth_first_tab(join); tab;
tab= next_depth_first_tab(join, tab))
{
bool is_hj;
+ if (tab->is_sort_nest)
+ {
+ cond= saved_cond;
+ continue;
+ }
/*
first_inner is the X in queries like:
@@ -12136,6 +12421,35 @@ end_sj_materialize(JOIN *join, JOIN_TAB *join_tab, bool end_of_records)
}
+enum_nested_loop_state
+end_nest_materialization(JOIN *join, JOIN_TAB *join_tab, bool end_of_records)
+{
+ int error;
+ THD *thd= join->thd;
+ SORT_NEST_INFO *nest_info= join->sort_nest_info;
+ DBUG_ENTER("end_sj_materialize");
+ if (!end_of_records)
+ {
+ TABLE *table= nest_info->table;
+ fill_record(thd, table, table->field,
+ nest_info->nest_base_table_cols, TRUE, FALSE);
+
+ if (unlikely(thd->is_error()))
+ DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */
+ if (unlikely((error= table->file->ha_write_tmp_row(table->record[0]))))
+ {
+ /* create_myisam_from_heap will generate error if needed */
+ if (table->file->is_fatal_error(error, HA_CHECK_DUP) &&
+ create_internal_tmp_table_from_heap(thd, table,
+ nest_info->tmp_table_param.start_recinfo,
+ &nest_info->tmp_table_param.recinfo,
+ error, 1, NULL))
+ DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */
+ }
+ }
+ DBUG_RETURN(NESTED_LOOP_OK);
+}
+
/*
Check whether a join buffer can be used to join the specified table
@@ -12367,7 +12681,7 @@ uint check_join_cache_usage(JOIN_TAB *tab,
Don't use join buffering if we're dictated not to by no_jbuf_after
(This is not meaningfully used currently)
*/
- if (table_index > no_jbuf_after)
+ if (table_index+1 > no_jbuf_after)
goto no_join_cache;
/*
@@ -12559,7 +12873,7 @@ void check_join_cache_usage_for_tables(JOIN *join, ulonglong options,
*/
prev_tab= tab - 1;
if (tab == join->join_tab + join->const_tables ||
- (tab->bush_root_tab && tab->bush_root_tab->bush_children->start == tab))
+ (tab->bush_root_tab && tab->bush_root_tab->bush_children->start == tab) || tab->is_sort_nest)
prev_tab= NULL;
switch (tab->type) {
@@ -12588,7 +12902,7 @@ void check_join_cache_usage_for_tables(JOIN *join, ulonglong options,
default:
tab->used_join_cache_level= 0;
}
- if (!tab->bush_children)
+ if (!tab->bush_children && !tab->is_sort_nest)
idx++;
}
}
@@ -12731,17 +13045,20 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after)
Later it should be improved.
*/
- if (tab->bush_root_tab && tab->bush_root_tab->bush_children->start == tab)
+ if ((tab->bush_root_tab && tab->bush_root_tab->bush_children->start == tab) ||
+ tab->is_sort_nest)
prev_tab= NULL;
- DBUG_ASSERT(tab->bush_children || tab->table == join->best_positions[i].table->table);
+ DBUG_ASSERT(tab->bush_children || tab->table == join->best_positions[i].table->table
+ || tab->is_sort_nest);
tab->partial_join_cardinality= join->best_positions[i].records_read *
(prev_tab? prev_tab->partial_join_cardinality : 1);
- if (!tab->bush_children)
+ if (!tab->bush_children && !tab->is_sort_nest)
i++;
}
check_join_cache_usage_for_tables(join, options, no_jbuf_after);
+ SORT_NEST_INFO *sort_nest_info= join->sort_nest_info;
JOIN_TAB *first_tab;
for (tab= first_tab= first_linear_tab(join, WITH_BUSH_ROOTS, WITHOUT_CONST_TABLES);
@@ -12768,7 +13085,8 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after)
end_sj_materialize.
*/
if (!(tab->bush_root_tab &&
- tab->bush_root_tab->bush_children->end == tab + 1))
+ tab->bush_root_tab->bush_children->end == tab + 1) &&
+ !(sort_nest_info && tab+1 == sort_nest_info->nest_tab))
{
tab->next_select=sub_select; /* normal select */
}
@@ -12958,7 +13276,7 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after)
It could be that sort_by_tab==NULL, and the plan is to use filesort()
on the first table.
*/
- if (join->order)
+ if (join->order && !join->sort_nest_info)
{
join->simple_order= 0;
join->need_tmp= 1;
@@ -13711,6 +14029,8 @@ static void update_depend_map(JOIN *join)
join_tab;
join_tab= next_linear_tab(join, join_tab, WITH_BUSH_ROOTS))
{
+ if (join_tab->is_sort_nest)
+ continue;
TABLE_REF *ref= &join_tab->ref;
table_map depend_map=0;
Item **item=ref->items;
@@ -14001,6 +14321,22 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond,
}
+bool JOIN::remove_const_from_order_by()
+{
+ ORDER *org_order= order;
+ order=remove_const(this, order,conds,1, &simple_order);
+ if (unlikely(thd->is_error()))
+ return TRUE;
+ /*
+ If we are using ORDER BY NULL or ORDER BY const_expression,
+ return result in any order (even if we are using a GROUP BY)
+ */
+ if (!order && org_order)
+ skip_sort_order= 1;
+ return FALSE;
+}
+
+
/**
Filter out ORDER items those are equal to constants in WHERE
@@ -14041,6 +14377,198 @@ ORDER *simple_remove_const(ORDER *order, COND *where)
}
+/*
+ This function basically tries to propgate all the multiple equalites
+ for the order by items, so that one can use them to generate QEP that would
+ also take into consideration equality propagation.
+ Example
+ select * from t1,t2 where t1.a=t2.a order by t1.a
+
+ So the possible join orders would be:
+
+ t1 join t2 then sort
+ t2 join t1 then sort
+ t1 sort(t1) join t2
+ t2 sort(t2) join t1 => this is only possible when equality propagation is
+ performed
+*/
+void propagate_equal_field_for_orderby(JOIN *join, ORDER *first_order)
+{
+ ORDER *order;
+ for (order= first_order; order; order= order->next)
+ {
+ if (optimizer_flag(join->thd, OPTIMIZER_SWITCH_ORDERBY_EQ_PROP) &&
+ join->cond_equal)
+ {
+ Item *item= order->item[0];
+ /*
+ TODO: equality substitution in the context of ORDER BY is
+ sometimes allowed when it is not allowed in the general case.
+ We make the below call for its side effect: it will locate the
+ multiple equality the item belongs to and set item->item_equal
+ accordingly.
+ */
+ (void)item->propagate_equal_fields(join->thd,
+ Value_source::
+ Context_identity(),
+ join->cond_equal);
+ }
+ }
+}
+
+/*
+ This function checks if by considering the current join_tab
+ would we be able to achieve the ordering
+*/
+
+bool check_join_prefix_contains_ordering(JOIN *join, JOIN_TAB *tab,
+ table_map previous_tables)
+{
+ ORDER *order;
+ for (order= join->order; order; order= order->next)
+ {
+ Item *order_item= order->item[0];
+ table_map order_tables=order_item->used_tables();
+ if (!(order_tables & ~previous_tables) ||
+ (order_item->excl_dep_on_table(previous_tables | tab->table->map)))
+ continue;
+ else
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+bool setup_sort_nest(JOIN *join)
+{
+ if (!join->sort_nest_needed())
+ return FALSE;
+
+ /*
+ The sort nest is only needed when there are more than one table
+ in the sort nest, else we can just sort with the first table if the
+ sort nest has only one table
+ */
+ SORT_NEST_INFO* sort_nest_info= join->sort_nest_info;
+ THD *thd= join->thd;
+ Field_iterator_table field_iterator;
+
+ JOIN_TAB *start_tab= join->join_tab+join->const_tables, *j, *tab;
+ tab= sort_nest_info->nest_tab;
+ sort_nest_info->nest_tables_map= 0;
+
+ if (unlikely(thd->trace_started()))
+ add_sort_nest_tables_to_trace(join);
+
+ /* This needs to be added to JOIN structure, looks the best option or we
+ can have a seperate struture NEST_INFO to hold it.
+ Final Implementation here should just walk over the where clause and collect
+ the field for which we should have a temp table field
+ */
+
+ for (j= start_tab; j < tab; j++)
+ {
+ TABLE *table= j->table;
+ field_iterator.set_table(table);
+ sort_nest_info->nest_tables_map|= table->map;
+ for (; !field_iterator.end_of_fields(); field_iterator.next())
+ {
+ Field *field= field_iterator.field();
+ if (!bitmap_is_set(table->read_set, field->field_index))
+ continue;
+ Item *item;
+ if (!(item= field_iterator.create_item(thd)))
+ return TRUE;
+ sort_nest_info->nest_base_table_cols.push_back(item, thd->mem_root);
+ }
+ }
+
+ uint non_order_fields= sort_nest_info->nest_base_table_cols.elements;
+ ORDER *order= join->order;
+
+ /*
+ Order by items need to be in the temp table ,we can avoid the Field items in
+ the order by list but we need to fields inside the temp table for expressions
+ */
+ for (order= join->order; order; order=order->next)
+ {
+ Item *item= order->item[0];
+ Item *res= substitute_for_best_equal_field(thd, NO_PARTICULAR_TAB, item,
+ join->cond_equal,
+ join->map2table, true);
+ res->update_used_tables();
+ sort_nest_info->nest_base_table_cols.push_back(res, thd->mem_root);
+ }
+
+ DBUG_ASSERT(!tab->table);
+
+ sort_nest_info->tmp_table_param.init();
+ sort_nest_info->tmp_table_param.bit_fields_as_long= TRUE;
+ sort_nest_info->tmp_table_param.field_count= sort_nest_info->nest_base_table_cols.elements;
+ sort_nest_info->tmp_table_param.force_not_null_cols= FALSE;
+
+ const LEX_CSTRING order_nest_name= { STRING_WITH_LEN("order-nest") };
+ if (!(tab->table= create_tmp_table(thd, &sort_nest_info->tmp_table_param,
+ sort_nest_info->nest_base_table_cols, (ORDER*) 0,
+ FALSE /* distinct */,
+ 0, /*save_sum_fields*/
+ thd->variables.option_bits | TMP_TABLE_ALL_COLUMNS,
+ HA_POS_ERROR /*rows_limit */,
+ &order_nest_name)))
+ return TRUE; /* purecov: inspected */
+
+ tab->table->map= sort_nest_info->nest_tables_map;
+ sort_nest_info->table= tab->table;
+ tab->type= JT_ALL;
+
+ /*
+ The list of temp table items created here, these are needed for the substitution
+ for items that would be evaluated in POST SORT NEST context
+ */
+ field_iterator.set_table(tab->table);
+ for (; !field_iterator.end_of_fields(); field_iterator.next())
+ {
+ Field *field= field_iterator.field();
+ Item *item;
+ if (!(item= new (thd->mem_root)Item_temptable_field(thd, field)))
+ return TRUE;
+ sort_nest_info->nest_temp_table_cols.push_back(item, thd->mem_root);
+ }
+
+ /*
+ Here we substitute order by items with the items of the temp table
+ */
+ List_iterator_fast<Item> it(sort_nest_info->nest_temp_table_cols);
+ Item *item;
+ order= join->order;
+ uint i=0;
+ while ((item= it++))
+ {
+ if (i++ < non_order_fields)
+ continue;
+ order->item[0]= item;
+ order= order->next;
+ }
+ tab->table->reginfo.join_tab= tab;
+
+ /*
+ Create mapping between base table to temp table
+ Need a key-value structure
+ would like to have base_table_field ----> temp_table_item mapping
+ We can use a hash-set that we already have in the file sql-hset.h
+ */
+
+ /*
+ Setting up the scan on the temp table
+ */
+ tab->read_first_record= join_init_read_record;
+ tab->read_record.read_record_func= rr_sequential;
+ tab[-1].next_select= end_nest_materialization;
+ sort_nest_info->materialized= FALSE;
+
+ return FALSE;
+}
+
static int
return_zero_rows(JOIN *join, select_result *result, List<TABLE_LIST> &tables,
List<Item> &fields, bool send_row, ulonglong select_options,
@@ -19721,6 +20249,10 @@ do_select(JOIN *join, Procedure *procedure)
JOIN_TAB *join_tab= join->join_tab +
(join->tables_list ? join->const_tables : 0);
+ SORT_NEST_INFO *sort_nest_info= join->sort_nest_info;
+ join_tab= sort_nest_info ? sort_nest_info->nest_tab
+ : join_tab;
+
if (join->outer_ref_cond && !join->outer_ref_cond->val_int())
error= NESTED_LOOP_NO_MORE_ROWS;
else
@@ -25951,6 +26483,13 @@ bool JOIN_TAB::save_explain_data(Explain_table_access *eta,
ctab->emb_sj_nest->sj_subq_pred->get_identifier());
eta->table_name.copy(table_name_buffer, len, cs);
}
+ else if (is_sort_nest)
+ {
+ size_t len= my_snprintf(table_name_buffer,
+ sizeof(table_name_buffer)-1,
+ "<order-nest>");
+ eta->table_name.copy(table_name_buffer, len, cs);
+ }
else
{
TABLE_LIST *real_table= table->pos_in_table_list;
@@ -28550,6 +29089,39 @@ select_handler *SELECT_LEX::find_select_handler(THD *thd)
return 0;
}
+double postjoin_oper_cost(THD *thd, double join_record_count, uint rec_len, uint idx)
+{
+ double cost= 0;
+ /*
+ For only one table in the order_nest, we don't need a fill the temp table, we can
+ just read the data into the filesort buffer and read the sorted data from the buffers.
+ */
+ if (idx)
+ cost= get_tmp_table_write_cost(thd, join_record_count,rec_len) *
+ join_record_count; // cost to fill tmp table
+
+ cost+= get_tmp_table_lookup_cost(thd, join_record_count,rec_len) *
+ join_record_count; // cost to perform post join operation used here
+ cost+= get_tmp_table_lookup_cost(thd, join_record_count, rec_len) +
+ (join_record_count == 0 ? 0 :
+ join_record_count * log2 (join_record_count)) *
+ SORT_INDEX_CMP_COST; // cost to perform sorting
+ return cost;
+}
+
+
+double calculate_record_count_for_sort_nest(JOIN *join, uint n_tables)
+{
+ double sort_nest_records=1, record_count;
+ JOIN_TAB *tab= join->join_tab + join->const_tables;
+ for (uint j= 0; j < n_tables ;j++, tab++)
+ {
+ record_count= tab->records_read * tab->cond_selectivity;
+ sort_nest_records= COST_MULT(sort_nest_records, record_count);
+ }
+ return sort_nest_records;
+}
+
/**
@} (end of group Query_Optimizer)
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 40a9ed303f7..e0a9886b984 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -289,13 +289,14 @@ typedef struct st_join_table {
/* TRUE <=> This join_tab is inside an SJM bush and is the last leaf tab here */
bool last_leaf_in_bush;
-
+
/*
ptr - this is a bush, and ptr points to description of child join_tab
range
NULL - this join tab has no bush children
*/
JOIN_TAB_RANGE *bush_children;
+ JOIN_TAB_RANGE *order_nest_children;
/* Special content for EXPLAIN 'Extra' column or NULL if none */
enum explain_extra_tag info;
@@ -524,6 +525,12 @@ typedef struct st_join_table {
/* Becomes true just after the used range filter has been built / filled */
bool is_rowid_filter_built;
+ /*
+ Set to true if we consider creating a nest for a prefix of the JOIN order
+ that satisfies the ordering
+ */
+ bool is_sort_nest;
+
void build_range_rowid_filter_if_needed();
void cleanup();
@@ -991,6 +998,9 @@ typedef struct st_position
/* Cost info for the range filter used at this position */
Range_rowid_filter_cost_info *range_rowid_filter_info;
+ /* Flag to be set to TRUE if the join prefix satisfies the ORDER BY CLAUSE */
+ bool sort_nest_operation_here;
+
} POSITION;
typedef Bounds_checked_array<Item_null_result*> Item_null_array;
@@ -1506,6 +1516,7 @@ class JOIN :public Sql_alloc
the optimize_cond() call in JOIN::optimize_inner() method.
*/
bool is_orig_degenerated;
+ SORT_NEST_INFO *sort_nest_info;
JOIN(THD *thd_arg, List<Item> &fields_arg, ulonglong select_options_arg,
select_result *result_arg)
@@ -1602,6 +1613,7 @@ class JOIN :public Sql_alloc
sjm_lookup_tables= 0;
sjm_scan_tables= 0;
is_orig_degenerated= false;
+ sort_nest_info= NULL;
}
/* True if the plan guarantees that it will be returned zero or one row */
@@ -1609,6 +1621,11 @@ class JOIN :public Sql_alloc
/* Number of tables actually joined at the top level */
uint exec_join_tab_cnt() { return tables_list ? top_join_tab_count : 0; }
+ /* TRUE if the sort-nest contains more than one table else FALSE */
+ bool sort_nest_needed() { return sort_nest_info ?
+ (sort_nest_info->n_tables == 1 ? FALSE : TRUE):
+ FALSE; }
+
/*
Number of tables in the join which also includes the temporary tables
created for GROUP BY, DISTINCT , WINDOW FUNCTION etc.
@@ -1721,7 +1738,8 @@ class JOIN :public Sql_alloc
JOIN_TAB *get_sort_by_join_tab()
{
return (need_tmp || !sort_by_table || skip_sort_order ||
- ((group || tmp_table_param.sum_func_count) && !group_list)) ?
+ ((group || tmp_table_param.sum_func_count) && !group_list) ||
+ sort_nest_info) ?
NULL : join_tab+const_tables;
}
bool setup_subquery_caches();
@@ -1748,11 +1766,20 @@ class JOIN :public Sql_alloc
bool test_if_need_tmp_table()
{
return ((const_tables != table_count &&
- ((select_distinct || !simple_order || !simple_group) ||
+ ((select_distinct || (!simple_order && !sort_nest_info) || !simple_group) ||
(group_list && order) ||
MY_TEST(select_options & OPTION_BUFFER_RESULT))) ||
(rollup.state != ROLLUP::STATE_NONE && select_distinct));
}
+
+ bool need_order_nest()
+ {
+ return ((const_tables != table_count &&
+ ((select_distinct || group_list) ||
+ MY_TEST(select_options & OPTION_BUFFER_RESULT))) ||
+ (rollup.state != ROLLUP::STATE_NONE && select_distinct) ||
+ select_lex->window_specs.elements > 0 || select_lex->agg_func_used());
+ }
bool choose_subquery_plan(table_map join_tables);
void get_partial_cost_and_fanout(int end_tab_idx,
table_map filter_map,
@@ -1783,6 +1810,7 @@ class JOIN :public Sql_alloc
bool fix_all_splittings_in_plan();
bool transform_in_predicates_into_in_subq(THD *thd);
+ bool remove_const_from_order_by();
private:
/**
Create a temporary table to be used for processing DISTINCT/ORDER
@@ -1853,6 +1881,7 @@ bool is_indexed_agg_distinct(JOIN *join, List<Item_field> *out_args);
bool simple_pred(Item_func *func_item, Item **args, bool *inv_order);
int opt_sum_query(THD* thd,
List<TABLE_LIST> &tables, List<Item> &all_fields, COND *conds);
+double calculate_record_count_for_sort_nest(JOIN *join, uint n_tables);
/* from sql_delete.cc, used by opt_range.cc */
extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b);
@@ -2098,6 +2127,10 @@ bool mysql_select(THD *thd,
void free_underlaid_joins(THD *thd, SELECT_LEX *select);
bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit,
select_result *result);
+void propagate_equal_field_for_orderby(JOIN *join, ORDER *first_order);
+bool check_join_prefix_contains_ordering(JOIN *join, JOIN_TAB *tab,
+ table_map previous_tables);
+bool setup_sort_nest(JOIN *join);
/*
General routine to change field->ptr of a NULL-terminated array of Field
@@ -2449,6 +2482,7 @@ double get_tmp_table_write_cost(THD *thd, double row_count, uint row_size);
void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array);
bool sort_and_filter_keyuse(THD *thd, DYNAMIC_ARRAY *keyuse,
bool skip_unprefixed_keyparts);
+double postjoin_oper_cost(THD *thd, double join_record_count, uint rec_len, uint idx);
struct st_cond_statistic
{
1
0
[Commits] 8d0dabc56b0: MDEV-20091 DROP TEMPORARY table is logged despite no CREATE was logged
by sujatha 25 Jul '19
by sujatha 25 Jul '19
25 Jul '19
revision-id: 8d0dabc56b09c6b40db15aac7da0da43d988759d (mariadb-10.1.39-122-g8d0dabc56b0)
parent(s): f6ea0389a4ea61dd0accbc3f949ef6c6d9a91417
author: Sujatha
committer: Sujatha
timestamp: 2019-07-25 14:24:04 +0530
message:
MDEV-20091 DROP TEMPORARY table is logged despite no CREATE was logged
Fixing post push test issues.
Recorded the result files for following:
rpl_stm_drop_create_temp_table.result
rpl_mixed_drop_create_temp_table.result.
---
.../rpl/r/rpl_mixed_drop_create_temp_table.result | 31 +++++-----------------
.../rpl/r/rpl_stm_drop_create_temp_table.result | 31 +++++-----------------
2 files changed, 14 insertions(+), 48 deletions(-)
diff --git a/mysql-test/suite/rpl/r/rpl_mixed_drop_create_temp_table.result b/mysql-test/suite/rpl/r/rpl_mixed_drop_create_temp_table.result
index da807748cee..d79b246c8d6 100644
--- a/mysql-test/suite/rpl/r/rpl_mixed_drop_create_temp_table.result
+++ b/mysql-test/suite/rpl/r/rpl_mixed_drop_create_temp_table.result
@@ -89,9 +89,6 @@ Warnings:
Note 1051 Unknown table 'test.tt_xx_1'
-b-b-b-b-b-b-b-b-b-b-b- >> Drop-Temp-If-Xe-Temp << -b-b-b-b-b-b-b-b-b-b-b-
include/show_binlog_events.inc
-Log_name Pos Event_type Server_id End_log_pos Info
-master-bin.000001 # Gtid # # GTID #-#-#
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_xx_1` /* generated by server */
-e-e-e-e-e-e-e-e-e-e-e- >> Drop-Temp-If-Xe-Temp << -e-e-e-e-e-e-e-e-e-e-e-
SET @commands= 'Drop-Temp-TXe-Temp';
@@ -112,7 +109,7 @@ Note 1051 Unknown table 'test.tt_1'
include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Gtid # # GTID #-#-#
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_tmp_2`,`test`.`tt_1` /* generated by server */
+master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_tmp_2` /* generated by server */
-e-e-e-e-e-e-e-e-e-e-e- >> Drop-Temp-If-TXe-Temp << -e-e-e-e-e-e-e-e-e-e-e-
SET @commands= 'Drop-Temp-NXe-Temp';
@@ -134,8 +131,6 @@ include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`nt_tmp_2` /* generated by server */
-master-bin.000001 # Gtid # # GTID #-#-#
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_1` /* generated by server */
-e-e-e-e-e-e-e-e-e-e-e- >> Drop-Temp-If-NXe-Temp << -e-e-e-e-e-e-e-e-e-e-e-
SET @commands= 'Drop-Temp-TN-Temp';
@@ -291,7 +286,6 @@ include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO tt_xx_1() VALUES (1)
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_xx_1` /* generated by server */
master-bin.000001 # Xid # # COMMIT /* XID */
-e-e-e-e-e-e-e-e-e-e-e- >> B T Drop-Temp-If-Xe-Temp C << -e-e-e-e-e-e-e-e-e-e-e-
@@ -314,8 +308,6 @@ master-bin.000001 # Query # # use `test`; INSERT INTO nt_xx_1() VALUES (1)
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO tt_xx_1() VALUES (1)
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_xx_1` /* generated by server */
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_xx_1` /* generated by server */
master-bin.000001 # Xid # # COMMIT /* XID */
-e-e-e-e-e-e-e-e-e-e-e- >> B T Drop-Temp-If-Xe-Temp N Drop-Temp-If-Xe-Temp C << -e-e-e-e-e-e-e-e-e-e-e-
@@ -368,7 +360,7 @@ include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO tt_xx_1() VALUES (1)
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_tmp_2`,`test`.`tt_1` /* generated by server */
+master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_tmp_2` /* generated by server */
master-bin.000001 # Xid # # COMMIT /* XID */
-e-e-e-e-e-e-e-e-e-e-e- >> B T Drop-Temp-If-TXe-Temp C << -e-e-e-e-e-e-e-e-e-e-e-
@@ -391,8 +383,8 @@ master-bin.000001 # Query # # use `test`; INSERT INTO nt_xx_1() VALUES (1)
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO tt_xx_1() VALUES (1)
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_tmp_2`,`test`.`tt_1` /* generated by server */
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_tmp_1`,`test`.`tt_1` /* generated by server */
+master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_tmp_2` /* generated by server */
+master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_tmp_1` /* generated by server */
master-bin.000001 # Xid # # COMMIT /* XID */
-e-e-e-e-e-e-e-e-e-e-e- >> B T Drop-Temp-If-TXe-Temp N Drop-Temp-If-TXe-Temp C << -e-e-e-e-e-e-e-e-e-e-e-
@@ -454,7 +446,6 @@ master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`nt_tmp_2` /
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO tt_xx_1() VALUES (1)
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_1` /* generated by server */
master-bin.000001 # Xid # # COMMIT /* XID */
-e-e-e-e-e-e-e-e-e-e-e- >> B T Drop-Temp-If-NXe-Temp C << -e-e-e-e-e-e-e-e-e-e-e-
@@ -483,8 +474,6 @@ master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`nt_tmp_1` /
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO tt_xx_1() VALUES (1)
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_1` /* generated by server */
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_1` /* generated by server */
master-bin.000001 # Xid # # COMMIT /* XID */
-e-e-e-e-e-e-e-e-e-e-e- >> B T Drop-Temp-If-NXe-Temp N Drop-Temp-If-NXe-Temp C << -e-e-e-e-e-e-e-e-e-e-e-
@@ -801,7 +790,6 @@ include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO tt_xx_1() VALUES (1)
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_xx_1` /* generated by server */
master-bin.000001 # Query # # ROLLBACK
-e-e-e-e-e-e-e-e-e-e-e- >> B T Drop-Temp-If-Xe-Temp R << -e-e-e-e-e-e-e-e-e-e-e-
@@ -826,8 +814,6 @@ master-bin.000001 # Query # # use `test`; INSERT INTO nt_xx_1() VALUES (1)
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO tt_xx_1() VALUES (1)
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_xx_1` /* generated by server */
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_xx_1` /* generated by server */
master-bin.000001 # Query # # ROLLBACK
-e-e-e-e-e-e-e-e-e-e-e- >> B T Drop-Temp-If-Xe-Temp N Drop-Temp-If-Xe-Temp R << -e-e-e-e-e-e-e-e-e-e-e-
@@ -882,7 +868,7 @@ include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO tt_xx_1() VALUES (1)
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_tmp_2`,`test`.`tt_1` /* generated by server */
+master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_tmp_2` /* generated by server */
master-bin.000001 # Query # # ROLLBACK
-e-e-e-e-e-e-e-e-e-e-e- >> B T Drop-Temp-If-TXe-Temp R << -e-e-e-e-e-e-e-e-e-e-e-
@@ -907,8 +893,8 @@ master-bin.000001 # Query # # use `test`; INSERT INTO nt_xx_1() VALUES (1)
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO tt_xx_1() VALUES (1)
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_tmp_2`,`test`.`tt_1` /* generated by server */
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_tmp_1`,`test`.`tt_1` /* generated by server */
+master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_tmp_2` /* generated by server */
+master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_tmp_1` /* generated by server */
master-bin.000001 # Query # # ROLLBACK
-e-e-e-e-e-e-e-e-e-e-e- >> B T Drop-Temp-If-TXe-Temp N Drop-Temp-If-TXe-Temp R << -e-e-e-e-e-e-e-e-e-e-e-
@@ -972,7 +958,6 @@ master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`nt_tmp_2` /
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO tt_xx_1() VALUES (1)
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_1` /* generated by server */
master-bin.000001 # Query # # ROLLBACK
-e-e-e-e-e-e-e-e-e-e-e- >> B T Drop-Temp-If-NXe-Temp R << -e-e-e-e-e-e-e-e-e-e-e-
@@ -1003,8 +988,6 @@ master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`nt_tmp_1` /
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO tt_xx_1() VALUES (1)
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_1` /* generated by server */
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_1` /* generated by server */
master-bin.000001 # Query # # ROLLBACK
-e-e-e-e-e-e-e-e-e-e-e- >> B T Drop-Temp-If-NXe-Temp N Drop-Temp-If-NXe-Temp R << -e-e-e-e-e-e-e-e-e-e-e-
diff --git a/mysql-test/suite/rpl/r/rpl_stm_drop_create_temp_table.result b/mysql-test/suite/rpl/r/rpl_stm_drop_create_temp_table.result
index 9dc86c0bfa7..0cad8f122de 100644
--- a/mysql-test/suite/rpl/r/rpl_stm_drop_create_temp_table.result
+++ b/mysql-test/suite/rpl/r/rpl_stm_drop_create_temp_table.result
@@ -89,9 +89,6 @@ Warnings:
Note 1051 Unknown table 'test.tt_xx_1'
-b-b-b-b-b-b-b-b-b-b-b- >> Drop-Temp-If-Xe-Temp << -b-b-b-b-b-b-b-b-b-b-b-
include/show_binlog_events.inc
-Log_name Pos Event_type Server_id End_log_pos Info
-master-bin.000001 # Gtid # # GTID #-#-#
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_xx_1` /* generated by server */
-e-e-e-e-e-e-e-e-e-e-e- >> Drop-Temp-If-Xe-Temp << -e-e-e-e-e-e-e-e-e-e-e-
SET @commands= 'Drop-Temp-TXe-Temp';
@@ -112,7 +109,7 @@ Note 1051 Unknown table 'test.tt_1'
include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Gtid # # GTID #-#-#
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_tmp_2`,`test`.`tt_1` /* generated by server */
+master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_tmp_2` /* generated by server */
-e-e-e-e-e-e-e-e-e-e-e- >> Drop-Temp-If-TXe-Temp << -e-e-e-e-e-e-e-e-e-e-e-
SET @commands= 'Drop-Temp-NXe-Temp';
@@ -134,8 +131,6 @@ include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`nt_tmp_2` /* generated by server */
-master-bin.000001 # Gtid # # GTID #-#-#
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_1` /* generated by server */
-e-e-e-e-e-e-e-e-e-e-e- >> Drop-Temp-If-NXe-Temp << -e-e-e-e-e-e-e-e-e-e-e-
SET @commands= 'Drop-Temp-TN-Temp';
@@ -291,7 +286,6 @@ include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO tt_xx_1() VALUES (1)
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_xx_1` /* generated by server */
master-bin.000001 # Xid # # COMMIT /* XID */
-e-e-e-e-e-e-e-e-e-e-e- >> B T Drop-Temp-If-Xe-Temp C << -e-e-e-e-e-e-e-e-e-e-e-
@@ -314,8 +308,6 @@ master-bin.000001 # Query # # use `test`; INSERT INTO nt_xx_1() VALUES (1)
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO tt_xx_1() VALUES (1)
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_xx_1` /* generated by server */
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_xx_1` /* generated by server */
master-bin.000001 # Xid # # COMMIT /* XID */
-e-e-e-e-e-e-e-e-e-e-e- >> B T Drop-Temp-If-Xe-Temp N Drop-Temp-If-Xe-Temp C << -e-e-e-e-e-e-e-e-e-e-e-
@@ -368,7 +360,7 @@ include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO tt_xx_1() VALUES (1)
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_tmp_2`,`test`.`tt_1` /* generated by server */
+master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_tmp_2` /* generated by server */
master-bin.000001 # Xid # # COMMIT /* XID */
-e-e-e-e-e-e-e-e-e-e-e- >> B T Drop-Temp-If-TXe-Temp C << -e-e-e-e-e-e-e-e-e-e-e-
@@ -391,8 +383,8 @@ master-bin.000001 # Query # # use `test`; INSERT INTO nt_xx_1() VALUES (1)
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO tt_xx_1() VALUES (1)
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_tmp_2`,`test`.`tt_1` /* generated by server */
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_tmp_1`,`test`.`tt_1` /* generated by server */
+master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_tmp_2` /* generated by server */
+master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_tmp_1` /* generated by server */
master-bin.000001 # Xid # # COMMIT /* XID */
-e-e-e-e-e-e-e-e-e-e-e- >> B T Drop-Temp-If-TXe-Temp N Drop-Temp-If-TXe-Temp C << -e-e-e-e-e-e-e-e-e-e-e-
@@ -454,7 +446,6 @@ master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`nt_tmp_2` /
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO tt_xx_1() VALUES (1)
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_1` /* generated by server */
master-bin.000001 # Xid # # COMMIT /* XID */
-e-e-e-e-e-e-e-e-e-e-e- >> B T Drop-Temp-If-NXe-Temp C << -e-e-e-e-e-e-e-e-e-e-e-
@@ -483,8 +474,6 @@ master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`nt_tmp_1` /
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO tt_xx_1() VALUES (1)
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_1` /* generated by server */
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_1` /* generated by server */
master-bin.000001 # Xid # # COMMIT /* XID */
-e-e-e-e-e-e-e-e-e-e-e- >> B T Drop-Temp-If-NXe-Temp N Drop-Temp-If-NXe-Temp C << -e-e-e-e-e-e-e-e-e-e-e-
@@ -801,7 +790,6 @@ include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO tt_xx_1() VALUES (1)
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_xx_1` /* generated by server */
master-bin.000001 # Query # # ROLLBACK
-e-e-e-e-e-e-e-e-e-e-e- >> B T Drop-Temp-If-Xe-Temp R << -e-e-e-e-e-e-e-e-e-e-e-
@@ -826,8 +814,6 @@ master-bin.000001 # Query # # use `test`; INSERT INTO nt_xx_1() VALUES (1)
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO tt_xx_1() VALUES (1)
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_xx_1` /* generated by server */
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_xx_1` /* generated by server */
master-bin.000001 # Query # # ROLLBACK
-e-e-e-e-e-e-e-e-e-e-e- >> B T Drop-Temp-If-Xe-Temp N Drop-Temp-If-Xe-Temp R << -e-e-e-e-e-e-e-e-e-e-e-
@@ -882,7 +868,7 @@ include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO tt_xx_1() VALUES (1)
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_tmp_2`,`test`.`tt_1` /* generated by server */
+master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_tmp_2` /* generated by server */
master-bin.000001 # Query # # ROLLBACK
-e-e-e-e-e-e-e-e-e-e-e- >> B T Drop-Temp-If-TXe-Temp R << -e-e-e-e-e-e-e-e-e-e-e-
@@ -907,8 +893,8 @@ master-bin.000001 # Query # # use `test`; INSERT INTO nt_xx_1() VALUES (1)
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO tt_xx_1() VALUES (1)
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_tmp_2`,`test`.`tt_1` /* generated by server */
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_tmp_1`,`test`.`tt_1` /* generated by server */
+master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_tmp_2` /* generated by server */
+master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_tmp_1` /* generated by server */
master-bin.000001 # Query # # ROLLBACK
-e-e-e-e-e-e-e-e-e-e-e- >> B T Drop-Temp-If-TXe-Temp N Drop-Temp-If-TXe-Temp R << -e-e-e-e-e-e-e-e-e-e-e-
@@ -972,7 +958,6 @@ master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`nt_tmp_2` /
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO tt_xx_1() VALUES (1)
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_1` /* generated by server */
master-bin.000001 # Query # # ROLLBACK
-e-e-e-e-e-e-e-e-e-e-e- >> B T Drop-Temp-If-NXe-Temp R << -e-e-e-e-e-e-e-e-e-e-e-
@@ -1003,8 +988,6 @@ master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`nt_tmp_1` /
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO tt_xx_1() VALUES (1)
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_1` /* generated by server */
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_1` /* generated by server */
master-bin.000001 # Query # # ROLLBACK
-e-e-e-e-e-e-e-e-e-e-e- >> B T Drop-Temp-If-NXe-Temp N Drop-Temp-If-NXe-Temp R << -e-e-e-e-e-e-e-e-e-e-e-
1
0
[Commits] 2c6d192a6cf: MDEV-20091 DROP TEMPORARY table is logged despite no CREATE was logged
by sujatha 23 Jul '19
by sujatha 23 Jul '19
23 Jul '19
revision-id: 2c6d192a6cfd7a00da3f0439c2f42c4f7b694119 (mariadb-10.1.39-106-g2c6d192a6cf)
parent(s): a5e268a2931c39c7b3cc2ff2e6e3fe6b5e85a383
author: Sujatha
committer: Sujatha
timestamp: 2019-07-23 15:46:51 +0530
message:
MDEV-20091 DROP TEMPORARY table is logged despite no CREATE was logged
MDEV-5589 commit set up a policy to skip DROP TEMPORARY TABLE binary logging
in case the target table has not been "CREATEed" in binlog (no CREATE
Query-log-event was logged into the binary log).
It turns out that
1. the rule did not cover non-existing table DROPped with IF-EXISTS clause.
The logged-create knowledge for the non-existing one does not even need
MDEV-5589 patch, and
2. connection close disobeys it to trigger automatic DROP-IF-EXISTS
binlogging.
Either 1 or 2 or even both is/are also responsible for unexpected binlog
records observed in MDEV-17863, actually rendering a referred
@@global.read_only irrelevant as far as the described stored procedure
definition *and* the ROW binlog-format are concerned.
---
mysql-test/extra/binlog_tests/drop_temp_table.test | 24 ++++---
.../rpl_tests/rpl_drop_create_temp_table.test | 4 ++
.../include/binlog_parallel_replication_marks.test | 9 ++-
.../r/binlog_parallel_replication_marks_row.result | 2 -
.../suite/binlog/r/binlog_row_drop_tmp_tbl.result | 8 ---
.../binlog/r/binlog_row_mix_innodb_myisam.result | 2 -
.../suite/binlog/r/binlog_stm_drop_tmp_tbl.result | 4 --
.../suite/rpl/r/create_or_replace_mix.result | 11 +++
.../suite/rpl/r/create_or_replace_row.result | 7 ++
.../suite/rpl/r/create_or_replace_statement.result | 11 +++
.../rpl/r/rpl_row_drop_create_temp_table.result | 27 -------
.../suite/rpl/r/rpl_row_drop_temp_table.result | 36 ++++++++++
mysql-test/suite/rpl/t/create_or_replace.inc | 13 ++++
.../suite/rpl/t/rpl_row_drop_temp_table.test | 54 ++++++++++++++
sql/sql_base.cc | 84 ++++++++++++----------
sql/sql_table.cc | 2 +-
16 files changed, 204 insertions(+), 94 deletions(-)
diff --git a/mysql-test/extra/binlog_tests/drop_temp_table.test b/mysql-test/extra/binlog_tests/drop_temp_table.test
index c852ee4c8a0..4241974d813 100644
--- a/mysql-test/extra/binlog_tests/drop_temp_table.test
+++ b/mysql-test/extra/binlog_tests/drop_temp_table.test
@@ -14,12 +14,8 @@ CREATE TEMPORARY TABLE `table:name` (a INT);
CREATE TEMPORARY TABLE shortn2 (a INT);
##############################################################################
-# BUG#46572 DROP TEMPORARY table IF EXISTS does not have a consistent behavior
-# in ROW mode
-#
-# In RBR, 'DROP TEMPORARY TABLE ...' statement should never be binlogged no
-# matter if the tables exist or not. In contrast, both in SBR and MBR, the
-# statement should be always binlogged no matter if the tables exist or not.
+# MDEV-20091: DROP TEMPORARY TABLE IF EXISTS statements will be written
+# to binlog only if the corresponding temporary table exists.
##############################################################################
CREATE TEMPORARY TABLE tmp(c1 int);
CREATE TEMPORARY TABLE tmp1(c1 int);
@@ -30,12 +26,12 @@ CREATE TABLE t(c1 int);
DROP TEMPORARY TABLE IF EXISTS tmp;
--disable_warnings
-# Before fixing BUG#46572, 'DROP TEMPORARY TABLE IF EXISTS...' statement was
-# binlogged when the table did not exist in RBR.
+# Post MDEV-20091: Following DROP TEMPORARY TABLE statement should not be
+# logged as the table is already dropped above.
DROP TEMPORARY TABLE IF EXISTS tmp;
-# In RBR, 'DROP TEMPORARY TABLE ...' statement is never binlogged no matter if
-# the tables exist or not.
+# Post MDEV-20091: Only DROP TEMPORARY TABLE statement should be written only
+# for 'tmp1' table.
DROP TEMPORARY TABLE IF EXISTS tmp, tmp1;
DROP TEMPORARY TABLE tmp3;
@@ -79,6 +75,12 @@ DROP DATABASE `drop-temp+table-test`;
# if there are open temporary tables. As such the implicit drop
# for temporary tables on session closing must be logged.
#
+# MDEV-20091: DROP TEMPORARY TABLE IF EXISTS statements will be written to
+# binlog only if the corresponding temporary table exists. In row based
+# replication temporary tables are not replicated hence their corresponding
+# DROP TEMPORARY TABLE statement will be not be written to binary log upon
+# session closure.
+#
RESET MASTER;
@@ -92,8 +94,10 @@ SELECT @@session.binlog_format;
--disconnect con1
-- connection default
+if (!`SELECT @@BINLOG_FORMAT = 'ROW'`) {
--let $wait_binlog_event= DROP
--source include/wait_for_binlog_event.inc
+}
-- source include/show_binlog_events.inc
RESET MASTER;
diff --git a/mysql-test/extra/rpl_tests/rpl_drop_create_temp_table.test b/mysql-test/extra/rpl_tests/rpl_drop_create_temp_table.test
index ffd7fe1a5c4..f8b521e3abf 100644
--- a/mysql-test/extra/rpl_tests/rpl_drop_create_temp_table.test
+++ b/mysql-test/extra/rpl_tests/rpl_drop_create_temp_table.test
@@ -32,6 +32,10 @@
# is any
# Drop-Temp-TT-Temp - Drops two temporary T-tables if there is any
# Drop-Temp-NN-Temp - Drops two temporary N-tables if there is any
+#
+# Note: MDEV-20091: DROP TEMPORARY TABLE IF EXISTS statements will be written
+# to binlog only if the corresponding temporary table exists.
+#
# Drop-Temp-Xe-Temp - Tries to drop a temporary table that does not exist
# Drop-Temp-NXe-Temp - Drops a temporary N-table if there is any and
# a temporary table that does not exist
diff --git a/mysql-test/include/binlog_parallel_replication_marks.test b/mysql-test/include/binlog_parallel_replication_marks.test
index ff35875aece..4e673bd30c3 100644
--- a/mysql-test/include/binlog_parallel_replication_marks.test
+++ b/mysql-test/include/binlog_parallel_replication_marks.test
@@ -49,9 +49,16 @@ connection default;
# We need to wait for the implicit DROP TEMPORARY TABLE to be logged after
# tmp_con disconnect, otherwise we get sporadic test failures.
+# MDEV-20091: DROP TEMPORARY TABLE IF EXISTS statements will be written to
+# binlog only if the corresponding temporary table exists. In row based
+# replication temporary tables are not replicated hence their corresponding
+# DROP TEMPORARY TABLE statement will be not be written to binary log upon
+# session closure.
+
+if (!`SELECT @@BINLOG_FORMAT = 'ROW'`) {
--let $wait_condition= SELECT variable_value > $before_drop_pos FROM information_schema.global_status WHERE variable_name = 'binlog_snapshot_position'
--source include/wait_condition.inc
-
+}
--let $binlog_pos2=query_get_value(SHOW MASTER STATUS, Position, 1)
--let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1)
diff --git a/mysql-test/suite/binlog/r/binlog_parallel_replication_marks_row.result b/mysql-test/suite/binlog/r/binlog_parallel_replication_marks_row.result
index e9a744a748e..1dafeee47e2 100644
--- a/mysql-test/suite/binlog/r/binlog_parallel_replication_marks_row.result
+++ b/mysql-test/suite/binlog/r/binlog_parallel_replication_marks_row.result
@@ -89,6 +89,4 @@ BEGIN
# server id 1 end_log_pos # Table_map: `test`.`t1` mapped to number #
# server id 1 end_log_pos # Write_rows: table id # flags: STMT_END_F
COMMIT/*!*/;
-# server id 1 end_log_pos # GTID #-#-# ddl
-DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `t5`
DROP TABLE t1;
diff --git a/mysql-test/suite/binlog/r/binlog_row_drop_tmp_tbl.result b/mysql-test/suite/binlog/r/binlog_row_drop_tmp_tbl.result
index dce2cc1408c..01ee24b9d48 100644
--- a/mysql-test/suite/binlog/r/binlog_row_drop_tmp_tbl.result
+++ b/mysql-test/suite/binlog/r/binlog_row_drop_tmp_tbl.result
@@ -30,15 +30,9 @@ master-bin.000001 # Query # # CREATE DATABASE `drop-temp+table-test`
master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # use `drop-temp+table-test`; CREATE TABLE t(c1 int)
master-bin.000001 # Gtid # # GTID #-#-#
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `drop-temp+table-test`.`tmp` /* generated by server */
-master-bin.000001 # Gtid # # GTID #-#-#
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `drop-temp+table-test`.`tmp` /* generated by server */
-master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # use `drop-temp+table-test`; DROP TABLE IF EXISTS `t` /* generated by server */
master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # use `drop-temp+table-test`; DROP TABLE IF EXISTS `tmp2`,`t` /* generated by server */
-master-bin.000001 # Gtid # # GTID #-#-#
-master-bin.000001 # Query # # use `drop-temp+table-test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `shortn2`,`table:name`,`shortn1`
DROP DATABASE `drop-temp+table-test`;
RESET MASTER;
CREATE TABLE t1 ( i text );
@@ -56,7 +50,5 @@ master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Table_map # # table_id: # (test.t1)
master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
master-bin.000001 # Query # # COMMIT
-master-bin.000001 # Gtid # # GTID #-#-#
-master-bin.000001 # Query # # use `test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `ttmp1`
RESET MASTER;
DROP TABLE t1;
diff --git a/mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result b/mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result
index f8f4fa5ec31..37018da86a0 100644
--- a/mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result
+++ b/mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result
@@ -303,8 +303,6 @@ master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # use `test`; create table t2 (n int) engine=innodb
-master-bin.000001 # Gtid # # GTID #-#-#
-master-bin.000001 # Query # # use `test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `t1`,`ti`
do release_lock("lock1");
drop table t0,t2;
set autocommit=0;
diff --git a/mysql-test/suite/binlog/r/binlog_stm_drop_tmp_tbl.result b/mysql-test/suite/binlog/r/binlog_stm_drop_tmp_tbl.result
index 127df219b02..4eeb8dd80c7 100644
--- a/mysql-test/suite/binlog/r/binlog_stm_drop_tmp_tbl.result
+++ b/mysql-test/suite/binlog/r/binlog_stm_drop_tmp_tbl.result
@@ -46,12 +46,8 @@ master-bin.000001 # Query # # use `drop-temp+table-test`; CREATE TABLE t(c1 int)
master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `drop-temp+table-test`.`tmp` /* generated by server */
master-bin.000001 # Gtid # # GTID #-#-#
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `drop-temp+table-test`.`tmp` /* generated by server */
-master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `drop-temp+table-test`.`tmp1` /* generated by server */
master-bin.000001 # Gtid # # GTID #-#-#
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `drop-temp+table-test`.`tmp` /* generated by server */
-master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # use `drop-temp+table-test`; DROP TEMPORARY TABLE `tmp3` /* generated by server */
master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `drop-temp+table-test`.`tmp2` /* generated by server */
diff --git a/mysql-test/suite/rpl/r/create_or_replace_mix.result b/mysql-test/suite/rpl/r/create_or_replace_mix.result
index c6cce358799..2c85bb3d93b 100644
--- a/mysql-test/suite/rpl/r/create_or_replace_mix.result
+++ b/mysql-test/suite/rpl/r/create_or_replace_mix.result
@@ -238,6 +238,13 @@ set binlog_format="STATEMENT";
ERROR HY000: Cannot switch out of the row-based binary log format when the session has open temporary tables
drop temporary table t8;
set @@binlog_format=@org_binlog_format;
+set @@session.binlog_format=default;
+drop temporary table if exists t9;
+Warnings:
+Note 1051 Unknown table 'test.t9'
+set session binlog_format=default;
+create temporary table t9 (i int);
+*** Must be no DROP logged for t9 when there was no CREATE, at disconnect too ***
include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Gtid # # GTID #-#-#
@@ -248,5 +255,9 @@ master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # use `test`; create temporary table t7 (a int)
master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`t7` /* generated by server */
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; create temporary table t9 (i int)
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `t9`
drop table t2;
include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/create_or_replace_row.result b/mysql-test/suite/rpl/r/create_or_replace_row.result
index 8f032107db9..cbb47cc4aba 100644
--- a/mysql-test/suite/rpl/r/create_or_replace_row.result
+++ b/mysql-test/suite/rpl/r/create_or_replace_row.result
@@ -260,6 +260,13 @@ set binlog_format="STATEMENT";
ERROR HY000: Cannot switch out of the row-based binary log format when the session has open temporary tables
drop temporary table t8;
set @@binlog_format=@org_binlog_format;
+set @@session.binlog_format=default;
+drop temporary table if exists t9;
+Warnings:
+Note 1051 Unknown table 'test.t9'
+set session binlog_format=default;
+create temporary table t9 (i int);
+*** Must be no DROP logged for t9 when there was no CREATE, at disconnect too ***
include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Gtid # # GTID #-#-#
diff --git a/mysql-test/suite/rpl/r/create_or_replace_statement.result b/mysql-test/suite/rpl/r/create_or_replace_statement.result
index 7bdbc64e9f2..6b47fafbe23 100644
--- a/mysql-test/suite/rpl/r/create_or_replace_statement.result
+++ b/mysql-test/suite/rpl/r/create_or_replace_statement.result
@@ -230,6 +230,13 @@ set binlog_format="STATEMENT";
ERROR HY000: Cannot switch out of the row-based binary log format when the session has open temporary tables
drop temporary table t8;
set @@binlog_format=@org_binlog_format;
+set @@session.binlog_format=default;
+drop temporary table if exists t9;
+Warnings:
+Note 1051 Unknown table 'test.t9'
+set session binlog_format=default;
+create temporary table t9 (i int);
+*** Must be no DROP logged for t9 when there was no CREATE, at disconnect too ***
include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Gtid # # GTID #-#-#
@@ -240,5 +247,9 @@ master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # use `test`; create temporary table t7 (a int)
master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`t7` /* generated by server */
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; create temporary table t9 (i int)
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `t9`
drop table t2;
include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/rpl_row_drop_create_temp_table.result b/mysql-test/suite/rpl/r/rpl_row_drop_create_temp_table.result
index 05b2c04e7ba..ec6d89551ae 100644
--- a/mysql-test/suite/rpl/r/rpl_row_drop_create_temp_table.result
+++ b/mysql-test/suite/rpl/r/rpl_row_drop_create_temp_table.result
@@ -83,9 +83,6 @@ Warnings:
Note 1051 Unknown table 'test.tt_xx_1'
-b-b-b-b-b-b-b-b-b-b-b- >> Drop-Temp-If-Xe-Temp << -b-b-b-b-b-b-b-b-b-b-b-
include/show_binlog_events.inc
-Log_name Pos Event_type Server_id End_log_pos Info
-master-bin.000001 # Gtid # # GTID #-#-#
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_xx_1` /* generated by server */
-e-e-e-e-e-e-e-e-e-e-e- >> Drop-Temp-If-Xe-Temp << -e-e-e-e-e-e-e-e-e-e-e-
SET @commands= 'Drop-Temp-TXe-Temp';
@@ -101,9 +98,6 @@ Warnings:
Note 1051 Unknown table 'test.tt_1'
-b-b-b-b-b-b-b-b-b-b-b- >> Drop-Temp-If-TXe-Temp << -b-b-b-b-b-b-b-b-b-b-b-
include/show_binlog_events.inc
-Log_name Pos Event_type Server_id End_log_pos Info
-master-bin.000001 # Gtid # # GTID #-#-#
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_1` /* generated by server */
-e-e-e-e-e-e-e-e-e-e-e- >> Drop-Temp-If-TXe-Temp << -e-e-e-e-e-e-e-e-e-e-e-
SET @commands= 'Drop-Temp-NXe-Temp';
@@ -119,9 +113,6 @@ Warnings:
Note 1051 Unknown table 'test.tt_1'
-b-b-b-b-b-b-b-b-b-b-b- >> Drop-Temp-If-NXe-Temp << -b-b-b-b-b-b-b-b-b-b-b-
include/show_binlog_events.inc
-Log_name Pos Event_type Server_id End_log_pos Info
-master-bin.000001 # Gtid # # GTID #-#-#
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_1` /* generated by server */
-e-e-e-e-e-e-e-e-e-e-e- >> Drop-Temp-If-NXe-Temp << -e-e-e-e-e-e-e-e-e-e-e-
SET @commands= 'Drop-Temp-TN-Temp';
@@ -264,7 +255,6 @@ Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Table_map # # table_id: # (test.tt_xx_1)
master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_xx_1` /* generated by server */
master-bin.000001 # Xid # # COMMIT /* XID */
-e-e-e-e-e-e-e-e-e-e-e- >> B T Drop-Temp-If-Xe-Temp C << -e-e-e-e-e-e-e-e-e-e-e-
@@ -289,8 +279,6 @@ master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Table_map # # table_id: # (test.tt_xx_1)
master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_xx_1` /* generated by server */
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_xx_1` /* generated by server */
master-bin.000001 # Xid # # COMMIT /* XID */
-e-e-e-e-e-e-e-e-e-e-e- >> B T Drop-Temp-If-Xe-Temp N Drop-Temp-If-Xe-Temp C << -e-e-e-e-e-e-e-e-e-e-e-
@@ -344,7 +332,6 @@ Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Table_map # # table_id: # (test.tt_xx_1)
master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_1` /* generated by server */
master-bin.000001 # Xid # # COMMIT /* XID */
-e-e-e-e-e-e-e-e-e-e-e- >> B T Drop-Temp-If-TXe-Temp C << -e-e-e-e-e-e-e-e-e-e-e-
@@ -369,8 +356,6 @@ master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Table_map # # table_id: # (test.tt_xx_1)
master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_1` /* generated by server */
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_1` /* generated by server */
master-bin.000001 # Xid # # COMMIT /* XID */
-e-e-e-e-e-e-e-e-e-e-e- >> B T Drop-Temp-If-TXe-Temp N Drop-Temp-If-TXe-Temp C << -e-e-e-e-e-e-e-e-e-e-e-
@@ -424,7 +409,6 @@ Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Table_map # # table_id: # (test.tt_xx_1)
master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_1` /* generated by server */
master-bin.000001 # Xid # # COMMIT /* XID */
-e-e-e-e-e-e-e-e-e-e-e- >> B T Drop-Temp-If-NXe-Temp C << -e-e-e-e-e-e-e-e-e-e-e-
@@ -449,8 +433,6 @@ master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Table_map # # table_id: # (test.tt_xx_1)
master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_1` /* generated by server */
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_1` /* generated by server */
master-bin.000001 # Xid # # COMMIT /* XID */
-e-e-e-e-e-e-e-e-e-e-e- >> B T Drop-Temp-If-NXe-Temp N Drop-Temp-If-NXe-Temp C << -e-e-e-e-e-e-e-e-e-e-e-
@@ -755,7 +737,6 @@ Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Table_map # # table_id: # (test.tt_xx_1)
master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_xx_1` /* generated by server */
master-bin.000001 # Query # # ROLLBACK
-e-e-e-e-e-e-e-e-e-e-e- >> B T Drop-Temp-If-Xe-Temp R << -e-e-e-e-e-e-e-e-e-e-e-
@@ -782,8 +763,6 @@ master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Table_map # # table_id: # (test.tt_xx_1)
master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_xx_1` /* generated by server */
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_xx_1` /* generated by server */
master-bin.000001 # Query # # ROLLBACK
-e-e-e-e-e-e-e-e-e-e-e- >> B T Drop-Temp-If-Xe-Temp N Drop-Temp-If-Xe-Temp R << -e-e-e-e-e-e-e-e-e-e-e-
@@ -839,7 +818,6 @@ Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Table_map # # table_id: # (test.tt_xx_1)
master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_1` /* generated by server */
master-bin.000001 # Query # # ROLLBACK
-e-e-e-e-e-e-e-e-e-e-e- >> B T Drop-Temp-If-TXe-Temp R << -e-e-e-e-e-e-e-e-e-e-e-
@@ -866,8 +844,6 @@ master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Table_map # # table_id: # (test.tt_xx_1)
master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_1` /* generated by server */
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_1` /* generated by server */
master-bin.000001 # Query # # ROLLBACK
-e-e-e-e-e-e-e-e-e-e-e- >> B T Drop-Temp-If-TXe-Temp N Drop-Temp-If-TXe-Temp R << -e-e-e-e-e-e-e-e-e-e-e-
@@ -923,7 +899,6 @@ Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Table_map # # table_id: # (test.tt_xx_1)
master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_1` /* generated by server */
master-bin.000001 # Query # # ROLLBACK
-e-e-e-e-e-e-e-e-e-e-e- >> B T Drop-Temp-If-NXe-Temp R << -e-e-e-e-e-e-e-e-e-e-e-
@@ -950,8 +925,6 @@ master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Table_map # # table_id: # (test.tt_xx_1)
master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_1` /* generated by server */
-master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt_1` /* generated by server */
master-bin.000001 # Query # # ROLLBACK
-e-e-e-e-e-e-e-e-e-e-e- >> B T Drop-Temp-If-NXe-Temp N Drop-Temp-If-NXe-Temp R << -e-e-e-e-e-e-e-e-e-e-e-
diff --git a/mysql-test/suite/rpl/r/rpl_row_drop_temp_table.result b/mysql-test/suite/rpl/r/rpl_row_drop_temp_table.result
new file mode 100644
index 00000000000..15b4d396522
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_row_drop_temp_table.result
@@ -0,0 +1,36 @@
+include/master-slave.inc
+[connection master]
+[connection slave]
+SET GLOBAL read_only=1;
+[connection master]
+CREATE PROCEDURE testproc()
+BEGIN
+DROP TEMPORARY TABLE IF EXISTS t1_tmp;
+DROP TEMPORARY TABLE IF EXISTS t2_tmp;
+CREATE TEMPORARY TABLE IF NOT EXISTS t1_tmp ( t1 varchar(400) DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+CREATE TEMPORARY TABLE IF NOT EXISTS t2_tmp ( t2 varchar(16) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+END|
+SET GLOBAL read_only=1;
+CALL testproc();
+******** None of the above DROP TEMPORARY TABLE statement should be found in binary log ********
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; CREATE DEFINER=`root`@`localhost` PROCEDURE `testproc`()
+BEGIN
+DROP TEMPORARY TABLE IF EXISTS t1_tmp;
+DROP TEMPORARY TABLE IF EXISTS t2_tmp;
+CREATE TEMPORARY TABLE IF NOT EXISTS t1_tmp ( t1 varchar(400) DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+CREATE TEMPORARY TABLE IF NOT EXISTS t2_tmp ( t2 varchar(16) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+END
+SELECT @@read_only;
+@@read_only
+1
+======== CLEAN UP =========
+[connection master]
+DROP TEMPORARY TABLE t1_tmp;
+DROP TEMPORARY TABLE t2_tmp;
+DROP PROCEDURE testproc;
+SET GLOBAL read_only=0;
+SET GLOBAL read_only=0;
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/create_or_replace.inc b/mysql-test/suite/rpl/t/create_or_replace.inc
index 7d0dc487061..35a6ead60ca 100644
--- a/mysql-test/suite/rpl/t/create_or_replace.inc
+++ b/mysql-test/suite/rpl/t/create_or_replace.inc
@@ -205,6 +205,19 @@ set binlog_format="STATEMENT";
drop temporary table t8;
set @@binlog_format=@org_binlog_format;
+# MDEV-20091:
+# 1. No DROP should be logged for non-existing tmp table, nor
+# 2. at the connection close when its creation has not been logged.
+set @@session.binlog_format=default;
+drop temporary table if exists t9;
+
+--connect(con1,localhost,root,,)
+set session binlog_format=default;
+create temporary table t9 (i int);
+--echo *** Must be no DROP logged for t9 when there was no CREATE, at disconnect too ***
+--disconnect con1
+
+--connection server_1
--source include/show_binlog_events.inc
# Clean up
diff --git a/mysql-test/suite/rpl/t/rpl_row_drop_temp_table.test b/mysql-test/suite/rpl/t/rpl_row_drop_temp_table.test
new file mode 100644
index 00000000000..5484928f383
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_drop_temp_table.test
@@ -0,0 +1,54 @@
+# ==== Purpose ====
+#
+# Test verifies that plain DROP TEMPORARY TABLE IF EXISTS statements are not
+# replicated during row based replication.
+#
+# ==== Implementation ====
+#
+# Steps:
+# 0 - Have a read_only master and slave. Binlog format should be "ROW".
+# 1 - Create a procedure which executes DROP TEMPORARY TABLE IF EXISTS
+# statements prior to CREATE TEMPORARY TABLE.
+# 2 - Execute the procedure.
+# 3 - Verify that the DROP TEMPORARY TABLE IF EXISTS statements within the
+# procedure are not written to the binary log.
+#
+# ==== References ====
+#
+# MDEV-20091: DROP TEMPORARY table is logged despite no CREATE was logged
+#
+
+--source include/have_binlog_format_row.inc
+--source include/have_innodb.inc
+--source include/master-slave.inc
+
+--source include/rpl_connection_slave.inc
+SET GLOBAL read_only=1;
+
+--source include/rpl_connection_master.inc
+DELIMITER |;
+CREATE PROCEDURE testproc()
+BEGIN
+ DROP TEMPORARY TABLE IF EXISTS t1_tmp;
+ DROP TEMPORARY TABLE IF EXISTS t2_tmp;
+ CREATE TEMPORARY TABLE IF NOT EXISTS t1_tmp ( t1 varchar(400) DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+ CREATE TEMPORARY TABLE IF NOT EXISTS t2_tmp ( t2 varchar(16) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+END|
+DELIMITER ;|
+SET GLOBAL read_only=1;
+CALL testproc();
+--echo ******** None of the above DROP TEMPORARY TABLE statement should be found in binary log ********
+--source include/show_binlog_events.inc
+--sync_slave_with_master
+SELECT @@read_only;
+
+--echo ======== CLEAN UP =========
+--source include/rpl_connection_master.inc
+DROP TEMPORARY TABLE t1_tmp;
+DROP TEMPORARY TABLE t2_tmp;
+DROP PROCEDURE testproc;
+SET GLOBAL read_only=0;
+--sync_slave_with_master
+SET GLOBAL read_only=0;
+
+--source include/rpl_end.inc
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 335d3a9dfce..e8bdff8b48f 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1205,7 +1205,7 @@ bool close_temporary_tables(THD *thd)
my_thread_id save_pseudo_thread_id= thd->variables.pseudo_thread_id;
char db_buf[FN_REFLEN];
String db(db_buf, sizeof(db_buf), system_charset_info);
-
+ bool at_least_one_create_logged;
/* Set pseudo_thread_id to be that of the processed table */
thd->variables.pseudo_thread_id= tmpkeyval(thd, table);
@@ -1217,56 +1217,62 @@ bool close_temporary_tables(THD *thd)
within the sublist of common pseudo_thread_id to create single
DROP query
*/
- for (;
+ for (at_least_one_create_logged= false;
table && is_user_table(table) &&
tmpkeyval(thd, table) == thd->variables.pseudo_thread_id &&
table->s->db.length == db.length() &&
memcmp(table->s->db.str, db.ptr(), db.length()) == 0;
table= next)
{
- /*
- We are going to add ` around the table names and possible more
- due to special characters
- */
- append_identifier(thd, &s_query, table->s->table_name.str,
- strlen(table->s->table_name.str));
- s_query.append(',');
+ if (table->s->table_creation_was_logged)
+ {
+ at_least_one_create_logged= true;
+ /*
+ We are going to add ` around the table names and possible more
+ due to special characters
+ */
+ append_identifier(thd, &s_query, table->s->table_name.str,
+ strlen(table->s->table_name.str));
+ s_query.append(',');
+ }
next= table->next;
mysql_lock_remove(thd, thd->lock, table);
close_temporary(table, 1, 1);
}
- thd->clear_error();
- CHARSET_INFO *cs_save= thd->variables.character_set_client;
- thd->variables.character_set_client= system_charset_info;
- thd->thread_specific_used= TRUE;
- Query_log_event qinfo(thd, s_query.ptr(),
- s_query.length() - 1 /* to remove trailing ',' */,
- FALSE, TRUE, FALSE, 0);
- qinfo.db= db.ptr();
- qinfo.db_len= db.length();
- thd->variables.character_set_client= cs_save;
-
- thd->get_stmt_da()->set_overwrite_status(true);
- thd->transaction.stmt.mark_dropped_temp_table();
- if ((error= (mysql_bin_log.write(&qinfo) || error)))
+ if (at_least_one_create_logged)
{
- /*
- If we're here following THD::cleanup, thence the connection
- has been closed already. So lets print a message to the
- error log instead of pushing yet another error into the
- stmt_da.
-
- Also, we keep the error flag so that we propagate the error
- up in the stack. This way, if we're the SQL thread we notice
- that close_temporary_tables failed. (Actually, the SQL
- thread only calls close_temporary_tables while applying old
- Start_log_event_v3 events.)
- */
- sql_print_error("Failed to write the DROP statement for "
- "temporary tables to binary log");
+ thd->clear_error();
+ CHARSET_INFO *cs_save= thd->variables.character_set_client;
+ thd->variables.character_set_client= system_charset_info;
+ thd->thread_specific_used= TRUE;
+ Query_log_event qinfo(thd, s_query.ptr(),
+ s_query.length() - 1 /* to remove trailing ',' */,
+ FALSE, TRUE, FALSE, 0);
+ qinfo.db= db.ptr();
+ qinfo.db_len= db.length();
+ thd->variables.character_set_client= cs_save;
+
+ thd->get_stmt_da()->set_overwrite_status(true);
+ thd->transaction.stmt.mark_dropped_temp_table();
+ if ((error= (mysql_bin_log.write(&qinfo) || error)))
+ {
+ /*
+ If we're here following THD::cleanup, thence the connection
+ has been closed already. So lets print a message to the
+ error log instead of pushing yet another error into the
+ stmt_da.
+
+ Also, we keep the error flag so that we propagate the error
+ up in the stack. This way, if we're the SQL thread we notice
+ that close_temporary_tables failed. (Actually, the SQL
+ thread only calls close_temporary_tables while applying old
+ Start_log_event_v3 events.)
+ */
+ sql_print_error("Failed to write the DROP statement for "
+ "temporary tables to binary log");
+ }
+ thd->get_stmt_da()->set_overwrite_status(false);
}
- thd->get_stmt_da()->set_overwrite_status(false);
-
thd->variables.pseudo_thread_id= save_pseudo_thread_id;
thd->thread_specific_used= save_thread_specific_used;
}
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 2696513d95f..25bbaf23617 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -2265,7 +2265,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
for (table= tables; table; table= table->next_local)
{
bool is_trans= 0;
- bool table_creation_was_logged= 1;
+ bool table_creation_was_logged= 0;
char *db=table->db;
size_t db_length= table->db_length;
handlerton *table_type= 0;
1
0