revision-id: c58811a5b05a26428c8bdb8dfd984f97caa8f4c1 (mariadb-10.4.10-7-gc58811a)
parent(s): 0308de94ee806c21b6776ecab73396da75282596
author: Igor Babaev
committer: Igor Babaev
timestamp: 2022-06-28 17:40:08 -0700
message:
An attempt to fix MDEV-21633
---
mysql-test/main/group_min_max.result | 8 +-
mysql-test/main/innodb_ext_key.result | 4 +-
mysql-test/main/opt_trace.result | 188 +--------
mysql-test/main/opt_trace_index_merge.result | 5 -
.../main/opt_trace_index_merge_innodb.result | 14 -
mysql-test/main/opt_tvc.result | 4 +-
mysql-test/main/rowid_filter_innodb.result | 118 +++---
mysql-test/main/selectivity.result | 2 +-
mysql-test/main/selectivity.test | 72 ++++
mysql-test/main/subselect.result | 4 +-
mysql-test/main/subselect_no_exists_to_in.result | 4 +-
mysql-test/main/subselect_no_mat.result | 4 +-
mysql-test/main/subselect_no_opts.result | 4 +-
mysql-test/main/subselect_no_scache.result | 4 +-
mysql-test/main/subselect_no_semijoin.result | 2 +-
mysql-test/main/subselect_sj2.result | 4 +-
mysql-test/main/subselect_sj2_jcl6.result | 4 +-
mysql-test/main/subselect_sj2_mat.result | 4 +-
sql/field.h | 2 +
sql/multi_range_read.cc | 3 +
sql/opt_range.cc | 315 ++++++++-------
sql/opt_range.h | 3 +-
sql/opt_range_mrr.cc | 1 +
sql/sql_select.cc | 438 +++++++++------------
sql/sql_statistics.cc | 2 +-
sql/structs.h | 1 +
sql/table.h | 1 +
27 files changed, 527 insertions(+), 688 deletions(-)
diff --git a/mysql-test/main/group_min_max.result b/mysql-test/main/group_min_max.result
index a28cc41..b9b4a9b 100644
--- a/mysql-test/main/group_min_max.result
+++ b/mysql-test/main/group_min_max.result
@@ -2078,19 +2078,19 @@ id select_type table type possible_keys key key_len ref rows Extra
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 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 77 99.22 Using where; Using index
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 77 85.71 Using where; Using index
Warnings:
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 ALL idx_t1_0,idx_t1_1,idx_t1_2 NULL NULL NULL 128 45.12 Using where; Using temporary; Using filesort
+1 SIMPLE t1 ALL idx_t1_0,idx_t1_1,idx_t1_2 NULL NULL NULL 128 74.41 Using where; Using temporary; Using filesort
Warnings:
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 ALL idx_t1_0,idx_t1_1,idx_t1_2 NULL NULL NULL 128 45.12 Using where; Using temporary; Using filesort
+1 SIMPLE t1 ALL idx_t1_0,idx_t1_1,idx_t1_2 NULL NULL NULL 128 74.41 Using where; Using temporary; Using filesort
Warnings:
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;
@@ -2098,7 +2098,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 index NULL idx_t2_1 163 NULL 164 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 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 77 99.22 Using where; Using index
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 77 85.71 Using where; Using index
Warnings:
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;
diff --git a/mysql-test/main/innodb_ext_key.result b/mysql-test/main/innodb_ext_key.result
index e0fa557..a484a98 100644
--- a/mysql-test/main/innodb_ext_key.result
+++ b/mysql-test/main/innodb_ext_key.result
@@ -1186,7 +1186,7 @@ EXPLAIN
"key_length": "3070",
"used_key_parts": ["f2", "pk1"],
"rows": 1,
- "filtered": 50,
+ "filtered": 100,
"index_condition": "t1.pk1 <= 5 and t1.pk2 <= 5 and t1.f2 = 'abc'",
"attached_condition": "t1.f1 <= '3'"
}
@@ -1216,7 +1216,7 @@ EXPLAIN
"key_length": "3011",
"used_key_parts": ["pk1", "f2", "pk2"],
"rows": 1,
- "filtered": 50,
+ "filtered": 100,
"index_condition": "t1.f2 <= 5 and t1.pk2 <= 5 and t1.pk1 = 'abc'",
"attached_condition": "t1.f1 <= '3'"
}
diff --git a/mysql-test/main/opt_trace.result b/mysql-test/main/opt_trace.result
index 72cee2a..07bff70 100644
--- a/mysql-test/main/opt_trace.result
+++ b/mysql-test/main/opt_trace.result
@@ -104,16 +104,6 @@ select * from v1 {
{
"rows_estimation": [
{
- "selectivity_for_indexes": [],
- "selectivity_for_columns": [
- {
- "column_name": "a",
- "selectivity_from_histogram": 0.5
- }
- ],
- "cond_selectivity": 0.5
- },
- {
"table": "t1",
"table_scan": {
"rows": 2,
@@ -250,16 +240,6 @@ select * from (select * from t1 where t1.a=1)q {
{
"rows_estimation": [
{
- "selectivity_for_indexes": [],
- "selectivity_for_columns": [
- {
- "column_name": "a",
- "selectivity_from_histogram": 0.5
- }
- ],
- "cond_selectivity": 0.5
- },
- {
"table": "t1",
"table_scan": {
"rows": 2,
@@ -401,16 +381,6 @@ select * from v2 {
{
"rows_estimation": [
{
- "selectivity_for_indexes": [],
- "selectivity_for_columns": [
- {
- "column_name": "a",
- "selectivity_from_histogram": 0.5
- }
- ],
- "cond_selectivity": 0.5
- },
- {
"table": "t1",
"table_scan": {
"rows": 2,
@@ -1420,20 +1390,6 @@ EXPLAIN SELECT MIN(d) FROM t1 where b=2 and c=3 group by a {
"analyzing_index_merge_union": []
}
}
- },
- {
- "selectivity_for_indexes": [],
- "selectivity_for_columns": [
- {
- "column_name": "b",
- "selectivity_from_histogram": 0.2891
- },
- {
- "column_name": "c",
- "selectivity_from_histogram": 0.2891
- }
- ],
- "cond_selectivity": 0.0836
}
]
},
@@ -1631,11 +1587,6 @@ EXPLAIN SELECT id,MIN(a),MAX(a) FROM t1 WHERE a>=20010104e0 GROUP BY id {
"analyzing_index_merge_union": []
}
}
- },
- {
- "selectivity_for_indexes": [],
- "selectivity_for_columns": [],
- "cond_selectivity": 1
}
]
},
@@ -1822,11 +1773,6 @@ EXPLAIN SELECT * FROM t1 WHERE a = 20010104e0 GROUP BY id {
"analyzing_index_merge_union": []
}
}
- },
- {
- "selectivity_for_indexes": [],
- "selectivity_for_columns": [],
- "cond_selectivity": 1
}
]
},
@@ -1933,7 +1879,7 @@ test.t1 analyze status OK
set optimizer_trace='enabled=on';
explain select * from t1 where a=1 and b=2 order by c limit 1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a_c,a_b a_c 5 NULL 180 Using where
+1 SIMPLE t1 ref a_c,a_b a_b 10 const,const 21 Using where; Using filesort
select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
explain select * from t1 where a=1 and b=2 order by c limit 1 {
@@ -2075,25 +2021,6 @@ explain select * from t1 where a=1 and b=2 order by c limit 1 {
"chosen": true
}
}
- },
- {
- "selectivity_for_indexes": [
- {
- "index_name": "a_b",
- "selectivity_from_index": 0.021
- }
- ],
- "selectivity_for_columns": [
- {
- "column_name": "a",
- "selectivity_from_histogram": 0.1797
- },
- {
- "column_name": "b",
- "selectivity_from_histogram": 0.0156
- }
- ],
- "cond_selectivity": 0.021
}
]
},
@@ -2166,19 +2093,19 @@ explain select * from t1 where a=1 and b=2 order by c limit 1 {
{
"index": "a_a",
"can_resolve_order": true,
- "updated_limit": 47,
- "index_scan_time": 47,
+ "updated_limit": 500,
+ "index_scan_time": 500,
"usable": false,
"cause": "cost"
},
{
"index": "a_c",
"can_resolve_order": true,
- "updated_limit": 47,
- "range_scan_time": 4.324,
- "index_scan_time": 4.324,
- "records": 180,
- "chosen": true
+ "updated_limit": 500,
+ "range_scan_time": 46,
+ "index_scan_time": 46,
+ "usable": false,
+ "cause": "cost"
},
{
"index": "a_b",
@@ -2187,66 +2114,6 @@ explain select * from t1 where a=1 and b=2 order by c limit 1 {
}
]
}
- },
- {
- "table": "t1",
- "range_analysis": {
- "table_scan": {
- "rows": 1000,
- "cost": 2e308
- },
- "potential_range_indexes": [
- {
- "index": "a_a",
- "usable": false,
- "cause": "not applicable"
- },
- {
- "index": "a_c",
- "usable": true,
- "key_parts": ["a", "c"]
- },
- {
- "index": "a_b",
- "usable": false,
- "cause": "not applicable"
- }
- ],
- "setup_range_conditions": [],
- "group_index_range": {
- "chosen": false,
- "cause": "no group by or distinct"
- },
- "analyzing_range_alternatives": {
- "range_scan_alternatives": [
- {
- "index": "a_c",
- "ranges": ["(1) <= (a) <= (1)"],
- "rowid_ordered": false,
- "using_mrr": false,
- "index_only": false,
- "rows": 180,
- "cost": 231.72,
- "chosen": true
- }
- ],
- "analyzing_roworder_intersect": {
- "cause": "too few roworder scans"
- },
- "analyzing_index_merge_union": []
- },
- "chosen_range_access_summary": {
- "range_access_plan": {
- "type": "range_scan",
- "index": "a_c",
- "rows": 180,
- "ranges": ["(1) <= (a) <= (1)"]
- },
- "rows_for_plan": 180,
- "cost_for_plan": 231.72,
- "chosen": true
- }
- }
}
]
}
@@ -3283,25 +3150,6 @@ explain select * from t1 where pk = 2 and a=5 and b=1 {
"chosen": true
}
}
- },
- {
- "selectivity_for_indexes": [
- {
- "index_name": "pk_a_b",
- "selectivity_from_index": 0.1
- }
- ],
- "selectivity_for_columns": [
- {
- "column_name": "a",
- "selectivity_from_histogram": 0.1
- },
- {
- "column_name": "b",
- "selectivity_from_histogram": 0.1
- }
- ],
- "cond_selectivity": 0.1
}
]
},
@@ -3860,16 +3708,6 @@ explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3 {
}
},
{
- "selectivity_for_indexes": [
- {
- "index_name": "a",
- "selectivity_from_index": 0.3
- }
- ],
- "selectivity_for_columns": [],
- "cond_selectivity": 0.3
- },
- {
"table": "t1",
"range_analysis": {
"table_scan": {
@@ -3923,16 +3761,6 @@ explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3 {
"chosen": true
}
}
- },
- {
- "selectivity_for_indexes": [
- {
- "index_name": "a",
- "selectivity_from_index": 0.3
- }
- ],
- "selectivity_for_columns": [],
- "cond_selectivity": 0.3
}
]
},
diff --git a/mysql-test/main/opt_trace_index_merge.result b/mysql-test/main/opt_trace_index_merge.result
index 7f1bd51..ed1a5a7 100644
--- a/mysql-test/main/opt_trace_index_merge.result
+++ b/mysql-test/main/opt_trace_index_merge.result
@@ -191,11 +191,6 @@ explain select * from t1 where a=1 or b=1 {
"chosen": true
}
}
- },
- {
- "selectivity_for_indexes": [],
- "selectivity_for_columns": [],
- "cond_selectivity": 0.002
}
]
},
diff --git a/mysql-test/main/opt_trace_index_merge_innodb.result b/mysql-test/main/opt_trace_index_merge_innodb.result
index afcf0b0..952d828 100644
--- a/mysql-test/main/opt_trace_index_merge_innodb.result
+++ b/mysql-test/main/opt_trace_index_merge_innodb.result
@@ -171,20 +171,6 @@ explain select * from t1 where pk1 != 0 and key1 = 1 {
"chosen": true
}
}
- },
- {
- "selectivity_for_indexes": [
- {
- "index_name": "PRIMARY",
- "selectivity_from_index": 1
- },
- {
- "index_name": "key1",
- "selectivity_from_index": 0.001
- }
- ],
- "selectivity_for_columns": [],
- "cond_selectivity": 0.001
}
]
},
diff --git a/mysql-test/main/opt_tvc.result b/mysql-test/main/opt_tvc.result
index 5329a9f..7886a99 100644
--- a/mysql-test/main/opt_tvc.result
+++ b/mysql-test/main/opt_tvc.result
@@ -444,7 +444,7 @@ where b in (3,5)
group by b
) as dr_table;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <derived2> ALL NULL NULL NULL NULL 12 100.00
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 6 100.00
2 DERIVED t1 ALL NULL NULL NULL NULL 6 100.00 Using temporary; Using filesort
2 DERIVED <subquery3> eq_ref distinct_key distinct_key 4 func 1 100.00
3 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
@@ -464,7 +464,7 @@ as tvc_0
group by b
) as dr_table;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <derived2> ALL NULL NULL NULL NULL 12 100.00
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 6 100.00
2 DERIVED t1 ALL NULL NULL NULL NULL 6 100.00 Using temporary; Using filesort
2 DERIVED <subquery3> eq_ref distinct_key distinct_key 4 func 1 100.00
3 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
diff --git a/mysql-test/main/rowid_filter_innodb.result b/mysql-test/main/rowid_filter_innodb.result
index 390c783..9d7775f 100644
--- a/mysql-test/main/rowid_filter_innodb.result
+++ b/mysql-test/main/rowid_filter_innodb.result
@@ -561,8 +561,8 @@ WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND
l_quantity > 45 AND
o_totalprice between 180000 and 230000;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE orders range PRIMARY,i_o_totalprice i_o_totalprice 9 NULL 144 Using where; Using index
-1 SIMPLE lineitem ref PRIMARY,i_l_shipdate,i_l_orderkey,i_l_orderkey_quantity,i_l_quantity PRIMARY 4 dbt3_s001.orders.o_orderkey 4 Using where
+1 SIMPLE lineitem range|filter PRIMARY,i_l_shipdate,i_l_orderkey,i_l_orderkey_quantity,i_l_quantity i_l_shipdate|i_l_quantity 4|9 NULL 510 (10%) Using index condition; Using where; Using rowid filter
+1 SIMPLE orders eq_ref PRIMARY,i_o_totalprice PRIMARY 4 dbt3_s001.lineitem.l_orderkey 1 Using where
set statement optimizer_switch='rowid_filter=on' for EXPLAIN FORMAT=JSON SELECT o_orderkey, l_linenumber, l_shipdate, l_quantity, o_totalprice
FROM orders JOIN lineitem ON o_orderkey=l_orderkey
WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND
@@ -573,20 +573,8 @@ EXPLAIN
"query_block": {
"select_id": 1,
"table": {
- "table_name": "orders",
- "access_type": "range",
- "possible_keys": ["PRIMARY", "i_o_totalprice"],
- "key": "i_o_totalprice",
- "key_length": "9",
- "used_key_parts": ["o_totalprice"],
- "rows": 144,
- "filtered": 100,
- "attached_condition": "orders.o_totalprice between 180000 and 230000",
- "using_index": true
- },
- "table": {
"table_name": "lineitem",
- "access_type": "ref",
+ "access_type": "range",
"possible_keys": [
"PRIMARY",
"i_l_shipdate",
@@ -594,13 +582,33 @@ EXPLAIN
"i_l_orderkey_quantity",
"i_l_quantity"
],
+ "key": "i_l_shipdate",
+ "key_length": "4",
+ "used_key_parts": ["l_shipDATE"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_l_quantity",
+ "used_key_parts": ["l_quantity"]
+ },
+ "rows": 605,
+ "selectivity_pct": 10.075
+ },
+ "rows": 510,
+ "filtered": 10.075,
+ "index_condition": "lineitem.l_shipDATE between '1997-01-01' and '1997-06-30'",
+ "attached_condition": "lineitem.l_quantity > 45"
+ },
+ "table": {
+ "table_name": "orders",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY", "i_o_totalprice"],
"key": "PRIMARY",
"key_length": "4",
- "used_key_parts": ["l_orderkey"],
- "ref": ["dbt3_s001.orders.o_orderkey"],
- "rows": 4,
- "filtered": 0.8557,
- "attached_condition": "lineitem.l_shipDATE between '1997-01-01' and '1997-06-30' and lineitem.l_quantity > 45"
+ "used_key_parts": ["o_orderkey"],
+ "ref": ["dbt3_s001.lineitem.l_orderkey"],
+ "rows": 1,
+ "filtered": 9.6,
+ "attached_condition": "orders.o_totalprice between 180000 and 230000"
}
}
}
@@ -610,8 +618,8 @@ WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND
l_quantity > 45 AND
o_totalprice between 180000 and 230000;
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 SIMPLE orders range PRIMARY,i_o_totalprice i_o_totalprice 9 NULL 144 144.00 100.00 100.00 Using where; Using index
-1 SIMPLE lineitem ref PRIMARY,i_l_shipdate,i_l_orderkey,i_l_orderkey_quantity,i_l_quantity PRIMARY 4 dbt3_s001.orders.o_orderkey 4 6.62 0.86 1.68 Using where
+1 SIMPLE lineitem range|filter PRIMARY,i_l_shipdate,i_l_orderkey,i_l_orderkey_quantity,i_l_quantity i_l_shipdate|i_l_quantity 4|9 NULL 510 (10%) 60.00 (11%) 10.07 100.00 Using index condition; Using where; Using rowid filter
+1 SIMPLE orders eq_ref PRIMARY,i_o_totalprice PRIMARY 4 dbt3_s001.lineitem.l_orderkey 1 1.00 9.60 26.67 Using where
set statement optimizer_switch='rowid_filter=on' for ANALYZE FORMAT=JSON SELECT o_orderkey, l_linenumber, l_shipdate, l_quantity, o_totalprice
FROM orders JOIN lineitem ON o_orderkey=l_orderkey
WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND
@@ -624,24 +632,8 @@ ANALYZE
"r_loops": 1,
"r_total_time_ms": "REPLACED",
"table": {
- "table_name": "orders",
- "access_type": "range",
- "possible_keys": ["PRIMARY", "i_o_totalprice"],
- "key": "i_o_totalprice",
- "key_length": "9",
- "used_key_parts": ["o_totalprice"],
- "r_loops": 1,
- "rows": 144,
- "r_rows": 144,
- "r_total_time_ms": "REPLACED",
- "filtered": 100,
- "r_filtered": 100,
- "attached_condition": "orders.o_totalprice between 180000 and 230000",
- "using_index": true
- },
- "table": {
"table_name": "lineitem",
- "access_type": "ref",
+ "access_type": "range",
"possible_keys": [
"PRIMARY",
"i_l_shipdate",
@@ -649,17 +641,45 @@ ANALYZE
"i_l_orderkey_quantity",
"i_l_quantity"
],
+ "key": "i_l_shipdate",
+ "key_length": "4",
+ "used_key_parts": ["l_shipDATE"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_l_quantity",
+ "used_key_parts": ["l_quantity"]
+ },
+ "rows": 605,
+ "selectivity_pct": 10.075,
+ "r_rows": 605,
+ "r_selectivity_pct": 11.765,
+ "r_buffer_size": "REPLACED",
+ "r_filling_time_ms": "REPLACED"
+ },
+ "r_loops": 1,
+ "rows": 510,
+ "r_rows": 60,
+ "r_total_time_ms": "REPLACED",
+ "filtered": 10.075,
+ "r_filtered": 100,
+ "index_condition": "lineitem.l_shipDATE between '1997-01-01' and '1997-06-30'",
+ "attached_condition": "lineitem.l_quantity > 45"
+ },
+ "table": {
+ "table_name": "orders",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY", "i_o_totalprice"],
"key": "PRIMARY",
"key_length": "4",
- "used_key_parts": ["l_orderkey"],
- "ref": ["dbt3_s001.orders.o_orderkey"],
- "r_loops": 144,
- "rows": 4,
- "r_rows": 6.625,
+ "used_key_parts": ["o_orderkey"],
+ "ref": ["dbt3_s001.lineitem.l_orderkey"],
+ "r_loops": 60,
+ "rows": 1,
+ "r_rows": 1,
"r_total_time_ms": "REPLACED",
- "filtered": 0.8557,
- "r_filtered": 1.6771,
- "attached_condition": "lineitem.l_shipDATE between '1997-01-01' and '1997-06-30' and lineitem.l_quantity > 45"
+ "filtered": 9.6,
+ "r_filtered": 26.667,
+ "attached_condition": "orders.o_totalprice between 180000 and 230000"
}
}
}
@@ -2105,7 +2125,7 @@ EXPLAIN
}
},
"rows": 1,
- "filtered": 1.5873,
+ "filtered": 100,
"attached_condition": "t1.f1 is null and t1.f2 is null and (t1.f2 between 'a' and 'z' or t1.f1 = 'a')"
}
}
@@ -2132,7 +2152,7 @@ EXPLAIN
}
},
"rows": 1,
- "filtered": 1.5873,
+ "filtered": 100,
"attached_condition": "t1.f1 is null and t1.f2 is null and (t1.f2 between 'a' and 'z' or t1.f1 = 'a')"
}
}
diff --git a/mysql-test/main/selectivity.result b/mysql-test/main/selectivity.result
index c548748..1ee927a 100644
--- a/mysql-test/main/selectivity.result
+++ b/mysql-test/main/selectivity.result
@@ -1790,7 +1790,7 @@ set optimizer_use_condition_selectivity=2;
explain extended select t1.b,t2.a,t3.a,t3.b from t1,t2,t3
where t1.c = t2.a AND t1.d = t3.a and t1.a = 50 and t1.b <= 100;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t1 range a a 10 NULL 9 9.00 Using index condition; Using where
+1 SIMPLE t1 range a a 10 NULL 9 10.00 Using index condition; Using where
1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.d 1 100.00
1 SIMPLE t2 eq_ref PRIMARY PRIMARY 4 test.t1.c 1 100.00 Using index
Warnings:
diff --git a/mysql-test/main/selectivity.test b/mysql-test/main/selectivity.test
index 3cf4f32..48e4a21 100644
--- a/mysql-test/main/selectivity.test
+++ b/mysql-test/main/selectivity.test
@@ -1235,6 +1235,78 @@ set optimizer_use_condition_selectivity= @@optimizer_use_condition_selectivity;
drop table t1,t2,t3;
+
+--echo #
+--echo # MDEV-20743: selectivity of equality conditions
+--echo #
+
+create table ta (a int);
+insert into ta select seq from seq_1_to_1000 order by rand(3);
+alter table ta add pk int primary key auto_increment;
+create table tb (b int);
+insert into tb select seq % 10 from seq_1_to_1000 order by rand(1009);
+alter table tb add pk int primary key auto_increment;
+create table tc (c int);
+insert into tc select seq % 10 from seq_1_to_1000 order by rand(2003);
+alter table tc add pk int primary key auto_increment;
+create table td (d int);
+insert into td select seq % 15 from seq_1_to_1000 order by rand(3019);
+alter table td add pk int primary key auto_increment;
+create table t1 (pk int primary key, a int, b int, c int, d int);
+insert into t1
+select ta.pk, a, b, c, d from ta, tb, tc, td where
+ ta.pk=tb.pk and ta.pk=tc.pk and ta.pk=td.pk;
+
+create table te (e int);
+insert into te select seq from seq_1_to_500 order by rand(4001);
+alter table te add pk int primary key auto_increment;
+create table tf (f int);
+insert into tf select seq % 10 from seq_1_to_500 order by rand(4507);
+alter table tf add pk int primary key auto_increment;
+create table tg (g int);
+insert into tg select seq % 20 from seq_1_to_500 order by rand(5003);
+alter table tg add pk int primary key auto_increment;
+create table t2 (pk int primary key, e int, f int, g int);
+insert into t2
+select te.pk, e, f, g from te, tf, tg where
+ te.pk=tf.pk and te.pk=tg.pk;
+
+select count(distinct a) from t1;
+select count(distinct b) from t1;
+select count(distinct c) from t1;
+select count(distinct d) from t1;
+select count(distinct e) from t2;
+select count(distinct f) from t2;
+select count(distinct g) from t2;
+
+set @@use_stat_tables='preferably';
+set optimizer_use_condition_selectivity=3;
+
+analyze table t1 persistent for all;
+
+select * from t1 where t1.b=t1.c;
+explain extended
+select * from t1 where t1.b=t1.c;
+
+select * from t1 where t1.b=t1.d;
+explain extended
+select * from t1 where t1.b=t1.d;
+
+select * from t1 where t1.b=t1.c and t1.c=t1.d;
+explain extended
+select * from t1 where t1.b=t1.c and t1.c=t1.d;
+
+create index idx on t1(b);
+
+select * from t1,t2 where t1.b=t1.c and t1.c=t1.d and t2.f=t2.g and t2.g=t1.b;
+explain extended
+select * from t1,t2 where t1.b=t1.c and t1.c=t1.d and t2.f=t2.g and t2.g=t1.b;
+
+set optimizer_use_condition_selectivity= @@optimizer_use_condition_selectivity;
+set use_stat_tables=@save_use_stat_tables;
+
+drop table ta,tb,tc,td,t1;
+
--echo # End of 10.1 tests
#
diff --git a/mysql-test/main/subselect.result b/mysql-test/main/subselect.result
index 349e7dc..224847f 100644
--- a/mysql-test/main/subselect.result
+++ b/mysql-test/main/subselect.result
@@ -1886,13 +1886,13 @@ id text
explain extended select * from t1 where id not in (select id from t1 where id < 8);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 12 100.00 Using where
-2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 100.00 Using index; Using where
+2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 58.33 Using index; Using where
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `test`.`t1` where !<expr_cache><`test`.`t1`.`id`>(<in_optimizer>(`test`.`t1`.`id`,<exists>(<primary_index_lookup>(<cache>(`test`.`t1`.`id`) in t1 on PRIMARY where `test`.`t1`.`id` < 8 and <cache>(`test`.`t1`.`id`) = `test`.`t1`.`id`))))
explain extended select * from t1 as tt where not exists (select id from t1 where id < 8 and (id = tt.id or id is null) having id is not null);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY tt ALL NULL NULL NULL NULL 12 100.00 Using where
-2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 test.tt.id 1 100.00 Using where; Using index
+2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 test.tt.id 1 58.33 Using where; Using index
Warnings:
Note 1276 Field or reference 'test.tt.id' of SELECT #2 was resolved in SELECT #1
Note 1003 /* select#1 */ select `test`.`tt`.`id` AS `id`,`test`.`tt`.`text` AS `text` from `test`.`t1` `tt` where !<in_optimizer>(1,<expr_cache><`test`.`tt`.`id`>(exists(/* select#2 */ select `test`.`t1`.`id` from `test`.`t1` where `test`.`t1`.`id` < 8 and `test`.`t1`.`id` = `test`.`tt`.`id` having `test`.`t1`.`id` is not null limit 1)))
diff --git a/mysql-test/main/subselect_no_exists_to_in.result b/mysql-test/main/subselect_no_exists_to_in.result
index 84c415d..b3ba535 100644
--- a/mysql-test/main/subselect_no_exists_to_in.result
+++ b/mysql-test/main/subselect_no_exists_to_in.result
@@ -1890,13 +1890,13 @@ id text
explain extended select * from t1 where id not in (select id from t1 where id < 8);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 12 100.00 Using where
-2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 100.00 Using index; Using where
+2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 58.33 Using index; Using where
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `test`.`t1` where !<expr_cache><`test`.`t1`.`id`>(<in_optimizer>(`test`.`t1`.`id`,<exists>(<primary_index_lookup>(<cache>(`test`.`t1`.`id`) in t1 on PRIMARY where `test`.`t1`.`id` < 8 and <cache>(`test`.`t1`.`id`) = `test`.`t1`.`id`))))
explain extended select * from t1 as tt where not exists (select id from t1 where id < 8 and (id = tt.id or id is null) having id is not null);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY tt ALL NULL NULL NULL NULL 12 100.00 Using where
-2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 test.tt.id 1 100.00 Using where; Using index
+2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 test.tt.id 1 58.33 Using where; Using index
Warnings:
Note 1276 Field or reference 'test.tt.id' of SELECT #2 was resolved in SELECT #1
Note 1003 /* select#1 */ select `test`.`tt`.`id` AS `id`,`test`.`tt`.`text` AS `text` from `test`.`t1` `tt` where !<expr_cache><`test`.`tt`.`id`>(exists(/* select#2 */ select `test`.`t1`.`id` from `test`.`t1` where `test`.`t1`.`id` < 8 and `test`.`t1`.`id` = `test`.`tt`.`id` having `test`.`t1`.`id` is not null limit 1))
diff --git a/mysql-test/main/subselect_no_mat.result b/mysql-test/main/subselect_no_mat.result
index 93035e2..6c874bc 100644
--- a/mysql-test/main/subselect_no_mat.result
+++ b/mysql-test/main/subselect_no_mat.result
@@ -1893,13 +1893,13 @@ id text
explain extended select * from t1 where id not in (select id from t1 where id < 8);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 12 100.00 Using where
-2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 100.00 Using index; Using where
+2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 58.33 Using index; Using where
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `test`.`t1` where !<expr_cache><`test`.`t1`.`id`>(<in_optimizer>(`test`.`t1`.`id`,<exists>(<primary_index_lookup>(<cache>(`test`.`t1`.`id`) in t1 on PRIMARY where `test`.`t1`.`id` < 8 and <cache>(`test`.`t1`.`id`) = `test`.`t1`.`id`))))
explain extended select * from t1 as tt where not exists (select id from t1 where id < 8 and (id = tt.id or id is null) having id is not null);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY tt ALL NULL NULL NULL NULL 12 100.00 Using where
-2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 test.tt.id 1 100.00 Using where; Using index
+2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 test.tt.id 1 58.33 Using where; Using index
Warnings:
Note 1276 Field or reference 'test.tt.id' of SELECT #2 was resolved in SELECT #1
Note 1003 /* select#1 */ select `test`.`tt`.`id` AS `id`,`test`.`tt`.`text` AS `text` from `test`.`t1` `tt` where !<in_optimizer>(1,<expr_cache><`test`.`tt`.`id`>(exists(/* select#2 */ select `test`.`t1`.`id` from `test`.`t1` where `test`.`t1`.`id` < 8 and `test`.`t1`.`id` = `test`.`tt`.`id` having `test`.`t1`.`id` is not null limit 1)))
diff --git a/mysql-test/main/subselect_no_opts.result b/mysql-test/main/subselect_no_opts.result
index 09f664d..dbc4eb5 100644
--- a/mysql-test/main/subselect_no_opts.result
+++ b/mysql-test/main/subselect_no_opts.result
@@ -1889,13 +1889,13 @@ id text
explain extended select * from t1 where id not in (select id from t1 where id < 8);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 12 100.00 Using where
-2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 100.00 Using index; Using where
+2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 58.33 Using index; Using where
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `test`.`t1` where !<in_optimizer>(`test`.`t1`.`id`,<exists>(<primary_index_lookup>(<cache>(`test`.`t1`.`id`) in t1 on PRIMARY where `test`.`t1`.`id` < 8 and <cache>(`test`.`t1`.`id`) = `test`.`t1`.`id`)))
explain extended select * from t1 as tt where not exists (select id from t1 where id < 8 and (id = tt.id or id is null) having id is not null);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY tt ALL NULL NULL NULL NULL 12 100.00 Using where
-2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 test.tt.id 1 100.00 Using where; Using index
+2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 test.tt.id 1 58.33 Using where; Using index
Warnings:
Note 1276 Field or reference 'test.tt.id' of SELECT #2 was resolved in SELECT #1
Note 1003 /* select#1 */ select `test`.`tt`.`id` AS `id`,`test`.`tt`.`text` AS `text` from `test`.`t1` `tt` where !<in_optimizer>(1,exists(/* select#2 */ select `test`.`t1`.`id` from `test`.`t1` where `test`.`t1`.`id` < 8 and `test`.`t1`.`id` = `test`.`tt`.`id` having `test`.`t1`.`id` is not null limit 1))
diff --git a/mysql-test/main/subselect_no_scache.result b/mysql-test/main/subselect_no_scache.result
index 765bb15..7e37b88 100644
--- a/mysql-test/main/subselect_no_scache.result
+++ b/mysql-test/main/subselect_no_scache.result
@@ -1892,13 +1892,13 @@ id text
explain extended select * from t1 where id not in (select id from t1 where id < 8);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 12 100.00 Using where
-2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 100.00 Using index; Using where
+2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 58.33 Using index; Using where
Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `test`.`t1` where !<in_optimizer>(`test`.`t1`.`id`,<exists>(<primary_index_lookup>(<cache>(`test`.`t1`.`id`) in t1 on PRIMARY where `test`.`t1`.`id` < 8 and <cache>(`test`.`t1`.`id`) = `test`.`t1`.`id`)))
explain extended select * from t1 as tt where not exists (select id from t1 where id < 8 and (id = tt.id or id is null) having id is not null);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY tt ALL NULL NULL NULL NULL 12 100.00 Using where
-2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 test.tt.id 1 100.00 Using where; Using index
+2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 test.tt.id 1 58.33 Using where; Using index
Warnings:
Note 1276 Field or reference 'test.tt.id' of SELECT #2 was resolved in SELECT #1
Note 1003 /* select#1 */ select `test`.`tt`.`id` AS `id`,`test`.`tt`.`text` AS `text` from `test`.`t1` `tt` where !<in_optimizer>(1,exists(/* select#2 */ select `test`.`t1`.`id` from `test`.`t1` where `test`.`t1`.`id` < 8 and `test`.`t1`.`id` = `test`.`tt`.`id` having `test`.`t1`.`id` is not null limit 1))
diff --git a/mysql-test/main/subselect_no_semijoin.result b/mysql-test/main/subselect_no_semijoin.result
index 97d2f3b..77e6306 100644
--- a/mysql-test/main/subselect_no_semijoin.result
+++ b/mysql-test/main/subselect_no_semijoin.result
@@ -1895,7 +1895,7 @@ Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `
explain extended select * from t1 as tt where not exists (select id from t1 where id < 8 and (id = tt.id or id is null) having id is not null);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY tt ALL NULL NULL NULL NULL 12 100.00 Using where
-2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 test.tt.id 1 100.00 Using where; Using index
+2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 test.tt.id 1 58.33 Using where; Using index
Warnings:
Note 1276 Field or reference 'test.tt.id' of SELECT #2 was resolved in SELECT #1
Note 1003 /* select#1 */ select `test`.`tt`.`id` AS `id`,`test`.`tt`.`text` AS `text` from `test`.`t1` `tt` where !<in_optimizer>(1,<expr_cache><`test`.`tt`.`id`>(exists(/* select#2 */ select `test`.`t1`.`id` from `test`.`t1` where `test`.`t1`.`id` < 8 and `test`.`t1`.`id` = `test`.`tt`.`id` having `test`.`t1`.`id` is not null limit 1)))
diff --git a/mysql-test/main/subselect_sj2.result b/mysql-test/main/subselect_sj2.result
index 8045a81..31e94cc 100644
--- a/mysql-test/main/subselect_sj2.result
+++ b/mysql-test/main/subselect_sj2.result
@@ -1032,8 +1032,8 @@ alias2.b = alias1.a AND
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL a NULL NULL NULL 38
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
-2 MATERIALIZED alias1 ALL a NULL NULL NULL 19 Using where
-2 MATERIALIZED alias2 ref a a 4 test.alias1.a 1 Using where
+2 MATERIALIZED alias2 ALL a NULL NULL NULL 19 Using where
+2 MATERIALIZED alias1 ref a a 4 test.alias2.a 1 Using where
SELECT * FROM t2
WHERE (a, a) IN (SELECT alias2.b, alias2.a FROM t1 AS alias1, t1 AS alias2
WHERE
diff --git a/mysql-test/main/subselect_sj2_jcl6.result b/mysql-test/main/subselect_sj2_jcl6.result
index 22310ab..3a8f4a6 100644
--- a/mysql-test/main/subselect_sj2_jcl6.result
+++ b/mysql-test/main/subselect_sj2_jcl6.result
@@ -1045,8 +1045,8 @@ alias2.b = alias1.a AND
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL a NULL NULL NULL 38
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
-2 MATERIALIZED alias1 ALL a NULL NULL NULL 19 Using where
-2 MATERIALIZED alias2 ref a a 4 test.alias1.a 1 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan
+2 MATERIALIZED alias2 ALL a NULL NULL NULL 19 Using where
+2 MATERIALIZED alias1 ref a a 4 test.alias2.a 1 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan
SELECT * FROM t2
WHERE (a, a) IN (SELECT alias2.b, alias2.a FROM t1 AS alias1, t1 AS alias2
WHERE
diff --git a/mysql-test/main/subselect_sj2_mat.result b/mysql-test/main/subselect_sj2_mat.result
index 7ccaed5..bbdd1bd 100644
--- a/mysql-test/main/subselect_sj2_mat.result
+++ b/mysql-test/main/subselect_sj2_mat.result
@@ -1034,8 +1034,8 @@ alias2.b = alias1.a AND
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL a NULL NULL NULL 38
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1
-2 MATERIALIZED alias1 ALL a NULL NULL NULL 19 Using where
-2 MATERIALIZED alias2 ref a a 4 test.alias1.a 1 Using where
+2 MATERIALIZED alias2 ALL a NULL NULL NULL 19 Using where
+2 MATERIALIZED alias1 ref a a 4 test.alias2.a 1 Using where
SELECT * FROM t2
WHERE (a, a) IN (SELECT alias2.b, alias2.a FROM t1 AS alias1, t1 AS alias2
WHERE
diff --git a/sql/field.h b/sql/field.h
index f07eab3..0abd582 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -718,6 +718,8 @@ class Field: public Value_source
*/
double cond_selectivity;
+ double ndv;
+
/*
The next field in the class of equal fields at the top AND level
of the WHERE clause
diff --git a/sql/multi_range_read.cc b/sql/multi_range_read.cc
index 8c6b0de..78ead1f0 100644
--- a/sql/multi_range_read.cc
+++ b/sql/multi_range_read.cc
@@ -198,6 +198,9 @@ handler::multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq,
}
total_rows += rows;
total_touched_blocks+= new_touched_blocks;
+ KEY_PART_INFO *kp= table->key_info[keyno]->key_part +
+ table->curr_key_tree_part;
+ kp->quick_cnt+= rows;
}
if (total_rows != HA_POS_ERROR)
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index c47da28..3202e34 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -3218,17 +3218,6 @@ double records_in_column_ranges(PARAM *param, uint idx,
on the rows of 'table' in the processed query.
The calculated selectivity is assigned to the field table->cond_selectivity.
- Selectivity is calculated as a product of selectivities imposed by:
-
- 1. possible range accesses. (if multiple range accesses use the same
- restrictions on the same field, we make adjustments for that)
- 2. Sargable conditions on fields for which we have column statistics (if
- a field is used in a possible range access, we assume that selectivity
- is already provided by the range access' estimates)
- 3. Reading a few records from the table pages and checking the condition
- selectivity (this is used for conditions like "column LIKE '%val%'"
- where approaches #1 and #2 do not provide selectivity data).
-
NOTE
Currently the selectivities of range conditions over different columns are
considered independent.
@@ -3238,7 +3227,8 @@ double records_in_column_ranges(PARAM *param, uint idx,
TRUE otherwise
*/
-bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
+bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table,
+ COND_EQUAL *cond_equal, Item **cond)
{
uint keynr;
uint max_quick_key_parts= 0;
@@ -3265,131 +3255,17 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
if (table->pos_in_table_list->schema_table)
DBUG_RETURN(FALSE);
- MY_BITMAP handled_columns;
- my_bitmap_map* buf;
- if (!(buf= (my_bitmap_map*)thd->alloc(table->s->column_bitmap_size)))
- DBUG_RETURN(TRUE);
- my_bitmap_init(&handled_columns, buf, table->s->fields, FALSE);
-
- /*
- Calculate the selectivity of the range conditions supported by indexes.
-
- First, take into account possible range accesses.
- range access estimates are the most precise, we prefer them to any other
- estimate sources.
- */
-
- Json_writer_object trace_wrapper(thd);
- Json_writer_array selectivity_for_indexes(thd, "selectivity_for_indexes");
-
- for (keynr= 0; keynr < table->s->keys; keynr++)
- {
- if (table->quick_keys.is_set(keynr))
- set_if_bigger(max_quick_key_parts, table->quick_key_parts[keynr]);
- }
-
- /*
- Walk through all indexes, indexes where range access uses more keyparts
- go first.
- */
- for (uint quick_key_parts= max_quick_key_parts;
- quick_key_parts; quick_key_parts--)
- {
- for (keynr= 0; keynr < table->s->keys; keynr++)
- {
- if (table->quick_keys.is_set(keynr) &&
- table->quick_key_parts[keynr] == quick_key_parts)
- {
- uint i;
- uint used_key_parts= table->quick_key_parts[keynr];
- double quick_cond_selectivity= table->quick_rows[keynr] /
- table_records;
- KEY *key_info= table->key_info + keynr;
- KEY_PART_INFO* key_part= key_info->key_part;
- /*
- Suppose, there are range conditions on two keys
- KEY1 (col1, col2)
- KEY2 (col3, col2)
-
- we don't want to count selectivity of condition on col2 twice.
-
- First, find the longest key prefix that's made of columns whose
- selectivity wasn't already accounted for.
- */
- for (i= 0; i < used_key_parts; i++, key_part++)
- {
- if (bitmap_is_set(&handled_columns, key_part->fieldnr-1))
- break;
- bitmap_set_bit(&handled_columns, key_part->fieldnr-1);
- }
- if (i)
- {
- double UNINIT_VAR(selectivity_mult);
-
- /*
- There is at least 1-column prefix of columns whose selectivity has
- not yet been accounted for.
- */
- table->cond_selectivity*= quick_cond_selectivity;
- Json_writer_object selectivity_for_index(thd);
- selectivity_for_index.add("index_name", key_info->name)
- .add("selectivity_from_index",
- quick_cond_selectivity);
- if (i != used_key_parts)
- {
- /*
- Range access got us estimate for #used_key_parts.
- We need estimate for #(i-1) key parts.
- */
- double f1= key_info->actual_rec_per_key(i-1);
- double f2= key_info->actual_rec_per_key(i);
- if (f1 > 0 && f2 > 0)
- selectivity_mult= f1 / f2;
- else
- {
- /*
- No statistics available, assume the selectivity is proportional
- to the number of key parts.
- (i=0 means 1 keypart, i=1 means 2 keyparts, so use i+1)
- */
- selectivity_mult= ((double)(i+1)) / i;
- }
- table->cond_selectivity*= selectivity_mult;
- selectivity_for_index.add("selectivity_multiplier",
- selectivity_mult);
- }
- /*
- We need to set selectivity for fields supported by indexes.
- For single-component indexes and for some first components
- of other indexes we do it here. For the remaining fields
- we do it later in this function, in the same way as for the
- fields not used in any indexes.
- */
- if (i == 1)
- {
- uint fieldnr= key_info->key_part[0].fieldnr;
- table->field[fieldnr-1]->cond_selectivity= quick_cond_selectivity;
- if (i != used_key_parts)
- table->field[fieldnr-1]->cond_selectivity*= selectivity_mult;
- bitmap_clear_bit(used_fields, fieldnr-1);
- }
- }
- }
- }
- }
- selectivity_for_indexes.end();
-
- /*
- Second step: calculate the selectivity of the range conditions not
- supported by any index and selectivity of the range condition
- over the fields whose selectivity has not been set yet.
- */
- Json_writer_array selectivity_for_columns(thd, "selectivity_for_columns");
+ if (thd->variables.use_stat_tables == 0 || !table->stats_is_read)
+ bitmap_clear_all(used_fields);
if (thd->variables.optimizer_use_condition_selectivity > 2 &&
- !bitmap_is_clear_all(used_fields) &&
- thd->variables.use_stat_tables > 0 && table->stats_is_read)
+ !bitmap_is_clear_all(used_fields))
{
+ /*
+ Calculate the selectivity of the range conditions not supported
+ by any index
+ */
+
PARAM param;
MEM_ROOT alloc;
SEL_TREE *tree;
@@ -3402,7 +3278,6 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
param.mem_root= &alloc;
param.old_root= thd->mem_root;
param.table= table;
- param.remove_false_where_parts= true;
if (create_key_parts_for_pseudo_indexes(¶m, used_fields))
goto free_alloc;
@@ -3412,6 +3287,7 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
param.using_real_indexes= FALSE;
param.real_keynr[0]= 0;
param.alloced_sel_args= 0;
+ param.remove_false_where_parts= true;
thd->no_errors=1;
@@ -3443,14 +3319,10 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
SEL_ARG *key= tree->keys[idx];
if (key)
{
- Json_writer_object selectivity_for_column(thd);
- selectivity_for_column.add("column_name", key->field->field_name);
if (key->type == SEL_ARG::IMPOSSIBLE)
{
rows= 0;
table->reginfo.impossible_range= 1;
- selectivity_for_column.add("selectivity_from_histogram", rows);
- selectivity_for_column.add("cause", "impossible range");
goto free_alloc;
}
else
@@ -3459,8 +3331,6 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
if (rows != DBL_MAX)
{
key->field->cond_selectivity= rows/table_records;
- selectivity_for_column.add("selectivity_from_histogram",
- key->field->cond_selectivity);
}
}
}
@@ -3469,12 +3339,9 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
for (Field **field_ptr= table->field; *field_ptr; field_ptr++)
{
Field *table_field= *field_ptr;
- if (bitmap_is_set(used_fields, table_field->field_index) &&
+ if (bitmap_is_set(table->read_set, table_field->field_index) &&
table_field->cond_selectivity < 1.0)
- {
- if (!bitmap_is_set(&handled_columns, table_field->field_index))
- table->cond_selectivity*= table_field->cond_selectivity;
- }
+ table->cond_selectivity*= table_field->cond_selectivity;
}
free_alloc:
@@ -3483,7 +3350,104 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
free_root(&alloc, MYF(0));
}
- selectivity_for_columns.end();
+
+ for (keynr= 0; keynr < table->s->keys; keynr++)
+ {
+ if (table->quick_keys.is_set(keynr))
+ set_if_bigger(max_quick_key_parts, table->quick_key_parts[keynr]);
+ }
+
+ bool is_sel_added;
+ do
+ {
+ is_sel_added= false;
+ for (uint quick_key_parts= 1;
+ quick_key_parts <= max_quick_key_parts;
+ quick_key_parts++)
+ {
+ for (keynr= 0; keynr < table->s->keys; keynr++)
+ {
+ uint used_key_parts= table->quick_key_parts[keynr];
+ if (!(table->quick_keys.is_set(keynr) &&
+ used_key_parts == quick_key_parts))
+ continue;
+ KEY *key_info= table->key_info + keynr;
+ KEY_PART_INFO* key_part= key_info->key_part;
+ if (bitmap_is_set(used_fields, key_part->fieldnr-1))
+ continue;
+ Field *first_kp_field= table->field[key_part->fieldnr-1];
+ double quick_cond_selectivity= table->quick_rows[keynr] /
+ table_records;
+ double selectivity_mult= 1.0;
+ uint i= 1;
+ for (key_part++; i < used_key_parts; i++, key_part++)
+ {
+ if (!bitmap_is_set(used_fields, key_part->fieldnr-1))
+ break;
+ selectivity_mult/=
+ table->field[key_part->fieldnr-1]->cond_selectivity;
+ }
+ if (i != used_key_parts)
+ continue;
+ first_kp_field->cond_selectivity= quick_cond_selectivity *
+ selectivity_mult;
+ set_if_smaller(first_kp_field->cond_selectivity, 1.0);
+ table->cond_selectivity*= first_kp_field->cond_selectivity;
+ bitmap_set_bit(used_fields, first_kp_field->field_index);
+ is_sel_added= true;
+ }
+ }
+ } while (is_sel_added);
+
+ for (uint quick_key_parts= 1;
+ quick_key_parts <= max_quick_key_parts;
+ quick_key_parts++)
+ {
+ for (keynr= 0; keynr < table->s->keys; keynr++)
+ {
+ uint used_key_parts= table->quick_key_parts[keynr];
+ if (!(table->quick_keys.is_set(keynr) &&
+ used_key_parts == quick_key_parts))
+ continue;
+ KEY *key_info= table->key_info + keynr;
+ KEY_PART_INFO* key_part= key_info->key_part;
+ if (bitmap_is_set(used_fields, key_part->fieldnr-1))
+ continue;
+ Field *first_kp_field= table->field[key_part->fieldnr-1];
+ double quick_cond_selectivity= table->quick_rows[keynr] /
+ table_records;
+ key_part+= used_key_parts - 1;
+ double selectivity_mult= 1.0;
+ for (uint i= used_key_parts - 1; i; i--, key_part--)
+ {
+ if (!bitmap_is_set(used_fields, key_part->fieldnr-1))
+ {
+ double field_selectivity;
+ double f1= key_info->actual_rec_per_key(i-1);
+ double f2= key_info->actual_rec_per_key(i);
+ if (f1 > 0 && f2 > 0)
+ field_selectivity= f2 / f1;
+ else
+ {
+ /*
+ No statistics available, assume the field selectivity
+ is equal to 1
+ */
+ field_selectivity= 1;
+ }
+ table->cond_selectivity*=
+ table->field[i]->cond_selectivity= field_selectivity;
+ bitmap_set_bit(used_fields, table->field[i]->field_index);
+ }
+ selectivity_mult/= table->field[key_part->fieldnr-1]->cond_selectivity;
+ }
+ first_kp_field->cond_selectivity= quick_cond_selectivity *
+ selectivity_mult;
+ set_if_smaller(first_kp_field->cond_selectivity, 1.0);
+ table->cond_selectivity*= first_kp_field->cond_selectivity;
+ bitmap_set_bit(used_fields, first_kp_field->field_index);
+ }
+ }
if (quick && (quick->get_type() == QUICK_SELECT_I::QS_TYPE_ROR_UNION ||
quick->get_type() == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE))
@@ -3491,8 +3455,6 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
table->cond_selectivity*= (quick->records/table_records);
}
- bitmap_union(used_fields, &handled_columns);
-
/* Check if we can improve selectivity estimates by using sampling */
ulong check_rows=
MY_MIN(thd->variables.optimizer_selectivity_sampling_limit,
@@ -3552,13 +3514,64 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
}
}
}
-
}
/* This list and its elements put to mem_root so should not be freed */
table->cond_selectivity_sampling_explain= &dt->list;
}
}
- trace_wrapper.add("cond_selectivity", table->cond_selectivity);
+
+ /*
+ Take into account selectivity of the equalities between columns
+ of the table s and discount selectivities of range conditions
+ induced by these equalities
+ */
+
+ if (cond_equal && cond_equal->current_level.elements)
+ {
+ Item_equal *item_equal;
+ List_iterator_fast<Item_equal> it(cond_equal->current_level);
+ table_map table_bit= table->map;
+ while ((item_equal= it++))
+ {
+ if (!(item_equal->used_tables() & table_bit))
+ continue;
+ uint eq_cnt= 0;
+ double max_ndv= 0.0;
+ Item_equal_fields_iterator fi(*item_equal);
+ bool found= false;
+ while (fi++)
+ {
+ Field *fld= fi.get_curr_field();
+ if (fld->table->map != table_bit)
+ continue;
+ set_if_bigger(max_ndv, fld->ndv);
+ if (!found)
+ found= true;
+ else
+ {
+ /*
+ The field fld is equal to some other field of the table whose range
+ condition selectivity has been already taken into accout. Discount
+ selectivit of the range condition for the field fld.
+ */
+ table->cond_selectivity/= fld->cond_selectivity;
+ eq_cnt++;
+ }
+ }
+ if (eq_cnt)
+ {
+ /*
+ There are equality predicates over fields of the table s. Their
+ selectivity has to be taken into account.
+ */
+ for ( ; eq_cnt; eq_cnt--)
+ table->cond_selectivity/= max_ndv;
+ }
+ }
+ }
+
+ set_if_smaller(table->cond_selectivity,1.0);
+
DBUG_RETURN(FALSE);
}
diff --git a/sql/opt_range.h b/sql/opt_range.h
index 73def7b..d49c6a3 100644
--- a/sql/opt_range.h
+++ b/sql/opt_range.h
@@ -1729,7 +1729,8 @@ SQL_SELECT *make_select(TABLE *head, table_map const_tables,
SORT_INFO* filesort,
bool allow_null_cond, int *error);
-bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond);
+bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table,
+ COND_EQUAL *cond_equl, Item **cond);
bool eq_ranges_exceeds_limit(RANGE_SEQ_IF *seq, void *seq_init_param,
uint limit);
diff --git a/sql/opt_range_mrr.cc b/sql/opt_range_mrr.cc
index 4afa06a..75c12ef 100644
--- a/sql/opt_range_mrr.cc
+++ b/sql/opt_range_mrr.cc
@@ -340,6 +340,7 @@ bool sel_arg_range_seq_next(range_seq_t rseq, KEY_MULTI_RANGE *range)
}
seq->param->range_count++;
seq->param->max_key_parts= MY_MAX(seq->param->max_key_parts, max_key_parts);
+ seq->param->table->curr_key_tree_part= key_tree->part;
return 0;
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 896135d..e1c27cb 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -5337,6 +5337,16 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
s->table->cond_selectivity= 1.0;
+ /* Calculate expected number of distinct values for fields */
+ double table_records= (double)table->stat_records();
+ for (Field **field_ptr= s->table->field; *field_ptr; field_ptr++)
+ {
+ Field *table_field= *field_ptr;
+ if (bitmap_is_set(s->table->read_set, table_field->field_index))
+ table_field->ndv= table_records /
+ get_column_avg_frequency(table_field);
+ }
+
/*
Perform range analysis if there are keys it could use (1).
Don't do range analysis for materialized subqueries (2).
@@ -5384,7 +5394,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
if (!sargable_cond)
sargable_cond= get_sargable_cond(join, s->table);
if (join->thd->variables.optimizer_use_condition_selectivity > 1)
- calculate_cond_selectivity_for_table(join->thd, s->table,
+ calculate_cond_selectivity_for_table(join->thd, s->table, join->cond_equal,
sargable_cond);
if (s->table->reginfo.impossible_range)
{
@@ -5433,7 +5443,14 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
add_table_scan_values_to_trace(thd, s);
}
else
+ {
+ Item **sargable_cond= NULL;
+ sargable_cond= get_sargable_cond(join, s->table);
+ if (join->thd->variables.optimizer_use_condition_selectivity > 1)
+ calculate_cond_selectivity_for_table(join->thd, s->table, join->cond_equal,
+ sargable_cond);
add_table_scan_values_to_trace(thd, s);
+ }
}
}
@@ -5494,13 +5511,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
if (!(join->select_options & SELECT_DESCRIBE) &&
unit->derived && unit->derived->is_materialized_derived())
{
- /*
- Calculate estimated number of rows for materialized derived
- table/view.
- */
- for (i= 0; i < join->table_count ; i++)
- if (double rr= join->best_positions[i].records_read)
- records= COST_MULT(records, rr);
+ records= join->join_record_count;
ha_rows rows= records > HA_ROWS_MAX ? HA_ROWS_MAX : (ha_rows) records;
set_if_smaller(rows, unit->select_limit_cnt);
join->select_lex->increase_derived_records(rows);
@@ -5872,7 +5883,9 @@ add_key_field(JOIN *join,
if (is_const)
{
stat[0].const_keys.merge(possible_keys);
- bitmap_set_bit(&field->table->cond_set, field->field_index);
+ if (possible_keys.is_clear_all() &&
+ join->thd->variables.optimizer_use_condition_selectivity > 2)
+ bitmap_set_bit(&field->table->cond_set, field->field_index);
}
else if (!eq_func)
{
@@ -7109,7 +7122,7 @@ void set_position(JOIN *join,uint idx,JOIN_TAB *table,KEYUSE *key)
inline
double matching_candidates_in_table(JOIN_TAB *s, bool with_found_constraint,
- uint use_cond_selectivity)
+ uint use_cond_selectivity)
{
ha_rows records;
double dbl_records;
@@ -7117,9 +7130,14 @@ double matching_candidates_in_table(JOIN_TAB *s, bool with_found_constraint,
if (use_cond_selectivity > 1)
{
TABLE *table= s->table;
- double sel= table->cond_selectivity;
- double table_records= (double)table->stat_records();
- dbl_records= table_records * sel;
+ if (s->quick)
+ dbl_records= table->quick_condition_rows;
+ else
+ {
+ double sel= table->cond_selectivity;
+ double table_records= (double)table->stat_records();
+ dbl_records= table_records * sel;
+ }
return dbl_records;
}
@@ -8862,115 +8880,88 @@ double JOIN::get_examined_rows()
*/
static
-double table_multi_eq_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s,
- table_map rem_tables, uint keyparts,
- uint16 *ref_keyuse_steps)
-{
+double table_multi_eq_cond_selectivity(JOIN *join, JOIN_TAB *s,
+ table_map rem_tables)
+{
double sel= 1.0;
+#if 1
+#else
COND_EQUAL *cond_equal= join->cond_equal;
-
if (!cond_equal || !cond_equal->current_level.elements)
return sel;
- if (!s->keyuse)
- return sel;
-
Item_equal *item_equal;
List_iterator_fast<Item_equal> it(cond_equal->current_level);
TABLE *table= s->table;
table_map table_bit= table->map;
- POSITION *pos= &join->positions[idx];
-
+
while ((item_equal= it++))
{
- /*
- Check whether we need to take into account the selectivity of
- multiple equality item_equal. If this is the case multiply
- the current value of sel by this selectivity
- */
table_map used_tables= item_equal->used_tables();
if (!(used_tables & table_bit))
+ {
+ /* Colums of table s are not used in this item_equal */
continue;
+ }
if (item_equal->get_const())
+ {
+ /*
+ Selectivity of the equalities from item_equal have been already
+ taken into account as selectivity of range condititions
+ */
continue;
-
- bool adjust_sel= FALSE;
+ }
+
+ double max_ndv= 0.0;
+ bool used_for_ref= false;
+ uint n= 0;
Item_equal_fields_iterator fi(*item_equal);
- while((fi++) && !adjust_sel)
+ while (fi++)
{
Field *fld= fi.get_curr_field();
if (fld->table->map != table_bit)
continue;
- if (pos->key == 0)
- adjust_sel= TRUE;
+ if (bitmap_is_set(&table->tmp_set, fld->field_index))
+ used_for_ref= true;
else
{
- uint i;
- KEYUSE *keyuse= pos->key;
- uint key= keyuse->key;
- for (i= 0; i < keyparts; i++)
- {
- if (i > 0)
- keyuse+= ref_keyuse_steps[i-1];
- uint fldno;
- if (is_hash_join_key_no(key))
- fldno= keyuse->keypart;
- else
- fldno= table->key_info[key].key_part[i].fieldnr - 1;
- if (fld->field_index == fldno)
- break;
- }
- keyuse= pos->key;
-
- if (i == keyparts)
- {
- /*
- Field fld is included in multiple equality item_equal
- and is not a part of the ref key.
- The selectivity of the multiple equality must be taken
- into account unless one of the ref arguments is
- equal to fld.
- */
- adjust_sel= TRUE;
- for (uint j= 0; j < keyparts && adjust_sel; j++)
- {
- if (j > 0)
- keyuse+= ref_keyuse_steps[j-1];
- Item *ref_item= keyuse->val;
- if (ref_item->real_item()->type() == Item::FIELD_ITEM)
- {
- Item_field *field_item= (Item_field *) (ref_item->real_item());
- if (item_equal->contains(field_item->field))
- adjust_sel= FALSE;
- }
- }
- }
+ set_if_bigger(max_ndv, fld->ndv);
+ n++;
}
}
- if (adjust_sel)
+ /*
+ n == number of fields of the multiple equality belonging to s that
+ are not accessed by ref in the currently evaluated partial plan
+ */
+ if (!used_for_ref)
+ {
+ /* no field of the multiple equality belonging to s is accessed by ref */
+ n--;
+ }
+ else
{
- /*
- If ref == 0 and there are no fields in the multiple equality
- item_equal that belong to the tables joined prior to s
- then the selectivity of multiple equality will be set to 1.0.
- */
- double eq_fld_sel= 1.0;
fi.rewind();
- while ((fi++))
+ bool found= false;
+ while(fi++)
{
- double curr_eq_fld_sel;
- Field *fld= fi.get_curr_field();
- if (!(fld->table->map & ~(table_bit | rem_tables)))
+ Field *fld= fi.get_curr_field();
+ if (fld->table->map & (rem_tables | table_bit))
continue;
- curr_eq_fld_sel= get_column_avg_frequency(fld) /
- fld->table->stat_records();
- if (curr_eq_fld_sel < 1.0)
- set_if_bigger(eq_fld_sel, curr_eq_fld_sel);
+ found= true;
+ set_if_bigger(max_ndv, fld->ndv);
}
- sel*= eq_fld_sel;
+ if (!found)
+ n--;
}
- }
- return sel;
+ if (max_ndv != 0.0) // max_ndv may be 0.0 if the table is empty
+ {
+ for ( ; n; n--)
+ sel/= max_ndv;
+ }
+ }
+#endif
+
+ return sel;
}
@@ -8983,15 +8974,6 @@ double table_multi_eq_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s,
@param rem_tables The bitmap of tables to be joined later
@detail
- Get selectivity of conditions that can be applied when joining this table
- with previous tables.
-
- For quick selects and full table scans, selectivity of COND(this_table)
- is accounted for in matching_candidates_in_table(). Here, we only count
- selectivity of COND(this_table, previous_tables).
-
- For other access methods, we need to calculate selectivity of the whole
- condition, "COND(this_table) AND COND(this_table, previous_tables)".
@retval
selectivity of the conditions imposed on the rows of s
@@ -9001,105 +8983,34 @@ static
double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s,
table_map rem_tables)
{
- uint16 ref_keyuse_steps[MAX_REF_PARTS - 1];
- Field *field;
TABLE *table= s->table;
- MY_BITMAP *read_set= table->read_set;
double sel= s->table->cond_selectivity;
- POSITION *pos= &join->positions[idx];
+ double table_records= table->stat_records();
uint keyparts= 0;
uint found_part_ref_or_null= 0;
+ POSITION *pos= &join->positions[idx];
- if (pos->key != 0)
+ /* Discount the selectivity of the access method used to join table s */
+ if (s->quick && s->quick->index != MAX_KEY && pos->key == 0)
{
/*
- A ref access or hash join is used for this table. ref access is created
- from
-
- tbl.keypart1=expr1 AND tbl.keypart2=expr2 AND ...
-
- and it will only return rows for which this condition is satisified.
- Suppose, certain expr{i} is a constant. Since ref access only returns
- rows that satisfy
-
- tbl.keypart{i}=const (*)
-
- then selectivity of this equality should not be counted in return value
- of this function. This function uses the value of
-
- table->cond_selectivity=selectivity(COND(tbl)) (**)
-
- as a starting point. This value includes selectivity of equality (*). We
- should somehow discount it.
-
- Looking at calculate_cond_selectivity_for_table(), one can see that that
- the value is not necessarily a direct multiplicand in
- table->cond_selectivity
-
- There are three possible ways to discount
- 1. There is a potential range access on t.keypart{i}=const.
- (an important special case: the used ref access has a const prefix for
- which a range estimate is available)
-
- 2. The field has a histogram. field[x]->cond_selectivity has the data.
-
- 3. Use index stats on this index:
- rec_per_key[key_part+1]/rec_per_key[key_part]
-
- (TODO: more details about the "t.key=othertable.col" case)
- */
- KEYUSE *keyuse= pos->key;
- KEYUSE *prev_ref_keyuse= keyuse;
- uint key= keyuse->key;
- bool used_range_selectivity= false;
-
- /*
- Check if we have a prefix of key=const that matches a quick select.
+ A range access to the table s is used when joining s.
+ Discount the selectivity of the range from sel.
*/
- if (!is_hash_join_key_no(key))
+ if (table_records > 0)
{
- key_part_map quick_key_map= (key_part_map(1) << table->quick_key_parts[key]) - 1;
- if (table->quick_rows[key] &&
- !(quick_key_map & ~table->const_key_parts[key]))
- {
- /*
- Ok, there is an equality for each of the key parts used by the
- quick select. This means, quick select's estimate can be reused to
- discount the selectivity of a prefix of a ref access.
- */
- for (; quick_key_map & 1 ; quick_key_map>>= 1)
- {
- while (keyuse->table == table && keyuse->key == key &&
- keyuse->keypart == keyparts)
- {
- keyuse++;
- }
- keyparts++;
- }
- /*
- Here we discount selectivity of the constant range CR. To calculate
- this selectivity we use elements from the quick_rows[] array.
- If we have indexes i1,...,ik with the same prefix compatible
- with CR any of the estimate quick_rows[i1], ... quick_rows[ik] could
- be used for this calculation but here we don't know which one was
- actually used. So sel could be greater than 1 and we have to cap it.
- However if sel becomes greater than 2 then with high probability
- something went wrong.
- */
- sel /= (double)table->quick_rows[key] / (double) table->stat_records();
- // MDEV-20595 FIXME: DBUG_ASSERT(sel > 0 && sel <= 2.0);
- set_if_smaller(sel, 1.0);
- used_range_selectivity= true;
- }
+ if (sel < 1.0)
+ sel/= s->quick->records/table_records;
+ set_if_smaller(sel, 1.0);
}
-
- /*
- Go through the "keypart{N}=..." equalities and find those that were
- already taken into account in table->cond_selectivity.
- */
- keyuse= pos->key;
- keyparts=0;
- while (keyuse->table == table && keyuse->key == key)
+ }
+ else if (pos->key != 0)
+ {
+ /* A ref access or hash join is used to join table */
+ bitmap_clear_all(&table->tmp_set);
+ KEYUSE *keyuse= pos->key;
+ uint key= keyuse->key;
+ do
{
if (!(keyuse->used_tables & (rem_tables | table->map)))
{
@@ -9116,97 +9027,102 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s,
!((keyuse->val->used_tables()) & ~pos->ref_depend_map) &&
!(found_part_ref_or_null & keyuse->optimize))
{
- /* Found a KEYUSE object that will be used by ref access */
- keyparts++;
found_part_ref_or_null|= keyuse->optimize & ~KEY_OPTIMIZE_EQ;
}
+ keyparts++;
}
- if (keyparts > keyuse->keypart)
+ if (keyparts - 1 == keyuse->keypart)
{
- /* Ok this is the keyuse that will be used for ref access */
- if (!used_range_selectivity && keyuse->val->const_item())
- {
- uint fldno;
- if (is_hash_join_key_no(key))
- fldno= keyuse->keypart;
- else
- fldno= table->key_info[key].key_part[keyparts-1].fieldnr - 1;
-
- if (table->field[fldno]->cond_selectivity > 0)
- {
- sel /= table->field[fldno]->cond_selectivity;
- // MDEV-20595 FIXME: DBUG_ASSERT(sel > 0 && sel <= 2.0);
- set_if_smaller(sel, 1.0);
+ uint fldno;
+ if (is_hash_join_key_no(key))
+ fldno= keyuse->keypart;
+ else
+ fldno= table->key_info[key].key_part[keyparts-1].fieldnr - 1;
+ if (keyuse->val->const_item())
+ {
+ DBUG_ASSERT(!is_hash_join_key_no(key));
+ if (table->field[fldno]->cond_selectivity < 1.0)
+ {
+ /*
+ The value of the field fld with number fldno of the table s
+ is calculated using a constant item: fld=c.
+ We need to discount the selectivity of this conditition.
+ Unfortunately this selectivity is not equal to the precomputed
+ table->field[fldno]->cond_selectivity unless fld=c is the only
+ condition imposed on fld. So we have to calculate the
+ selectivity of fld=c somehow and discount it from sel.
+ Currently we use rec_per_key values of index with number key
+ to calculate this selectivity.
+ */
+ double discount_sel;
+ KEY *key_info= table->key_info + key;
+ uint keypart= keyuse->keypart;
+ if (keypart == 0)
+ {
+ double rec_per_key= key_info->actual_rec_per_key(0);
+ if (rec_per_key == 0)
+ rec_per_key= 1;
+ discount_sel= rec_per_key / table_records;
+ }
+ else
+ {
+ discount_sel= key_info->actual_rec_per_key(keypart) /
+ key_info->actual_rec_per_key(keypart - 1);
+ }
+ sel/= discount_sel;
}
- /*
- TODO: we could do better here:
- 1. cond_selectivity might be =1 (the default) because quick
- select on some index prevented us from analyzing
- histogram for this column.
- 2. we could get an estimate through this?
- rec_per_key[key_part-1] / rec_per_key[key_part]
- */
}
- if (keyparts > 1)
+ else if (keyuse->val->real_item()->type() == Item::FIELD_ITEM)
{
- ref_keyuse_steps[keyparts-2]= (uint16)(keyuse - prev_ref_keyuse);
- prev_ref_keyuse= keyuse;
+ Field *start_field= table->field[fldno];
+ bitmap_set_bit(&table->tmp_set, fldno);
+ if (start_field->next_equal_field)
+ {
+ Field *next_field;
+ bool need_discount= false;
+ Field *value_field=
+ ((Item_field *) (keyuse->val->real_item()))->field;
+ for (next_field= start_field->next_equal_field;
+ next_field != start_field;
+ next_field= next_field->next_equal_field)
+ {
+ if (next_field == value_field)
+ {
+ need_discount= true;
+ break;
+ }
+ }
+ /*
+ To join the table s ref access is used that employs
+ the equality
+ */
+ if (need_discount)
+ {
+ next_field= start_field;
+ do
+ {
+ if (next_field->table == start_field->table)
+ sel/= next_field->cond_selectivity;
+ next_field= next_field->next_equal_field;
+ } while (next_field != start_field);
+ }
+ }
}
}
}
}
keyuse++;
- }
+ } while (keyuse->table == table && keyuse->key == key);
}
- else
+ else
{
- /*
- The table is accessed with full table scan, or quick select.
- Selectivity of COND(table) is already accounted for in
- matching_candidates_in_table().
- */
sel= 1;
}
- /*
- If the field f from the table is equal to a field from one the
- earlier joined tables then the selectivity of the range conditions
- over the field f must be discounted.
-
- We need to discount selectivity only if we're using ref-based
- access method (and have sel!=1).
- If we use ALL/range/index_merge, then sel==1, and no need to discount.
- */
- if (pos->key != NULL)
- {
- for (Field **f_ptr=table->field ; (field= *f_ptr) ; f_ptr++)
- {
- if (!bitmap_is_set(read_set, field->field_index) ||
- !field->next_equal_field)
- continue;
- for (Field *next_field= field->next_equal_field;
- next_field != field;
- next_field= next_field->next_equal_field)
- {
- if (!(next_field->table->map & rem_tables) && next_field->table != table)
- {
- if (field->cond_selectivity > 0)
- {
- sel/= field->cond_selectivity;
- // MDEV-20595 FIXME: DBUG_ASSERT(sel > 0 && sel <= 2.0);
- set_if_smaller(sel, 1.0);
- }
- break;
- }
- }
- }
- }
-
- sel*= table_multi_eq_cond_selectivity(join, idx, s, rem_tables,
- keyparts, ref_keyuse_steps);
+ sel*= table_multi_eq_cond_selectivity(join, s, rem_tables);
- DBUG_ASSERT(0.0 < sel && sel <= 1.0);
+ DBUG_ASSERT(0.0 < sel && sel <= 1.0 + DBL_EPSILON);
return sel;
}
diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc
index a94fb11..ebf5d2d 100644
--- a/sql/sql_statistics.cc
+++ b/sql/sql_statistics.cc
@@ -3824,7 +3824,7 @@ double get_column_avg_frequency(Field * field)
Column_statistics *col_stats= field->read_stats;
- if (!col_stats)
+ if (!col_stats || col_stats->get_avg_frequency() == 0.0)
res= (double)table->stat_records();
else
res= col_stats->get_avg_frequency();
diff --git a/sql/structs.h b/sql/structs.h
index 0c00aee..6064b66 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -72,6 +72,7 @@ typedef struct st_key_part_info { /* Info about a key part */
NOT necessarily the original Field */
uint offset; /* Offset in record (from 0) */
uint null_offset; /* Offset to null_bit in record */
+ uint quick_cnt;
/* Length of key part in bytes, excluding NULL flag and length bytes */
uint16 length;
/*
diff --git a/sql/table.h b/sql/table.h
index 8297774..a7f48f9 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -1244,6 +1244,7 @@ struct TABLE
*/
ha_rows quick_rows[MAX_KEY];
uint quick_key_parts[MAX_KEY];
+ uint16 curr_quick_cnt;
double quick_costs[MAX_KEY];
/*
1
0
[Commits] 85145b9: MDEV-28846 Poor performance when rowid filter contains no elements
by IgorBabaev 24 Jun '22
by IgorBabaev 24 Jun '22
24 Jun '22
revision-id: 85145b9e605057f5053f9dd929468e25e9f823e5 (mariadb-10.4.23-83-g85145b9)
parent(s): 6e7c6fcfd1f1ac131c423c1ba084d61abad10e8b
author: Igor Babaev
committer: Igor Babaev
timestamp: 2022-06-23 23:53:19 -0700
message:
MDEV-28846 Poor performance when rowid filter contains no elements
This is a preliminary patch, no test cases are added.
---
sql/rowid_filter.cc | 6 ++++--
sql/rowid_filter.h | 10 +++++++++-
sql/sql_analyze_stmt.h | 12 ++++++++++--
sql/sql_select.cc | 2 ++
4 files changed, 25 insertions(+), 5 deletions(-)
diff --git a/sql/rowid_filter.cc b/sql/rowid_filter.cc
index 75f2ab7..bc72259 100644
--- a/sql/rowid_filter.cc
+++ b/sql/rowid_filter.cc
@@ -575,9 +575,10 @@ bool Range_rowid_filter::fill()
if (quick->init() || quick->reset())
rc= 1;
- while (!rc)
+ for ( ; ; )
{
- rc= quick->get_next();
+ if ((rc= quick->get_next()))
+ break;
if (thd->killed)
rc= 1;
if (!rc)
@@ -598,6 +599,7 @@ bool Range_rowid_filter::fill()
file->pushed_idx_cond_keyno= pushed_idx_cond_keyno_save;
file->in_range_check_pushed_down= in_range_check_pushed_down_save;
tracker->report_container_buff_size(table->file->ref_length);
+ tracker->report_time_fill_container_ms();
if (rc != HA_ERR_END_OF_FILE)
return 1;
diff --git a/sql/rowid_filter.h b/sql/rowid_filter.h
index 467b688..c02d128 100644
--- a/sql/rowid_filter.h
+++ b/sql/rowid_filter.h
@@ -192,6 +192,8 @@ class Rowid_filter_container : public Sql_alloc
*/
virtual bool check(void *ctxt, char *elem) = 0;
+ virtual bool is_empty() = 0;
+
virtual ~Rowid_filter_container() {}
};
@@ -231,6 +233,8 @@ class Rowid_filter : public Sql_alloc
virtual ~Rowid_filter() {}
+ bool is_empty() { return container->is_empty(); }
+
Rowid_filter_container *get_container() { return container; }
void set_tracker(Rowid_filter_tracker *track_arg) { tracker= track_arg; }
@@ -300,7 +304,7 @@ class Refpos_container_sorted_array : public Sql_alloc
public:
- Refpos_container_sorted_array(uint max_elems, uint elem_sz)
+ Refpos_container_sorted_array(uint max_elems, uint elem_sz)
: max_elements(max_elems), elem_size(elem_sz), array(0) {}
~Refpos_container_sorted_array()
@@ -339,6 +343,8 @@ class Refpos_container_sorted_array : public Sql_alloc
my_qsort2(array->front(), array->elements()/elem_size,
elem_size, (qsort2_cmp) cmp, cmp_arg);
}
+
+ bool is_empty() { return elements() == 0; }
};
@@ -368,6 +374,8 @@ class Rowid_filter_sorted_array: public Rowid_filter_container
bool add(void *ctxt, char *elem) { return refpos_container.add(elem); }
bool check(void *ctxt, char *elem);
+
+ bool is_empty() { return refpos_container.is_empty(); }
};
/**
diff --git a/sql/sql_analyze_stmt.h b/sql/sql_analyze_stmt.h
index eec5282..17ebb9c 100644
--- a/sql/sql_analyze_stmt.h
+++ b/sql/sql_analyze_stmt.h
@@ -306,6 +306,9 @@ class Rowid_filter_tracker : public Sql_alloc
/* Size of the rowid filter container buffer */
size_t container_buff_size;
+ /* Time spent to fill the rowid filter container */
+ double time_fill_container_ms;
+
/* Count of elements that were used to fill the rowid filter container */
uint container_elements;
@@ -314,7 +317,7 @@ class Rowid_filter_tracker : public Sql_alloc
uint n_positive_checks;
public:
Rowid_filter_tracker(bool do_timing) :
- time_tracker(do_timing), container_buff_size(0),
+ time_tracker(do_timing), container_buff_size(0), time_fill_container_ms(0),
container_elements(0), n_checks(0), n_positive_checks(0)
{}
@@ -339,9 +342,14 @@ class Rowid_filter_tracker : public Sql_alloc
return &time_tracker;
}
+ void report_time_fill_container_ms()
+ {
+ time_fill_container_ms= time_tracker.get_time_ms();
+ }
+
double get_time_fill_container_ms()
{
- return time_tracker.get_time_ms();
+ return time_fill_container_ms;
}
void increment_checked_elements_count(bool was_checked)
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 735e00d..7c2f081 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -20599,6 +20599,8 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
DBUG_RETURN(NESTED_LOOP_ERROR);
join_tab->build_range_rowid_filter_if_needed();
+ if (join_tab->rowid_filter && join_tab->rowid_filter->is_empty())
+ rc= NESTED_LOOP_NO_MORE_ROWS;
join->return_tab= join_tab;
1
0
[Commits] 2adebf4: MDEV-7487 Semi-join optimization for single-table update/delete statements
by IgorBabaev 21 Jun '22
by IgorBabaev 21 Jun '22
21 Jun '22
revision-id: 2adebf4876283859066c11f23e89965733594363 (mariadb-10.6.1-480-g2adebf4)
parent(s): f7d2374083184261897e86bced158d9ae2c4aaaf
author: Igor Babaev
committer: Igor Babaev
timestamp: 2022-06-20 16:43:44 -0700
message:
MDEV-7487 Semi-join optimization for single-table update/delete statements
This patch allows to use semi-join optimization at the top level of
single-table update and delete statements.
The problem of supporting such optimization became easy to resolve after
processing a single-table update/delete statement started using JOIN
structure. This allowed to use JOIN::prepare() not only for multi-table
updates/deletes but for single-table ones as well. This was done in the
patch for mdev-28883:
Re-design the upper level of handling UPDATE and DELETE statements.
Note that JOIN::prepare() detects all subqueries that can be considered
as candidates for semi-join optimization. The code added by this patch
looks for such candidates at the top level and if such candidates are found
in the processed single-table update/delete the statement is handled in
the same way as a multi-table update/delete.
Approved by Oleksandr Byelkin <sanja(a)mariadb.com>
---
mysql-test/main/delete_single_to_multi.result | 2355 ++++++++++++++++++++
mysql-test/main/delete_single_to_multi.test | 797 +++++++
mysql-test/main/log_state.result | 2 +-
.../main/myisam_explain_non_select_all.result | 45 +-
mysql-test/main/opt_trace.result | 20 +
mysql-test/main/update_single_to_multi.result | 2302 +++++++++++++++++++
mysql-test/main/update_single_to_multi.test | 549 +++++
sql/opt_subselect.cc | 63 +-
sql/sql_class.h | 1 +
sql/sql_delete.cc | 11 +-
sql/sql_lex.h | 2 +
sql/sql_select.cc | 3 +-
sql/sql_update.cc | 11 +-
sql/sql_yacc.yy | 13 +
14 files changed, 6140 insertions(+), 34 deletions(-)
diff --git a/mysql-test/main/delete_single_to_multi.result b/mysql-test/main/delete_single_to_multi.result
new file mode 100644
index 0000000..c6da861
--- /dev/null
+++ b/mysql-test/main/delete_single_to_multi.result
@@ -0,0 +1,2355 @@
+DROP DATABASE IF EXISTS dbt3_s001;
+CREATE DATABASE dbt3_s001;
+use dbt3_s001;
+create index i_n_name on nation(n_name);
+analyze table nation;
+Table Op Msg_type Msg_text
+dbt3_s001.nation analyze status Engine-independent statistics collected
+dbt3_s001.nation analyze status OK
+# Pullout
+# =======
+explain
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (7%) Using where; Using rowid filter
+explain format=json
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_n_name"],
+ "key": "i_n_name",
+ "key_length": "26",
+ "used_key_parts": ["n_name"],
+ "ref": ["const"],
+ "rows": 1,
+ "filtered": 100,
+ "index_condition": "nation.n_name = 'PERU'"
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "key": "i_c_nationkey",
+ "key_length": "5",
+ "used_key_parts": ["c_nationkey"],
+ "ref": ["dbt3_s001.nation.n_nationkey"],
+ "rows": 11,
+ "filtered": 100
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 108,
+ "selectivity_pct": 7.2
+ },
+ "rows": 11,
+ "filtered": 7.199999809,
+ "attached_condition": "orders.o_orderDATE between '1992-01-01' and '1992-06-30'"
+ }
+ }
+ ]
+ }
+}
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+5382 138423.03
+644 201268.06
+737 12984.85
+create table t as
+select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+explain
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (7%) Using where; Using rowid filter
+explain format=json
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_n_name"],
+ "key": "i_n_name",
+ "key_length": "26",
+ "used_key_parts": ["n_name"],
+ "ref": ["const"],
+ "rows": 1,
+ "filtered": 100,
+ "index_condition": "nation.n_name = 'PERU'"
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "key": "i_c_nationkey",
+ "key_length": "5",
+ "used_key_parts": ["c_nationkey"],
+ "ref": ["dbt3_s001.nation.n_nationkey"],
+ "rows": 11,
+ "filtered": 100
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 108,
+ "selectivity_pct": 7.2
+ },
+ "rows": 11,
+ "filtered": 7.199999809,
+ "attached_condition": "orders.o_orderDATE between '1992-01-01' and '1992-06-30'"
+ }
+ }
+ ]
+ }
+}
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+insert into orders select * from t;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+5382 138423.03
+644 201268.06
+737 12984.85
+drop table t;
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+1 8 357.84
+3 8 645.4
+4 1 444.37
+5 8 50.52
+6 1 642.13
+7 8 763.98
+8 1 957.34
+create table t as
+select * from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+explain
+delete from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+delete from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+insert into partsupp select * from t;
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+1 8 357.84
+3 8 645.4
+4 1 444.37
+5 8 50.52
+6 1 642.13
+7 8 763.98
+8 1 957.34
+drop table t;
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+1 8 357.84
+3 8 645.4
+4 1 444.37
+5 8 50.52
+6 1 642.13
+7 8 763.98
+8 1 957.34
+create table t as
+select * from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+explain
+delete from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+delete from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+insert into partsupp select * from t;
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+1 8 357.84
+3 8 645.4
+4 1 444.37
+5 8 50.52
+6 1 642.13
+7 8 763.98
+8 1 957.34
+drop table t;
+explain
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY lineitem ref PRIMARY,i_l_suppkey_partkey,i_l_partkey,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity i_l_suppkey 5 dbt3_s001.supplier.s_suppkey 100 Using where
+1 PRIMARY orders eq_ref|filter PRIMARY,i_o_orderdate,i_o_custkey PRIMARY|i_o_orderdate 4|4 dbt3_s001.lineitem.l_orderkey 1 (7%) Using where; Using rowid filter
+1 PRIMARY customer eq_ref PRIMARY,i_c_nationkey PRIMARY 4 dbt3_s001.orders.o_custkey 1 Using where
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.lineitem.l_partkey 1 Using where
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+l_orderkey l_linenumber l_tax
+2500 2 0.02
+2500 4 0.02
+4996 1 0.01
+933 1 0.04
+create table t as
+select * from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+explain
+delete from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY lineitem ref PRIMARY,i_l_suppkey_partkey,i_l_partkey,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity i_l_suppkey 5 dbt3_s001.supplier.s_suppkey 100 Using where
+1 PRIMARY orders eq_ref|filter PRIMARY,i_o_orderdate,i_o_custkey PRIMARY|i_o_orderdate 4|4 dbt3_s001.lineitem.l_orderkey 1 (7%) Using where; Using rowid filter
+1 PRIMARY customer eq_ref PRIMARY,i_c_nationkey PRIMARY 4 dbt3_s001.orders.o_custkey 1 Using where
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.lineitem.l_partkey 1 Using where
+delete from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+l_orderkey l_linenumber l_tax
+insert into lineitem select * from t;
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+l_orderkey l_linenumber l_tax
+2500 2 0.02
+2500 4 0.02
+4996 1 0.01
+933 1 0.04
+drop table t;
+# FirstMatch
+# ==========
+explain
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY,i_c_nationkey NULL NULL NULL 150 Using where
+1 PRIMARY nation eq_ref|filter PRIMARY,i_n_regionkey PRIMARY|i_n_regionkey 4|5 dbt3_s001.customer.c_nationkey 1 (40%) Using where; Using rowid filter
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (6%) Using where; FirstMatch(nation); Using rowid filter
+explain format=json
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ALL",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "rows": 150,
+ "filtered": 100,
+ "attached_condition": "customer.c_nationkey is not null"
+ }
+ },
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY", "i_n_regionkey"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["n_nationkey"],
+ "ref": ["dbt3_s001.customer.c_nationkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_n_regionkey",
+ "used_key_parts": ["n_regionkey"]
+ },
+ "rows": 10,
+ "selectivity_pct": 40
+ },
+ "rows": 1,
+ "filtered": 40,
+ "attached_condition": "nation.n_regionkey in (1,2)"
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 89,
+ "selectivity_pct": 5.933333333
+ },
+ "rows": 11,
+ "filtered": 5.933333397,
+ "attached_condition": "orders.o_orderDATE between '1992-10-09' and '1993-03-08'",
+ "first_match": "nation"
+ }
+ }
+ ]
+ }
+}
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+create table t as
+select * from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+explain
+delete from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY,i_c_nationkey NULL NULL NULL 150 Using where
+1 PRIMARY nation eq_ref|filter PRIMARY,i_n_regionkey PRIMARY|i_n_regionkey 4|5 dbt3_s001.customer.c_nationkey 1 (40%) Using where; Using rowid filter
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (6%) Using where; FirstMatch(nation); Using rowid filter
+explain format=json
+delete from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ALL",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "rows": 150,
+ "filtered": 100,
+ "attached_condition": "customer.c_nationkey is not null"
+ }
+ },
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY", "i_n_regionkey"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["n_nationkey"],
+ "ref": ["dbt3_s001.customer.c_nationkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_n_regionkey",
+ "used_key_parts": ["n_regionkey"]
+ },
+ "rows": 10,
+ "selectivity_pct": 40
+ },
+ "rows": 1,
+ "filtered": 40,
+ "attached_condition": "nation.n_regionkey in (1,2)"
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 89,
+ "selectivity_pct": 5.933333333
+ },
+ "rows": 11,
+ "filtered": 5.933333397,
+ "attached_condition": "orders.o_orderDATE between '1992-10-09' and '1993-03-08'",
+ "first_match": "nation"
+ }
+ }
+ ]
+ }
+}
+delete from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+drop table t;
+explain
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (14%) Using where; FirstMatch(customer); Using rowid filter
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+c_name c_acctbal
+Customer#000000008 6819.74
+Customer#000000035 1228.24
+Customer#000000061 1536.24
+Customer#000000097 2164.48
+Customer#000000121 6428.32
+Customer#000000133 2314.67
+create table t as
+select * from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+explain
+delete from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (14%) Using where; FirstMatch(customer); Using rowid filter
+delete from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+c_name c_acctbal
+Customer#000000008 6819.74
+Customer#000000035 1228.24
+Customer#000000061 1536.24
+Customer#000000097 2164.48
+Customer#000000121 6428.32
+Customer#000000133 2314.67
+drop table t;
+# Materialization
+# ===============
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 dbt3_s001.orders.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 28 Using index condition; Using where
+explain format=json
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'",
+ "attached_condition": "orders.o_custkey is not null"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["dbt3_s001.orders.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000005 794.47
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000035 1228.24
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000040 1335.3
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000098 -551.37
+Customer#000000109 -716.1
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000136 -842.39
+Customer#000000140 9963.15
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+explain
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 dbt3_s001.orders.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 28 Using index condition; Using where
+explain format=json
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'",
+ "attached_condition": "orders.o_custkey is not null"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["dbt3_s001.orders.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000005 794.47
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000035 1228.24
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000040 1335.3
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000098 -551.37
+Customer#000000109 -716.1
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000136 -842.39
+Customer#000000140 9963.15
+drop table t;
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 114 Using index condition; Using where
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+c_name c_acctbal
+Customer#000000001 711.56
+Customer#000000002 121.65
+Customer#000000007 9561.95
+Customer#000000008 6819.74
+Customer#000000010 2753.54
+Customer#000000011 -272.6
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000029 7618.27
+Customer#000000031 5236.89
+Customer#000000034 8589.7
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000043 9904.28
+Customer#000000044 7315.94
+Customer#000000046 5744.59
+Customer#000000047 274.58
+Customer#000000049 4573.94
+Customer#000000053 4113.64
+Customer#000000055 4572.11
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000070 4867.52
+Customer#000000071 -611.19
+Customer#000000073 4288.5
+Customer#000000074 2764.43
+Customer#000000076 5745.33
+Customer#000000079 5121.28
+Customer#000000080 7383.53
+Customer#000000082 9468.34
+Customer#000000083 6463.51
+Customer#000000085 3386.64
+Customer#000000086 3306.32
+Customer#000000088 8031.44
+Customer#000000091 4643.14
+Customer#000000092 1182.91
+Customer#000000095 5327.38
+Customer#000000097 2164.48
+Customer#000000100 9889.89
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000104 -588.38
+Customer#000000106 3288.42
+Customer#000000109 -716.1
+Customer#000000110 7462.99
+Customer#000000112 2953.35
+Customer#000000118 3582.37
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000131 8595.53
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+Customer#000000136 -842.39
+Customer#000000137 7838.3
+Customer#000000139 7897.78
+Customer#000000142 2209.81
+Customer#000000143 2186.5
+Customer#000000148 2135.6
+Customer#000000149 8959.65
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+explain
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 114 Using index condition; Using where
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+c_name c_acctbal
+Customer#000000001 711.56
+Customer#000000002 121.65
+Customer#000000007 9561.95
+Customer#000000008 6819.74
+Customer#000000010 2753.54
+Customer#000000011 -272.6
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000029 7618.27
+Customer#000000031 5236.89
+Customer#000000034 8589.7
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000043 9904.28
+Customer#000000044 7315.94
+Customer#000000046 5744.59
+Customer#000000047 274.58
+Customer#000000049 4573.94
+Customer#000000053 4113.64
+Customer#000000055 4572.11
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000070 4867.52
+Customer#000000071 -611.19
+Customer#000000073 4288.5
+Customer#000000074 2764.43
+Customer#000000076 5745.33
+Customer#000000079 5121.28
+Customer#000000080 7383.53
+Customer#000000082 9468.34
+Customer#000000083 6463.51
+Customer#000000085 3386.64
+Customer#000000086 3306.32
+Customer#000000088 8031.44
+Customer#000000091 4643.14
+Customer#000000092 1182.91
+Customer#000000095 5327.38
+Customer#000000097 2164.48
+Customer#000000100 9889.89
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000104 -588.38
+Customer#000000106 3288.42
+Customer#000000109 -716.1
+Customer#000000110 7462.99
+Customer#000000112 2953.35
+Customer#000000118 3582.37
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000131 8595.53
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+Customer#000000136 -842.39
+Customer#000000137 7838.3
+Customer#000000139 7897.78
+Customer#000000142 2209.81
+Customer#000000143 2186.5
+Customer#000000148 2135.6
+Customer#000000149 8959.65
+drop table t;
+# Materialization SJM
+# ===================
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 <subquery2>.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 28 Using index condition; Using temporary
+explain format=json
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "having_condition": "count(orders.o_custkey) > 1",
+ "temporary_table": {
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'"
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["<subquery2>.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+explain
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 <subquery2>.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 28 Using index condition; Using temporary
+explain format=json
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "having_condition": "count(orders.o_custkey) > 1",
+ "temporary_table": {
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'"
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["<subquery2>.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+drop table t;
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 dbt3_s001.customer.c_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 242 Using index condition; Using temporary
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000016 4681.03
+Customer#000000037 -917.75
+Customer#000000046 5744.59
+Customer#000000091 4643.14
+Customer#000000103 2757.45
+Customer#000000118 3582.37
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+explain
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 dbt3_s001.customer.c_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 242 Using index condition; Using temporary
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000016 4681.03
+Customer#000000037 -917.75
+Customer#000000046 5744.59
+Customer#000000091 4643.14
+Customer#000000103 2757.45
+Customer#000000118 3582.37
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+drop table t;
+# Pullout PS
+# ==========
+prepare stmt from "
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+";
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+5382 138423.03
+644 201268.06
+737 12984.85
+create table t as
+select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+execute stmt;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+insert into orders select * from t;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+5382 138423.03
+644 201268.06
+737 12984.85
+create table r as
+select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+execute stmt;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+insert into orders select * from r;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+5382 138423.03
+644 201268.06
+737 12984.85
+drop table t,r;
+deallocate prepare stmt;
+# FirstMatch PS
+# =============
+prepare stmt from "
+delete from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+";
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+create table t as
+select * from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+execute stmt;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+create table r as
+select * from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+execute stmt;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+insert into customer select * from r;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+drop table t,r;
+deallocate prepare stmt;
+# Materialization PS
+# ==================
+prepare stmt from "
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08') and c_name like ?;
+";
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000005 794.47
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000035 1228.24
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000040 1335.3
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000098 -551.37
+Customer#000000109 -716.1
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000136 -842.39
+Customer#000000140 9963.15
+set @a1='Customer#%1_';
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08') and c_name like @a1;
+execute stmt using @a1;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000005 794.47
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000035 1228.24
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000040 1335.3
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000098 -551.37
+Customer#000000109 -716.1
+Customer#000000136 -842.39
+Customer#000000140 9963.15
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000005 794.47
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000035 1228.24
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000040 1335.3
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000098 -551.37
+Customer#000000109 -716.1
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000136 -842.39
+Customer#000000140 9963.15
+set @a2='Customer#%3_';
+create table r as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08') and c_name like @a2;
+execute stmt using @a2;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000005 794.47
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000040 1335.3
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000098 -551.37
+Customer#000000109 -716.1
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000140 9963.15
+insert into customer select * from r;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000005 794.47
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000035 1228.24
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000040 1335.3
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000098 -551.37
+Customer#000000109 -716.1
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000136 -842.39
+Customer#000000140 9963.15
+drop table t,r;
+deallocate prepare stmt;
+# Materialization SJM PS
+# ======================
+prepare stmt from "
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08') and c_acctbal between ? and ?;
+";
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+set @a1=3500;
+set @a2=4000;
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1) and c_acctbal between @a1 and @a2;
+execute stmt using @a1, @a2;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+set @a3=-1000;
+set @a4=3500;
+create table r as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1) and c_acctbal between @a3 and @a4;
+execute stmt using @a3, @a4;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+insert into customer select * from r;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+drop table t,r;
+deallocate prepare stmt;
+# Pullout SP
+# ==========
+create procedure p(a1 int, a2 int)
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU')) and o_totalprice between a1 and a2;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+644 201268.06
+737 12984.85
+create table t as
+select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU')) and o_totalprice between 150000 and 200000;
+call p(150000, 200000);
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+644 201268.06
+737 12984.85
+insert into orders select * from t;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+644 201268.06
+737 12984.85
+create table r as
+select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU')) and o_totalprice between 180000 and 210000;
+call p(180000, 210000);
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5121 150334.57
+737 12984.85
+insert into orders select * from r;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+644 201268.06
+737 12984.85
+drop table t,r;
+drop procedure p;
+# FirstMatch SP
+# =============
+create procedure p(a int)
+delete from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08') and c_acctbal > a;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+create table t as
+select * from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08') and c_acctbal > 4000;
+call p(4000);
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000097 2164.48
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000133 2314.67
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+create table r as
+select * from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08') and c_acctbal > 2000;
+call p(2000);
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000047 274.58
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+insert into customer select * from r;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+drop table t,r;
+drop procedure p;
+# Materialization SP
+# ==================
+create procedure p()
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000140 9963.15
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+call p();
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000140 9963.15
+create table r as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+call p();
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+insert into customer select * from r;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000140 9963.15
+drop table t,r;
+drop procedure p;
+# Materialization SJM SP
+# ======================
+create procedure p()
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+call p();
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+create table r as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+call p();
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+insert into customer select * from r;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+drop table t,r;
+drop procedure p;
+# Checking limitations
+# ====================
+# Check for DELETE ... RETURNING with SJ subquery in WHERE
+select c_name from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name
+Customer#000000013
+Customer#000000016
+Customer#000000025
+Customer#000000032
+Customer#000000037
+Customer#000000038
+Customer#000000052
+Customer#000000056
+Customer#000000065
+Customer#000000076
+Customer#000000091
+Customer#000000115
+Customer#000000116
+Customer#000000118
+Customer#000000140
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+explain
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08') returning c_name;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL NULL NULL NULL NULL 141 Using where
+2 DEPENDENT SUBQUERY orders index_subquery|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 func 175 (2%) Using where; Using rowid filter
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08') returning c_name;
+c_name
+Customer#000000013
+Customer#000000016
+Customer#000000025
+Customer#000000032
+Customer#000000037
+Customer#000000038
+Customer#000000052
+Customer#000000056
+Customer#000000065
+Customer#000000076
+Customer#000000091
+Customer#000000115
+Customer#000000116
+Customer#000000118
+Customer#000000140
+select c_name from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name
+insert into customer select * from t;
+select c_name from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name
+Customer#000000013
+Customer#000000016
+Customer#000000025
+Customer#000000032
+Customer#000000037
+Customer#000000038
+Customer#000000052
+Customer#000000056
+Customer#000000065
+Customer#000000076
+Customer#000000091
+Customer#000000115
+Customer#000000116
+Customer#000000118
+Customer#000000140
+drop table t;
+select c_name from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name
+Customer#000000013
+Customer#000000032
+Customer#000000037
+Customer#000000056
+Customer#000000118
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+explain
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1) returning c_name;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL NULL NULL NULL NULL 141 Using where
+2 DEPENDENT SUBQUERY orders range i_o_orderdate i_o_orderdate 4 NULL 28 Using index condition; Using temporary
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1) returning c_name;
+c_name
+Customer#000000013
+Customer#000000032
+Customer#000000037
+Customer#000000056
+Customer#000000118
+select c_name from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name
+insert into customer select * from t;
+select c_name from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name
+Customer#000000013
+Customer#000000032
+Customer#000000037
+Customer#000000056
+Customer#000000118
+drop table t;
+# Check for DELETE ... RETURNING with SJ subquery in WHERE
+select c_name from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name
+Customer#000000013
+Customer#000000016
+Customer#000000025
+Customer#000000032
+Customer#000000037
+Customer#000000038
+Customer#000000052
+Customer#000000056
+Customer#000000065
+Customer#000000076
+Customer#000000091
+Customer#000000115
+Customer#000000116
+Customer#000000118
+Customer#000000140
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+explain
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08') returning c_name;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL NULL NULL NULL NULL 141 Using where
+2 DEPENDENT SUBQUERY orders index_subquery|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 func 175 (2%) Using where; Using rowid filter
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08') returning c_name;
+c_name
+Customer#000000013
+Customer#000000016
+Customer#000000025
+Customer#000000032
+Customer#000000037
+Customer#000000038
+Customer#000000052
+Customer#000000056
+Customer#000000065
+Customer#000000076
+Customer#000000091
+Customer#000000115
+Customer#000000116
+Customer#000000118
+Customer#000000140
+select c_name from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name
+insert into customer select * from t;
+drop table t;
+# Check for DELETE ... ORDER BY ...LIMIT with SJ subquery in WHERE
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+o_orderkey o_totalprice
+1221 117397.16
+1856 189361.42
+324 26868.85
+4903 34363.63
+5607 24660.06
+# Should not use semi-join conversion because has ORDER BY ... LIMIT
+explain
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2))
+order by o_totalprice limit 500;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY orders range i_o_orderdate i_o_orderdate 4 NULL 108 Using where; Using filesort
+2 DEPENDENT SUBQUERY customer unique_subquery|filter PRIMARY,i_c_nationkey PRIMARY|i_c_nationkey 4|5 func 1 (10%) Using where; Using rowid filter
+create table t as
+select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+select o_orderkey, o_totalprice from t;
+o_orderkey o_totalprice
+1221 117397.16
+324 26868.85
+1856 189361.42
+4903 34363.63
+5607 24660.06
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2))
+order by o_totalprice limit 500;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+o_orderkey o_totalprice
+insert into orders select * from t;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+o_orderkey o_totalprice
+1221 117397.16
+1856 189361.42
+324 26868.85
+4903 34363.63
+5607 24660.06
+drop table t;
+# Should use semi-join converion
+explain
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer range PRIMARY,i_c_nationkey i_c_nationkey 5 NULL 14 Using index condition
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 12 (7%) Using where; Using rowid filter
+create table t as
+select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+select o_orderkey, o_totalprice from t;
+o_orderkey o_totalprice
+1221 117397.16
+324 26868.85
+1856 189361.42
+4903 34363.63
+5607 24660.06
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+o_orderkey o_totalprice
+insert into orders select * from t;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+o_orderkey o_totalprice
+1221 117397.16
+1856 189361.42
+324 26868.85
+4903 34363.63
+5607 24660.06
+drop table t;
+DROP DATABASE dbt3_s001;
diff --git a/mysql-test/main/delete_single_to_multi.test b/mysql-test/main/delete_single_to_multi.test
new file mode 100644
index 0000000..7d4811f
--- /dev/null
+++ b/mysql-test/main/delete_single_to_multi.test
@@ -0,0 +1,797 @@
+--disable_warnings
+DROP DATABASE IF EXISTS dbt3_s001;
+--enable_warnings
+
+CREATE DATABASE dbt3_s001;
+
+use dbt3_s001;
+
+--disable_query_log
+--disable_result_log
+--disable_warnings
+--source include/dbt3_s001.inc
+--enable_warnings
+--enable_result_log
+--enable_query_log
+
+create index i_n_name on nation(n_name);
+analyze table nation;
+
+
+--echo # Pullout
+--echo # =======
+
+let $c1=
+ o_orderDATE between '1992-01-01' and '1992-06-30' and
+ o_custkey in (select c_custkey from customer
+ where c_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+
+eval
+explain
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+explain format=json
+select o_orderkey, o_totalprice from orders where $c1;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+create table t as
+select * from orders where $c1;
+
+eval
+explain
+delete from orders where $c1;
+eval
+explain format=json
+delete from orders where $c1;
+eval
+delete from orders where $c1;
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+
+
+insert into orders select * from t;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+drop table t;
+
+
+let $c2=
+ (ps_partkey, ps_suppkey) in
+ (select p_partkey, s_suppkey from part, supplier
+ where p_retailprice between 901 and 910 and
+ s_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+
+eval
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+--sorted_result
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+eval
+create table t as
+select * from partsupp where $c2;
+
+eval
+explain
+delete from partsupp where $c2;
+eval
+delete from partsupp where $c2;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+
+insert into partsupp select * from t;
+--sorted_result
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+drop table t;
+
+
+let $c3=
+ ps_partkey in (select p_partkey from part
+ where p_retailprice between 901 and 910) and
+ ps_suppkey in (select s_suppkey from supplier
+ where s_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+eval
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+--sorted_result
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+eval
+create table t as
+select * from partsupp where $c3;
+
+eval
+explain
+delete from partsupp where $c3;
+eval
+delete from partsupp where $c3;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+
+insert into partsupp select * from t;
+--sorted_result
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+drop table t;
+
+
+let $c4=
+ l_orderkey in (select o_orderkey from orders
+ where o_custkey in
+ (select c_custkey from customer
+ where c_nationkey in
+ (select n_nationkey from nation
+ where n_name='PERU'))
+ and
+ o_orderDATE between '1992-06-30' and '1992-12-31')
+ and
+ (l_partkey, l_suppkey) in
+ (select p_partkey, s_suppkey from part, supplier
+ where p_retailprice between 901 and 1000 and
+ s_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+
+eval
+explain
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+--sorted_result
+eval
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+eval
+create table t as
+select * from lineitem where $c4;
+
+eval
+explain
+delete from lineitem where $c4;
+eval
+delete from lineitem where $c4;
+eval
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+
+insert into lineitem select * from t;
+--sorted_result
+eval
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+drop table t;
+
+
+--echo # FirstMatch
+--echo # ==========
+
+let $c5=
+ c_nationkey in (select n_nationkey from nation
+ where n_regionkey in (1,2))
+ and
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-10-09' and '1993-03-08');
+
+eval
+explain
+select c_name, c_acctbal from customer where $c5;
+eval
+explain format=json
+select c_name, c_acctbal from customer where $c5;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+eval
+create table t as
+select * from customer where $c5;
+
+eval
+explain
+delete from customer where $c5;
+eval
+explain format=json
+delete from customer where $c5;
+eval
+delete from customer where $c5;
+eval
+select c_name, c_acctbal from customer where $c5;
+
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+drop table t;
+
+
+let $c6=
+ c_nationkey in (select n_nationkey from nation where n_name='PERU')
+ and
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between "1992-01-09" and "1993-01-08");
+
+eval
+explain
+select c_name, c_acctbal from customer where $c6;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c6;
+eval
+create table t as
+select * from customer where $c6;
+
+eval
+explain
+delete from customer where $c6;
+eval
+delete from customer where $c6;
+eval
+select c_name, c_acctbal from customer where $c6;
+
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c6;
+drop table t;
+
+
+--echo # Materialization
+--echo # ===============
+
+let $c7=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-01-09' and '1992-03-08');
+
+eval
+explain
+select c_name, c_acctbal from customer where $c7;
+eval
+explain format=json
+select c_name, c_acctbal from customer where $c7;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+eval
+create table t as
+select * from customer where $c7;
+
+eval
+explain
+delete from customer where $c7;
+eval
+explain format=json
+delete from customer where $c7;
+eval
+delete from customer where $c7;
+eval
+select c_name, c_acctbal from customer where $c7;
+
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+drop table t;
+
+
+let $c8=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-06-09' and '1993-01-08');
+
+eval
+explain
+select c_name, c_acctbal from customer where $c8;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c8;
+eval
+create table t as
+select * from customer where $c8;
+
+eval
+explain
+delete from customer where $c8;
+eval
+delete from customer where $c8;
+eval
+select c_name, c_acctbal from customer where $c8;
+
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c8;
+drop table t;
+
+
+--echo # Materialization SJM
+--echo # ===================
+
+let $c9=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+
+eval
+explain
+select c_name, c_acctbal from customer where $c9;
+eval
+explain format=json
+select c_name, c_acctbal from customer where $c9;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+eval
+create table t as
+select * from customer where $c9;
+
+eval
+explain
+delete from customer where $c9;
+eval
+explain format=json
+delete from customer where $c9;
+eval
+delete from customer where $c9;
+eval
+select c_name, c_acctbal from customer where $c9;
+
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+drop table t;
+
+
+let $c10=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+
+eval
+explain
+select c_name, c_acctbal from customer where $c10;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c10;
+eval
+create table t as
+select * from customer where $c10;
+
+eval
+explain
+delete from customer where $c10;
+eval
+delete from customer where $c10;
+eval
+select c_name, c_acctbal from customer where $c10;
+
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c10;
+drop table t;
+
+
+--echo # Pullout PS
+--echo # ==========
+
+eval
+prepare stmt from "
+delete from orders where $c1;
+";
+
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+create table t as
+select * from orders where $c1;
+execute stmt;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+insert into orders select * from t;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+create table r as
+select * from orders where $c1;
+execute stmt;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+insert into orders select * from r;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+drop table t,r;
+
+deallocate prepare stmt;
+
+
+--echo # FirstMatch PS
+--echo # =============
+
+eval
+prepare stmt from "
+delete from customer where $c5;
+";
+
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+eval
+create table t as
+select * from customer where $c5;
+execute stmt;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+eval
+create table r as
+select * from customer where $c5;
+execute stmt;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+insert into customer select * from r;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+drop table t,r;
+
+deallocate prepare stmt;
+
+
+--echo # Materialization PS
+--echo # ==================
+
+eval
+prepare stmt from "
+delete from customer where $c7 and c_name like ?;
+";
+
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+set @a1='Customer#%1_';
+eval
+create table t as
+select * from customer where $c7 and c_name like @a1;
+execute stmt using @a1;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+set @a2='Customer#%3_';
+eval
+create table r as
+select * from customer where $c7 and c_name like @a2;
+execute stmt using @a2;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+insert into customer select * from r;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+drop table t,r;
+
+deallocate prepare stmt;
+
+
+--echo # Materialization SJM PS
+--echo # ======================
+
+eval
+prepare stmt from "
+delete from customer where $c7 and c_acctbal between ? and ?;
+";
+
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+set @a1=3500;
+set @a2=4000;
+eval
+create table t as
+select * from customer where $c9 and c_acctbal between @a1 and @a2;
+execute stmt using @a1, @a2;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+set @a3=-1000;
+set @a4=3500;
+eval
+create table r as
+select * from customer where $c9 and c_acctbal between @a3 and @a4;
+execute stmt using @a3, @a4;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+insert into customer select * from r;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+drop table t,r;
+
+deallocate prepare stmt;
+
+
+--echo # Pullout SP
+--echo # ==========
+
+eval
+create procedure p(a1 int, a2 int)
+delete from orders where $c1 and o_totalprice between a1 and a2;
+
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+create table t as
+select * from orders where $c1 and o_totalprice between 150000 and 200000;
+call p(150000, 200000);
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+insert into orders select * from t;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+create table r as
+select * from orders where $c1 and o_totalprice between 180000 and 210000;
+call p(180000, 210000);
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+insert into orders select * from r;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+drop table t,r;
+
+drop procedure p;
+
+
+--echo # FirstMatch SP
+--echo # =============
+
+eval
+create procedure p(a int)
+delete from customer where $c5 and c_acctbal > a;
+
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+eval
+create table t as
+select * from customer where $c5 and c_acctbal > 4000;
+call p(4000);
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+eval
+create table r as
+select * from customer where $c5 and c_acctbal > 2000;
+call p(2000);
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+insert into customer select * from r;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+drop table t,r;
+
+drop procedure p;
+
+
+--echo # Materialization SP
+--echo # ==================
+
+eval
+create procedure p()
+delete from customer where $c7;
+
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+eval
+create table t as
+select * from customer where $c7;
+call p();
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+eval
+create table r as
+select * from customer where $c7;
+call p();
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+insert into customer select * from r;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+drop table t,r;
+
+drop procedure p;
+
+
+--echo # Materialization SJM SP
+--echo # ======================
+
+eval
+create procedure p()
+delete from customer where $c9;
+
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+eval
+create table t as
+select * from customer where $c9;
+call p();
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+eval
+create table r as
+select * from customer where $c9;
+call p();
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+insert into customer select * from r;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+drop table t,r;
+
+drop procedure p;
+
+--echo # Checking limitations
+--echo # ====================
+
+--echo # Check for DELETE ... RETURNING with SJ subquery in WHERE
+
+--sorted_result
+eval
+select c_name from customer where $c7;
+eval
+create table t as
+select * from customer where $c7;
+eval
+explain
+delete from customer where $c7 returning c_name;
+--sorted_result
+eval
+delete from customer where $c7 returning c_name;
+--sorted_result
+eval
+select c_name from customer where $c7;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name from customer where $c7;
+drop table t;
+
+--sorted_result
+eval
+select c_name from customer where $c9;
+eval
+create table t as
+select * from customer where $c9;
+eval
+explain
+delete from customer where $c9 returning c_name;
+--sorted_result
+eval
+delete from customer where $c9 returning c_name;
+--sorted_result
+eval
+select c_name from customer where $c9;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name from customer where $c9;
+drop table t;
+
+--echo # Check for DELETE ... RETURNING with SJ subquery in WHERE
+
+--sorted_result
+eval
+select c_name from customer where $c7;
+eval
+create table t as
+select * from customer where $c7;
+eval
+explain
+delete from customer where $c7 returning c_name;
+--sorted_result
+eval
+delete from customer where $c7 returning c_name;
+--sorted_result
+eval
+select c_name from customer where $c7;
+insert into customer select * from t;
+drop table t;
+
+--echo # Check for DELETE ... ORDER BY ...LIMIT with SJ subquery in WHERE
+
+let $c11=
+ o_orderDATE between '1992-01-01' and '1992-06-30' and
+ o_custkey in (select c_custkey from customer
+ where c_nationkey in (1,2));
+
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c11;
+
+--echo # Should not use semi-join conversion because has ORDER BY ... LIMIT
+eval
+explain
+delete from orders where $c11
+order by o_totalprice limit 500;
+eval
+create table t as
+select * from orders where $c11;
+select o_orderkey, o_totalprice from t;
+eval
+delete from orders where $c11
+order by o_totalprice limit 500;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c11;
+insert into orders select * from t;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c11;
+drop table t;
+
+--echo # Should use semi-join converion
+eval
+explain
+delete from orders where $c11;
+eval
+create table t as
+select * from orders where $c11;
+select o_orderkey, o_totalprice from t;
+eval
+delete from orders where $c11;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c11;
+insert into orders select * from t;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c11;
+drop table t;
+
+DROP DATABASE dbt3_s001;
diff --git a/mysql-test/main/log_state.result b/mysql-test/main/log_state.result
index 5e7aac8..1b1c737 100644
--- a/mysql-test/main/log_state.result
+++ b/mysql-test/main/log_state.result
@@ -243,7 +243,7 @@ rows_examined sql_text
4 UPDATE t1 SET a=a+sleep(.02) WHERE a>2
8 UPDATE t1 SET a=a+sleep(.02) ORDER BY a DESC
1 UPDATE t2 set b=b+sleep(.02) limit 1
-4 UPDATE t1 SET a=a+sleep(.02) WHERE a in (SELECT b from t2)
+10 UPDATE t1 SET a=a+sleep(.02) WHERE a in (SELECT b from t2)
6 DELETE FROM t1 WHERE a=a+sleep(.02) ORDER BY a LIMIT 2
disconnect con2;
connection default;
diff --git a/mysql-test/main/myisam_explain_non_select_all.result b/mysql-test/main/myisam_explain_non_select_all.result
index 20b769b..5df9ced 100644
--- a/mysql-test/main/myisam_explain_non_select_all.result
+++ b/mysql-test/main/myisam_explain_non_select_all.result
@@ -240,14 +240,16 @@ Warnings:
Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
EXPLAIN UPDATE t1 SET a = 10 WHERE 1 IN (SELECT 1 FROM t2 WHERE t2.b < 3);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
-2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED UPDATE t1 SET a = 10 WHERE 1 IN (SELECT 1 FROM t2 WHERE t2.b < 3);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
-2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 100.00 Using where
# Status of EXPLAIN EXTENDED query
Variable_name Value
Handler_read_key 4
@@ -271,8 +273,9 @@ Handler_read_key 5
Handler_read_rnd_next 8
# Status of testing query execution:
Variable_name Value
-Handler_read_key 4
-Handler_read_rnd_next 5
+Handler_read_key 5
+Handler_read_rnd 3
+Handler_read_rnd_next 12
Handler_update 3
DROP TABLE t1, t2;
@@ -290,13 +293,13 @@ Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be
EXPLAIN UPDATE t1 SET a = 10 WHERE a IN (SELECT b FROM t2 WHERE t1.a < 3);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
-2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY t2 ALL NULL NULL NULL NULL 3 Using where; FirstMatch(t1)
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED UPDATE t1 SET a = 10 WHERE a IN (SELECT b FROM t2 WHERE t1.a < 3);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
-2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where
+1 PRIMARY t2 ALL NULL NULL NULL NULL 3 100.00 Using where; FirstMatch(t1)
Warnings:
Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1
# Status of EXPLAIN EXTENDED query
@@ -984,14 +987,16 @@ Warnings:
Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
EXPLAIN UPDATE t1 SET a = 10 WHERE a IN (SELECT a FROM t2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
-2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED UPDATE t1 SET a = 10 WHERE a IN (SELECT a FROM t2);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
-2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 100.00
# Status of EXPLAIN EXTENDED query
Variable_name Value
Handler_read_key 4
@@ -1015,8 +1020,8 @@ Handler_read_key 7
Handler_read_rnd_next 8
# Status of testing query execution:
Variable_name Value
-Handler_read_key 4
-Handler_read_rnd_next 10
+Handler_read_key 7
+Handler_read_rnd_next 8
Handler_update 3
DROP TABLE t1, t2;
@@ -1079,14 +1084,14 @@ Warnings:
Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
EXPLAIN DELETE FROM t1 WHERE a1 IN (SELECT a2 FROM t2 WHERE a2 > 2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where
-2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 5 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5
+1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using where; FirstMatch(t1)
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED DELETE FROM t1 WHERE a1 IN (SELECT a2 FROM t2 WHERE a2 > 2);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 5 100.00 Using where
-2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5 100.00
+1 PRIMARY t2 ALL NULL NULL NULL NULL 5 100.00 Using where; FirstMatch(t1)
# Status of EXPLAIN EXTENDED query
Variable_name Value
Handler_read_key 4
@@ -3074,14 +3079,14 @@ Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be
EXPLAIN UPDATE t1 SET a = 10 WHERE a IN (SELECT * FROM (SELECT b FROM t2 ORDER BY b LIMIT 2,2) x);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
-2 DEPENDENT SUBQUERY <derived3> index_subquery key0 key0 5 func 2
+1 PRIMARY <derived3> ref key0 key0 5 test.t1.a 2 FirstMatch(t1)
3 DERIVED t2 ALL NULL NULL NULL NULL 3 Using filesort
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED UPDATE t1 SET a = 10 WHERE a IN (SELECT * FROM (SELECT b FROM t2 ORDER BY b LIMIT 2,2) x);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
-2 DEPENDENT SUBQUERY <derived3> index_subquery key0 key0 5 func 2 100.00
+1 PRIMARY <derived3> ref key0 key0 5 test.t1.a 2 100.00 FirstMatch(t1)
3 DERIVED t2 ALL NULL NULL NULL NULL 3 100.00 Using filesort
# Status of EXPLAIN EXTENDED query
Variable_name Value
diff --git a/mysql-test/main/opt_trace.result b/mysql-test/main/opt_trace.result
index 0555f72..e46bd80 100644
--- a/mysql-test/main/opt_trace.result
+++ b/mysql-test/main/opt_trace.result
@@ -3948,6 +3948,16 @@ explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3 {
}
},
{
+ "table": "t0",
+ "rowid_filters": [
+ {
+ "key": "a",
+ "build_cost": 0.174715752,
+ "rows": 3
+ }
+ ]
+ },
+ {
"selectivity_for_indexes": [
{
"index_name": "a",
@@ -4013,6 +4023,16 @@ explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3 {
}
},
{
+ "table": "t1",
+ "rowid_filters": [
+ {
+ "key": "a",
+ "build_cost": 0.174715752,
+ "rows": 3
+ }
+ ]
+ },
+ {
"selectivity_for_indexes": [
{
"index_name": "a",
diff --git a/mysql-test/main/update_single_to_multi.result b/mysql-test/main/update_single_to_multi.result
new file mode 100644
index 0000000..015fd06
--- /dev/null
+++ b/mysql-test/main/update_single_to_multi.result
@@ -0,0 +1,2302 @@
+DROP DATABASE IF EXISTS dbt3_s001;
+CREATE DATABASE dbt3_s001;
+use dbt3_s001;
+create index i_n_name on nation(n_name);
+analyze table nation;
+Table Op Msg_type Msg_text
+dbt3_s001.nation analyze status Engine-independent statistics collected
+dbt3_s001.nation analyze status OK
+# Pullout
+# =======
+explain
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (7%) Using where; Using rowid filter
+explain format=json
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_n_name"],
+ "key": "i_n_name",
+ "key_length": "26",
+ "used_key_parts": ["n_name"],
+ "ref": ["const"],
+ "rows": 1,
+ "filtered": 100,
+ "index_condition": "nation.n_name = 'PERU'"
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "key": "i_c_nationkey",
+ "key_length": "5",
+ "used_key_parts": ["c_nationkey"],
+ "ref": ["dbt3_s001.nation.n_nationkey"],
+ "rows": 11,
+ "filtered": 100
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 108,
+ "selectivity_pct": 7.2
+ },
+ "rows": 11,
+ "filtered": 7.199999809,
+ "attached_condition": "orders.o_orderDATE between '1992-01-01' and '1992-06-30'"
+ }
+ }
+ ]
+ }
+}
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201268.06
+2880 145761.99
+3142 16030.15
+5382 138423.03
+5095 184583.99
+737 12984.85
+1729 12137.76
+5121 150334.57
+explain
+update orders set o_totalprice = o_totalprice-50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (7%) Using where; Using rowid filter
+explain format=json
+update orders set o_totalprice = o_totalprice-50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_n_name"],
+ "key": "i_n_name",
+ "key_length": "26",
+ "used_key_parts": ["n_name"],
+ "ref": ["const"],
+ "rows": 1,
+ "filtered": 100,
+ "index_condition": "nation.n_name = 'PERU'"
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "key": "i_c_nationkey",
+ "key_length": "5",
+ "used_key_parts": ["c_nationkey"],
+ "ref": ["dbt3_s001.nation.n_nationkey"],
+ "rows": 11,
+ "filtered": 100
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 108,
+ "selectivity_pct": 7.2
+ },
+ "rows": 11,
+ "filtered": 7.199999809,
+ "attached_condition": "orders.o_orderDATE between '1992-01-01' and '1992-06-30'"
+ }
+ }
+ ]
+ }
+}
+update orders set o_totalprice = o_totalprice-50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201218.06
+2880 145711.99
+3142 15980.15
+5382 138373.03
+5095 184533.99
+737 12934.85
+1729 12087.76
+5121 150284.57
+update orders set o_totalprice= o_totalprice+50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201268.06
+2880 145761.99
+3142 16030.15
+5382 138423.03
+5095 184583.99
+737 12984.85
+1729 12137.76
+5121 150334.57
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+4 1 444.37
+6 1 642.13
+8 1 957.34
+1 8 357.84
+3 8 645.4
+5 8 50.52
+7 8 763.98
+explain
+update partsupp set ps_supplycost = ps_supplycost+2 where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+update partsupp set ps_supplycost = ps_supplycost+2 where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+4 1 446.37
+6 1 644.13
+8 1 959.34
+1 8 359.84
+3 8 647.4
+5 8 52.52
+7 8 765.98
+update partsupp set ps_supplycost = ps_supplycost-2 where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+4 1 444.37
+6 1 642.13
+8 1 957.34
+1 8 357.84
+3 8 645.4
+5 8 50.52
+7 8 763.98
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+4 1 444.37
+6 1 642.13
+8 1 957.34
+1 8 357.84
+3 8 645.4
+5 8 50.52
+7 8 763.98
+explain
+update partsupp set ps_supplycost = ps_supplycost+10 where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+update partsupp set ps_supplycost = ps_supplycost+10 where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+4 1 454.37
+6 1 652.13
+8 1 967.34
+1 8 367.84
+3 8 655.4
+5 8 60.52
+7 8 773.98
+update partsupp set ps_supplycost = ps_supplycost-10 where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+4 1 444.37
+6 1 642.13
+8 1 957.34
+1 8 357.84
+3 8 645.4
+5 8 50.52
+7 8 763.98
+explain
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY lineitem ref PRIMARY,i_l_suppkey_partkey,i_l_partkey,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity i_l_suppkey 5 dbt3_s001.supplier.s_suppkey 100 Using where
+1 PRIMARY orders eq_ref|filter PRIMARY,i_o_orderdate,i_o_custkey PRIMARY|i_o_orderdate 4|4 dbt3_s001.lineitem.l_orderkey 1 (7%) Using where; Using rowid filter
+1 PRIMARY customer eq_ref PRIMARY,i_c_nationkey PRIMARY 4 dbt3_s001.orders.o_custkey 1 Using where
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.lineitem.l_partkey 1 Using where
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+l_orderkey l_linenumber l_tax
+4996 1 0.01
+933 1 0.04
+2500 2 0.02
+2500 4 0.02
+explain
+update lineitem set l_tax = (l_tax*100+1)/100 where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY lineitem ref PRIMARY,i_l_suppkey_partkey,i_l_partkey,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity i_l_suppkey 5 dbt3_s001.supplier.s_suppkey 100 Using where
+1 PRIMARY orders eq_ref|filter PRIMARY,i_o_orderdate,i_o_custkey PRIMARY|i_o_orderdate 4|4 dbt3_s001.lineitem.l_orderkey 1 (7%) Using where; Using rowid filter
+1 PRIMARY customer eq_ref PRIMARY,i_c_nationkey PRIMARY 4 dbt3_s001.orders.o_custkey 1 Using where
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.lineitem.l_partkey 1 Using where
+update lineitem set l_tax = (l_tax*100+1)/100 where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+l_orderkey l_linenumber l_tax
+4996 1 0.02
+933 1 0.05
+2500 2 0.03
+2500 4 0.03
+update lineitem set l_tax = (l_tax*100-1)/100 where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+l_orderkey l_linenumber l_tax
+4996 1 0.01
+933 1 0.04
+2500 2 0.02
+2500 4 0.02
+# FirstMatch
+# ==========
+explain
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY,i_c_nationkey NULL NULL NULL 150 Using where
+1 PRIMARY nation eq_ref|filter PRIMARY,i_n_regionkey PRIMARY|i_n_regionkey 4|5 dbt3_s001.customer.c_nationkey 1 (40%) Using where; Using rowid filter
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (6%) Using where; FirstMatch(nation); Using rowid filter
+explain format=json
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ALL",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "rows": 150,
+ "filtered": 100,
+ "attached_condition": "customer.c_nationkey is not null"
+ }
+ },
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY", "i_n_regionkey"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["n_nationkey"],
+ "ref": ["dbt3_s001.customer.c_nationkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_n_regionkey",
+ "used_key_parts": ["n_regionkey"]
+ },
+ "rows": 10,
+ "selectivity_pct": 40
+ },
+ "rows": 1,
+ "filtered": 40,
+ "attached_condition": "nation.n_regionkey in (1,2)"
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 89,
+ "selectivity_pct": 5.933333333
+ },
+ "rows": 11,
+ "filtered": 5.933333397,
+ "attached_condition": "orders.o_orderDATE between '1992-10-09' and '1993-03-08'",
+ "first_match": "nation"
+ }
+ }
+ ]
+ }
+}
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+explain
+update customer set c_acctbal = c_acctbal+10 where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY,i_c_nationkey NULL NULL NULL 150 Using where
+1 PRIMARY nation eq_ref|filter PRIMARY,i_n_regionkey PRIMARY|i_n_regionkey 4|5 dbt3_s001.customer.c_nationkey 1 (40%) Using where; Using rowid filter
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (6%) Using where; FirstMatch(nation); Using rowid filter
+explain format=json
+update customer set c_acctbal = c_acctbal+10 where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ALL",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "rows": 150,
+ "filtered": 100,
+ "attached_condition": "customer.c_nationkey is not null"
+ }
+ },
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY", "i_n_regionkey"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["n_nationkey"],
+ "ref": ["dbt3_s001.customer.c_nationkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_n_regionkey",
+ "used_key_parts": ["n_regionkey"]
+ },
+ "rows": 10,
+ "selectivity_pct": 40
+ },
+ "rows": 1,
+ "filtered": 40,
+ "attached_condition": "nation.n_regionkey in (1,2)"
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 89,
+ "selectivity_pct": 5.933333333
+ },
+ "rows": 11,
+ "filtered": 5.933333397,
+ "attached_condition": "orders.o_orderDATE between '1992-10-09' and '1993-03-08'",
+ "first_match": "nation"
+ }
+ }
+ ]
+ }
+}
+update customer set c_acctbal = c_acctbal+10 where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9571.95
+Customer#000000019 8924.71
+Customer#000000022 601.98
+Customer#000000025 7143.7
+Customer#000000028 1017.18
+Customer#000000037 -907.75
+Customer#000000040 1345.3
+Customer#000000047 284.58
+Customer#000000059 3468.6
+Customer#000000061 1546.24
+Customer#000000064 -636.64
+Customer#000000067 8176.59
+Customer#000000082 9478.34
+Customer#000000091 4653.14
+Customer#000000094 5510.11
+Customer#000000097 2174.48
+Customer#000000101 7480.96
+Customer#000000103 2767.45
+Customer#000000106 3298.42
+Customer#000000115 7518.92
+Customer#000000121 6438.32
+Customer#000000122 7875.46
+Customer#000000127 9290.71
+Customer#000000130 5083.58
+Customer#000000133 2324.67
+Customer#000000139 7907.78
+update customer set c_acctbal = c_acctbal-10 where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+explain
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (14%) Using where; FirstMatch(customer); Using rowid filter
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+c_name c_acctbal
+Customer#000000008 6819.74
+Customer#000000035 1228.24
+Customer#000000061 1536.24
+Customer#000000097 2164.48
+Customer#000000121 6428.32
+Customer#000000133 2314.67
+explain
+update customer set c_acctbal = c_acctbal+20 where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (14%) Using where; FirstMatch(customer); Using rowid filter
+update customer set c_acctbal = c_acctbal+20 where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+c_name c_acctbal
+Customer#000000008 6839.74
+Customer#000000035 1248.24
+Customer#000000061 1556.24
+Customer#000000097 2184.48
+Customer#000000121 6448.32
+Customer#000000133 2334.67
+update customer set c_acctbal = c_acctbal-20 where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+c_name c_acctbal
+Customer#000000008 6819.74
+Customer#000000035 1228.24
+Customer#000000061 1536.24
+Customer#000000097 2164.48
+Customer#000000121 6428.32
+Customer#000000133 2314.67
+# Materialization
+# ===============
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 dbt3_s001.orders.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 28 Using index condition; Using where
+explain format=json
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'",
+ "attached_condition": "orders.o_custkey is not null"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["dbt3_s001.orders.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7133.7
+Customer#000000013 3857.34
+Customer#000000065 8795.16
+Customer#000000032 3471.53
+Customer#000000023 3332.02
+Customer#000000035 1228.24
+Customer#000000091 4643.14
+Customer#000000016 4681.03
+Customer#000000098 -551.37
+Customer#000000037 -917.75
+Customer#000000136 -842.39
+Customer#000000118 3582.37
+Customer#000000022 591.98
+Customer#000000005 794.47
+Customer#000000109 -716.1
+Customer#000000038 6345.11
+Customer#000000076 5745.33
+Customer#000000056 6530.86
+Customer#000000040 1335.3
+Customer#000000116 8403.99
+Customer#000000115 7508.92
+Customer#000000140 9963.15
+Customer#000000017 6.34
+Customer#000000052 5630.28
+explain
+update customer set c_acctbal = c_acctbal+5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 dbt3_s001.orders.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 28 Using index condition; Using where
+explain format=json
+update customer set c_acctbal = c_acctbal+5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'",
+ "attached_condition": "orders.o_custkey is not null"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["dbt3_s001.orders.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+update customer set c_acctbal = c_acctbal+5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7138.7
+Customer#000000013 3862.34
+Customer#000000065 8800.16
+Customer#000000032 3476.53
+Customer#000000023 3337.02
+Customer#000000035 1233.24
+Customer#000000091 4648.14
+Customer#000000016 4686.03
+Customer#000000098 -546.37
+Customer#000000037 -912.75
+Customer#000000136 -837.39
+Customer#000000118 3587.37
+Customer#000000022 596.98
+Customer#000000005 799.47
+Customer#000000109 -711.1
+Customer#000000038 6350.11
+Customer#000000076 5750.33
+Customer#000000056 6535.86
+Customer#000000040 1340.3
+Customer#000000116 8408.99
+Customer#000000115 7513.92
+Customer#000000140 9968.15
+Customer#000000017 11.34
+Customer#000000052 5635.28
+update customer set c_acctbal = c_acctbal-5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7133.7
+Customer#000000013 3857.34
+Customer#000000065 8795.16
+Customer#000000032 3471.53
+Customer#000000023 3332.02
+Customer#000000035 1228.24
+Customer#000000091 4643.14
+Customer#000000016 4681.03
+Customer#000000098 -551.37
+Customer#000000037 -917.75
+Customer#000000136 -842.39
+Customer#000000118 3582.37
+Customer#000000022 591.98
+Customer#000000005 794.47
+Customer#000000109 -716.1
+Customer#000000038 6345.11
+Customer#000000076 5745.33
+Customer#000000056 6530.86
+Customer#000000040 1335.3
+Customer#000000116 8403.99
+Customer#000000115 7508.92
+Customer#000000140 9963.15
+Customer#000000017 6.34
+Customer#000000052 5630.28
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 114 Using index condition; Using where
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+c_name c_acctbal
+Customer#000000001 711.56
+Customer#000000002 121.65
+Customer#000000007 9561.95
+Customer#000000008 6819.74
+Customer#000000010 2753.54
+Customer#000000011 -272.6
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000029 7618.27
+Customer#000000031 5236.89
+Customer#000000034 8589.7
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000043 9904.28
+Customer#000000044 7315.94
+Customer#000000046 5744.59
+Customer#000000047 274.58
+Customer#000000049 4573.94
+Customer#000000053 4113.64
+Customer#000000055 4572.11
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000070 4867.52
+Customer#000000071 -611.19
+Customer#000000073 4288.5
+Customer#000000074 2764.43
+Customer#000000076 5745.33
+Customer#000000079 5121.28
+Customer#000000080 7383.53
+Customer#000000082 9468.34
+Customer#000000083 6463.51
+Customer#000000085 3386.64
+Customer#000000086 3306.32
+Customer#000000088 8031.44
+Customer#000000091 4643.14
+Customer#000000092 1182.91
+Customer#000000095 5327.38
+Customer#000000097 2164.48
+Customer#000000100 9889.89
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000104 -588.38
+Customer#000000106 3288.42
+Customer#000000109 -716.1
+Customer#000000110 7462.99
+Customer#000000112 2953.35
+Customer#000000118 3582.37
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000131 8595.53
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+Customer#000000136 -842.39
+Customer#000000137 7838.3
+Customer#000000139 7897.78
+Customer#000000142 2209.81
+Customer#000000143 2186.5
+Customer#000000148 2135.6
+Customer#000000149 8959.65
+explain
+update customer set c_acctbal = c_acctbal+1 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 114 Using index condition; Using where
+update customer set c_acctbal = c_acctbal+1 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+c_name c_acctbal
+Customer#000000001 712.56
+Customer#000000002 122.65
+Customer#000000007 9562.95
+Customer#000000008 6820.74
+Customer#000000010 2754.54
+Customer#000000011 -271.6
+Customer#000000016 4682.03
+Customer#000000017 7.34
+Customer#000000019 8915.71
+Customer#000000022 592.98
+Customer#000000023 3333.02
+Customer#000000025 7134.7
+Customer#000000028 1008.18
+Customer#000000029 7619.27
+Customer#000000031 5237.89
+Customer#000000034 8590.7
+Customer#000000037 -916.75
+Customer#000000040 1336.3
+Customer#000000043 9905.28
+Customer#000000044 7316.94
+Customer#000000046 5745.59
+Customer#000000047 275.58
+Customer#000000049 4574.94
+Customer#000000053 4114.64
+Customer#000000055 4573.11
+Customer#000000061 1537.24
+Customer#000000064 -645.64
+Customer#000000067 8167.59
+Customer#000000070 4868.52
+Customer#000000071 -610.19
+Customer#000000073 4289.5
+Customer#000000074 2765.43
+Customer#000000076 5746.33
+Customer#000000079 5122.28
+Customer#000000080 7384.53
+Customer#000000082 9469.34
+Customer#000000083 6464.51
+Customer#000000085 3387.64
+Customer#000000086 3307.32
+Customer#000000088 8032.44
+Customer#000000091 4644.14
+Customer#000000092 1183.91
+Customer#000000095 5328.38
+Customer#000000097 2165.48
+Customer#000000100 9890.89
+Customer#000000101 7471.96
+Customer#000000103 2758.45
+Customer#000000104 -587.38
+Customer#000000106 3289.42
+Customer#000000109 -715.1
+Customer#000000110 7463.99
+Customer#000000112 2954.35
+Customer#000000118 3583.37
+Customer#000000121 6429.32
+Customer#000000122 7866.46
+Customer#000000127 9281.71
+Customer#000000130 5074.58
+Customer#000000131 8596.53
+Customer#000000133 2315.67
+Customer#000000134 4609.9
+Customer#000000136 -841.39
+Customer#000000137 7839.3
+Customer#000000139 7898.78
+Customer#000000142 2210.81
+Customer#000000143 2187.5
+Customer#000000148 2136.6
+Customer#000000149 8960.65
+update customer set c_acctbal = c_acctbal-1 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+c_name c_acctbal
+Customer#000000001 711.56
+Customer#000000002 121.65
+Customer#000000007 9561.95
+Customer#000000008 6819.74
+Customer#000000010 2753.54
+Customer#000000011 -272.6
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000029 7618.27
+Customer#000000031 5236.89
+Customer#000000034 8589.7
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000043 9904.28
+Customer#000000044 7315.94
+Customer#000000046 5744.59
+Customer#000000047 274.58
+Customer#000000049 4573.94
+Customer#000000053 4113.64
+Customer#000000055 4572.11
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000070 4867.52
+Customer#000000071 -611.19
+Customer#000000073 4288.5
+Customer#000000074 2764.43
+Customer#000000076 5745.33
+Customer#000000079 5121.28
+Customer#000000080 7383.53
+Customer#000000082 9468.34
+Customer#000000083 6463.51
+Customer#000000085 3386.64
+Customer#000000086 3306.32
+Customer#000000088 8031.44
+Customer#000000091 4643.14
+Customer#000000092 1182.91
+Customer#000000095 5327.38
+Customer#000000097 2164.48
+Customer#000000100 9889.89
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000104 -588.38
+Customer#000000106 3288.42
+Customer#000000109 -716.1
+Customer#000000110 7462.99
+Customer#000000112 2953.35
+Customer#000000118 3582.37
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000131 8595.53
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+Customer#000000136 -842.39
+Customer#000000137 7838.3
+Customer#000000139 7897.78
+Customer#000000142 2209.81
+Customer#000000143 2186.5
+Customer#000000148 2135.6
+Customer#000000149 8959.65
+# Materialization SJM
+# ===================
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 <subquery2>.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 28 Using index condition; Using temporary
+explain format=json
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "having_condition": "count(orders.o_custkey) > 1",
+ "temporary_table": {
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'"
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["<subquery2>.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000118 3582.37
+Customer#000000056 6530.86
+explain
+update customer set c_acctbal = c_acctbal-5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 <subquery2>.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 28 Using index condition; Using temporary
+explain format=json
+update customer set c_acctbal = c_acctbal-5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "having_condition": "count(orders.o_custkey) > 1",
+ "temporary_table": {
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'"
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["<subquery2>.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+update customer set c_acctbal = c_acctbal-5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3852.34
+Customer#000000032 3466.53
+Customer#000000037 -922.75
+Customer#000000118 3577.37
+Customer#000000056 6525.86
+update customer set c_acctbal = c_acctbal+5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000118 3582.37
+Customer#000000056 6530.86
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 dbt3_s001.customer.c_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 242 Using index condition; Using temporary
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000016 4681.03
+Customer#000000037 -917.75
+Customer#000000046 5744.59
+Customer#000000091 4643.14
+Customer#000000103 2757.45
+Customer#000000118 3582.37
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+explain
+update customer set c_acctbal = c_acctbal-1 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 dbt3_s001.customer.c_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 242 Using index condition; Using temporary
+update customer set c_acctbal = c_acctbal-1 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+c_name c_acctbal
+Customer#000000007 9560.95
+Customer#000000016 4680.03
+Customer#000000037 -918.75
+Customer#000000046 5743.59
+Customer#000000091 4642.14
+Customer#000000103 2756.45
+Customer#000000118 3581.37
+Customer#000000133 2313.67
+Customer#000000134 4607.9
+update customer set c_acctbal = c_acctbal+1 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000016 4681.03
+Customer#000000037 -917.75
+Customer#000000046 5744.59
+Customer#000000091 4643.14
+Customer#000000103 2757.45
+Customer#000000118 3582.37
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+# Pullout PS
+# ==========
+prepare stmt from "
+update orders set o_totalprice = o_totalprice+? where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+";
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201268.06
+2880 145761.99
+3142 16030.15
+5382 138423.03
+5095 184583.99
+737 12984.85
+1729 12137.76
+5121 150334.57
+set @a1=-20;
+execute stmt using @a1;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201248.06
+2880 145741.99
+3142 16010.15
+5382 138403.03
+5095 184563.99
+737 12964.85
+1729 12117.76
+5121 150314.57
+set @a2=-10;
+execute stmt using @a2;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201238.06
+2880 145731.99
+3142 16000.15
+5382 138393.03
+5095 184553.99
+737 12954.85
+1729 12107.76
+5121 150304.57
+execute stmt using -(@a1+@a2);
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201268.06
+2880 145761.99
+3142 16030.15
+5382 138423.03
+5095 184583.99
+737 12984.85
+1729 12137.76
+5121 150334.57
+deallocate prepare stmt;
+# FirstMatch PS
+# =============
+prepare stmt from "
+update customer set c_acctbal = c_acctbal+? where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+";
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+set @a1=15;
+execute stmt using @a1;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9576.95
+Customer#000000019 8929.71
+Customer#000000022 606.98
+Customer#000000025 7148.7
+Customer#000000028 1022.18
+Customer#000000037 -902.75
+Customer#000000040 1350.3
+Customer#000000047 289.58
+Customer#000000059 3473.6
+Customer#000000061 1551.24
+Customer#000000064 -631.64
+Customer#000000067 8181.59
+Customer#000000082 9483.34
+Customer#000000091 4658.14
+Customer#000000094 5515.11
+Customer#000000097 2179.48
+Customer#000000101 7485.96
+Customer#000000103 2772.45
+Customer#000000106 3303.42
+Customer#000000115 7523.92
+Customer#000000121 6443.32
+Customer#000000122 7880.46
+Customer#000000127 9295.71
+Customer#000000130 5088.58
+Customer#000000133 2329.67
+Customer#000000139 7912.78
+set @a2=5;
+execute stmt using @a2;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9581.95
+Customer#000000019 8934.71
+Customer#000000022 611.98
+Customer#000000025 7153.7
+Customer#000000028 1027.1799999999998
+Customer#000000037 -897.75
+Customer#000000040 1355.3
+Customer#000000047 294.58
+Customer#000000059 3478.6
+Customer#000000061 1556.24
+Customer#000000064 -626.64
+Customer#000000067 8186.59
+Customer#000000082 9488.34
+Customer#000000091 4663.14
+Customer#000000094 5520.11
+Customer#000000097 2184.48
+Customer#000000101 7490.96
+Customer#000000103 2777.45
+Customer#000000106 3308.42
+Customer#000000115 7528.92
+Customer#000000121 6448.32
+Customer#000000122 7885.46
+Customer#000000127 9300.71
+Customer#000000130 5093.58
+Customer#000000133 2334.67
+Customer#000000139 7917.78
+execute stmt using -(@a1+@a2);
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.1799999999998
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+deallocate prepare stmt;
+# Materialization PS
+# ==================
+prepare stmt from "
+update customer set c_acctbal = c_acctbal+? where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+";
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7133.7
+Customer#000000013 3857.34
+Customer#000000065 8795.16
+Customer#000000032 3471.53
+Customer#000000023 3332.02
+Customer#000000035 1228.24
+Customer#000000091 4643.14
+Customer#000000016 4681.03
+Customer#000000098 -551.37
+Customer#000000037 -917.75
+Customer#000000136 -842.39
+Customer#000000118 3582.37
+Customer#000000022 591.98
+Customer#000000005 794.47
+Customer#000000109 -716.1
+Customer#000000038 6345.11
+Customer#000000076 5745.33
+Customer#000000056 6530.86
+Customer#000000040 1335.3
+Customer#000000116 8403.99
+Customer#000000115 7508.92
+Customer#000000140 9963.15
+Customer#000000017 6.34
+Customer#000000052 5630.28
+set @a1=7;
+execute stmt using @a1;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7140.7
+Customer#000000013 3864.34
+Customer#000000065 8802.16
+Customer#000000032 3478.53
+Customer#000000023 3339.02
+Customer#000000035 1235.24
+Customer#000000091 4650.14
+Customer#000000016 4688.03
+Customer#000000098 -544.37
+Customer#000000037 -910.75
+Customer#000000136 -835.39
+Customer#000000118 3589.37
+Customer#000000022 598.98
+Customer#000000005 801.47
+Customer#000000109 -709.1
+Customer#000000038 6352.11
+Customer#000000076 5752.33
+Customer#000000056 6537.86
+Customer#000000040 1342.3
+Customer#000000116 8410.99
+Customer#000000115 7515.92
+Customer#000000140 9970.15
+Customer#000000017 13.34
+Customer#000000052 5637.28
+set @a2=3;
+execute stmt using @a2;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7143.7
+Customer#000000013 3867.34
+Customer#000000065 8805.16
+Customer#000000032 3481.53
+Customer#000000023 3342.02
+Customer#000000035 1238.24
+Customer#000000091 4653.14
+Customer#000000016 4691.03
+Customer#000000098 -541.37
+Customer#000000037 -907.75
+Customer#000000136 -832.39
+Customer#000000118 3592.37
+Customer#000000022 601.98
+Customer#000000005 804.47
+Customer#000000109 -706.1
+Customer#000000038 6355.11
+Customer#000000076 5755.33
+Customer#000000056 6540.86
+Customer#000000040 1345.3
+Customer#000000116 8413.99
+Customer#000000115 7518.92
+Customer#000000140 9973.15
+Customer#000000017 16.34
+Customer#000000052 5640.28
+execute stmt using -(@a1+@a2);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7133.7
+Customer#000000013 3857.34
+Customer#000000065 8795.16
+Customer#000000032 3471.53
+Customer#000000023 3332.02
+Customer#000000035 1228.24
+Customer#000000091 4643.14
+Customer#000000016 4681.03
+Customer#000000098 -551.37
+Customer#000000037 -917.75
+Customer#000000136 -842.39
+Customer#000000118 3582.37
+Customer#000000022 591.98
+Customer#000000005 794.47
+Customer#000000109 -716.1
+Customer#000000038 6345.11
+Customer#000000076 5745.33
+Customer#000000056 6530.86
+Customer#000000040 1335.3
+Customer#000000116 8403.99
+Customer#000000115 7508.92
+Customer#000000140 9963.15
+Customer#000000017 6.34
+Customer#000000052 5630.28
+deallocate prepare stmt;
+# Materialization SJM PS
+# ======================
+prepare stmt from "
+update customer set c_acctbal = c_acctbal+? where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+";
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000118 3582.37
+Customer#000000056 6530.86
+set @a1=-2;
+execute stmt using @a1;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3855.34
+Customer#000000032 3469.53
+Customer#000000037 -919.75
+Customer#000000118 3580.37
+Customer#000000056 6528.86
+set @a2=-1;
+execute stmt using @a2;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3854.34
+Customer#000000032 3468.53
+Customer#000000037 -920.75
+Customer#000000118 3579.37
+Customer#000000056 6527.86
+execute stmt using -(@a1+@a2);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000118 3582.37
+Customer#000000056 6530.86
+deallocate prepare stmt;
+# Pullout SP
+# ==========
+create procedure p(d int)
+update orders set o_totalprice = o_totalprice+d where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201268.06
+2880 145761.99
+3142 16030.15
+5382 138423.03
+5095 184583.99
+737 12984.85
+1729 12137.76
+5121 150334.57
+call p(-10);
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201258.06
+2880 145751.99
+3142 16020.15
+5382 138413.03
+5095 184573.99
+737 12974.85
+1729 12127.76
+5121 150324.57
+call p(-20);
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201238.06
+2880 145731.99
+3142 16000.15
+5382 138393.03
+5095 184553.99
+737 12954.85
+1729 12107.76
+5121 150304.57
+call p(10+20);
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201268.06
+2880 145761.99
+3142 16030.15
+5382 138423.03
+5095 184583.99
+737 12984.85
+1729 12137.76
+5121 150334.57
+drop procedure p;
+# FirstMatch SP
+# =============
+create procedure p(d int)
+update customer set c_acctbal = c_acctbal+d where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.1799999999998
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+call p(5);
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9566.95
+Customer#000000019 8919.71
+Customer#000000022 596.98
+Customer#000000025 7138.7
+Customer#000000028 1012.1799999999998
+Customer#000000037 -912.75
+Customer#000000040 1340.3
+Customer#000000047 279.58
+Customer#000000059 3463.6
+Customer#000000061 1541.24
+Customer#000000064 -641.64
+Customer#000000067 8171.59
+Customer#000000082 9473.34
+Customer#000000091 4648.14
+Customer#000000094 5505.11
+Customer#000000097 2169.48
+Customer#000000101 7475.96
+Customer#000000103 2762.45
+Customer#000000106 3293.42
+Customer#000000115 7513.92
+Customer#000000121 6433.32
+Customer#000000122 7870.46
+Customer#000000127 9285.71
+Customer#000000130 5078.58
+Customer#000000133 2319.67
+Customer#000000139 7902.78
+call p(15);
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9581.95
+Customer#000000019 8934.71
+Customer#000000022 611.98
+Customer#000000025 7153.7
+Customer#000000028 1027.1799999999998
+Customer#000000037 -897.75
+Customer#000000040 1355.3
+Customer#000000047 294.58
+Customer#000000059 3478.6
+Customer#000000061 1556.24
+Customer#000000064 -626.64
+Customer#000000067 8186.59
+Customer#000000082 9488.34
+Customer#000000091 4663.14
+Customer#000000094 5520.11
+Customer#000000097 2184.48
+Customer#000000101 7490.96
+Customer#000000103 2777.45
+Customer#000000106 3308.42
+Customer#000000115 7528.92
+Customer#000000121 6448.32
+Customer#000000122 7885.46
+Customer#000000127 9300.71
+Customer#000000130 5093.58
+Customer#000000133 2334.67
+Customer#000000139 7917.78
+call p(-(5+15));
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.1799999999998
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+drop procedure p;
+# Materialization SP
+# ==================
+create procedure p(d int)
+update customer set c_acctbal = c_acctbal+d where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7133.7
+Customer#000000013 3857.34
+Customer#000000065 8795.16
+Customer#000000032 3471.53
+Customer#000000023 3332.02
+Customer#000000035 1228.24
+Customer#000000091 4643.14
+Customer#000000016 4681.03
+Customer#000000098 -551.37
+Customer#000000037 -917.75
+Customer#000000136 -842.39
+Customer#000000118 3582.37
+Customer#000000022 591.98
+Customer#000000005 794.47
+Customer#000000109 -716.1
+Customer#000000038 6345.11
+Customer#000000076 5745.33
+Customer#000000056 6530.86
+Customer#000000040 1335.3
+Customer#000000116 8403.99
+Customer#000000115 7508.92
+Customer#000000140 9963.15
+Customer#000000017 6.34
+Customer#000000052 5630.28
+call p(3);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7136.7
+Customer#000000013 3860.34
+Customer#000000065 8798.16
+Customer#000000032 3474.53
+Customer#000000023 3335.02
+Customer#000000035 1231.24
+Customer#000000091 4646.14
+Customer#000000016 4684.03
+Customer#000000098 -548.37
+Customer#000000037 -914.75
+Customer#000000136 -839.39
+Customer#000000118 3585.37
+Customer#000000022 594.98
+Customer#000000005 797.47
+Customer#000000109 -713.1
+Customer#000000038 6348.11
+Customer#000000076 5748.33
+Customer#000000056 6533.86
+Customer#000000040 1338.3
+Customer#000000116 8406.99
+Customer#000000115 7511.92
+Customer#000000140 9966.15
+Customer#000000017 9.34
+Customer#000000052 5633.28
+call p(7);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7143.7
+Customer#000000013 3867.34
+Customer#000000065 8805.16
+Customer#000000032 3481.53
+Customer#000000023 3342.02
+Customer#000000035 1238.24
+Customer#000000091 4653.14
+Customer#000000016 4691.03
+Customer#000000098 -541.37
+Customer#000000037 -907.75
+Customer#000000136 -832.39
+Customer#000000118 3592.37
+Customer#000000022 601.98
+Customer#000000005 804.47
+Customer#000000109 -706.1
+Customer#000000038 6355.11
+Customer#000000076 5755.33
+Customer#000000056 6540.86
+Customer#000000040 1345.3
+Customer#000000116 8413.99
+Customer#000000115 7518.92
+Customer#000000140 9973.15
+Customer#000000017 16.34
+Customer#000000052 5640.28
+call p(-(3+7));
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7133.7
+Customer#000000013 3857.34
+Customer#000000065 8795.16
+Customer#000000032 3471.53
+Customer#000000023 3332.02
+Customer#000000035 1228.24
+Customer#000000091 4643.14
+Customer#000000016 4681.03
+Customer#000000098 -551.37
+Customer#000000037 -917.75
+Customer#000000136 -842.39
+Customer#000000118 3582.37
+Customer#000000022 591.98
+Customer#000000005 794.47
+Customer#000000109 -716.1
+Customer#000000038 6345.11
+Customer#000000076 5745.33
+Customer#000000056 6530.86
+Customer#000000040 1335.3
+Customer#000000116 8403.99
+Customer#000000115 7508.92
+Customer#000000140 9963.15
+Customer#000000017 6.34
+Customer#000000052 5630.28
+drop procedure p;
+# Materialization SJM SP
+# ======================
+create procedure p(d int)
+update customer set c_acctbal = c_acctbal+d where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000118 3582.37
+Customer#000000056 6530.86
+call p(-1);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3856.34
+Customer#000000032 3470.53
+Customer#000000037 -918.75
+Customer#000000118 3581.37
+Customer#000000056 6529.86
+call p(-2);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3854.34
+Customer#000000032 3468.53
+Customer#000000037 -920.75
+Customer#000000118 3579.37
+Customer#000000056 6527.86
+call p(1+2);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000118 3582.37
+Customer#000000056 6530.86
+drop procedure p;
+# Checking limitations
+# ====================
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+o_orderkey o_totalprice
+1221 117397.16
+324 26868.85
+1856 189361.42
+1344 43809.37
+1925 146382.71
+3139 40975.96
+4903 34363.63
+5607 24660.06
+# Should not use semi-join conversion because has ORDER BY ... LIMIT
+explain
+update orders set o_totalprice = o_totalprice-50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2))
+order by o_totalprice limit 500;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY orders range i_o_orderdate i_o_orderdate 4 NULL 108 Using where; Using filesort
+2 DEPENDENT SUBQUERY customer unique_subquery|filter PRIMARY,i_c_nationkey PRIMARY|i_c_nationkey 4|5 func 1 (10%) Using where; Using rowid filter
+update orders set o_totalprice = o_totalprice-50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2))
+order by o_totalprice limit 500;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+o_orderkey o_totalprice
+1221 117347.16
+324 26818.85
+1856 189311.42
+1344 43759.37
+1925 146332.71
+3139 40925.96
+4903 34313.63
+5607 24610.06
+update orders set o_totalprice = o_totalprice+50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2))
+order by o_totalprice limit 500;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+o_orderkey o_totalprice
+1221 117397.16
+324 26868.85
+1856 189361.42
+1344 43809.37
+1925 146382.71
+3139 40975.96
+4903 34363.63
+5607 24660.06
+# Should use semi-join converion
+explain
+update orders set o_totalprice = o_totalprice-50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer range PRIMARY,i_c_nationkey i_c_nationkey 5 NULL 15 Using index condition
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (7%) Using where; Using rowid filter
+update orders set o_totalprice = o_totalprice-50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+o_orderkey o_totalprice
+1221 117347.16
+324 26818.85
+1856 189311.42
+1344 43759.37
+1925 146332.71
+3139 40925.96
+4903 34313.63
+5607 24610.06
+update orders set o_totalprice = o_totalprice+50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+o_orderkey o_totalprice
+1221 117397.16
+324 26868.85
+1856 189361.42
+1344 43809.37
+1925 146382.71
+3139 40975.96
+4903 34363.63
+5607 24660.06
+DROP DATABASE dbt3_s001;
diff --git a/mysql-test/main/update_single_to_multi.test b/mysql-test/main/update_single_to_multi.test
new file mode 100644
index 0000000..0fe5686
--- /dev/null
+++ b/mysql-test/main/update_single_to_multi.test
@@ -0,0 +1,549 @@
+--disable_warnings
+DROP DATABASE IF EXISTS dbt3_s001;
+--enable_warnings
+
+CREATE DATABASE dbt3_s001;
+
+use dbt3_s001;
+
+--disable_query_log
+--disable_result_log
+--disable_warnings
+--source include/dbt3_s001.inc
+--enable_warnings
+--enable_result_log
+--enable_query_log
+
+create index i_n_name on nation(n_name);
+analyze table nation;
+
+
+--echo # Pullout
+--echo # =======
+
+let $c1=
+ o_orderDATE between '1992-01-01' and '1992-06-30' and
+ o_custkey in (select c_custkey from customer
+ where c_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+
+eval
+explain
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+explain format=json
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+
+eval
+explain
+update orders set o_totalprice = o_totalprice-50 where $c1;
+eval
+explain format=json
+update orders set o_totalprice = o_totalprice-50 where $c1;
+eval
+update orders set o_totalprice = o_totalprice-50 where $c1;
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+
+eval
+update orders set o_totalprice= o_totalprice+50 where $c1;
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+
+
+let $c2=
+ (ps_partkey, ps_suppkey) in
+ (select p_partkey, s_suppkey from part, supplier
+ where p_retailprice between 901 and 910 and
+ s_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+
+eval
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+
+eval
+explain
+update partsupp set ps_supplycost = ps_supplycost+2 where $c2;
+eval
+update partsupp set ps_supplycost = ps_supplycost+2 where $c2;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+
+eval
+update partsupp set ps_supplycost = ps_supplycost-2 where $c2;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+
+
+let $c3=
+ ps_partkey in (select p_partkey from part
+ where p_retailprice between 901 and 910) and
+ ps_suppkey in (select s_suppkey from supplier
+ where s_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+eval
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+
+eval
+explain
+update partsupp set ps_supplycost = ps_supplycost+10 where $c3;
+eval
+update partsupp set ps_supplycost = ps_supplycost+10 where $c3;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+
+eval
+update partsupp set ps_supplycost = ps_supplycost-10 where $c3;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+
+
+let $c4=
+ l_orderkey in (select o_orderkey from orders
+ where o_custkey in
+ (select c_custkey from customer
+ where c_nationkey in
+ (select n_nationkey from nation
+ where n_name='PERU'))
+ and
+ o_orderDATE between '1992-06-30' and '1992-12-31')
+ and
+ (l_partkey, l_suppkey) in
+ (select p_partkey, s_suppkey from part, supplier
+ where p_retailprice between 901 and 1000 and
+ s_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+
+eval
+explain
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+eval
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+
+eval
+explain
+update lineitem set l_tax = (l_tax*100+1)/100 where $c4;
+eval
+update lineitem set l_tax = (l_tax*100+1)/100 where $c4;
+eval
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+
+eval
+update lineitem set l_tax = (l_tax*100-1)/100 where $c4;
+eval
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+
+
+--echo # FirstMatch
+--echo # ==========
+
+let $c5=
+ c_nationkey in (select n_nationkey from nation
+ where n_regionkey in (1,2))
+ and
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-10-09' and '1993-03-08');
+
+eval
+explain
+select c_name, c_acctbal from customer where $c5;
+eval
+explain format=json
+select c_name, c_acctbal from customer where $c5;
+eval
+select c_name, c_acctbal from customer where $c5;
+
+eval
+explain
+update customer set c_acctbal = c_acctbal+10 where $c5;
+eval
+explain format=json
+update customer set c_acctbal = c_acctbal+10 where $c5;
+eval
+update customer set c_acctbal = c_acctbal+10 where $c5;
+eval
+select c_name, c_acctbal from customer where $c5;
+
+eval
+update customer set c_acctbal = c_acctbal-10 where $c5;
+eval
+select c_name, c_acctbal from customer where $c5;
+
+
+let $c6=
+ c_nationkey in (select n_nationkey from nation where n_name='PERU')
+ and
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between "1992-01-09" and "1993-01-08");
+
+eval
+explain
+select c_name, c_acctbal from customer where $c6;
+eval
+select c_name, c_acctbal from customer where $c6;
+
+eval
+explain
+update customer set c_acctbal = c_acctbal+20 where $c6;
+eval
+update customer set c_acctbal = c_acctbal+20 where $c6;
+eval
+select c_name, c_acctbal from customer where $c6;
+
+eval
+update customer set c_acctbal = c_acctbal-20 where $c6;
+eval
+select c_name, c_acctbal from customer where $c6;
+
+
+--echo # Materialization
+--echo # ===============
+
+let $c7=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-01-09' and '1992-03-08');
+
+eval
+explain
+select c_name, c_acctbal from customer where $c7;
+eval
+explain format=json
+select c_name, c_acctbal from customer where $c7;
+eval
+select c_name, c_acctbal from customer where $c7;
+
+eval
+explain
+update customer set c_acctbal = c_acctbal+5 where $c7;
+eval
+explain format=json
+update customer set c_acctbal = c_acctbal+5 where $c7;
+eval
+update customer set c_acctbal = c_acctbal+5 where $c7;
+eval
+select c_name, c_acctbal from customer where $c7;
+
+eval
+update customer set c_acctbal = c_acctbal-5 where $c7;
+eval
+select c_name, c_acctbal from customer where $c7;
+
+
+let $c8=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-06-09' and '1993-01-08');
+
+eval
+explain
+select c_name, c_acctbal from customer where $c8;
+eval
+select c_name, c_acctbal from customer where $c8;
+
+eval
+explain
+update customer set c_acctbal = c_acctbal+1 where $c8;
+eval
+update customer set c_acctbal = c_acctbal+1 where $c8;
+eval
+select c_name, c_acctbal from customer where $c8;
+
+eval
+update customer set c_acctbal = c_acctbal-1 where $c8;
+eval
+select c_name, c_acctbal from customer where $c8;
+
+
+--echo # Materialization SJM
+--echo # ===================
+
+let $c9=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+
+eval
+explain
+select c_name, c_acctbal from customer where $c9;
+eval
+explain format=json
+select c_name, c_acctbal from customer where $c9;
+eval
+select c_name, c_acctbal from customer where $c9;
+
+eval
+explain
+update customer set c_acctbal = c_acctbal-5 where $c9;
+eval
+explain format=json
+update customer set c_acctbal = c_acctbal-5 where $c9;
+eval
+update customer set c_acctbal = c_acctbal-5 where $c9;
+eval
+select c_name, c_acctbal from customer where $c9;
+
+eval
+update customer set c_acctbal = c_acctbal+5 where $c9;
+eval
+select c_name, c_acctbal from customer where $c9;
+
+
+let $c10=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+
+eval
+explain
+select c_name, c_acctbal from customer where $c10;
+eval
+select c_name, c_acctbal from customer where $c10;
+
+eval
+explain
+update customer set c_acctbal = c_acctbal-1 where $c10;
+eval
+update customer set c_acctbal = c_acctbal-1 where $c10;
+eval
+select c_name, c_acctbal from customer where $c10;
+
+eval
+update customer set c_acctbal = c_acctbal+1 where $c10;
+eval
+select c_name, c_acctbal from customer where $c10;
+
+
+--echo # Pullout PS
+--echo # ==========
+
+eval
+prepare stmt from "
+update orders set o_totalprice = o_totalprice+? where $c1;
+";
+
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+set @a1=-20;
+execute stmt using @a1;
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+set @a2=-10;
+execute stmt using @a2;
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+execute stmt using -(@a1+@a2);
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+
+deallocate prepare stmt;
+
+
+--echo # FirstMatch PS
+--echo # =============
+
+eval
+prepare stmt from "
+update customer set c_acctbal = c_acctbal+? where $c5;
+";
+
+eval
+select c_name, c_acctbal from customer where $c5;
+set @a1=15;
+execute stmt using @a1;
+eval
+select c_name, c_acctbal from customer where $c5;
+set @a2=5;
+execute stmt using @a2;
+eval
+select c_name, c_acctbal from customer where $c5;
+execute stmt using -(@a1+@a2);
+eval
+select c_name, c_acctbal from customer where $c5;
+
+deallocate prepare stmt;
+
+
+--echo # Materialization PS
+--echo # ==================
+
+eval
+prepare stmt from "
+update customer set c_acctbal = c_acctbal+? where $c7;
+";
+
+eval
+select c_name, c_acctbal from customer where $c7;
+set @a1=7;
+execute stmt using @a1;
+eval
+select c_name, c_acctbal from customer where $c7;
+set @a2=3;
+execute stmt using @a2;
+eval
+select c_name, c_acctbal from customer where $c7;
+execute stmt using -(@a1+@a2);
+eval
+select c_name, c_acctbal from customer where $c7;
+
+deallocate prepare stmt;
+
+
+--echo # Materialization SJM PS
+--echo # ======================
+
+eval
+prepare stmt from "
+update customer set c_acctbal = c_acctbal+? where $c9;
+";
+
+eval
+select c_name, c_acctbal from customer where $c9;
+set @a1=-2;
+execute stmt using @a1;
+eval
+select c_name, c_acctbal from customer where $c9;
+set @a2=-1;
+execute stmt using @a2;
+eval
+select c_name, c_acctbal from customer where $c9;
+execute stmt using -(@a1+@a2);
+eval
+select c_name, c_acctbal from customer where $c9;
+
+deallocate prepare stmt;
+
+
+--echo # Pullout SP
+--echo # ==========
+
+eval
+create procedure p(d int)
+update orders set o_totalprice = o_totalprice+d where $c1;
+
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+call p(-10);
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+call p(-20);
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+call p(10+20);
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+
+drop procedure p;
+
+
+--echo # FirstMatch SP
+--echo # =============
+
+eval
+create procedure p(d int)
+update customer set c_acctbal = c_acctbal+d where $c5;
+
+eval
+select c_name, c_acctbal from customer where $c5;
+call p(5);
+eval
+select c_name, c_acctbal from customer where $c5;
+call p(15);
+eval
+select c_name, c_acctbal from customer where $c5;
+call p(-(5+15));
+eval
+select c_name, c_acctbal from customer where $c5;
+
+drop procedure p;
+
+
+--echo # Materialization SP
+--echo # ==================
+
+eval
+create procedure p(d int)
+update customer set c_acctbal = c_acctbal+d where $c7;
+
+eval
+select c_name, c_acctbal from customer where $c7;
+call p(3);
+eval
+select c_name, c_acctbal from customer where $c7;
+call p(7);
+eval
+select c_name, c_acctbal from customer where $c7;
+call p(-(3+7));
+eval
+select c_name, c_acctbal from customer where $c7;
+
+drop procedure p;
+
+
+--echo # Materialization SJM SP
+--echo # ======================
+
+eval
+create procedure p(d int)
+update customer set c_acctbal = c_acctbal+d where $c9;
+
+eval
+select c_name, c_acctbal from customer where $c9;
+call p(-1);
+eval
+select c_name, c_acctbal from customer where $c9;
+call p(-2);
+eval
+select c_name, c_acctbal from customer where $c9;
+call p(1+2);
+eval
+select c_name, c_acctbal from customer where $c9;
+
+drop procedure p;
+
+--echo # Checking limitations
+--echo # ====================
+
+let $c11=
+ o_orderDATE between '1992-01-01' and '1992-06-30' and
+ o_custkey in (select c_custkey from customer
+ where c_nationkey in (1,2));
+
+eval
+select o_orderkey, o_totalprice from orders where $c11;
+--echo # Should not use semi-join conversion because has ORDER BY ... LIMIT
+eval
+explain
+update orders set o_totalprice = o_totalprice-50 where $c11
+order by o_totalprice limit 500;
+eval
+update orders set o_totalprice = o_totalprice-50 where $c11
+order by o_totalprice limit 500;
+eval
+select o_orderkey, o_totalprice from orders where $c11;
+eval
+update orders set o_totalprice = o_totalprice+50 where $c11
+order by o_totalprice limit 500;
+eval
+select o_orderkey, o_totalprice from orders where $c11;
+
+--echo # Should use semi-join converion
+eval
+explain
+update orders set o_totalprice = o_totalprice-50 where $c11;
+eval
+update orders set o_totalprice = o_totalprice-50 where $c11;
+eval
+select o_orderkey, o_totalprice from orders where $c11;
+eval
+update orders set o_totalprice = o_totalprice+50 where $c11;
+eval
+select o_orderkey, o_totalprice from orders where $c11;
+
+DROP DATABASE dbt3_s001;
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index fa338f0..cd88e78 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -533,6 +533,31 @@ bool is_materialization_applicable(THD *thd, Item_in_subselect *in_subs,
}
+/**
+ @brief Check whether an IN subquery must be excluded from conversion to SJ
+
+ @param thd global context the processed statement
+ @returns true if the IN subquery must be excluded from conversion to SJ
+
+ @note
+ Currently a top level IN subquery of an update/delete statement
+ is not converted to SJ if the statement contains ORDER BY ... LIMIT
+ or contains RETURNING.
+*/
+
+bool SELECT_LEX::is_sj_conversion_prohibited(THD *thd)
+{
+ DBUG_ASSERT(master_unit()->item->substype() == Item_subselect::IN_SUBS);
+ SELECT_LEX *outer_sl= outer_select();
+ return !outer_sl->outer_select() &&
+ (thd->lex->sql_command == SQLCOM_UPDATE ||
+ thd->lex->sql_command == SQLCOM_DELETE) &&
+ ((outer_sl->order_list.elements &&
+ outer_sl->get_limit() != HA_POS_ERROR) ||
+ (thd->lex->sql_command == SQLCOM_DELETE &&
+ thd->lex->has_returning()));
+}
+
/*
Check if we need JOIN::prepare()-phase subquery rewrites and if yes, do them
@@ -675,9 +700,9 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
3. Subquery does not have GROUP BY or ORDER BY
4. Subquery does not use aggregate functions or HAVING
5. Subquery predicate is at the AND-top-level of ON/WHERE clause
- 6. We are not in a subquery of a single table UPDATE/DELETE that
- doesn't have a JOIN (TODO: We should handle this at some
- point by switching to multi-table UPDATE/DELETE)
+ 6. We are not in a top level subquery of a single-table UPDATE or
+ DELETE with ORDER BY ... LIMIT and we are not in a top level
+ subquery of a single-table DELETE with returning
7. We're not in a table-less subquery like "SELECT 1"
8. No execution method was already chosen (by a prepared statement)
9. Parent select is not a table-less select
@@ -692,9 +717,7 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
!select_lex->group_list.elements && !join->order && // 3
!join->having && !select_lex->with_sum_func && // 4
in_subs->emb_on_expr_nest && // 5
- select_lex->outer_select()->join && // 6
- (!thd->lex->m_sql_cmd ||
- thd->lex->m_sql_cmd->sql_command_code() == SQLCOM_UPDATE_MULTI) &&
+ !select_lex->is_sj_conversion_prohibited(thd) && // 6
parent_unit->first_select()->leaf_tables.elements && // 7
!in_subs->has_strategy() && // 8
select_lex->outer_select()->table_list.first && // 9
@@ -754,7 +777,8 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
*/
if (in_subs && !in_subs->has_strategy())
{
- if (is_materialization_applicable(thd, in_subs, select_lex))
+ if (!select_lex->is_sj_conversion_prohibited(thd) &&
+ is_materialization_applicable(thd, in_subs, select_lex))
{
in_subs->add_strategy(SUBS_MATERIALIZATION);
@@ -7260,3 +7284,28 @@ bool TABLE_LIST::is_sjm_scan_table()
{
return is_active_sjm() && sj_mat_info->is_sj_scan;
}
+
+
+/**
+ @brief Check whether this subselect can be lifted to the top level
+ @returns true if the test is positive, false otherwise
+*/
+
+bool SELECT_LEX::is_sj_subselect_lifted_to_top()
+{
+ st_select_lex *sl= this;
+ st_select_lex *outer_sl= outer_select();
+ for ( ; outer_sl; sl= outer_sl, outer_sl= outer_sl->outer_select())
+ {
+ List_iterator_fast<Item_in_subselect> it(outer_sl->sj_subselects);
+ Item_in_subselect *in_subs;
+ while ((in_subs= it++))
+ {
+ if (in_subs->unit->first_select() == sl)
+ break;
+ }
+ if (!in_subs)
+ return false;
+ }
+ return true;
+}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 167df5b..3a2704f 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -7005,6 +7005,7 @@ class multi_delete :public select_result_interceptor
// Methods used by ColumnStore
uint get_num_of_tables() const { return num_of_tables; }
TABLE_LIST* get_tables() const { return delete_tables; }
+ void set_delete_tables (TABLE_LIST *tbl) { delete_tables= tbl; }
public:
multi_delete(THD *thd_arg, TABLE_LIST *dt, uint num_of_tables);
~multi_delete();
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 2ff4331..ed4b6be 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -1591,10 +1591,16 @@ bool Sql_cmd_delete::prepare_inner(THD *thd)
select_lex->order_list.first,
false, NULL, NULL, NULL,
select_lex, &lex->unit)))
-
{
goto err;
}
+
+ if (!multitable &&
+ select_lex->sj_subselects.elements)
+ multitable= true;
+
+ if (!multitable)
+ ((multi_delete *)result)->set_delete_tables(0);
}
if (multitable)
@@ -1638,7 +1644,8 @@ bool Sql_cmd_delete::prepare_inner(THD *thd)
{
TABLE_LIST *duplicate;
if ((duplicate= unique_table(thd, target_tbl->correspondent_table,
- lex->query_tables, 0)))
+ lex->query_tables, 0)) &&
+ !duplicate->select_lex->is_sj_subselect_lifted_to_top())
{
update_non_unique_table_error(target_tbl->correspondent_table,
"DELETE", duplicate);
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index e733b4f..d1f0274 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -1642,6 +1642,8 @@ class st_select_lex: public st_select_lex_node
void lex_start(LEX *plex);
bool is_unit_nest() { return (nest_flags & UNIT_NEST_FL); }
void mark_as_unit_nest() { nest_flags= UNIT_NEST_FL; }
+ bool is_sj_conversion_prohibited(THD *thd);
+ bool is_sj_subselect_lifted_to_top();
};
typedef class st_select_lex SELECT_LEX;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index bf49d69..a7e5bc7 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -5834,8 +5834,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
s->needed_reg=select->needed_reg;
select->quick=0;
impossible_range= records == 0 && s->table->reginfo.impossible_range;
- if (join->thd->lex->sql_command == SQLCOM_SELECT &&
- optimizer_flag(join->thd, OPTIMIZER_SWITCH_USE_ROWID_FILTER))
+ if (optimizer_flag(join->thd, OPTIMIZER_SWITCH_USE_ROWID_FILTER))
s->table->init_cost_info_for_usable_range_rowid_filters(join->thd);
}
if (!impossible_range)
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 6b14c4f..b056b13 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -2471,6 +2471,8 @@ int multi_update::do_updates()
table = cur_table->table;
if (table == table_to_update)
continue; // Already updated
+ if (table->file->pushed_rowid_filter)
+ table->file->disable_pushed_rowid_filter();
org_updated= updated;
tmp_table= tmp_tables[cur_table->shared];
tmp_table->file->extra(HA_EXTRA_CACHE); // Change to read cache
@@ -2665,7 +2667,8 @@ int multi_update::do_updates()
check_opt_it.rewind();
while (TABLE *tbl= check_opt_it++)
tbl->file->ha_rnd_end();
-
+ if (table->file->save_pushed_rowid_filter)
+ table->file->enable_pushed_rowid_filter();
}
DBUG_RETURN(0);
@@ -2676,6 +2679,8 @@ int multi_update::do_updates()
}
err2:
+ if (table->file->save_pushed_rowid_filter)
+ table->file->enable_pushed_rowid_filter();
if (table->file->inited)
(void) table->file->ha_rnd_end();
if (tmp_table->file->inited)
@@ -2955,7 +2960,9 @@ bool Sql_cmd_update::prepare_inner(THD *thd)
{
goto err;
}
-
+ if (!multitable &&
+ select_lex->sj_subselects.elements)
+ multitable= true;
}
if (table_list->has_period())
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index a587a37..13dc602 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -13370,8 +13370,21 @@ delete_single_table:
YYPS->m_lock_type,
YYPS->m_mdl_type,
NULL,
+ 0)))
+ MYSQL_YYABORT;
+ Select->table_list.save_and_clear(&Lex->auxiliary_table_list);
+ Lex->table_count= 1;
+ Lex->query_tables= 0;
+ Lex->query_tables_last= &Lex->query_tables;
+ if (unlikely(!Select->
+ add_table_to_list(thd, $2, NULL, TL_OPTION_UPDATING,
+ YYPS->m_lock_type,
+ YYPS->m_mdl_type,
+ NULL,
$3)))
MYSQL_YYABORT;
+ Lex->auxiliary_table_list.first->correspondent_table=
+ Lex->query_tables;
YYPS->m_lock_type= TL_READ_DEFAULT;
YYPS->m_mdl_type= MDL_SHARED_READ;
}
1
0
[Commits] 6ded84a: MDEV-7487 Semi-join optimization for single-table update/delete statements
by IgorBabaev 20 Jun '22
by IgorBabaev 20 Jun '22
20 Jun '22
revision-id: 6ded84a3eb0893eed23bd13bb3129740e045e121 (mariadb-10.6.1-472-g6ded84a)
parent(s): 596cde07f17c490c43db10ce0a8cbb7bd4dbf5ae
author: Igor Babaev
committer: Igor Babaev
timestamp: 2022-06-19 23:43:17 -0700
message:
MDEV-7487 Semi-join optimization for single-table update/delete statements
This patch allows to use semi-join optimization at the top level of
single-table update and delete statements.
The problem of supporting such optimization became easy to resolve after
processing a single-table update/delete statement started using JOIN
structure. This allowed to use JOIN::prepare() not only for multi-table
updates/deletes but for single-table ones as well. This was done in the
patch for mdev-28883:
Re-design the upper level of handling UPDATE and DELETE statements.
Note that JOIN::prepare() detects all subqueries that can be considered
as candidates for semi-join optimization. The code added by this patch
looks for such candidates at the top level and if such candidates are found
in the processed single-table update/delete the statement is handled in
the same way as a multi-table update/delete.
Approved by Oleksandr Byelkin <sanja(a)mariadb.com>
---
mysql-test/main/delete_single_to_multi.result | 2355 ++++++++++++++++++++
mysql-test/main/delete_single_to_multi.test | 797 +++++++
mysql-test/main/log_state.result | 2 +-
.../main/myisam_explain_non_select_all.result | 45 +-
mysql-test/main/opt_trace.result | 20 +
mysql-test/main/update_single_to_multi.result | 2302 +++++++++++++++++++
mysql-test/main/update_single_to_multi.test | 549 +++++
sql/opt_subselect.cc | 63 +-
sql/sql_class.h | 1 +
sql/sql_delete.cc | 11 +-
sql/sql_lex.h | 2 +
sql/sql_select.cc | 3 +-
sql/sql_update.cc | 11 +-
sql/sql_yacc.yy | 13 +
14 files changed, 6140 insertions(+), 34 deletions(-)
diff --git a/mysql-test/main/delete_single_to_multi.result b/mysql-test/main/delete_single_to_multi.result
new file mode 100644
index 0000000..c6da861
--- /dev/null
+++ b/mysql-test/main/delete_single_to_multi.result
@@ -0,0 +1,2355 @@
+DROP DATABASE IF EXISTS dbt3_s001;
+CREATE DATABASE dbt3_s001;
+use dbt3_s001;
+create index i_n_name on nation(n_name);
+analyze table nation;
+Table Op Msg_type Msg_text
+dbt3_s001.nation analyze status Engine-independent statistics collected
+dbt3_s001.nation analyze status OK
+# Pullout
+# =======
+explain
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (7%) Using where; Using rowid filter
+explain format=json
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_n_name"],
+ "key": "i_n_name",
+ "key_length": "26",
+ "used_key_parts": ["n_name"],
+ "ref": ["const"],
+ "rows": 1,
+ "filtered": 100,
+ "index_condition": "nation.n_name = 'PERU'"
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "key": "i_c_nationkey",
+ "key_length": "5",
+ "used_key_parts": ["c_nationkey"],
+ "ref": ["dbt3_s001.nation.n_nationkey"],
+ "rows": 11,
+ "filtered": 100
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 108,
+ "selectivity_pct": 7.2
+ },
+ "rows": 11,
+ "filtered": 7.199999809,
+ "attached_condition": "orders.o_orderDATE between '1992-01-01' and '1992-06-30'"
+ }
+ }
+ ]
+ }
+}
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+5382 138423.03
+644 201268.06
+737 12984.85
+create table t as
+select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+explain
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (7%) Using where; Using rowid filter
+explain format=json
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_n_name"],
+ "key": "i_n_name",
+ "key_length": "26",
+ "used_key_parts": ["n_name"],
+ "ref": ["const"],
+ "rows": 1,
+ "filtered": 100,
+ "index_condition": "nation.n_name = 'PERU'"
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "key": "i_c_nationkey",
+ "key_length": "5",
+ "used_key_parts": ["c_nationkey"],
+ "ref": ["dbt3_s001.nation.n_nationkey"],
+ "rows": 11,
+ "filtered": 100
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 108,
+ "selectivity_pct": 7.2
+ },
+ "rows": 11,
+ "filtered": 7.199999809,
+ "attached_condition": "orders.o_orderDATE between '1992-01-01' and '1992-06-30'"
+ }
+ }
+ ]
+ }
+}
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+insert into orders select * from t;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+5382 138423.03
+644 201268.06
+737 12984.85
+drop table t;
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+1 8 357.84
+3 8 645.4
+4 1 444.37
+5 8 50.52
+6 1 642.13
+7 8 763.98
+8 1 957.34
+create table t as
+select * from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+explain
+delete from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+delete from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+insert into partsupp select * from t;
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+1 8 357.84
+3 8 645.4
+4 1 444.37
+5 8 50.52
+6 1 642.13
+7 8 763.98
+8 1 957.34
+drop table t;
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+1 8 357.84
+3 8 645.4
+4 1 444.37
+5 8 50.52
+6 1 642.13
+7 8 763.98
+8 1 957.34
+create table t as
+select * from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+explain
+delete from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+delete from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+insert into partsupp select * from t;
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+1 8 357.84
+3 8 645.4
+4 1 444.37
+5 8 50.52
+6 1 642.13
+7 8 763.98
+8 1 957.34
+drop table t;
+explain
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY lineitem ref PRIMARY,i_l_suppkey_partkey,i_l_partkey,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity i_l_suppkey 5 dbt3_s001.supplier.s_suppkey 100 Using where
+1 PRIMARY orders eq_ref|filter PRIMARY,i_o_orderdate,i_o_custkey PRIMARY|i_o_orderdate 4|4 dbt3_s001.lineitem.l_orderkey 1 (7%) Using where; Using rowid filter
+1 PRIMARY customer eq_ref PRIMARY,i_c_nationkey PRIMARY 4 dbt3_s001.orders.o_custkey 1 Using where
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.lineitem.l_partkey 1 Using where
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+l_orderkey l_linenumber l_tax
+2500 2 0.02
+2500 4 0.02
+4996 1 0.01
+933 1 0.04
+create table t as
+select * from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+explain
+delete from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY lineitem ref PRIMARY,i_l_suppkey_partkey,i_l_partkey,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity i_l_suppkey 5 dbt3_s001.supplier.s_suppkey 100 Using where
+1 PRIMARY orders eq_ref|filter PRIMARY,i_o_orderdate,i_o_custkey PRIMARY|i_o_orderdate 4|4 dbt3_s001.lineitem.l_orderkey 1 (7%) Using where; Using rowid filter
+1 PRIMARY customer eq_ref PRIMARY,i_c_nationkey PRIMARY 4 dbt3_s001.orders.o_custkey 1 Using where
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.lineitem.l_partkey 1 Using where
+delete from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+l_orderkey l_linenumber l_tax
+insert into lineitem select * from t;
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+l_orderkey l_linenumber l_tax
+2500 2 0.02
+2500 4 0.02
+4996 1 0.01
+933 1 0.04
+drop table t;
+# FirstMatch
+# ==========
+explain
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY,i_c_nationkey NULL NULL NULL 150 Using where
+1 PRIMARY nation eq_ref|filter PRIMARY,i_n_regionkey PRIMARY|i_n_regionkey 4|5 dbt3_s001.customer.c_nationkey 1 (40%) Using where; Using rowid filter
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (6%) Using where; FirstMatch(nation); Using rowid filter
+explain format=json
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ALL",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "rows": 150,
+ "filtered": 100,
+ "attached_condition": "customer.c_nationkey is not null"
+ }
+ },
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY", "i_n_regionkey"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["n_nationkey"],
+ "ref": ["dbt3_s001.customer.c_nationkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_n_regionkey",
+ "used_key_parts": ["n_regionkey"]
+ },
+ "rows": 10,
+ "selectivity_pct": 40
+ },
+ "rows": 1,
+ "filtered": 40,
+ "attached_condition": "nation.n_regionkey in (1,2)"
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 89,
+ "selectivity_pct": 5.933333333
+ },
+ "rows": 11,
+ "filtered": 5.933333397,
+ "attached_condition": "orders.o_orderDATE between '1992-10-09' and '1993-03-08'",
+ "first_match": "nation"
+ }
+ }
+ ]
+ }
+}
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+create table t as
+select * from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+explain
+delete from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY,i_c_nationkey NULL NULL NULL 150 Using where
+1 PRIMARY nation eq_ref|filter PRIMARY,i_n_regionkey PRIMARY|i_n_regionkey 4|5 dbt3_s001.customer.c_nationkey 1 (40%) Using where; Using rowid filter
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (6%) Using where; FirstMatch(nation); Using rowid filter
+explain format=json
+delete from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ALL",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "rows": 150,
+ "filtered": 100,
+ "attached_condition": "customer.c_nationkey is not null"
+ }
+ },
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY", "i_n_regionkey"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["n_nationkey"],
+ "ref": ["dbt3_s001.customer.c_nationkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_n_regionkey",
+ "used_key_parts": ["n_regionkey"]
+ },
+ "rows": 10,
+ "selectivity_pct": 40
+ },
+ "rows": 1,
+ "filtered": 40,
+ "attached_condition": "nation.n_regionkey in (1,2)"
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 89,
+ "selectivity_pct": 5.933333333
+ },
+ "rows": 11,
+ "filtered": 5.933333397,
+ "attached_condition": "orders.o_orderDATE between '1992-10-09' and '1993-03-08'",
+ "first_match": "nation"
+ }
+ }
+ ]
+ }
+}
+delete from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+drop table t;
+explain
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (14%) Using where; FirstMatch(customer); Using rowid filter
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+c_name c_acctbal
+Customer#000000008 6819.74
+Customer#000000035 1228.24
+Customer#000000061 1536.24
+Customer#000000097 2164.48
+Customer#000000121 6428.32
+Customer#000000133 2314.67
+create table t as
+select * from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+explain
+delete from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (14%) Using where; FirstMatch(customer); Using rowid filter
+delete from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+c_name c_acctbal
+Customer#000000008 6819.74
+Customer#000000035 1228.24
+Customer#000000061 1536.24
+Customer#000000097 2164.48
+Customer#000000121 6428.32
+Customer#000000133 2314.67
+drop table t;
+# Materialization
+# ===============
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 dbt3_s001.orders.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 28 Using index condition; Using where
+explain format=json
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'",
+ "attached_condition": "orders.o_custkey is not null"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["dbt3_s001.orders.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000005 794.47
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000035 1228.24
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000040 1335.3
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000098 -551.37
+Customer#000000109 -716.1
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000136 -842.39
+Customer#000000140 9963.15
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+explain
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 dbt3_s001.orders.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 28 Using index condition; Using where
+explain format=json
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'",
+ "attached_condition": "orders.o_custkey is not null"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["dbt3_s001.orders.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000005 794.47
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000035 1228.24
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000040 1335.3
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000098 -551.37
+Customer#000000109 -716.1
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000136 -842.39
+Customer#000000140 9963.15
+drop table t;
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 114 Using index condition; Using where
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+c_name c_acctbal
+Customer#000000001 711.56
+Customer#000000002 121.65
+Customer#000000007 9561.95
+Customer#000000008 6819.74
+Customer#000000010 2753.54
+Customer#000000011 -272.6
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000029 7618.27
+Customer#000000031 5236.89
+Customer#000000034 8589.7
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000043 9904.28
+Customer#000000044 7315.94
+Customer#000000046 5744.59
+Customer#000000047 274.58
+Customer#000000049 4573.94
+Customer#000000053 4113.64
+Customer#000000055 4572.11
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000070 4867.52
+Customer#000000071 -611.19
+Customer#000000073 4288.5
+Customer#000000074 2764.43
+Customer#000000076 5745.33
+Customer#000000079 5121.28
+Customer#000000080 7383.53
+Customer#000000082 9468.34
+Customer#000000083 6463.51
+Customer#000000085 3386.64
+Customer#000000086 3306.32
+Customer#000000088 8031.44
+Customer#000000091 4643.14
+Customer#000000092 1182.91
+Customer#000000095 5327.38
+Customer#000000097 2164.48
+Customer#000000100 9889.89
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000104 -588.38
+Customer#000000106 3288.42
+Customer#000000109 -716.1
+Customer#000000110 7462.99
+Customer#000000112 2953.35
+Customer#000000118 3582.37
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000131 8595.53
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+Customer#000000136 -842.39
+Customer#000000137 7838.3
+Customer#000000139 7897.78
+Customer#000000142 2209.81
+Customer#000000143 2186.5
+Customer#000000148 2135.6
+Customer#000000149 8959.65
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+explain
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 114 Using index condition; Using where
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+c_name c_acctbal
+Customer#000000001 711.56
+Customer#000000002 121.65
+Customer#000000007 9561.95
+Customer#000000008 6819.74
+Customer#000000010 2753.54
+Customer#000000011 -272.6
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000029 7618.27
+Customer#000000031 5236.89
+Customer#000000034 8589.7
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000043 9904.28
+Customer#000000044 7315.94
+Customer#000000046 5744.59
+Customer#000000047 274.58
+Customer#000000049 4573.94
+Customer#000000053 4113.64
+Customer#000000055 4572.11
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000070 4867.52
+Customer#000000071 -611.19
+Customer#000000073 4288.5
+Customer#000000074 2764.43
+Customer#000000076 5745.33
+Customer#000000079 5121.28
+Customer#000000080 7383.53
+Customer#000000082 9468.34
+Customer#000000083 6463.51
+Customer#000000085 3386.64
+Customer#000000086 3306.32
+Customer#000000088 8031.44
+Customer#000000091 4643.14
+Customer#000000092 1182.91
+Customer#000000095 5327.38
+Customer#000000097 2164.48
+Customer#000000100 9889.89
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000104 -588.38
+Customer#000000106 3288.42
+Customer#000000109 -716.1
+Customer#000000110 7462.99
+Customer#000000112 2953.35
+Customer#000000118 3582.37
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000131 8595.53
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+Customer#000000136 -842.39
+Customer#000000137 7838.3
+Customer#000000139 7897.78
+Customer#000000142 2209.81
+Customer#000000143 2186.5
+Customer#000000148 2135.6
+Customer#000000149 8959.65
+drop table t;
+# Materialization SJM
+# ===================
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 <subquery2>.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 28 Using index condition; Using temporary
+explain format=json
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "having_condition": "count(orders.o_custkey) > 1",
+ "temporary_table": {
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'"
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["<subquery2>.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+explain
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 <subquery2>.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 28 Using index condition; Using temporary
+explain format=json
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "having_condition": "count(orders.o_custkey) > 1",
+ "temporary_table": {
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'"
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["<subquery2>.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+drop table t;
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 dbt3_s001.customer.c_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 242 Using index condition; Using temporary
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000016 4681.03
+Customer#000000037 -917.75
+Customer#000000046 5744.59
+Customer#000000091 4643.14
+Customer#000000103 2757.45
+Customer#000000118 3582.37
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+explain
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 dbt3_s001.customer.c_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 242 Using index condition; Using temporary
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000016 4681.03
+Customer#000000037 -917.75
+Customer#000000046 5744.59
+Customer#000000091 4643.14
+Customer#000000103 2757.45
+Customer#000000118 3582.37
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+drop table t;
+# Pullout PS
+# ==========
+prepare stmt from "
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+";
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+5382 138423.03
+644 201268.06
+737 12984.85
+create table t as
+select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+execute stmt;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+insert into orders select * from t;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+5382 138423.03
+644 201268.06
+737 12984.85
+create table r as
+select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+execute stmt;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+insert into orders select * from r;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+5382 138423.03
+644 201268.06
+737 12984.85
+drop table t,r;
+deallocate prepare stmt;
+# FirstMatch PS
+# =============
+prepare stmt from "
+delete from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+";
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+create table t as
+select * from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+execute stmt;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+create table r as
+select * from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+execute stmt;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+insert into customer select * from r;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+drop table t,r;
+deallocate prepare stmt;
+# Materialization PS
+# ==================
+prepare stmt from "
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08') and c_name like ?;
+";
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000005 794.47
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000035 1228.24
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000040 1335.3
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000098 -551.37
+Customer#000000109 -716.1
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000136 -842.39
+Customer#000000140 9963.15
+set @a1='Customer#%1_';
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08') and c_name like @a1;
+execute stmt using @a1;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000005 794.47
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000035 1228.24
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000040 1335.3
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000098 -551.37
+Customer#000000109 -716.1
+Customer#000000136 -842.39
+Customer#000000140 9963.15
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000005 794.47
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000035 1228.24
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000040 1335.3
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000098 -551.37
+Customer#000000109 -716.1
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000136 -842.39
+Customer#000000140 9963.15
+set @a2='Customer#%3_';
+create table r as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08') and c_name like @a2;
+execute stmt using @a2;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000005 794.47
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000040 1335.3
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000098 -551.37
+Customer#000000109 -716.1
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000140 9963.15
+insert into customer select * from r;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000005 794.47
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000035 1228.24
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000040 1335.3
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000098 -551.37
+Customer#000000109 -716.1
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000136 -842.39
+Customer#000000140 9963.15
+drop table t,r;
+deallocate prepare stmt;
+# Materialization SJM PS
+# ======================
+prepare stmt from "
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08') and c_acctbal between ? and ?;
+";
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+set @a1=3500;
+set @a2=4000;
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1) and c_acctbal between @a1 and @a2;
+execute stmt using @a1, @a2;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+set @a3=-1000;
+set @a4=3500;
+create table r as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1) and c_acctbal between @a3 and @a4;
+execute stmt using @a3, @a4;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+insert into customer select * from r;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+drop table t,r;
+deallocate prepare stmt;
+# Pullout SP
+# ==========
+create procedure p(a1 int, a2 int)
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU')) and o_totalprice between a1 and a2;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+644 201268.06
+737 12984.85
+create table t as
+select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU')) and o_totalprice between 150000 and 200000;
+call p(150000, 200000);
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+644 201268.06
+737 12984.85
+insert into orders select * from t;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+644 201268.06
+737 12984.85
+create table r as
+select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU')) and o_totalprice between 180000 and 210000;
+call p(180000, 210000);
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5121 150334.57
+737 12984.85
+insert into orders select * from r;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+644 201268.06
+737 12984.85
+drop table t,r;
+drop procedure p;
+# FirstMatch SP
+# =============
+create procedure p(a int)
+delete from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08') and c_acctbal > a;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+create table t as
+select * from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08') and c_acctbal > 4000;
+call p(4000);
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000097 2164.48
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000133 2314.67
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+create table r as
+select * from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08') and c_acctbal > 2000;
+call p(2000);
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000047 274.58
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+insert into customer select * from r;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+drop table t,r;
+drop procedure p;
+# Materialization SP
+# ==================
+create procedure p()
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000140 9963.15
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+call p();
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000140 9963.15
+create table r as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+call p();
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+insert into customer select * from r;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000140 9963.15
+drop table t,r;
+drop procedure p;
+# Materialization SJM SP
+# ======================
+create procedure p()
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+call p();
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+create table r as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+call p();
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+insert into customer select * from r;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+drop table t,r;
+drop procedure p;
+# Checking limitations
+# ====================
+# Check for DELETE ... RETURNING with SJ subquery in WHERE
+select c_name from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name
+Customer#000000013
+Customer#000000016
+Customer#000000025
+Customer#000000032
+Customer#000000037
+Customer#000000038
+Customer#000000052
+Customer#000000056
+Customer#000000065
+Customer#000000076
+Customer#000000091
+Customer#000000115
+Customer#000000116
+Customer#000000118
+Customer#000000140
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+explain
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08') returning c_name;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL NULL NULL NULL NULL 141 Using where
+2 DEPENDENT SUBQUERY orders index_subquery|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 func 175 (2%) Using where; Using rowid filter
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08') returning c_name;
+c_name
+Customer#000000013
+Customer#000000016
+Customer#000000025
+Customer#000000032
+Customer#000000037
+Customer#000000038
+Customer#000000052
+Customer#000000056
+Customer#000000065
+Customer#000000076
+Customer#000000091
+Customer#000000115
+Customer#000000116
+Customer#000000118
+Customer#000000140
+select c_name from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name
+insert into customer select * from t;
+select c_name from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name
+Customer#000000013
+Customer#000000016
+Customer#000000025
+Customer#000000032
+Customer#000000037
+Customer#000000038
+Customer#000000052
+Customer#000000056
+Customer#000000065
+Customer#000000076
+Customer#000000091
+Customer#000000115
+Customer#000000116
+Customer#000000118
+Customer#000000140
+drop table t;
+select c_name from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name
+Customer#000000013
+Customer#000000032
+Customer#000000037
+Customer#000000056
+Customer#000000118
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+explain
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1) returning c_name;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL NULL NULL NULL NULL 141 Using where
+2 DEPENDENT SUBQUERY orders range i_o_orderdate i_o_orderdate 4 NULL 28 Using index condition; Using temporary
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1) returning c_name;
+c_name
+Customer#000000013
+Customer#000000032
+Customer#000000037
+Customer#000000056
+Customer#000000118
+select c_name from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name
+insert into customer select * from t;
+select c_name from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name
+Customer#000000013
+Customer#000000032
+Customer#000000037
+Customer#000000056
+Customer#000000118
+drop table t;
+# Check for DELETE ... RETURNING with SJ subquery in WHERE
+select c_name from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name
+Customer#000000013
+Customer#000000016
+Customer#000000025
+Customer#000000032
+Customer#000000037
+Customer#000000038
+Customer#000000052
+Customer#000000056
+Customer#000000065
+Customer#000000076
+Customer#000000091
+Customer#000000115
+Customer#000000116
+Customer#000000118
+Customer#000000140
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+explain
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08') returning c_name;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL NULL NULL NULL NULL 141 Using where
+2 DEPENDENT SUBQUERY orders index_subquery|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 func 175 (2%) Using where; Using rowid filter
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08') returning c_name;
+c_name
+Customer#000000013
+Customer#000000016
+Customer#000000025
+Customer#000000032
+Customer#000000037
+Customer#000000038
+Customer#000000052
+Customer#000000056
+Customer#000000065
+Customer#000000076
+Customer#000000091
+Customer#000000115
+Customer#000000116
+Customer#000000118
+Customer#000000140
+select c_name from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name
+insert into customer select * from t;
+drop table t;
+# Check for DELETE ... ORDER BY ...LIMIT with SJ subquery in WHERE
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+o_orderkey o_totalprice
+1221 117397.16
+1856 189361.42
+324 26868.85
+4903 34363.63
+5607 24660.06
+# Should not use semi-join conversion because has ORDER BY ... LIMIT
+explain
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2))
+order by o_totalprice limit 500;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY orders range i_o_orderdate i_o_orderdate 4 NULL 108 Using where; Using filesort
+2 DEPENDENT SUBQUERY customer unique_subquery|filter PRIMARY,i_c_nationkey PRIMARY|i_c_nationkey 4|5 func 1 (10%) Using where; Using rowid filter
+create table t as
+select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+select o_orderkey, o_totalprice from t;
+o_orderkey o_totalprice
+1221 117397.16
+324 26868.85
+1856 189361.42
+4903 34363.63
+5607 24660.06
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2))
+order by o_totalprice limit 500;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+o_orderkey o_totalprice
+insert into orders select * from t;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+o_orderkey o_totalprice
+1221 117397.16
+1856 189361.42
+324 26868.85
+4903 34363.63
+5607 24660.06
+drop table t;
+# Should use semi-join converion
+explain
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer range PRIMARY,i_c_nationkey i_c_nationkey 5 NULL 14 Using index condition
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 12 (7%) Using where; Using rowid filter
+create table t as
+select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+select o_orderkey, o_totalprice from t;
+o_orderkey o_totalprice
+1221 117397.16
+324 26868.85
+1856 189361.42
+4903 34363.63
+5607 24660.06
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+o_orderkey o_totalprice
+insert into orders select * from t;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+o_orderkey o_totalprice
+1221 117397.16
+1856 189361.42
+324 26868.85
+4903 34363.63
+5607 24660.06
+drop table t;
+DROP DATABASE dbt3_s001;
diff --git a/mysql-test/main/delete_single_to_multi.test b/mysql-test/main/delete_single_to_multi.test
new file mode 100644
index 0000000..7d4811f
--- /dev/null
+++ b/mysql-test/main/delete_single_to_multi.test
@@ -0,0 +1,797 @@
+--disable_warnings
+DROP DATABASE IF EXISTS dbt3_s001;
+--enable_warnings
+
+CREATE DATABASE dbt3_s001;
+
+use dbt3_s001;
+
+--disable_query_log
+--disable_result_log
+--disable_warnings
+--source include/dbt3_s001.inc
+--enable_warnings
+--enable_result_log
+--enable_query_log
+
+create index i_n_name on nation(n_name);
+analyze table nation;
+
+
+--echo # Pullout
+--echo # =======
+
+let $c1=
+ o_orderDATE between '1992-01-01' and '1992-06-30' and
+ o_custkey in (select c_custkey from customer
+ where c_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+
+eval
+explain
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+explain format=json
+select o_orderkey, o_totalprice from orders where $c1;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+create table t as
+select * from orders where $c1;
+
+eval
+explain
+delete from orders where $c1;
+eval
+explain format=json
+delete from orders where $c1;
+eval
+delete from orders where $c1;
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+
+
+insert into orders select * from t;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+drop table t;
+
+
+let $c2=
+ (ps_partkey, ps_suppkey) in
+ (select p_partkey, s_suppkey from part, supplier
+ where p_retailprice between 901 and 910 and
+ s_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+
+eval
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+--sorted_result
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+eval
+create table t as
+select * from partsupp where $c2;
+
+eval
+explain
+delete from partsupp where $c2;
+eval
+delete from partsupp where $c2;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+
+insert into partsupp select * from t;
+--sorted_result
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+drop table t;
+
+
+let $c3=
+ ps_partkey in (select p_partkey from part
+ where p_retailprice between 901 and 910) and
+ ps_suppkey in (select s_suppkey from supplier
+ where s_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+eval
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+--sorted_result
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+eval
+create table t as
+select * from partsupp where $c3;
+
+eval
+explain
+delete from partsupp where $c3;
+eval
+delete from partsupp where $c3;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+
+insert into partsupp select * from t;
+--sorted_result
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+drop table t;
+
+
+let $c4=
+ l_orderkey in (select o_orderkey from orders
+ where o_custkey in
+ (select c_custkey from customer
+ where c_nationkey in
+ (select n_nationkey from nation
+ where n_name='PERU'))
+ and
+ o_orderDATE between '1992-06-30' and '1992-12-31')
+ and
+ (l_partkey, l_suppkey) in
+ (select p_partkey, s_suppkey from part, supplier
+ where p_retailprice between 901 and 1000 and
+ s_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+
+eval
+explain
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+--sorted_result
+eval
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+eval
+create table t as
+select * from lineitem where $c4;
+
+eval
+explain
+delete from lineitem where $c4;
+eval
+delete from lineitem where $c4;
+eval
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+
+insert into lineitem select * from t;
+--sorted_result
+eval
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+drop table t;
+
+
+--echo # FirstMatch
+--echo # ==========
+
+let $c5=
+ c_nationkey in (select n_nationkey from nation
+ where n_regionkey in (1,2))
+ and
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-10-09' and '1993-03-08');
+
+eval
+explain
+select c_name, c_acctbal from customer where $c5;
+eval
+explain format=json
+select c_name, c_acctbal from customer where $c5;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+eval
+create table t as
+select * from customer where $c5;
+
+eval
+explain
+delete from customer where $c5;
+eval
+explain format=json
+delete from customer where $c5;
+eval
+delete from customer where $c5;
+eval
+select c_name, c_acctbal from customer where $c5;
+
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+drop table t;
+
+
+let $c6=
+ c_nationkey in (select n_nationkey from nation where n_name='PERU')
+ and
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between "1992-01-09" and "1993-01-08");
+
+eval
+explain
+select c_name, c_acctbal from customer where $c6;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c6;
+eval
+create table t as
+select * from customer where $c6;
+
+eval
+explain
+delete from customer where $c6;
+eval
+delete from customer where $c6;
+eval
+select c_name, c_acctbal from customer where $c6;
+
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c6;
+drop table t;
+
+
+--echo # Materialization
+--echo # ===============
+
+let $c7=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-01-09' and '1992-03-08');
+
+eval
+explain
+select c_name, c_acctbal from customer where $c7;
+eval
+explain format=json
+select c_name, c_acctbal from customer where $c7;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+eval
+create table t as
+select * from customer where $c7;
+
+eval
+explain
+delete from customer where $c7;
+eval
+explain format=json
+delete from customer where $c7;
+eval
+delete from customer where $c7;
+eval
+select c_name, c_acctbal from customer where $c7;
+
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+drop table t;
+
+
+let $c8=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-06-09' and '1993-01-08');
+
+eval
+explain
+select c_name, c_acctbal from customer where $c8;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c8;
+eval
+create table t as
+select * from customer where $c8;
+
+eval
+explain
+delete from customer where $c8;
+eval
+delete from customer where $c8;
+eval
+select c_name, c_acctbal from customer where $c8;
+
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c8;
+drop table t;
+
+
+--echo # Materialization SJM
+--echo # ===================
+
+let $c9=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+
+eval
+explain
+select c_name, c_acctbal from customer where $c9;
+eval
+explain format=json
+select c_name, c_acctbal from customer where $c9;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+eval
+create table t as
+select * from customer where $c9;
+
+eval
+explain
+delete from customer where $c9;
+eval
+explain format=json
+delete from customer where $c9;
+eval
+delete from customer where $c9;
+eval
+select c_name, c_acctbal from customer where $c9;
+
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+drop table t;
+
+
+let $c10=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+
+eval
+explain
+select c_name, c_acctbal from customer where $c10;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c10;
+eval
+create table t as
+select * from customer where $c10;
+
+eval
+explain
+delete from customer where $c10;
+eval
+delete from customer where $c10;
+eval
+select c_name, c_acctbal from customer where $c10;
+
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c10;
+drop table t;
+
+
+--echo # Pullout PS
+--echo # ==========
+
+eval
+prepare stmt from "
+delete from orders where $c1;
+";
+
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+create table t as
+select * from orders where $c1;
+execute stmt;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+insert into orders select * from t;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+create table r as
+select * from orders where $c1;
+execute stmt;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+insert into orders select * from r;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+drop table t,r;
+
+deallocate prepare stmt;
+
+
+--echo # FirstMatch PS
+--echo # =============
+
+eval
+prepare stmt from "
+delete from customer where $c5;
+";
+
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+eval
+create table t as
+select * from customer where $c5;
+execute stmt;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+eval
+create table r as
+select * from customer where $c5;
+execute stmt;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+insert into customer select * from r;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+drop table t,r;
+
+deallocate prepare stmt;
+
+
+--echo # Materialization PS
+--echo # ==================
+
+eval
+prepare stmt from "
+delete from customer where $c7 and c_name like ?;
+";
+
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+set @a1='Customer#%1_';
+eval
+create table t as
+select * from customer where $c7 and c_name like @a1;
+execute stmt using @a1;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+set @a2='Customer#%3_';
+eval
+create table r as
+select * from customer where $c7 and c_name like @a2;
+execute stmt using @a2;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+insert into customer select * from r;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+drop table t,r;
+
+deallocate prepare stmt;
+
+
+--echo # Materialization SJM PS
+--echo # ======================
+
+eval
+prepare stmt from "
+delete from customer where $c7 and c_acctbal between ? and ?;
+";
+
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+set @a1=3500;
+set @a2=4000;
+eval
+create table t as
+select * from customer where $c9 and c_acctbal between @a1 and @a2;
+execute stmt using @a1, @a2;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+set @a3=-1000;
+set @a4=3500;
+eval
+create table r as
+select * from customer where $c9 and c_acctbal between @a3 and @a4;
+execute stmt using @a3, @a4;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+insert into customer select * from r;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+drop table t,r;
+
+deallocate prepare stmt;
+
+
+--echo # Pullout SP
+--echo # ==========
+
+eval
+create procedure p(a1 int, a2 int)
+delete from orders where $c1 and o_totalprice between a1 and a2;
+
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+create table t as
+select * from orders where $c1 and o_totalprice between 150000 and 200000;
+call p(150000, 200000);
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+insert into orders select * from t;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+create table r as
+select * from orders where $c1 and o_totalprice between 180000 and 210000;
+call p(180000, 210000);
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+insert into orders select * from r;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+drop table t,r;
+
+drop procedure p;
+
+
+--echo # FirstMatch SP
+--echo # =============
+
+eval
+create procedure p(a int)
+delete from customer where $c5 and c_acctbal > a;
+
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+eval
+create table t as
+select * from customer where $c5 and c_acctbal > 4000;
+call p(4000);
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+eval
+create table r as
+select * from customer where $c5 and c_acctbal > 2000;
+call p(2000);
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+insert into customer select * from r;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+drop table t,r;
+
+drop procedure p;
+
+
+--echo # Materialization SP
+--echo # ==================
+
+eval
+create procedure p()
+delete from customer where $c7;
+
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+eval
+create table t as
+select * from customer where $c7;
+call p();
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+eval
+create table r as
+select * from customer where $c7;
+call p();
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+insert into customer select * from r;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+drop table t,r;
+
+drop procedure p;
+
+
+--echo # Materialization SJM SP
+--echo # ======================
+
+eval
+create procedure p()
+delete from customer where $c9;
+
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+eval
+create table t as
+select * from customer where $c9;
+call p();
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+eval
+create table r as
+select * from customer where $c9;
+call p();
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+insert into customer select * from r;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+drop table t,r;
+
+drop procedure p;
+
+--echo # Checking limitations
+--echo # ====================
+
+--echo # Check for DELETE ... RETURNING with SJ subquery in WHERE
+
+--sorted_result
+eval
+select c_name from customer where $c7;
+eval
+create table t as
+select * from customer where $c7;
+eval
+explain
+delete from customer where $c7 returning c_name;
+--sorted_result
+eval
+delete from customer where $c7 returning c_name;
+--sorted_result
+eval
+select c_name from customer where $c7;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name from customer where $c7;
+drop table t;
+
+--sorted_result
+eval
+select c_name from customer where $c9;
+eval
+create table t as
+select * from customer where $c9;
+eval
+explain
+delete from customer where $c9 returning c_name;
+--sorted_result
+eval
+delete from customer where $c9 returning c_name;
+--sorted_result
+eval
+select c_name from customer where $c9;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name from customer where $c9;
+drop table t;
+
+--echo # Check for DELETE ... RETURNING with SJ subquery in WHERE
+
+--sorted_result
+eval
+select c_name from customer where $c7;
+eval
+create table t as
+select * from customer where $c7;
+eval
+explain
+delete from customer where $c7 returning c_name;
+--sorted_result
+eval
+delete from customer where $c7 returning c_name;
+--sorted_result
+eval
+select c_name from customer where $c7;
+insert into customer select * from t;
+drop table t;
+
+--echo # Check for DELETE ... ORDER BY ...LIMIT with SJ subquery in WHERE
+
+let $c11=
+ o_orderDATE between '1992-01-01' and '1992-06-30' and
+ o_custkey in (select c_custkey from customer
+ where c_nationkey in (1,2));
+
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c11;
+
+--echo # Should not use semi-join conversion because has ORDER BY ... LIMIT
+eval
+explain
+delete from orders where $c11
+order by o_totalprice limit 500;
+eval
+create table t as
+select * from orders where $c11;
+select o_orderkey, o_totalprice from t;
+eval
+delete from orders where $c11
+order by o_totalprice limit 500;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c11;
+insert into orders select * from t;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c11;
+drop table t;
+
+--echo # Should use semi-join converion
+eval
+explain
+delete from orders where $c11;
+eval
+create table t as
+select * from orders where $c11;
+select o_orderkey, o_totalprice from t;
+eval
+delete from orders where $c11;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c11;
+insert into orders select * from t;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c11;
+drop table t;
+
+DROP DATABASE dbt3_s001;
diff --git a/mysql-test/main/log_state.result b/mysql-test/main/log_state.result
index 5e7aac8..1b1c737 100644
--- a/mysql-test/main/log_state.result
+++ b/mysql-test/main/log_state.result
@@ -243,7 +243,7 @@ rows_examined sql_text
4 UPDATE t1 SET a=a+sleep(.02) WHERE a>2
8 UPDATE t1 SET a=a+sleep(.02) ORDER BY a DESC
1 UPDATE t2 set b=b+sleep(.02) limit 1
-4 UPDATE t1 SET a=a+sleep(.02) WHERE a in (SELECT b from t2)
+10 UPDATE t1 SET a=a+sleep(.02) WHERE a in (SELECT b from t2)
6 DELETE FROM t1 WHERE a=a+sleep(.02) ORDER BY a LIMIT 2
disconnect con2;
connection default;
diff --git a/mysql-test/main/myisam_explain_non_select_all.result b/mysql-test/main/myisam_explain_non_select_all.result
index 20b769b..5df9ced 100644
--- a/mysql-test/main/myisam_explain_non_select_all.result
+++ b/mysql-test/main/myisam_explain_non_select_all.result
@@ -240,14 +240,16 @@ Warnings:
Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
EXPLAIN UPDATE t1 SET a = 10 WHERE 1 IN (SELECT 1 FROM t2 WHERE t2.b < 3);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
-2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED UPDATE t1 SET a = 10 WHERE 1 IN (SELECT 1 FROM t2 WHERE t2.b < 3);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
-2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 100.00 Using where
# Status of EXPLAIN EXTENDED query
Variable_name Value
Handler_read_key 4
@@ -271,8 +273,9 @@ Handler_read_key 5
Handler_read_rnd_next 8
# Status of testing query execution:
Variable_name Value
-Handler_read_key 4
-Handler_read_rnd_next 5
+Handler_read_key 5
+Handler_read_rnd 3
+Handler_read_rnd_next 12
Handler_update 3
DROP TABLE t1, t2;
@@ -290,13 +293,13 @@ Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be
EXPLAIN UPDATE t1 SET a = 10 WHERE a IN (SELECT b FROM t2 WHERE t1.a < 3);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
-2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY t2 ALL NULL NULL NULL NULL 3 Using where; FirstMatch(t1)
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED UPDATE t1 SET a = 10 WHERE a IN (SELECT b FROM t2 WHERE t1.a < 3);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
-2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where
+1 PRIMARY t2 ALL NULL NULL NULL NULL 3 100.00 Using where; FirstMatch(t1)
Warnings:
Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1
# Status of EXPLAIN EXTENDED query
@@ -984,14 +987,16 @@ Warnings:
Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
EXPLAIN UPDATE t1 SET a = 10 WHERE a IN (SELECT a FROM t2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
-2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED UPDATE t1 SET a = 10 WHERE a IN (SELECT a FROM t2);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
-2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 100.00
# Status of EXPLAIN EXTENDED query
Variable_name Value
Handler_read_key 4
@@ -1015,8 +1020,8 @@ Handler_read_key 7
Handler_read_rnd_next 8
# Status of testing query execution:
Variable_name Value
-Handler_read_key 4
-Handler_read_rnd_next 10
+Handler_read_key 7
+Handler_read_rnd_next 8
Handler_update 3
DROP TABLE t1, t2;
@@ -1079,14 +1084,14 @@ Warnings:
Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
EXPLAIN DELETE FROM t1 WHERE a1 IN (SELECT a2 FROM t2 WHERE a2 > 2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where
-2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 5 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5
+1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using where; FirstMatch(t1)
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED DELETE FROM t1 WHERE a1 IN (SELECT a2 FROM t2 WHERE a2 > 2);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 5 100.00 Using where
-2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5 100.00
+1 PRIMARY t2 ALL NULL NULL NULL NULL 5 100.00 Using where; FirstMatch(t1)
# Status of EXPLAIN EXTENDED query
Variable_name Value
Handler_read_key 4
@@ -3074,14 +3079,14 @@ Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be
EXPLAIN UPDATE t1 SET a = 10 WHERE a IN (SELECT * FROM (SELECT b FROM t2 ORDER BY b LIMIT 2,2) x);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
-2 DEPENDENT SUBQUERY <derived3> index_subquery key0 key0 5 func 2
+1 PRIMARY <derived3> ref key0 key0 5 test.t1.a 2 FirstMatch(t1)
3 DERIVED t2 ALL NULL NULL NULL NULL 3 Using filesort
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED UPDATE t1 SET a = 10 WHERE a IN (SELECT * FROM (SELECT b FROM t2 ORDER BY b LIMIT 2,2) x);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
-2 DEPENDENT SUBQUERY <derived3> index_subquery key0 key0 5 func 2 100.00
+1 PRIMARY <derived3> ref key0 key0 5 test.t1.a 2 100.00 FirstMatch(t1)
3 DERIVED t2 ALL NULL NULL NULL NULL 3 100.00 Using filesort
# Status of EXPLAIN EXTENDED query
Variable_name Value
diff --git a/mysql-test/main/opt_trace.result b/mysql-test/main/opt_trace.result
index 0555f72..e46bd80 100644
--- a/mysql-test/main/opt_trace.result
+++ b/mysql-test/main/opt_trace.result
@@ -3948,6 +3948,16 @@ explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3 {
}
},
{
+ "table": "t0",
+ "rowid_filters": [
+ {
+ "key": "a",
+ "build_cost": 0.174715752,
+ "rows": 3
+ }
+ ]
+ },
+ {
"selectivity_for_indexes": [
{
"index_name": "a",
@@ -4013,6 +4023,16 @@ explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3 {
}
},
{
+ "table": "t1",
+ "rowid_filters": [
+ {
+ "key": "a",
+ "build_cost": 0.174715752,
+ "rows": 3
+ }
+ ]
+ },
+ {
"selectivity_for_indexes": [
{
"index_name": "a",
diff --git a/mysql-test/main/update_single_to_multi.result b/mysql-test/main/update_single_to_multi.result
new file mode 100644
index 0000000..015fd06
--- /dev/null
+++ b/mysql-test/main/update_single_to_multi.result
@@ -0,0 +1,2302 @@
+DROP DATABASE IF EXISTS dbt3_s001;
+CREATE DATABASE dbt3_s001;
+use dbt3_s001;
+create index i_n_name on nation(n_name);
+analyze table nation;
+Table Op Msg_type Msg_text
+dbt3_s001.nation analyze status Engine-independent statistics collected
+dbt3_s001.nation analyze status OK
+# Pullout
+# =======
+explain
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (7%) Using where; Using rowid filter
+explain format=json
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_n_name"],
+ "key": "i_n_name",
+ "key_length": "26",
+ "used_key_parts": ["n_name"],
+ "ref": ["const"],
+ "rows": 1,
+ "filtered": 100,
+ "index_condition": "nation.n_name = 'PERU'"
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "key": "i_c_nationkey",
+ "key_length": "5",
+ "used_key_parts": ["c_nationkey"],
+ "ref": ["dbt3_s001.nation.n_nationkey"],
+ "rows": 11,
+ "filtered": 100
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 108,
+ "selectivity_pct": 7.2
+ },
+ "rows": 11,
+ "filtered": 7.199999809,
+ "attached_condition": "orders.o_orderDATE between '1992-01-01' and '1992-06-30'"
+ }
+ }
+ ]
+ }
+}
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201268.06
+2880 145761.99
+3142 16030.15
+5382 138423.03
+5095 184583.99
+737 12984.85
+1729 12137.76
+5121 150334.57
+explain
+update orders set o_totalprice = o_totalprice-50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (7%) Using where; Using rowid filter
+explain format=json
+update orders set o_totalprice = o_totalprice-50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_n_name"],
+ "key": "i_n_name",
+ "key_length": "26",
+ "used_key_parts": ["n_name"],
+ "ref": ["const"],
+ "rows": 1,
+ "filtered": 100,
+ "index_condition": "nation.n_name = 'PERU'"
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "key": "i_c_nationkey",
+ "key_length": "5",
+ "used_key_parts": ["c_nationkey"],
+ "ref": ["dbt3_s001.nation.n_nationkey"],
+ "rows": 11,
+ "filtered": 100
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 108,
+ "selectivity_pct": 7.2
+ },
+ "rows": 11,
+ "filtered": 7.199999809,
+ "attached_condition": "orders.o_orderDATE between '1992-01-01' and '1992-06-30'"
+ }
+ }
+ ]
+ }
+}
+update orders set o_totalprice = o_totalprice-50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201218.06
+2880 145711.99
+3142 15980.15
+5382 138373.03
+5095 184533.99
+737 12934.85
+1729 12087.76
+5121 150284.57
+update orders set o_totalprice= o_totalprice+50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201268.06
+2880 145761.99
+3142 16030.15
+5382 138423.03
+5095 184583.99
+737 12984.85
+1729 12137.76
+5121 150334.57
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+4 1 444.37
+6 1 642.13
+8 1 957.34
+1 8 357.84
+3 8 645.4
+5 8 50.52
+7 8 763.98
+explain
+update partsupp set ps_supplycost = ps_supplycost+2 where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+update partsupp set ps_supplycost = ps_supplycost+2 where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+4 1 446.37
+6 1 644.13
+8 1 959.34
+1 8 359.84
+3 8 647.4
+5 8 52.52
+7 8 765.98
+update partsupp set ps_supplycost = ps_supplycost-2 where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+4 1 444.37
+6 1 642.13
+8 1 957.34
+1 8 357.84
+3 8 645.4
+5 8 50.52
+7 8 763.98
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+4 1 444.37
+6 1 642.13
+8 1 957.34
+1 8 357.84
+3 8 645.4
+5 8 50.52
+7 8 763.98
+explain
+update partsupp set ps_supplycost = ps_supplycost+10 where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+update partsupp set ps_supplycost = ps_supplycost+10 where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+4 1 454.37
+6 1 652.13
+8 1 967.34
+1 8 367.84
+3 8 655.4
+5 8 60.52
+7 8 773.98
+update partsupp set ps_supplycost = ps_supplycost-10 where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+4 1 444.37
+6 1 642.13
+8 1 957.34
+1 8 357.84
+3 8 645.4
+5 8 50.52
+7 8 763.98
+explain
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY lineitem ref PRIMARY,i_l_suppkey_partkey,i_l_partkey,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity i_l_suppkey 5 dbt3_s001.supplier.s_suppkey 100 Using where
+1 PRIMARY orders eq_ref|filter PRIMARY,i_o_orderdate,i_o_custkey PRIMARY|i_o_orderdate 4|4 dbt3_s001.lineitem.l_orderkey 1 (7%) Using where; Using rowid filter
+1 PRIMARY customer eq_ref PRIMARY,i_c_nationkey PRIMARY 4 dbt3_s001.orders.o_custkey 1 Using where
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.lineitem.l_partkey 1 Using where
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+l_orderkey l_linenumber l_tax
+4996 1 0.01
+933 1 0.04
+2500 2 0.02
+2500 4 0.02
+explain
+update lineitem set l_tax = (l_tax*100+1)/100 where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY lineitem ref PRIMARY,i_l_suppkey_partkey,i_l_partkey,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity i_l_suppkey 5 dbt3_s001.supplier.s_suppkey 100 Using where
+1 PRIMARY orders eq_ref|filter PRIMARY,i_o_orderdate,i_o_custkey PRIMARY|i_o_orderdate 4|4 dbt3_s001.lineitem.l_orderkey 1 (7%) Using where; Using rowid filter
+1 PRIMARY customer eq_ref PRIMARY,i_c_nationkey PRIMARY 4 dbt3_s001.orders.o_custkey 1 Using where
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.lineitem.l_partkey 1 Using where
+update lineitem set l_tax = (l_tax*100+1)/100 where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+l_orderkey l_linenumber l_tax
+4996 1 0.02
+933 1 0.05
+2500 2 0.03
+2500 4 0.03
+update lineitem set l_tax = (l_tax*100-1)/100 where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+l_orderkey l_linenumber l_tax
+4996 1 0.01
+933 1 0.04
+2500 2 0.02
+2500 4 0.02
+# FirstMatch
+# ==========
+explain
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY,i_c_nationkey NULL NULL NULL 150 Using where
+1 PRIMARY nation eq_ref|filter PRIMARY,i_n_regionkey PRIMARY|i_n_regionkey 4|5 dbt3_s001.customer.c_nationkey 1 (40%) Using where; Using rowid filter
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (6%) Using where; FirstMatch(nation); Using rowid filter
+explain format=json
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ALL",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "rows": 150,
+ "filtered": 100,
+ "attached_condition": "customer.c_nationkey is not null"
+ }
+ },
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY", "i_n_regionkey"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["n_nationkey"],
+ "ref": ["dbt3_s001.customer.c_nationkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_n_regionkey",
+ "used_key_parts": ["n_regionkey"]
+ },
+ "rows": 10,
+ "selectivity_pct": 40
+ },
+ "rows": 1,
+ "filtered": 40,
+ "attached_condition": "nation.n_regionkey in (1,2)"
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 89,
+ "selectivity_pct": 5.933333333
+ },
+ "rows": 11,
+ "filtered": 5.933333397,
+ "attached_condition": "orders.o_orderDATE between '1992-10-09' and '1993-03-08'",
+ "first_match": "nation"
+ }
+ }
+ ]
+ }
+}
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+explain
+update customer set c_acctbal = c_acctbal+10 where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY,i_c_nationkey NULL NULL NULL 150 Using where
+1 PRIMARY nation eq_ref|filter PRIMARY,i_n_regionkey PRIMARY|i_n_regionkey 4|5 dbt3_s001.customer.c_nationkey 1 (40%) Using where; Using rowid filter
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (6%) Using where; FirstMatch(nation); Using rowid filter
+explain format=json
+update customer set c_acctbal = c_acctbal+10 where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ALL",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "rows": 150,
+ "filtered": 100,
+ "attached_condition": "customer.c_nationkey is not null"
+ }
+ },
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY", "i_n_regionkey"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["n_nationkey"],
+ "ref": ["dbt3_s001.customer.c_nationkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_n_regionkey",
+ "used_key_parts": ["n_regionkey"]
+ },
+ "rows": 10,
+ "selectivity_pct": 40
+ },
+ "rows": 1,
+ "filtered": 40,
+ "attached_condition": "nation.n_regionkey in (1,2)"
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 89,
+ "selectivity_pct": 5.933333333
+ },
+ "rows": 11,
+ "filtered": 5.933333397,
+ "attached_condition": "orders.o_orderDATE between '1992-10-09' and '1993-03-08'",
+ "first_match": "nation"
+ }
+ }
+ ]
+ }
+}
+update customer set c_acctbal = c_acctbal+10 where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9571.95
+Customer#000000019 8924.71
+Customer#000000022 601.98
+Customer#000000025 7143.7
+Customer#000000028 1017.18
+Customer#000000037 -907.75
+Customer#000000040 1345.3
+Customer#000000047 284.58
+Customer#000000059 3468.6
+Customer#000000061 1546.24
+Customer#000000064 -636.64
+Customer#000000067 8176.59
+Customer#000000082 9478.34
+Customer#000000091 4653.14
+Customer#000000094 5510.11
+Customer#000000097 2174.48
+Customer#000000101 7480.96
+Customer#000000103 2767.45
+Customer#000000106 3298.42
+Customer#000000115 7518.92
+Customer#000000121 6438.32
+Customer#000000122 7875.46
+Customer#000000127 9290.71
+Customer#000000130 5083.58
+Customer#000000133 2324.67
+Customer#000000139 7907.78
+update customer set c_acctbal = c_acctbal-10 where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+explain
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (14%) Using where; FirstMatch(customer); Using rowid filter
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+c_name c_acctbal
+Customer#000000008 6819.74
+Customer#000000035 1228.24
+Customer#000000061 1536.24
+Customer#000000097 2164.48
+Customer#000000121 6428.32
+Customer#000000133 2314.67
+explain
+update customer set c_acctbal = c_acctbal+20 where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (14%) Using where; FirstMatch(customer); Using rowid filter
+update customer set c_acctbal = c_acctbal+20 where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+c_name c_acctbal
+Customer#000000008 6839.74
+Customer#000000035 1248.24
+Customer#000000061 1556.24
+Customer#000000097 2184.48
+Customer#000000121 6448.32
+Customer#000000133 2334.67
+update customer set c_acctbal = c_acctbal-20 where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+c_name c_acctbal
+Customer#000000008 6819.74
+Customer#000000035 1228.24
+Customer#000000061 1536.24
+Customer#000000097 2164.48
+Customer#000000121 6428.32
+Customer#000000133 2314.67
+# Materialization
+# ===============
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 dbt3_s001.orders.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 28 Using index condition; Using where
+explain format=json
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'",
+ "attached_condition": "orders.o_custkey is not null"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["dbt3_s001.orders.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7133.7
+Customer#000000013 3857.34
+Customer#000000065 8795.16
+Customer#000000032 3471.53
+Customer#000000023 3332.02
+Customer#000000035 1228.24
+Customer#000000091 4643.14
+Customer#000000016 4681.03
+Customer#000000098 -551.37
+Customer#000000037 -917.75
+Customer#000000136 -842.39
+Customer#000000118 3582.37
+Customer#000000022 591.98
+Customer#000000005 794.47
+Customer#000000109 -716.1
+Customer#000000038 6345.11
+Customer#000000076 5745.33
+Customer#000000056 6530.86
+Customer#000000040 1335.3
+Customer#000000116 8403.99
+Customer#000000115 7508.92
+Customer#000000140 9963.15
+Customer#000000017 6.34
+Customer#000000052 5630.28
+explain
+update customer set c_acctbal = c_acctbal+5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 dbt3_s001.orders.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 28 Using index condition; Using where
+explain format=json
+update customer set c_acctbal = c_acctbal+5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'",
+ "attached_condition": "orders.o_custkey is not null"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["dbt3_s001.orders.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+update customer set c_acctbal = c_acctbal+5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7138.7
+Customer#000000013 3862.34
+Customer#000000065 8800.16
+Customer#000000032 3476.53
+Customer#000000023 3337.02
+Customer#000000035 1233.24
+Customer#000000091 4648.14
+Customer#000000016 4686.03
+Customer#000000098 -546.37
+Customer#000000037 -912.75
+Customer#000000136 -837.39
+Customer#000000118 3587.37
+Customer#000000022 596.98
+Customer#000000005 799.47
+Customer#000000109 -711.1
+Customer#000000038 6350.11
+Customer#000000076 5750.33
+Customer#000000056 6535.86
+Customer#000000040 1340.3
+Customer#000000116 8408.99
+Customer#000000115 7513.92
+Customer#000000140 9968.15
+Customer#000000017 11.34
+Customer#000000052 5635.28
+update customer set c_acctbal = c_acctbal-5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7133.7
+Customer#000000013 3857.34
+Customer#000000065 8795.16
+Customer#000000032 3471.53
+Customer#000000023 3332.02
+Customer#000000035 1228.24
+Customer#000000091 4643.14
+Customer#000000016 4681.03
+Customer#000000098 -551.37
+Customer#000000037 -917.75
+Customer#000000136 -842.39
+Customer#000000118 3582.37
+Customer#000000022 591.98
+Customer#000000005 794.47
+Customer#000000109 -716.1
+Customer#000000038 6345.11
+Customer#000000076 5745.33
+Customer#000000056 6530.86
+Customer#000000040 1335.3
+Customer#000000116 8403.99
+Customer#000000115 7508.92
+Customer#000000140 9963.15
+Customer#000000017 6.34
+Customer#000000052 5630.28
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 114 Using index condition; Using where
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+c_name c_acctbal
+Customer#000000001 711.56
+Customer#000000002 121.65
+Customer#000000007 9561.95
+Customer#000000008 6819.74
+Customer#000000010 2753.54
+Customer#000000011 -272.6
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000029 7618.27
+Customer#000000031 5236.89
+Customer#000000034 8589.7
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000043 9904.28
+Customer#000000044 7315.94
+Customer#000000046 5744.59
+Customer#000000047 274.58
+Customer#000000049 4573.94
+Customer#000000053 4113.64
+Customer#000000055 4572.11
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000070 4867.52
+Customer#000000071 -611.19
+Customer#000000073 4288.5
+Customer#000000074 2764.43
+Customer#000000076 5745.33
+Customer#000000079 5121.28
+Customer#000000080 7383.53
+Customer#000000082 9468.34
+Customer#000000083 6463.51
+Customer#000000085 3386.64
+Customer#000000086 3306.32
+Customer#000000088 8031.44
+Customer#000000091 4643.14
+Customer#000000092 1182.91
+Customer#000000095 5327.38
+Customer#000000097 2164.48
+Customer#000000100 9889.89
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000104 -588.38
+Customer#000000106 3288.42
+Customer#000000109 -716.1
+Customer#000000110 7462.99
+Customer#000000112 2953.35
+Customer#000000118 3582.37
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000131 8595.53
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+Customer#000000136 -842.39
+Customer#000000137 7838.3
+Customer#000000139 7897.78
+Customer#000000142 2209.81
+Customer#000000143 2186.5
+Customer#000000148 2135.6
+Customer#000000149 8959.65
+explain
+update customer set c_acctbal = c_acctbal+1 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 114 Using index condition; Using where
+update customer set c_acctbal = c_acctbal+1 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+c_name c_acctbal
+Customer#000000001 712.56
+Customer#000000002 122.65
+Customer#000000007 9562.95
+Customer#000000008 6820.74
+Customer#000000010 2754.54
+Customer#000000011 -271.6
+Customer#000000016 4682.03
+Customer#000000017 7.34
+Customer#000000019 8915.71
+Customer#000000022 592.98
+Customer#000000023 3333.02
+Customer#000000025 7134.7
+Customer#000000028 1008.18
+Customer#000000029 7619.27
+Customer#000000031 5237.89
+Customer#000000034 8590.7
+Customer#000000037 -916.75
+Customer#000000040 1336.3
+Customer#000000043 9905.28
+Customer#000000044 7316.94
+Customer#000000046 5745.59
+Customer#000000047 275.58
+Customer#000000049 4574.94
+Customer#000000053 4114.64
+Customer#000000055 4573.11
+Customer#000000061 1537.24
+Customer#000000064 -645.64
+Customer#000000067 8167.59
+Customer#000000070 4868.52
+Customer#000000071 -610.19
+Customer#000000073 4289.5
+Customer#000000074 2765.43
+Customer#000000076 5746.33
+Customer#000000079 5122.28
+Customer#000000080 7384.53
+Customer#000000082 9469.34
+Customer#000000083 6464.51
+Customer#000000085 3387.64
+Customer#000000086 3307.32
+Customer#000000088 8032.44
+Customer#000000091 4644.14
+Customer#000000092 1183.91
+Customer#000000095 5328.38
+Customer#000000097 2165.48
+Customer#000000100 9890.89
+Customer#000000101 7471.96
+Customer#000000103 2758.45
+Customer#000000104 -587.38
+Customer#000000106 3289.42
+Customer#000000109 -715.1
+Customer#000000110 7463.99
+Customer#000000112 2954.35
+Customer#000000118 3583.37
+Customer#000000121 6429.32
+Customer#000000122 7866.46
+Customer#000000127 9281.71
+Customer#000000130 5074.58
+Customer#000000131 8596.53
+Customer#000000133 2315.67
+Customer#000000134 4609.9
+Customer#000000136 -841.39
+Customer#000000137 7839.3
+Customer#000000139 7898.78
+Customer#000000142 2210.81
+Customer#000000143 2187.5
+Customer#000000148 2136.6
+Customer#000000149 8960.65
+update customer set c_acctbal = c_acctbal-1 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+c_name c_acctbal
+Customer#000000001 711.56
+Customer#000000002 121.65
+Customer#000000007 9561.95
+Customer#000000008 6819.74
+Customer#000000010 2753.54
+Customer#000000011 -272.6
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000029 7618.27
+Customer#000000031 5236.89
+Customer#000000034 8589.7
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000043 9904.28
+Customer#000000044 7315.94
+Customer#000000046 5744.59
+Customer#000000047 274.58
+Customer#000000049 4573.94
+Customer#000000053 4113.64
+Customer#000000055 4572.11
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000070 4867.52
+Customer#000000071 -611.19
+Customer#000000073 4288.5
+Customer#000000074 2764.43
+Customer#000000076 5745.33
+Customer#000000079 5121.28
+Customer#000000080 7383.53
+Customer#000000082 9468.34
+Customer#000000083 6463.51
+Customer#000000085 3386.64
+Customer#000000086 3306.32
+Customer#000000088 8031.44
+Customer#000000091 4643.14
+Customer#000000092 1182.91
+Customer#000000095 5327.38
+Customer#000000097 2164.48
+Customer#000000100 9889.89
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000104 -588.38
+Customer#000000106 3288.42
+Customer#000000109 -716.1
+Customer#000000110 7462.99
+Customer#000000112 2953.35
+Customer#000000118 3582.37
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000131 8595.53
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+Customer#000000136 -842.39
+Customer#000000137 7838.3
+Customer#000000139 7897.78
+Customer#000000142 2209.81
+Customer#000000143 2186.5
+Customer#000000148 2135.6
+Customer#000000149 8959.65
+# Materialization SJM
+# ===================
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 <subquery2>.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 28 Using index condition; Using temporary
+explain format=json
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "having_condition": "count(orders.o_custkey) > 1",
+ "temporary_table": {
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'"
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["<subquery2>.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000118 3582.37
+Customer#000000056 6530.86
+explain
+update customer set c_acctbal = c_acctbal-5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 <subquery2>.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 28 Using index condition; Using temporary
+explain format=json
+update customer set c_acctbal = c_acctbal-5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "having_condition": "count(orders.o_custkey) > 1",
+ "temporary_table": {
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'"
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["<subquery2>.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+update customer set c_acctbal = c_acctbal-5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3852.34
+Customer#000000032 3466.53
+Customer#000000037 -922.75
+Customer#000000118 3577.37
+Customer#000000056 6525.86
+update customer set c_acctbal = c_acctbal+5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000118 3582.37
+Customer#000000056 6530.86
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 dbt3_s001.customer.c_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 242 Using index condition; Using temporary
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000016 4681.03
+Customer#000000037 -917.75
+Customer#000000046 5744.59
+Customer#000000091 4643.14
+Customer#000000103 2757.45
+Customer#000000118 3582.37
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+explain
+update customer set c_acctbal = c_acctbal-1 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 dbt3_s001.customer.c_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 242 Using index condition; Using temporary
+update customer set c_acctbal = c_acctbal-1 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+c_name c_acctbal
+Customer#000000007 9560.95
+Customer#000000016 4680.03
+Customer#000000037 -918.75
+Customer#000000046 5743.59
+Customer#000000091 4642.14
+Customer#000000103 2756.45
+Customer#000000118 3581.37
+Customer#000000133 2313.67
+Customer#000000134 4607.9
+update customer set c_acctbal = c_acctbal+1 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000016 4681.03
+Customer#000000037 -917.75
+Customer#000000046 5744.59
+Customer#000000091 4643.14
+Customer#000000103 2757.45
+Customer#000000118 3582.37
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+# Pullout PS
+# ==========
+prepare stmt from "
+update orders set o_totalprice = o_totalprice+? where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+";
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201268.06
+2880 145761.99
+3142 16030.15
+5382 138423.03
+5095 184583.99
+737 12984.85
+1729 12137.76
+5121 150334.57
+set @a1=-20;
+execute stmt using @a1;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201248.06
+2880 145741.99
+3142 16010.15
+5382 138403.03
+5095 184563.99
+737 12964.85
+1729 12117.76
+5121 150314.57
+set @a2=-10;
+execute stmt using @a2;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201238.06
+2880 145731.99
+3142 16000.15
+5382 138393.03
+5095 184553.99
+737 12954.85
+1729 12107.76
+5121 150304.57
+execute stmt using -(@a1+@a2);
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201268.06
+2880 145761.99
+3142 16030.15
+5382 138423.03
+5095 184583.99
+737 12984.85
+1729 12137.76
+5121 150334.57
+deallocate prepare stmt;
+# FirstMatch PS
+# =============
+prepare stmt from "
+update customer set c_acctbal = c_acctbal+? where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+";
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+set @a1=15;
+execute stmt using @a1;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9576.95
+Customer#000000019 8929.71
+Customer#000000022 606.98
+Customer#000000025 7148.7
+Customer#000000028 1022.18
+Customer#000000037 -902.75
+Customer#000000040 1350.3
+Customer#000000047 289.58
+Customer#000000059 3473.6
+Customer#000000061 1551.24
+Customer#000000064 -631.64
+Customer#000000067 8181.59
+Customer#000000082 9483.34
+Customer#000000091 4658.14
+Customer#000000094 5515.11
+Customer#000000097 2179.48
+Customer#000000101 7485.96
+Customer#000000103 2772.45
+Customer#000000106 3303.42
+Customer#000000115 7523.92
+Customer#000000121 6443.32
+Customer#000000122 7880.46
+Customer#000000127 9295.71
+Customer#000000130 5088.58
+Customer#000000133 2329.67
+Customer#000000139 7912.78
+set @a2=5;
+execute stmt using @a2;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9581.95
+Customer#000000019 8934.71
+Customer#000000022 611.98
+Customer#000000025 7153.7
+Customer#000000028 1027.1799999999998
+Customer#000000037 -897.75
+Customer#000000040 1355.3
+Customer#000000047 294.58
+Customer#000000059 3478.6
+Customer#000000061 1556.24
+Customer#000000064 -626.64
+Customer#000000067 8186.59
+Customer#000000082 9488.34
+Customer#000000091 4663.14
+Customer#000000094 5520.11
+Customer#000000097 2184.48
+Customer#000000101 7490.96
+Customer#000000103 2777.45
+Customer#000000106 3308.42
+Customer#000000115 7528.92
+Customer#000000121 6448.32
+Customer#000000122 7885.46
+Customer#000000127 9300.71
+Customer#000000130 5093.58
+Customer#000000133 2334.67
+Customer#000000139 7917.78
+execute stmt using -(@a1+@a2);
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.1799999999998
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+deallocate prepare stmt;
+# Materialization PS
+# ==================
+prepare stmt from "
+update customer set c_acctbal = c_acctbal+? where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+";
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7133.7
+Customer#000000013 3857.34
+Customer#000000065 8795.16
+Customer#000000032 3471.53
+Customer#000000023 3332.02
+Customer#000000035 1228.24
+Customer#000000091 4643.14
+Customer#000000016 4681.03
+Customer#000000098 -551.37
+Customer#000000037 -917.75
+Customer#000000136 -842.39
+Customer#000000118 3582.37
+Customer#000000022 591.98
+Customer#000000005 794.47
+Customer#000000109 -716.1
+Customer#000000038 6345.11
+Customer#000000076 5745.33
+Customer#000000056 6530.86
+Customer#000000040 1335.3
+Customer#000000116 8403.99
+Customer#000000115 7508.92
+Customer#000000140 9963.15
+Customer#000000017 6.34
+Customer#000000052 5630.28
+set @a1=7;
+execute stmt using @a1;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7140.7
+Customer#000000013 3864.34
+Customer#000000065 8802.16
+Customer#000000032 3478.53
+Customer#000000023 3339.02
+Customer#000000035 1235.24
+Customer#000000091 4650.14
+Customer#000000016 4688.03
+Customer#000000098 -544.37
+Customer#000000037 -910.75
+Customer#000000136 -835.39
+Customer#000000118 3589.37
+Customer#000000022 598.98
+Customer#000000005 801.47
+Customer#000000109 -709.1
+Customer#000000038 6352.11
+Customer#000000076 5752.33
+Customer#000000056 6537.86
+Customer#000000040 1342.3
+Customer#000000116 8410.99
+Customer#000000115 7515.92
+Customer#000000140 9970.15
+Customer#000000017 13.34
+Customer#000000052 5637.28
+set @a2=3;
+execute stmt using @a2;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7143.7
+Customer#000000013 3867.34
+Customer#000000065 8805.16
+Customer#000000032 3481.53
+Customer#000000023 3342.02
+Customer#000000035 1238.24
+Customer#000000091 4653.14
+Customer#000000016 4691.03
+Customer#000000098 -541.37
+Customer#000000037 -907.75
+Customer#000000136 -832.39
+Customer#000000118 3592.37
+Customer#000000022 601.98
+Customer#000000005 804.47
+Customer#000000109 -706.1
+Customer#000000038 6355.11
+Customer#000000076 5755.33
+Customer#000000056 6540.86
+Customer#000000040 1345.3
+Customer#000000116 8413.99
+Customer#000000115 7518.92
+Customer#000000140 9973.15
+Customer#000000017 16.34
+Customer#000000052 5640.28
+execute stmt using -(@a1+@a2);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7133.7
+Customer#000000013 3857.34
+Customer#000000065 8795.16
+Customer#000000032 3471.53
+Customer#000000023 3332.02
+Customer#000000035 1228.24
+Customer#000000091 4643.14
+Customer#000000016 4681.03
+Customer#000000098 -551.37
+Customer#000000037 -917.75
+Customer#000000136 -842.39
+Customer#000000118 3582.37
+Customer#000000022 591.98
+Customer#000000005 794.47
+Customer#000000109 -716.1
+Customer#000000038 6345.11
+Customer#000000076 5745.33
+Customer#000000056 6530.86
+Customer#000000040 1335.3
+Customer#000000116 8403.99
+Customer#000000115 7508.92
+Customer#000000140 9963.15
+Customer#000000017 6.34
+Customer#000000052 5630.28
+deallocate prepare stmt;
+# Materialization SJM PS
+# ======================
+prepare stmt from "
+update customer set c_acctbal = c_acctbal+? where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+";
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000118 3582.37
+Customer#000000056 6530.86
+set @a1=-2;
+execute stmt using @a1;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3855.34
+Customer#000000032 3469.53
+Customer#000000037 -919.75
+Customer#000000118 3580.37
+Customer#000000056 6528.86
+set @a2=-1;
+execute stmt using @a2;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3854.34
+Customer#000000032 3468.53
+Customer#000000037 -920.75
+Customer#000000118 3579.37
+Customer#000000056 6527.86
+execute stmt using -(@a1+@a2);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000118 3582.37
+Customer#000000056 6530.86
+deallocate prepare stmt;
+# Pullout SP
+# ==========
+create procedure p(d int)
+update orders set o_totalprice = o_totalprice+d where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201268.06
+2880 145761.99
+3142 16030.15
+5382 138423.03
+5095 184583.99
+737 12984.85
+1729 12137.76
+5121 150334.57
+call p(-10);
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201258.06
+2880 145751.99
+3142 16020.15
+5382 138413.03
+5095 184573.99
+737 12974.85
+1729 12127.76
+5121 150324.57
+call p(-20);
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201238.06
+2880 145731.99
+3142 16000.15
+5382 138393.03
+5095 184553.99
+737 12954.85
+1729 12107.76
+5121 150304.57
+call p(10+20);
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201268.06
+2880 145761.99
+3142 16030.15
+5382 138423.03
+5095 184583.99
+737 12984.85
+1729 12137.76
+5121 150334.57
+drop procedure p;
+# FirstMatch SP
+# =============
+create procedure p(d int)
+update customer set c_acctbal = c_acctbal+d where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.1799999999998
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+call p(5);
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9566.95
+Customer#000000019 8919.71
+Customer#000000022 596.98
+Customer#000000025 7138.7
+Customer#000000028 1012.1799999999998
+Customer#000000037 -912.75
+Customer#000000040 1340.3
+Customer#000000047 279.58
+Customer#000000059 3463.6
+Customer#000000061 1541.24
+Customer#000000064 -641.64
+Customer#000000067 8171.59
+Customer#000000082 9473.34
+Customer#000000091 4648.14
+Customer#000000094 5505.11
+Customer#000000097 2169.48
+Customer#000000101 7475.96
+Customer#000000103 2762.45
+Customer#000000106 3293.42
+Customer#000000115 7513.92
+Customer#000000121 6433.32
+Customer#000000122 7870.46
+Customer#000000127 9285.71
+Customer#000000130 5078.58
+Customer#000000133 2319.67
+Customer#000000139 7902.78
+call p(15);
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9581.95
+Customer#000000019 8934.71
+Customer#000000022 611.98
+Customer#000000025 7153.7
+Customer#000000028 1027.1799999999998
+Customer#000000037 -897.75
+Customer#000000040 1355.3
+Customer#000000047 294.58
+Customer#000000059 3478.6
+Customer#000000061 1556.24
+Customer#000000064 -626.64
+Customer#000000067 8186.59
+Customer#000000082 9488.34
+Customer#000000091 4663.14
+Customer#000000094 5520.11
+Customer#000000097 2184.48
+Customer#000000101 7490.96
+Customer#000000103 2777.45
+Customer#000000106 3308.42
+Customer#000000115 7528.92
+Customer#000000121 6448.32
+Customer#000000122 7885.46
+Customer#000000127 9300.71
+Customer#000000130 5093.58
+Customer#000000133 2334.67
+Customer#000000139 7917.78
+call p(-(5+15));
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.1799999999998
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+drop procedure p;
+# Materialization SP
+# ==================
+create procedure p(d int)
+update customer set c_acctbal = c_acctbal+d where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7133.7
+Customer#000000013 3857.34
+Customer#000000065 8795.16
+Customer#000000032 3471.53
+Customer#000000023 3332.02
+Customer#000000035 1228.24
+Customer#000000091 4643.14
+Customer#000000016 4681.03
+Customer#000000098 -551.37
+Customer#000000037 -917.75
+Customer#000000136 -842.39
+Customer#000000118 3582.37
+Customer#000000022 591.98
+Customer#000000005 794.47
+Customer#000000109 -716.1
+Customer#000000038 6345.11
+Customer#000000076 5745.33
+Customer#000000056 6530.86
+Customer#000000040 1335.3
+Customer#000000116 8403.99
+Customer#000000115 7508.92
+Customer#000000140 9963.15
+Customer#000000017 6.34
+Customer#000000052 5630.28
+call p(3);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7136.7
+Customer#000000013 3860.34
+Customer#000000065 8798.16
+Customer#000000032 3474.53
+Customer#000000023 3335.02
+Customer#000000035 1231.24
+Customer#000000091 4646.14
+Customer#000000016 4684.03
+Customer#000000098 -548.37
+Customer#000000037 -914.75
+Customer#000000136 -839.39
+Customer#000000118 3585.37
+Customer#000000022 594.98
+Customer#000000005 797.47
+Customer#000000109 -713.1
+Customer#000000038 6348.11
+Customer#000000076 5748.33
+Customer#000000056 6533.86
+Customer#000000040 1338.3
+Customer#000000116 8406.99
+Customer#000000115 7511.92
+Customer#000000140 9966.15
+Customer#000000017 9.34
+Customer#000000052 5633.28
+call p(7);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7143.7
+Customer#000000013 3867.34
+Customer#000000065 8805.16
+Customer#000000032 3481.53
+Customer#000000023 3342.02
+Customer#000000035 1238.24
+Customer#000000091 4653.14
+Customer#000000016 4691.03
+Customer#000000098 -541.37
+Customer#000000037 -907.75
+Customer#000000136 -832.39
+Customer#000000118 3592.37
+Customer#000000022 601.98
+Customer#000000005 804.47
+Customer#000000109 -706.1
+Customer#000000038 6355.11
+Customer#000000076 5755.33
+Customer#000000056 6540.86
+Customer#000000040 1345.3
+Customer#000000116 8413.99
+Customer#000000115 7518.92
+Customer#000000140 9973.15
+Customer#000000017 16.34
+Customer#000000052 5640.28
+call p(-(3+7));
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7133.7
+Customer#000000013 3857.34
+Customer#000000065 8795.16
+Customer#000000032 3471.53
+Customer#000000023 3332.02
+Customer#000000035 1228.24
+Customer#000000091 4643.14
+Customer#000000016 4681.03
+Customer#000000098 -551.37
+Customer#000000037 -917.75
+Customer#000000136 -842.39
+Customer#000000118 3582.37
+Customer#000000022 591.98
+Customer#000000005 794.47
+Customer#000000109 -716.1
+Customer#000000038 6345.11
+Customer#000000076 5745.33
+Customer#000000056 6530.86
+Customer#000000040 1335.3
+Customer#000000116 8403.99
+Customer#000000115 7508.92
+Customer#000000140 9963.15
+Customer#000000017 6.34
+Customer#000000052 5630.28
+drop procedure p;
+# Materialization SJM SP
+# ======================
+create procedure p(d int)
+update customer set c_acctbal = c_acctbal+d where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000118 3582.37
+Customer#000000056 6530.86
+call p(-1);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3856.34
+Customer#000000032 3470.53
+Customer#000000037 -918.75
+Customer#000000118 3581.37
+Customer#000000056 6529.86
+call p(-2);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3854.34
+Customer#000000032 3468.53
+Customer#000000037 -920.75
+Customer#000000118 3579.37
+Customer#000000056 6527.86
+call p(1+2);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000118 3582.37
+Customer#000000056 6530.86
+drop procedure p;
+# Checking limitations
+# ====================
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+o_orderkey o_totalprice
+1221 117397.16
+324 26868.85
+1856 189361.42
+1344 43809.37
+1925 146382.71
+3139 40975.96
+4903 34363.63
+5607 24660.06
+# Should not use semi-join conversion because has ORDER BY ... LIMIT
+explain
+update orders set o_totalprice = o_totalprice-50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2))
+order by o_totalprice limit 500;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY orders range i_o_orderdate i_o_orderdate 4 NULL 108 Using where; Using filesort
+2 DEPENDENT SUBQUERY customer unique_subquery|filter PRIMARY,i_c_nationkey PRIMARY|i_c_nationkey 4|5 func 1 (10%) Using where; Using rowid filter
+update orders set o_totalprice = o_totalprice-50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2))
+order by o_totalprice limit 500;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+o_orderkey o_totalprice
+1221 117347.16
+324 26818.85
+1856 189311.42
+1344 43759.37
+1925 146332.71
+3139 40925.96
+4903 34313.63
+5607 24610.06
+update orders set o_totalprice = o_totalprice+50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2))
+order by o_totalprice limit 500;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+o_orderkey o_totalprice
+1221 117397.16
+324 26868.85
+1856 189361.42
+1344 43809.37
+1925 146382.71
+3139 40975.96
+4903 34363.63
+5607 24660.06
+# Should use semi-join converion
+explain
+update orders set o_totalprice = o_totalprice-50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer range PRIMARY,i_c_nationkey i_c_nationkey 5 NULL 15 Using index condition
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (7%) Using where; Using rowid filter
+update orders set o_totalprice = o_totalprice-50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+o_orderkey o_totalprice
+1221 117347.16
+324 26818.85
+1856 189311.42
+1344 43759.37
+1925 146332.71
+3139 40925.96
+4903 34313.63
+5607 24610.06
+update orders set o_totalprice = o_totalprice+50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+o_orderkey o_totalprice
+1221 117397.16
+324 26868.85
+1856 189361.42
+1344 43809.37
+1925 146382.71
+3139 40975.96
+4903 34363.63
+5607 24660.06
+DROP DATABASE dbt3_s001;
diff --git a/mysql-test/main/update_single_to_multi.test b/mysql-test/main/update_single_to_multi.test
new file mode 100644
index 0000000..0fe5686
--- /dev/null
+++ b/mysql-test/main/update_single_to_multi.test
@@ -0,0 +1,549 @@
+--disable_warnings
+DROP DATABASE IF EXISTS dbt3_s001;
+--enable_warnings
+
+CREATE DATABASE dbt3_s001;
+
+use dbt3_s001;
+
+--disable_query_log
+--disable_result_log
+--disable_warnings
+--source include/dbt3_s001.inc
+--enable_warnings
+--enable_result_log
+--enable_query_log
+
+create index i_n_name on nation(n_name);
+analyze table nation;
+
+
+--echo # Pullout
+--echo # =======
+
+let $c1=
+ o_orderDATE between '1992-01-01' and '1992-06-30' and
+ o_custkey in (select c_custkey from customer
+ where c_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+
+eval
+explain
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+explain format=json
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+
+eval
+explain
+update orders set o_totalprice = o_totalprice-50 where $c1;
+eval
+explain format=json
+update orders set o_totalprice = o_totalprice-50 where $c1;
+eval
+update orders set o_totalprice = o_totalprice-50 where $c1;
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+
+eval
+update orders set o_totalprice= o_totalprice+50 where $c1;
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+
+
+let $c2=
+ (ps_partkey, ps_suppkey) in
+ (select p_partkey, s_suppkey from part, supplier
+ where p_retailprice between 901 and 910 and
+ s_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+
+eval
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+
+eval
+explain
+update partsupp set ps_supplycost = ps_supplycost+2 where $c2;
+eval
+update partsupp set ps_supplycost = ps_supplycost+2 where $c2;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+
+eval
+update partsupp set ps_supplycost = ps_supplycost-2 where $c2;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+
+
+let $c3=
+ ps_partkey in (select p_partkey from part
+ where p_retailprice between 901 and 910) and
+ ps_suppkey in (select s_suppkey from supplier
+ where s_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+eval
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+
+eval
+explain
+update partsupp set ps_supplycost = ps_supplycost+10 where $c3;
+eval
+update partsupp set ps_supplycost = ps_supplycost+10 where $c3;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+
+eval
+update partsupp set ps_supplycost = ps_supplycost-10 where $c3;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+
+
+let $c4=
+ l_orderkey in (select o_orderkey from orders
+ where o_custkey in
+ (select c_custkey from customer
+ where c_nationkey in
+ (select n_nationkey from nation
+ where n_name='PERU'))
+ and
+ o_orderDATE between '1992-06-30' and '1992-12-31')
+ and
+ (l_partkey, l_suppkey) in
+ (select p_partkey, s_suppkey from part, supplier
+ where p_retailprice between 901 and 1000 and
+ s_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+
+eval
+explain
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+eval
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+
+eval
+explain
+update lineitem set l_tax = (l_tax*100+1)/100 where $c4;
+eval
+update lineitem set l_tax = (l_tax*100+1)/100 where $c4;
+eval
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+
+eval
+update lineitem set l_tax = (l_tax*100-1)/100 where $c4;
+eval
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+
+
+--echo # FirstMatch
+--echo # ==========
+
+let $c5=
+ c_nationkey in (select n_nationkey from nation
+ where n_regionkey in (1,2))
+ and
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-10-09' and '1993-03-08');
+
+eval
+explain
+select c_name, c_acctbal from customer where $c5;
+eval
+explain format=json
+select c_name, c_acctbal from customer where $c5;
+eval
+select c_name, c_acctbal from customer where $c5;
+
+eval
+explain
+update customer set c_acctbal = c_acctbal+10 where $c5;
+eval
+explain format=json
+update customer set c_acctbal = c_acctbal+10 where $c5;
+eval
+update customer set c_acctbal = c_acctbal+10 where $c5;
+eval
+select c_name, c_acctbal from customer where $c5;
+
+eval
+update customer set c_acctbal = c_acctbal-10 where $c5;
+eval
+select c_name, c_acctbal from customer where $c5;
+
+
+let $c6=
+ c_nationkey in (select n_nationkey from nation where n_name='PERU')
+ and
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between "1992-01-09" and "1993-01-08");
+
+eval
+explain
+select c_name, c_acctbal from customer where $c6;
+eval
+select c_name, c_acctbal from customer where $c6;
+
+eval
+explain
+update customer set c_acctbal = c_acctbal+20 where $c6;
+eval
+update customer set c_acctbal = c_acctbal+20 where $c6;
+eval
+select c_name, c_acctbal from customer where $c6;
+
+eval
+update customer set c_acctbal = c_acctbal-20 where $c6;
+eval
+select c_name, c_acctbal from customer where $c6;
+
+
+--echo # Materialization
+--echo # ===============
+
+let $c7=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-01-09' and '1992-03-08');
+
+eval
+explain
+select c_name, c_acctbal from customer where $c7;
+eval
+explain format=json
+select c_name, c_acctbal from customer where $c7;
+eval
+select c_name, c_acctbal from customer where $c7;
+
+eval
+explain
+update customer set c_acctbal = c_acctbal+5 where $c7;
+eval
+explain format=json
+update customer set c_acctbal = c_acctbal+5 where $c7;
+eval
+update customer set c_acctbal = c_acctbal+5 where $c7;
+eval
+select c_name, c_acctbal from customer where $c7;
+
+eval
+update customer set c_acctbal = c_acctbal-5 where $c7;
+eval
+select c_name, c_acctbal from customer where $c7;
+
+
+let $c8=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-06-09' and '1993-01-08');
+
+eval
+explain
+select c_name, c_acctbal from customer where $c8;
+eval
+select c_name, c_acctbal from customer where $c8;
+
+eval
+explain
+update customer set c_acctbal = c_acctbal+1 where $c8;
+eval
+update customer set c_acctbal = c_acctbal+1 where $c8;
+eval
+select c_name, c_acctbal from customer where $c8;
+
+eval
+update customer set c_acctbal = c_acctbal-1 where $c8;
+eval
+select c_name, c_acctbal from customer where $c8;
+
+
+--echo # Materialization SJM
+--echo # ===================
+
+let $c9=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+
+eval
+explain
+select c_name, c_acctbal from customer where $c9;
+eval
+explain format=json
+select c_name, c_acctbal from customer where $c9;
+eval
+select c_name, c_acctbal from customer where $c9;
+
+eval
+explain
+update customer set c_acctbal = c_acctbal-5 where $c9;
+eval
+explain format=json
+update customer set c_acctbal = c_acctbal-5 where $c9;
+eval
+update customer set c_acctbal = c_acctbal-5 where $c9;
+eval
+select c_name, c_acctbal from customer where $c9;
+
+eval
+update customer set c_acctbal = c_acctbal+5 where $c9;
+eval
+select c_name, c_acctbal from customer where $c9;
+
+
+let $c10=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+
+eval
+explain
+select c_name, c_acctbal from customer where $c10;
+eval
+select c_name, c_acctbal from customer where $c10;
+
+eval
+explain
+update customer set c_acctbal = c_acctbal-1 where $c10;
+eval
+update customer set c_acctbal = c_acctbal-1 where $c10;
+eval
+select c_name, c_acctbal from customer where $c10;
+
+eval
+update customer set c_acctbal = c_acctbal+1 where $c10;
+eval
+select c_name, c_acctbal from customer where $c10;
+
+
+--echo # Pullout PS
+--echo # ==========
+
+eval
+prepare stmt from "
+update orders set o_totalprice = o_totalprice+? where $c1;
+";
+
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+set @a1=-20;
+execute stmt using @a1;
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+set @a2=-10;
+execute stmt using @a2;
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+execute stmt using -(@a1+@a2);
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+
+deallocate prepare stmt;
+
+
+--echo # FirstMatch PS
+--echo # =============
+
+eval
+prepare stmt from "
+update customer set c_acctbal = c_acctbal+? where $c5;
+";
+
+eval
+select c_name, c_acctbal from customer where $c5;
+set @a1=15;
+execute stmt using @a1;
+eval
+select c_name, c_acctbal from customer where $c5;
+set @a2=5;
+execute stmt using @a2;
+eval
+select c_name, c_acctbal from customer where $c5;
+execute stmt using -(@a1+@a2);
+eval
+select c_name, c_acctbal from customer where $c5;
+
+deallocate prepare stmt;
+
+
+--echo # Materialization PS
+--echo # ==================
+
+eval
+prepare stmt from "
+update customer set c_acctbal = c_acctbal+? where $c7;
+";
+
+eval
+select c_name, c_acctbal from customer where $c7;
+set @a1=7;
+execute stmt using @a1;
+eval
+select c_name, c_acctbal from customer where $c7;
+set @a2=3;
+execute stmt using @a2;
+eval
+select c_name, c_acctbal from customer where $c7;
+execute stmt using -(@a1+@a2);
+eval
+select c_name, c_acctbal from customer where $c7;
+
+deallocate prepare stmt;
+
+
+--echo # Materialization SJM PS
+--echo # ======================
+
+eval
+prepare stmt from "
+update customer set c_acctbal = c_acctbal+? where $c9;
+";
+
+eval
+select c_name, c_acctbal from customer where $c9;
+set @a1=-2;
+execute stmt using @a1;
+eval
+select c_name, c_acctbal from customer where $c9;
+set @a2=-1;
+execute stmt using @a2;
+eval
+select c_name, c_acctbal from customer where $c9;
+execute stmt using -(@a1+@a2);
+eval
+select c_name, c_acctbal from customer where $c9;
+
+deallocate prepare stmt;
+
+
+--echo # Pullout SP
+--echo # ==========
+
+eval
+create procedure p(d int)
+update orders set o_totalprice = o_totalprice+d where $c1;
+
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+call p(-10);
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+call p(-20);
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+call p(10+20);
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+
+drop procedure p;
+
+
+--echo # FirstMatch SP
+--echo # =============
+
+eval
+create procedure p(d int)
+update customer set c_acctbal = c_acctbal+d where $c5;
+
+eval
+select c_name, c_acctbal from customer where $c5;
+call p(5);
+eval
+select c_name, c_acctbal from customer where $c5;
+call p(15);
+eval
+select c_name, c_acctbal from customer where $c5;
+call p(-(5+15));
+eval
+select c_name, c_acctbal from customer where $c5;
+
+drop procedure p;
+
+
+--echo # Materialization SP
+--echo # ==================
+
+eval
+create procedure p(d int)
+update customer set c_acctbal = c_acctbal+d where $c7;
+
+eval
+select c_name, c_acctbal from customer where $c7;
+call p(3);
+eval
+select c_name, c_acctbal from customer where $c7;
+call p(7);
+eval
+select c_name, c_acctbal from customer where $c7;
+call p(-(3+7));
+eval
+select c_name, c_acctbal from customer where $c7;
+
+drop procedure p;
+
+
+--echo # Materialization SJM SP
+--echo # ======================
+
+eval
+create procedure p(d int)
+update customer set c_acctbal = c_acctbal+d where $c9;
+
+eval
+select c_name, c_acctbal from customer where $c9;
+call p(-1);
+eval
+select c_name, c_acctbal from customer where $c9;
+call p(-2);
+eval
+select c_name, c_acctbal from customer where $c9;
+call p(1+2);
+eval
+select c_name, c_acctbal from customer where $c9;
+
+drop procedure p;
+
+--echo # Checking limitations
+--echo # ====================
+
+let $c11=
+ o_orderDATE between '1992-01-01' and '1992-06-30' and
+ o_custkey in (select c_custkey from customer
+ where c_nationkey in (1,2));
+
+eval
+select o_orderkey, o_totalprice from orders where $c11;
+--echo # Should not use semi-join conversion because has ORDER BY ... LIMIT
+eval
+explain
+update orders set o_totalprice = o_totalprice-50 where $c11
+order by o_totalprice limit 500;
+eval
+update orders set o_totalprice = o_totalprice-50 where $c11
+order by o_totalprice limit 500;
+eval
+select o_orderkey, o_totalprice from orders where $c11;
+eval
+update orders set o_totalprice = o_totalprice+50 where $c11
+order by o_totalprice limit 500;
+eval
+select o_orderkey, o_totalprice from orders where $c11;
+
+--echo # Should use semi-join converion
+eval
+explain
+update orders set o_totalprice = o_totalprice-50 where $c11;
+eval
+update orders set o_totalprice = o_totalprice-50 where $c11;
+eval
+select o_orderkey, o_totalprice from orders where $c11;
+eval
+update orders set o_totalprice = o_totalprice+50 where $c11;
+eval
+select o_orderkey, o_totalprice from orders where $c11;
+
+DROP DATABASE dbt3_s001;
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index fa338f0..cd88e78 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -533,6 +533,31 @@ bool is_materialization_applicable(THD *thd, Item_in_subselect *in_subs,
}
+/**
+ @brief Check whether an IN subquery must be excluded from conversion to SJ
+
+ @param thd global context the processed statement
+ @returns true if the IN subquery must be excluded from conversion to SJ
+
+ @note
+ Currently a top level IN subquery of an update/delete statement
+ is not converted to SJ if the statement contains ORDER BY ... LIMIT
+ or contains RETURNING.
+*/
+
+bool SELECT_LEX::is_sj_conversion_prohibited(THD *thd)
+{
+ DBUG_ASSERT(master_unit()->item->substype() == Item_subselect::IN_SUBS);
+ SELECT_LEX *outer_sl= outer_select();
+ return !outer_sl->outer_select() &&
+ (thd->lex->sql_command == SQLCOM_UPDATE ||
+ thd->lex->sql_command == SQLCOM_DELETE) &&
+ ((outer_sl->order_list.elements &&
+ outer_sl->get_limit() != HA_POS_ERROR) ||
+ (thd->lex->sql_command == SQLCOM_DELETE &&
+ thd->lex->has_returning()));
+}
+
/*
Check if we need JOIN::prepare()-phase subquery rewrites and if yes, do them
@@ -675,9 +700,9 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
3. Subquery does not have GROUP BY or ORDER BY
4. Subquery does not use aggregate functions or HAVING
5. Subquery predicate is at the AND-top-level of ON/WHERE clause
- 6. We are not in a subquery of a single table UPDATE/DELETE that
- doesn't have a JOIN (TODO: We should handle this at some
- point by switching to multi-table UPDATE/DELETE)
+ 6. We are not in a top level subquery of a single-table UPDATE or
+ DELETE with ORDER BY ... LIMIT and we are not in a top level
+ subquery of a single-table DELETE with returning
7. We're not in a table-less subquery like "SELECT 1"
8. No execution method was already chosen (by a prepared statement)
9. Parent select is not a table-less select
@@ -692,9 +717,7 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
!select_lex->group_list.elements && !join->order && // 3
!join->having && !select_lex->with_sum_func && // 4
in_subs->emb_on_expr_nest && // 5
- select_lex->outer_select()->join && // 6
- (!thd->lex->m_sql_cmd ||
- thd->lex->m_sql_cmd->sql_command_code() == SQLCOM_UPDATE_MULTI) &&
+ !select_lex->is_sj_conversion_prohibited(thd) && // 6
parent_unit->first_select()->leaf_tables.elements && // 7
!in_subs->has_strategy() && // 8
select_lex->outer_select()->table_list.first && // 9
@@ -754,7 +777,8 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
*/
if (in_subs && !in_subs->has_strategy())
{
- if (is_materialization_applicable(thd, in_subs, select_lex))
+ if (!select_lex->is_sj_conversion_prohibited(thd) &&
+ is_materialization_applicable(thd, in_subs, select_lex))
{
in_subs->add_strategy(SUBS_MATERIALIZATION);
@@ -7260,3 +7284,28 @@ bool TABLE_LIST::is_sjm_scan_table()
{
return is_active_sjm() && sj_mat_info->is_sj_scan;
}
+
+
+/**
+ @brief Check whether this subselect can be lifted to the top level
+ @returns true if the test is positive, false otherwise
+*/
+
+bool SELECT_LEX::is_sj_subselect_lifted_to_top()
+{
+ st_select_lex *sl= this;
+ st_select_lex *outer_sl= outer_select();
+ for ( ; outer_sl; sl= outer_sl, outer_sl= outer_sl->outer_select())
+ {
+ List_iterator_fast<Item_in_subselect> it(outer_sl->sj_subselects);
+ Item_in_subselect *in_subs;
+ while ((in_subs= it++))
+ {
+ if (in_subs->unit->first_select() == sl)
+ break;
+ }
+ if (!in_subs)
+ return false;
+ }
+ return true;
+}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 167df5b..3a2704f 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -7005,6 +7005,7 @@ class multi_delete :public select_result_interceptor
// Methods used by ColumnStore
uint get_num_of_tables() const { return num_of_tables; }
TABLE_LIST* get_tables() const { return delete_tables; }
+ void set_delete_tables (TABLE_LIST *tbl) { delete_tables= tbl; }
public:
multi_delete(THD *thd_arg, TABLE_LIST *dt, uint num_of_tables);
~multi_delete();
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 2ff4331..ed4b6be 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -1591,10 +1591,16 @@ bool Sql_cmd_delete::prepare_inner(THD *thd)
select_lex->order_list.first,
false, NULL, NULL, NULL,
select_lex, &lex->unit)))
-
{
goto err;
}
+
+ if (!multitable &&
+ select_lex->sj_subselects.elements)
+ multitable= true;
+
+ if (!multitable)
+ ((multi_delete *)result)->set_delete_tables(0);
}
if (multitable)
@@ -1638,7 +1644,8 @@ bool Sql_cmd_delete::prepare_inner(THD *thd)
{
TABLE_LIST *duplicate;
if ((duplicate= unique_table(thd, target_tbl->correspondent_table,
- lex->query_tables, 0)))
+ lex->query_tables, 0)) &&
+ !duplicate->select_lex->is_sj_subselect_lifted_to_top())
{
update_non_unique_table_error(target_tbl->correspondent_table,
"DELETE", duplicate);
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 0badc32..bb997cc 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -1642,6 +1642,8 @@ class st_select_lex: public st_select_lex_node
void lex_start(LEX *plex);
bool is_unit_nest() { return (nest_flags & UNIT_NEST_FL); }
void mark_as_unit_nest() { nest_flags= UNIT_NEST_FL; }
+ bool is_sj_conversion_prohibited(THD *thd);
+ bool is_sj_subselect_lifted_to_top();
};
typedef class st_select_lex SELECT_LEX;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index bf49d69..a7e5bc7 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -5834,8 +5834,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
s->needed_reg=select->needed_reg;
select->quick=0;
impossible_range= records == 0 && s->table->reginfo.impossible_range;
- if (join->thd->lex->sql_command == SQLCOM_SELECT &&
- optimizer_flag(join->thd, OPTIMIZER_SWITCH_USE_ROWID_FILTER))
+ if (optimizer_flag(join->thd, OPTIMIZER_SWITCH_USE_ROWID_FILTER))
s->table->init_cost_info_for_usable_range_rowid_filters(join->thd);
}
if (!impossible_range)
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 6b14c4f..b056b13 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -2471,6 +2471,8 @@ int multi_update::do_updates()
table = cur_table->table;
if (table == table_to_update)
continue; // Already updated
+ if (table->file->pushed_rowid_filter)
+ table->file->disable_pushed_rowid_filter();
org_updated= updated;
tmp_table= tmp_tables[cur_table->shared];
tmp_table->file->extra(HA_EXTRA_CACHE); // Change to read cache
@@ -2665,7 +2667,8 @@ int multi_update::do_updates()
check_opt_it.rewind();
while (TABLE *tbl= check_opt_it++)
tbl->file->ha_rnd_end();
-
+ if (table->file->save_pushed_rowid_filter)
+ table->file->enable_pushed_rowid_filter();
}
DBUG_RETURN(0);
@@ -2676,6 +2679,8 @@ int multi_update::do_updates()
}
err2:
+ if (table->file->save_pushed_rowid_filter)
+ table->file->enable_pushed_rowid_filter();
if (table->file->inited)
(void) table->file->ha_rnd_end();
if (tmp_table->file->inited)
@@ -2955,7 +2960,9 @@ bool Sql_cmd_update::prepare_inner(THD *thd)
{
goto err;
}
-
+ if (!multitable &&
+ select_lex->sj_subselects.elements)
+ multitable= true;
}
if (table_list->has_period())
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index a587a37..13dc602 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -13370,8 +13370,21 @@ delete_single_table:
YYPS->m_lock_type,
YYPS->m_mdl_type,
NULL,
+ 0)))
+ MYSQL_YYABORT;
+ Select->table_list.save_and_clear(&Lex->auxiliary_table_list);
+ Lex->table_count= 1;
+ Lex->query_tables= 0;
+ Lex->query_tables_last= &Lex->query_tables;
+ if (unlikely(!Select->
+ add_table_to_list(thd, $2, NULL, TL_OPTION_UPDATING,
+ YYPS->m_lock_type,
+ YYPS->m_mdl_type,
+ NULL,
$3)))
MYSQL_YYABORT;
+ Lex->auxiliary_table_list.first->correspondent_table=
+ Lex->query_tables;
YYPS->m_lock_type= TL_READ_DEFAULT;
YYPS->m_mdl_type= MDL_SHARED_READ;
}
1
0
[Commits] 7f41880: MDEV-7487 Semi-join optimization for single-table update/delete statements
by IgorBabaev 20 Jun '22
by IgorBabaev 20 Jun '22
20 Jun '22
revision-id: 7f418808d1a25a2374671a806b2dd6ca12d27554 (mariadb-10.6.1-472-g7f41880)
parent(s): 596cde07f17c490c43db10ce0a8cbb7bd4dbf5ae
author: Igor Babaev
committer: Igor Babaev
timestamp: 2022-06-19 23:40:44 -0700
message:
MDEV-7487 Semi-join optimization for single-table update/delete statements
This patch allows to use semi-join optimization at the top level of
single-table update and delete statements.
The problem of supporting such optimization became easy to resolve after
processing a single-table update/delete statement started using JOIN
structure. This allowed to use JOIN::prepare() not only for multi-table
updates/deletes but for single-table ones as well. This was done in the
patch for mdev-28883:
Re-design the upper level of handling UPDATE and DELETE statements.
Note that JOIN::prepare() detects all subqueries that can be considered
as candidates for semi-join optimization. The code added by this patch
looks for such candidates at the top level and if such candidates are found
in the processed single-table update/delete the statement is handled in
the same way as a multi-table update/delete.
Approved by Oleksandr Byelkin <sanja(a)mariadb.com>
---
mysql-test/main/delete_single_to_multi.result | 2355 ++++++++++++++++++++
mysql-test/main/delete_single_to_multi.test | 797 +++++++
mysql-test/main/log_state.result | 2 +-
.../main/myisam_explain_non_select_all.result | 45 +-
mysql-test/main/opt_trace.result | 20 +
mysql-test/main/update_single_to_multi.result | 2302 +++++++++++++++++++
mysql-test/main/update_single_to_multi.test | 549 +++++
sql/opt_subselect.cc | 63 +-
sql/sql_class.h | 1 +
sql/sql_delete.cc | 11 +-
sql/sql_lex.h | 2 +
sql/sql_select.cc | 3 +-
sql/sql_update.cc | 11 +-
sql/sql_yacc.yy | 13 +
14 files changed, 6140 insertions(+), 34 deletions(-)
diff --git a/mysql-test/main/delete_single_to_multi.result b/mysql-test/main/delete_single_to_multi.result
new file mode 100644
index 0000000..c6da861
--- /dev/null
+++ b/mysql-test/main/delete_single_to_multi.result
@@ -0,0 +1,2355 @@
+DROP DATABASE IF EXISTS dbt3_s001;
+CREATE DATABASE dbt3_s001;
+use dbt3_s001;
+create index i_n_name on nation(n_name);
+analyze table nation;
+Table Op Msg_type Msg_text
+dbt3_s001.nation analyze status Engine-independent statistics collected
+dbt3_s001.nation analyze status OK
+# Pullout
+# =======
+explain
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (7%) Using where; Using rowid filter
+explain format=json
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_n_name"],
+ "key": "i_n_name",
+ "key_length": "26",
+ "used_key_parts": ["n_name"],
+ "ref": ["const"],
+ "rows": 1,
+ "filtered": 100,
+ "index_condition": "nation.n_name = 'PERU'"
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "key": "i_c_nationkey",
+ "key_length": "5",
+ "used_key_parts": ["c_nationkey"],
+ "ref": ["dbt3_s001.nation.n_nationkey"],
+ "rows": 11,
+ "filtered": 100
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 108,
+ "selectivity_pct": 7.2
+ },
+ "rows": 11,
+ "filtered": 7.199999809,
+ "attached_condition": "orders.o_orderDATE between '1992-01-01' and '1992-06-30'"
+ }
+ }
+ ]
+ }
+}
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+5382 138423.03
+644 201268.06
+737 12984.85
+create table t as
+select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+explain
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (7%) Using where; Using rowid filter
+explain format=json
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_n_name"],
+ "key": "i_n_name",
+ "key_length": "26",
+ "used_key_parts": ["n_name"],
+ "ref": ["const"],
+ "rows": 1,
+ "filtered": 100,
+ "index_condition": "nation.n_name = 'PERU'"
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "key": "i_c_nationkey",
+ "key_length": "5",
+ "used_key_parts": ["c_nationkey"],
+ "ref": ["dbt3_s001.nation.n_nationkey"],
+ "rows": 11,
+ "filtered": 100
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 108,
+ "selectivity_pct": 7.2
+ },
+ "rows": 11,
+ "filtered": 7.199999809,
+ "attached_condition": "orders.o_orderDATE between '1992-01-01' and '1992-06-30'"
+ }
+ }
+ ]
+ }
+}
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+insert into orders select * from t;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+5382 138423.03
+644 201268.06
+737 12984.85
+drop table t;
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+1 8 357.84
+3 8 645.4
+4 1 444.37
+5 8 50.52
+6 1 642.13
+7 8 763.98
+8 1 957.34
+create table t as
+select * from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+explain
+delete from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+delete from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+insert into partsupp select * from t;
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+1 8 357.84
+3 8 645.4
+4 1 444.37
+5 8 50.52
+6 1 642.13
+7 8 763.98
+8 1 957.34
+drop table t;
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+1 8 357.84
+3 8 645.4
+4 1 444.37
+5 8 50.52
+6 1 642.13
+7 8 763.98
+8 1 957.34
+create table t as
+select * from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+explain
+delete from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+delete from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+insert into partsupp select * from t;
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+1 8 357.84
+3 8 645.4
+4 1 444.37
+5 8 50.52
+6 1 642.13
+7 8 763.98
+8 1 957.34
+drop table t;
+explain
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY lineitem ref PRIMARY,i_l_suppkey_partkey,i_l_partkey,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity i_l_suppkey 5 dbt3_s001.supplier.s_suppkey 100 Using where
+1 PRIMARY orders eq_ref|filter PRIMARY,i_o_orderdate,i_o_custkey PRIMARY|i_o_orderdate 4|4 dbt3_s001.lineitem.l_orderkey 1 (7%) Using where; Using rowid filter
+1 PRIMARY customer eq_ref PRIMARY,i_c_nationkey PRIMARY 4 dbt3_s001.orders.o_custkey 1 Using where
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.lineitem.l_partkey 1 Using where
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+l_orderkey l_linenumber l_tax
+2500 2 0.02
+2500 4 0.02
+4996 1 0.01
+933 1 0.04
+create table t as
+select * from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+explain
+delete from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY lineitem ref PRIMARY,i_l_suppkey_partkey,i_l_partkey,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity i_l_suppkey 5 dbt3_s001.supplier.s_suppkey 100 Using where
+1 PRIMARY orders eq_ref|filter PRIMARY,i_o_orderdate,i_o_custkey PRIMARY|i_o_orderdate 4|4 dbt3_s001.lineitem.l_orderkey 1 (7%) Using where; Using rowid filter
+1 PRIMARY customer eq_ref PRIMARY,i_c_nationkey PRIMARY 4 dbt3_s001.orders.o_custkey 1 Using where
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.lineitem.l_partkey 1 Using where
+delete from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+l_orderkey l_linenumber l_tax
+insert into lineitem select * from t;
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+l_orderkey l_linenumber l_tax
+2500 2 0.02
+2500 4 0.02
+4996 1 0.01
+933 1 0.04
+drop table t;
+# FirstMatch
+# ==========
+explain
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY,i_c_nationkey NULL NULL NULL 150 Using where
+1 PRIMARY nation eq_ref|filter PRIMARY,i_n_regionkey PRIMARY|i_n_regionkey 4|5 dbt3_s001.customer.c_nationkey 1 (40%) Using where; Using rowid filter
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (6%) Using where; FirstMatch(nation); Using rowid filter
+explain format=json
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ALL",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "rows": 150,
+ "filtered": 100,
+ "attached_condition": "customer.c_nationkey is not null"
+ }
+ },
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY", "i_n_regionkey"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["n_nationkey"],
+ "ref": ["dbt3_s001.customer.c_nationkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_n_regionkey",
+ "used_key_parts": ["n_regionkey"]
+ },
+ "rows": 10,
+ "selectivity_pct": 40
+ },
+ "rows": 1,
+ "filtered": 40,
+ "attached_condition": "nation.n_regionkey in (1,2)"
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 89,
+ "selectivity_pct": 5.933333333
+ },
+ "rows": 11,
+ "filtered": 5.933333397,
+ "attached_condition": "orders.o_orderDATE between '1992-10-09' and '1993-03-08'",
+ "first_match": "nation"
+ }
+ }
+ ]
+ }
+}
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+create table t as
+select * from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+explain
+delete from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY,i_c_nationkey NULL NULL NULL 150 Using where
+1 PRIMARY nation eq_ref|filter PRIMARY,i_n_regionkey PRIMARY|i_n_regionkey 4|5 dbt3_s001.customer.c_nationkey 1 (40%) Using where; Using rowid filter
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (6%) Using where; FirstMatch(nation); Using rowid filter
+explain format=json
+delete from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ALL",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "rows": 150,
+ "filtered": 100,
+ "attached_condition": "customer.c_nationkey is not null"
+ }
+ },
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY", "i_n_regionkey"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["n_nationkey"],
+ "ref": ["dbt3_s001.customer.c_nationkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_n_regionkey",
+ "used_key_parts": ["n_regionkey"]
+ },
+ "rows": 10,
+ "selectivity_pct": 40
+ },
+ "rows": 1,
+ "filtered": 40,
+ "attached_condition": "nation.n_regionkey in (1,2)"
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 89,
+ "selectivity_pct": 5.933333333
+ },
+ "rows": 11,
+ "filtered": 5.933333397,
+ "attached_condition": "orders.o_orderDATE between '1992-10-09' and '1993-03-08'",
+ "first_match": "nation"
+ }
+ }
+ ]
+ }
+}
+delete from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+drop table t;
+explain
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (14%) Using where; FirstMatch(customer); Using rowid filter
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+c_name c_acctbal
+Customer#000000008 6819.74
+Customer#000000035 1228.24
+Customer#000000061 1536.24
+Customer#000000097 2164.48
+Customer#000000121 6428.32
+Customer#000000133 2314.67
+create table t as
+select * from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+explain
+delete from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (14%) Using where; FirstMatch(customer); Using rowid filter
+delete from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+c_name c_acctbal
+Customer#000000008 6819.74
+Customer#000000035 1228.24
+Customer#000000061 1536.24
+Customer#000000097 2164.48
+Customer#000000121 6428.32
+Customer#000000133 2314.67
+drop table t;
+# Materialization
+# ===============
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 dbt3_s001.orders.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 28 Using index condition; Using where
+explain format=json
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'",
+ "attached_condition": "orders.o_custkey is not null"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["dbt3_s001.orders.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000005 794.47
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000035 1228.24
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000040 1335.3
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000098 -551.37
+Customer#000000109 -716.1
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000136 -842.39
+Customer#000000140 9963.15
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+explain
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 dbt3_s001.orders.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 28 Using index condition; Using where
+explain format=json
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'",
+ "attached_condition": "orders.o_custkey is not null"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["dbt3_s001.orders.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000005 794.47
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000035 1228.24
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000040 1335.3
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000098 -551.37
+Customer#000000109 -716.1
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000136 -842.39
+Customer#000000140 9963.15
+drop table t;
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 114 Using index condition; Using where
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+c_name c_acctbal
+Customer#000000001 711.56
+Customer#000000002 121.65
+Customer#000000007 9561.95
+Customer#000000008 6819.74
+Customer#000000010 2753.54
+Customer#000000011 -272.6
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000029 7618.27
+Customer#000000031 5236.89
+Customer#000000034 8589.7
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000043 9904.28
+Customer#000000044 7315.94
+Customer#000000046 5744.59
+Customer#000000047 274.58
+Customer#000000049 4573.94
+Customer#000000053 4113.64
+Customer#000000055 4572.11
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000070 4867.52
+Customer#000000071 -611.19
+Customer#000000073 4288.5
+Customer#000000074 2764.43
+Customer#000000076 5745.33
+Customer#000000079 5121.28
+Customer#000000080 7383.53
+Customer#000000082 9468.34
+Customer#000000083 6463.51
+Customer#000000085 3386.64
+Customer#000000086 3306.32
+Customer#000000088 8031.44
+Customer#000000091 4643.14
+Customer#000000092 1182.91
+Customer#000000095 5327.38
+Customer#000000097 2164.48
+Customer#000000100 9889.89
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000104 -588.38
+Customer#000000106 3288.42
+Customer#000000109 -716.1
+Customer#000000110 7462.99
+Customer#000000112 2953.35
+Customer#000000118 3582.37
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000131 8595.53
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+Customer#000000136 -842.39
+Customer#000000137 7838.3
+Customer#000000139 7897.78
+Customer#000000142 2209.81
+Customer#000000143 2186.5
+Customer#000000148 2135.6
+Customer#000000149 8959.65
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+explain
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 114 Using index condition; Using where
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+c_name c_acctbal
+Customer#000000001 711.56
+Customer#000000002 121.65
+Customer#000000007 9561.95
+Customer#000000008 6819.74
+Customer#000000010 2753.54
+Customer#000000011 -272.6
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000029 7618.27
+Customer#000000031 5236.89
+Customer#000000034 8589.7
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000043 9904.28
+Customer#000000044 7315.94
+Customer#000000046 5744.59
+Customer#000000047 274.58
+Customer#000000049 4573.94
+Customer#000000053 4113.64
+Customer#000000055 4572.11
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000070 4867.52
+Customer#000000071 -611.19
+Customer#000000073 4288.5
+Customer#000000074 2764.43
+Customer#000000076 5745.33
+Customer#000000079 5121.28
+Customer#000000080 7383.53
+Customer#000000082 9468.34
+Customer#000000083 6463.51
+Customer#000000085 3386.64
+Customer#000000086 3306.32
+Customer#000000088 8031.44
+Customer#000000091 4643.14
+Customer#000000092 1182.91
+Customer#000000095 5327.38
+Customer#000000097 2164.48
+Customer#000000100 9889.89
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000104 -588.38
+Customer#000000106 3288.42
+Customer#000000109 -716.1
+Customer#000000110 7462.99
+Customer#000000112 2953.35
+Customer#000000118 3582.37
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000131 8595.53
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+Customer#000000136 -842.39
+Customer#000000137 7838.3
+Customer#000000139 7897.78
+Customer#000000142 2209.81
+Customer#000000143 2186.5
+Customer#000000148 2135.6
+Customer#000000149 8959.65
+drop table t;
+# Materialization SJM
+# ===================
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 <subquery2>.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 28 Using index condition; Using temporary
+explain format=json
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "having_condition": "count(orders.o_custkey) > 1",
+ "temporary_table": {
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'"
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["<subquery2>.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+explain
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 <subquery2>.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 28 Using index condition; Using temporary
+explain format=json
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "having_condition": "count(orders.o_custkey) > 1",
+ "temporary_table": {
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'"
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["<subquery2>.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+drop table t;
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 dbt3_s001.customer.c_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 242 Using index condition; Using temporary
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000016 4681.03
+Customer#000000037 -917.75
+Customer#000000046 5744.59
+Customer#000000091 4643.14
+Customer#000000103 2757.45
+Customer#000000118 3582.37
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+explain
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 dbt3_s001.customer.c_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 242 Using index condition; Using temporary
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000016 4681.03
+Customer#000000037 -917.75
+Customer#000000046 5744.59
+Customer#000000091 4643.14
+Customer#000000103 2757.45
+Customer#000000118 3582.37
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+drop table t;
+# Pullout PS
+# ==========
+prepare stmt from "
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+";
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+5382 138423.03
+644 201268.06
+737 12984.85
+create table t as
+select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+execute stmt;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+insert into orders select * from t;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+5382 138423.03
+644 201268.06
+737 12984.85
+create table r as
+select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+execute stmt;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+insert into orders select * from r;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+5382 138423.03
+644 201268.06
+737 12984.85
+drop table t,r;
+deallocate prepare stmt;
+# FirstMatch PS
+# =============
+prepare stmt from "
+delete from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+";
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+create table t as
+select * from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+execute stmt;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+create table r as
+select * from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+execute stmt;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+insert into customer select * from r;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+drop table t,r;
+deallocate prepare stmt;
+# Materialization PS
+# ==================
+prepare stmt from "
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08') and c_name like ?;
+";
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000005 794.47
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000035 1228.24
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000040 1335.3
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000098 -551.37
+Customer#000000109 -716.1
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000136 -842.39
+Customer#000000140 9963.15
+set @a1='Customer#%1_';
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08') and c_name like @a1;
+execute stmt using @a1;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000005 794.47
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000035 1228.24
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000040 1335.3
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000098 -551.37
+Customer#000000109 -716.1
+Customer#000000136 -842.39
+Customer#000000140 9963.15
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000005 794.47
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000035 1228.24
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000040 1335.3
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000098 -551.37
+Customer#000000109 -716.1
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000136 -842.39
+Customer#000000140 9963.15
+set @a2='Customer#%3_';
+create table r as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08') and c_name like @a2;
+execute stmt using @a2;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000005 794.47
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000040 1335.3
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000098 -551.37
+Customer#000000109 -716.1
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000140 9963.15
+insert into customer select * from r;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000005 794.47
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000035 1228.24
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000040 1335.3
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000098 -551.37
+Customer#000000109 -716.1
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000136 -842.39
+Customer#000000140 9963.15
+drop table t,r;
+deallocate prepare stmt;
+# Materialization SJM PS
+# ======================
+prepare stmt from "
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08') and c_acctbal between ? and ?;
+";
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+set @a1=3500;
+set @a2=4000;
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1) and c_acctbal between @a1 and @a2;
+execute stmt using @a1, @a2;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+set @a3=-1000;
+set @a4=3500;
+create table r as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1) and c_acctbal between @a3 and @a4;
+execute stmt using @a3, @a4;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+insert into customer select * from r;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+drop table t,r;
+deallocate prepare stmt;
+# Pullout SP
+# ==========
+create procedure p(a1 int, a2 int)
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU')) and o_totalprice between a1 and a2;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+644 201268.06
+737 12984.85
+create table t as
+select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU')) and o_totalprice between 150000 and 200000;
+call p(150000, 200000);
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+644 201268.06
+737 12984.85
+insert into orders select * from t;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+644 201268.06
+737 12984.85
+create table r as
+select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU')) and o_totalprice between 180000 and 210000;
+call p(180000, 210000);
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5121 150334.57
+737 12984.85
+insert into orders select * from r;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+644 201268.06
+737 12984.85
+drop table t,r;
+drop procedure p;
+# FirstMatch SP
+# =============
+create procedure p(a int)
+delete from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08') and c_acctbal > a;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+create table t as
+select * from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08') and c_acctbal > 4000;
+call p(4000);
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000097 2164.48
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000133 2314.67
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+create table r as
+select * from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08') and c_acctbal > 2000;
+call p(2000);
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000047 274.58
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+insert into customer select * from r;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+drop table t,r;
+drop procedure p;
+# Materialization SP
+# ==================
+create procedure p()
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000140 9963.15
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+call p();
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000140 9963.15
+create table r as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+call p();
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+insert into customer select * from r;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000140 9963.15
+drop table t,r;
+drop procedure p;
+# Materialization SJM SP
+# ======================
+create procedure p()
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+call p();
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+create table r as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+call p();
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+insert into customer select * from r;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+drop table t,r;
+drop procedure p;
+# Checking limitations
+# ====================
+# Check for DELETE ... RETURNING with SJ subquery in WHERE
+select c_name from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name
+Customer#000000013
+Customer#000000016
+Customer#000000025
+Customer#000000032
+Customer#000000037
+Customer#000000038
+Customer#000000052
+Customer#000000056
+Customer#000000065
+Customer#000000076
+Customer#000000091
+Customer#000000115
+Customer#000000116
+Customer#000000118
+Customer#000000140
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+explain
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08') returning c_name;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL NULL NULL NULL NULL 141 Using where
+2 DEPENDENT SUBQUERY orders index_subquery|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 func 175 (2%) Using where; Using rowid filter
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08') returning c_name;
+c_name
+Customer#000000013
+Customer#000000016
+Customer#000000025
+Customer#000000032
+Customer#000000037
+Customer#000000038
+Customer#000000052
+Customer#000000056
+Customer#000000065
+Customer#000000076
+Customer#000000091
+Customer#000000115
+Customer#000000116
+Customer#000000118
+Customer#000000140
+select c_name from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name
+insert into customer select * from t;
+select c_name from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name
+Customer#000000013
+Customer#000000016
+Customer#000000025
+Customer#000000032
+Customer#000000037
+Customer#000000038
+Customer#000000052
+Customer#000000056
+Customer#000000065
+Customer#000000076
+Customer#000000091
+Customer#000000115
+Customer#000000116
+Customer#000000118
+Customer#000000140
+drop table t;
+select c_name from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name
+Customer#000000013
+Customer#000000032
+Customer#000000037
+Customer#000000056
+Customer#000000118
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+explain
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1) returning c_name;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL NULL NULL NULL NULL 141 Using where
+2 DEPENDENT SUBQUERY orders range i_o_orderdate i_o_orderdate 4 NULL 28 Using index condition; Using temporary
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1) returning c_name;
+c_name
+Customer#000000013
+Customer#000000032
+Customer#000000037
+Customer#000000056
+Customer#000000118
+select c_name from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name
+insert into customer select * from t;
+select c_name from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name
+Customer#000000013
+Customer#000000032
+Customer#000000037
+Customer#000000056
+Customer#000000118
+drop table t;
+# Check for DELETE ... RETURNING with SJ subquery in WHERE
+select c_name from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name
+Customer#000000013
+Customer#000000016
+Customer#000000025
+Customer#000000032
+Customer#000000037
+Customer#000000038
+Customer#000000052
+Customer#000000056
+Customer#000000065
+Customer#000000076
+Customer#000000091
+Customer#000000115
+Customer#000000116
+Customer#000000118
+Customer#000000140
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+explain
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08') returning c_name;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL NULL NULL NULL NULL 141 Using where
+2 DEPENDENT SUBQUERY orders index_subquery|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 func 175 (2%) Using where; Using rowid filter
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08') returning c_name;
+c_name
+Customer#000000013
+Customer#000000016
+Customer#000000025
+Customer#000000032
+Customer#000000037
+Customer#000000038
+Customer#000000052
+Customer#000000056
+Customer#000000065
+Customer#000000076
+Customer#000000091
+Customer#000000115
+Customer#000000116
+Customer#000000118
+Customer#000000140
+select c_name from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name
+insert into customer select * from t;
+drop table t;
+# Check for DELETE ... ORDER BY ...LIMIT with SJ subquery in WHERE
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+o_orderkey o_totalprice
+1221 117397.16
+1856 189361.42
+324 26868.85
+4903 34363.63
+5607 24660.06
+# Should not use semi-join conversion because has ORDER BY ... LIMIT
+explain
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2))
+order by o_totalprice limit 500;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY orders range i_o_orderdate i_o_orderdate 4 NULL 108 Using where; Using filesort
+2 DEPENDENT SUBQUERY customer unique_subquery|filter PRIMARY,i_c_nationkey PRIMARY|i_c_nationkey 4|5 func 1 (10%) Using where; Using rowid filter
+create table t as
+select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+select o_orderkey, o_totalprice from t;
+o_orderkey o_totalprice
+1221 117397.16
+324 26868.85
+1856 189361.42
+4903 34363.63
+5607 24660.06
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2))
+order by o_totalprice limit 500;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+o_orderkey o_totalprice
+insert into orders select * from t;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+o_orderkey o_totalprice
+1221 117397.16
+1856 189361.42
+324 26868.85
+4903 34363.63
+5607 24660.06
+drop table t;
+# Should use semi-join converion
+explain
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer range PRIMARY,i_c_nationkey i_c_nationkey 5 NULL 14 Using index condition
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 12 (7%) Using where; Using rowid filter
+create table t as
+select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+select o_orderkey, o_totalprice from t;
+o_orderkey o_totalprice
+1221 117397.16
+324 26868.85
+1856 189361.42
+4903 34363.63
+5607 24660.06
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+o_orderkey o_totalprice
+insert into orders select * from t;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+o_orderkey o_totalprice
+1221 117397.16
+1856 189361.42
+324 26868.85
+4903 34363.63
+5607 24660.06
+drop table t;
+DROP DATABASE dbt3_s001;
diff --git a/mysql-test/main/delete_single_to_multi.test b/mysql-test/main/delete_single_to_multi.test
new file mode 100644
index 0000000..7d4811f
--- /dev/null
+++ b/mysql-test/main/delete_single_to_multi.test
@@ -0,0 +1,797 @@
+--disable_warnings
+DROP DATABASE IF EXISTS dbt3_s001;
+--enable_warnings
+
+CREATE DATABASE dbt3_s001;
+
+use dbt3_s001;
+
+--disable_query_log
+--disable_result_log
+--disable_warnings
+--source include/dbt3_s001.inc
+--enable_warnings
+--enable_result_log
+--enable_query_log
+
+create index i_n_name on nation(n_name);
+analyze table nation;
+
+
+--echo # Pullout
+--echo # =======
+
+let $c1=
+ o_orderDATE between '1992-01-01' and '1992-06-30' and
+ o_custkey in (select c_custkey from customer
+ where c_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+
+eval
+explain
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+explain format=json
+select o_orderkey, o_totalprice from orders where $c1;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+create table t as
+select * from orders where $c1;
+
+eval
+explain
+delete from orders where $c1;
+eval
+explain format=json
+delete from orders where $c1;
+eval
+delete from orders where $c1;
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+
+
+insert into orders select * from t;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+drop table t;
+
+
+let $c2=
+ (ps_partkey, ps_suppkey) in
+ (select p_partkey, s_suppkey from part, supplier
+ where p_retailprice between 901 and 910 and
+ s_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+
+eval
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+--sorted_result
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+eval
+create table t as
+select * from partsupp where $c2;
+
+eval
+explain
+delete from partsupp where $c2;
+eval
+delete from partsupp where $c2;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+
+insert into partsupp select * from t;
+--sorted_result
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+drop table t;
+
+
+let $c3=
+ ps_partkey in (select p_partkey from part
+ where p_retailprice between 901 and 910) and
+ ps_suppkey in (select s_suppkey from supplier
+ where s_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+eval
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+--sorted_result
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+eval
+create table t as
+select * from partsupp where $c3;
+
+eval
+explain
+delete from partsupp where $c3;
+eval
+delete from partsupp where $c3;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+
+insert into partsupp select * from t;
+--sorted_result
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+drop table t;
+
+
+let $c4=
+ l_orderkey in (select o_orderkey from orders
+ where o_custkey in
+ (select c_custkey from customer
+ where c_nationkey in
+ (select n_nationkey from nation
+ where n_name='PERU'))
+ and
+ o_orderDATE between '1992-06-30' and '1992-12-31')
+ and
+ (l_partkey, l_suppkey) in
+ (select p_partkey, s_suppkey from part, supplier
+ where p_retailprice between 901 and 1000 and
+ s_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+
+eval
+explain
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+--sorted_result
+eval
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+eval
+create table t as
+select * from lineitem where $c4;
+
+eval
+explain
+delete from lineitem where $c4;
+eval
+delete from lineitem where $c4;
+eval
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+
+insert into lineitem select * from t;
+--sorted_result
+eval
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+drop table t;
+
+
+--echo # FirstMatch
+--echo # ==========
+
+let $c5=
+ c_nationkey in (select n_nationkey from nation
+ where n_regionkey in (1,2))
+ and
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-10-09' and '1993-03-08');
+
+eval
+explain
+select c_name, c_acctbal from customer where $c5;
+eval
+explain format=json
+select c_name, c_acctbal from customer where $c5;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+eval
+create table t as
+select * from customer where $c5;
+
+eval
+explain
+delete from customer where $c5;
+eval
+explain format=json
+delete from customer where $c5;
+eval
+delete from customer where $c5;
+eval
+select c_name, c_acctbal from customer where $c5;
+
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+drop table t;
+
+
+let $c6=
+ c_nationkey in (select n_nationkey from nation where n_name='PERU')
+ and
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between "1992-01-09" and "1993-01-08");
+
+eval
+explain
+select c_name, c_acctbal from customer where $c6;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c6;
+eval
+create table t as
+select * from customer where $c6;
+
+eval
+explain
+delete from customer where $c6;
+eval
+delete from customer where $c6;
+eval
+select c_name, c_acctbal from customer where $c6;
+
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c6;
+drop table t;
+
+
+--echo # Materialization
+--echo # ===============
+
+let $c7=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-01-09' and '1992-03-08');
+
+eval
+explain
+select c_name, c_acctbal from customer where $c7;
+eval
+explain format=json
+select c_name, c_acctbal from customer where $c7;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+eval
+create table t as
+select * from customer where $c7;
+
+eval
+explain
+delete from customer where $c7;
+eval
+explain format=json
+delete from customer where $c7;
+eval
+delete from customer where $c7;
+eval
+select c_name, c_acctbal from customer where $c7;
+
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+drop table t;
+
+
+let $c8=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-06-09' and '1993-01-08');
+
+eval
+explain
+select c_name, c_acctbal from customer where $c8;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c8;
+eval
+create table t as
+select * from customer where $c8;
+
+eval
+explain
+delete from customer where $c8;
+eval
+delete from customer where $c8;
+eval
+select c_name, c_acctbal from customer where $c8;
+
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c8;
+drop table t;
+
+
+--echo # Materialization SJM
+--echo # ===================
+
+let $c9=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+
+eval
+explain
+select c_name, c_acctbal from customer where $c9;
+eval
+explain format=json
+select c_name, c_acctbal from customer where $c9;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+eval
+create table t as
+select * from customer where $c9;
+
+eval
+explain
+delete from customer where $c9;
+eval
+explain format=json
+delete from customer where $c9;
+eval
+delete from customer where $c9;
+eval
+select c_name, c_acctbal from customer where $c9;
+
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+drop table t;
+
+
+let $c10=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+
+eval
+explain
+select c_name, c_acctbal from customer where $c10;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c10;
+eval
+create table t as
+select * from customer where $c10;
+
+eval
+explain
+delete from customer where $c10;
+eval
+delete from customer where $c10;
+eval
+select c_name, c_acctbal from customer where $c10;
+
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c10;
+drop table t;
+
+
+--echo # Pullout PS
+--echo # ==========
+
+eval
+prepare stmt from "
+delete from orders where $c1;
+";
+
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+create table t as
+select * from orders where $c1;
+execute stmt;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+insert into orders select * from t;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+create table r as
+select * from orders where $c1;
+execute stmt;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+insert into orders select * from r;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+drop table t,r;
+
+deallocate prepare stmt;
+
+
+--echo # FirstMatch PS
+--echo # =============
+
+eval
+prepare stmt from "
+delete from customer where $c5;
+";
+
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+eval
+create table t as
+select * from customer where $c5;
+execute stmt;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+eval
+create table r as
+select * from customer where $c5;
+execute stmt;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+insert into customer select * from r;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+drop table t,r;
+
+deallocate prepare stmt;
+
+
+--echo # Materialization PS
+--echo # ==================
+
+eval
+prepare stmt from "
+delete from customer where $c7 and c_name like ?;
+";
+
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+set @a1='Customer#%1_';
+eval
+create table t as
+select * from customer where $c7 and c_name like @a1;
+execute stmt using @a1;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+set @a2='Customer#%3_';
+eval
+create table r as
+select * from customer where $c7 and c_name like @a2;
+execute stmt using @a2;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+insert into customer select * from r;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+drop table t,r;
+
+deallocate prepare stmt;
+
+
+--echo # Materialization SJM PS
+--echo # ======================
+
+eval
+prepare stmt from "
+delete from customer where $c7 and c_acctbal between ? and ?;
+";
+
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+set @a1=3500;
+set @a2=4000;
+eval
+create table t as
+select * from customer where $c9 and c_acctbal between @a1 and @a2;
+execute stmt using @a1, @a2;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+set @a3=-1000;
+set @a4=3500;
+eval
+create table r as
+select * from customer where $c9 and c_acctbal between @a3 and @a4;
+execute stmt using @a3, @a4;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+insert into customer select * from r;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+drop table t,r;
+
+deallocate prepare stmt;
+
+
+--echo # Pullout SP
+--echo # ==========
+
+eval
+create procedure p(a1 int, a2 int)
+delete from orders where $c1 and o_totalprice between a1 and a2;
+
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+create table t as
+select * from orders where $c1 and o_totalprice between 150000 and 200000;
+call p(150000, 200000);
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+insert into orders select * from t;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+create table r as
+select * from orders where $c1 and o_totalprice between 180000 and 210000;
+call p(180000, 210000);
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+insert into orders select * from r;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+drop table t,r;
+
+drop procedure p;
+
+
+--echo # FirstMatch SP
+--echo # =============
+
+eval
+create procedure p(a int)
+delete from customer where $c5 and c_acctbal > a;
+
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+eval
+create table t as
+select * from customer where $c5 and c_acctbal > 4000;
+call p(4000);
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+eval
+create table r as
+select * from customer where $c5 and c_acctbal > 2000;
+call p(2000);
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+insert into customer select * from r;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+drop table t,r;
+
+drop procedure p;
+
+
+--echo # Materialization SP
+--echo # ==================
+
+eval
+create procedure p()
+delete from customer where $c7;
+
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+eval
+create table t as
+select * from customer where $c7;
+call p();
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+eval
+create table r as
+select * from customer where $c7;
+call p();
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+insert into customer select * from r;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+drop table t,r;
+
+drop procedure p;
+
+
+--echo # Materialization SJM SP
+--echo # ======================
+
+eval
+create procedure p()
+delete from customer where $c9;
+
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+eval
+create table t as
+select * from customer where $c9;
+call p();
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+eval
+create table r as
+select * from customer where $c9;
+call p();
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+insert into customer select * from r;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+drop table t,r;
+
+drop procedure p;
+
+--echo # Checking limitations
+--echo # ====================
+
+--echo # Check for DELETE ... RETURNING with SJ subquery in WHERE
+
+--sorted_result
+eval
+select c_name from customer where $c7;
+eval
+create table t as
+select * from customer where $c7;
+eval
+explain
+delete from customer where $c7 returning c_name;
+--sorted_result
+eval
+delete from customer where $c7 returning c_name;
+--sorted_result
+eval
+select c_name from customer where $c7;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name from customer where $c7;
+drop table t;
+
+--sorted_result
+eval
+select c_name from customer where $c9;
+eval
+create table t as
+select * from customer where $c9;
+eval
+explain
+delete from customer where $c9 returning c_name;
+--sorted_result
+eval
+delete from customer where $c9 returning c_name;
+--sorted_result
+eval
+select c_name from customer where $c9;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name from customer where $c9;
+drop table t;
+
+--echo # Check for DELETE ... RETURNING with SJ subquery in WHERE
+
+--sorted_result
+eval
+select c_name from customer where $c7;
+eval
+create table t as
+select * from customer where $c7;
+eval
+explain
+delete from customer where $c7 returning c_name;
+--sorted_result
+eval
+delete from customer where $c7 returning c_name;
+--sorted_result
+eval
+select c_name from customer where $c7;
+insert into customer select * from t;
+drop table t;
+
+--echo # Check for DELETE ... ORDER BY ...LIMIT with SJ subquery in WHERE
+
+let $c11=
+ o_orderDATE between '1992-01-01' and '1992-06-30' and
+ o_custkey in (select c_custkey from customer
+ where c_nationkey in (1,2));
+
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c11;
+
+--echo # Should not use semi-join conversion because has ORDER BY ... LIMIT
+eval
+explain
+delete from orders where $c11
+order by o_totalprice limit 500;
+eval
+create table t as
+select * from orders where $c11;
+select o_orderkey, o_totalprice from t;
+eval
+delete from orders where $c11
+order by o_totalprice limit 500;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c11;
+insert into orders select * from t;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c11;
+drop table t;
+
+--echo # Should use semi-join converion
+eval
+explain
+delete from orders where $c11;
+eval
+create table t as
+select * from orders where $c11;
+select o_orderkey, o_totalprice from t;
+eval
+delete from orders where $c11;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c11;
+insert into orders select * from t;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c11;
+drop table t;
+
+DROP DATABASE dbt3_s001;
diff --git a/mysql-test/main/log_state.result b/mysql-test/main/log_state.result
index 5e7aac8..1b1c737 100644
--- a/mysql-test/main/log_state.result
+++ b/mysql-test/main/log_state.result
@@ -243,7 +243,7 @@ rows_examined sql_text
4 UPDATE t1 SET a=a+sleep(.02) WHERE a>2
8 UPDATE t1 SET a=a+sleep(.02) ORDER BY a DESC
1 UPDATE t2 set b=b+sleep(.02) limit 1
-4 UPDATE t1 SET a=a+sleep(.02) WHERE a in (SELECT b from t2)
+10 UPDATE t1 SET a=a+sleep(.02) WHERE a in (SELECT b from t2)
6 DELETE FROM t1 WHERE a=a+sleep(.02) ORDER BY a LIMIT 2
disconnect con2;
connection default;
diff --git a/mysql-test/main/myisam_explain_non_select_all.result b/mysql-test/main/myisam_explain_non_select_all.result
index 20b769b..5df9ced 100644
--- a/mysql-test/main/myisam_explain_non_select_all.result
+++ b/mysql-test/main/myisam_explain_non_select_all.result
@@ -240,14 +240,16 @@ Warnings:
Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
EXPLAIN UPDATE t1 SET a = 10 WHERE 1 IN (SELECT 1 FROM t2 WHERE t2.b < 3);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
-2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED UPDATE t1 SET a = 10 WHERE 1 IN (SELECT 1 FROM t2 WHERE t2.b < 3);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
-2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 100.00 Using where
# Status of EXPLAIN EXTENDED query
Variable_name Value
Handler_read_key 4
@@ -271,8 +273,9 @@ Handler_read_key 5
Handler_read_rnd_next 8
# Status of testing query execution:
Variable_name Value
-Handler_read_key 4
-Handler_read_rnd_next 5
+Handler_read_key 5
+Handler_read_rnd 3
+Handler_read_rnd_next 12
Handler_update 3
DROP TABLE t1, t2;
@@ -290,13 +293,13 @@ Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be
EXPLAIN UPDATE t1 SET a = 10 WHERE a IN (SELECT b FROM t2 WHERE t1.a < 3);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
-2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY t2 ALL NULL NULL NULL NULL 3 Using where; FirstMatch(t1)
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED UPDATE t1 SET a = 10 WHERE a IN (SELECT b FROM t2 WHERE t1.a < 3);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
-2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where
+1 PRIMARY t2 ALL NULL NULL NULL NULL 3 100.00 Using where; FirstMatch(t1)
Warnings:
Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1
# Status of EXPLAIN EXTENDED query
@@ -984,14 +987,16 @@ Warnings:
Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
EXPLAIN UPDATE t1 SET a = 10 WHERE a IN (SELECT a FROM t2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
-2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED UPDATE t1 SET a = 10 WHERE a IN (SELECT a FROM t2);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
-2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 100.00
# Status of EXPLAIN EXTENDED query
Variable_name Value
Handler_read_key 4
@@ -1015,8 +1020,8 @@ Handler_read_key 7
Handler_read_rnd_next 8
# Status of testing query execution:
Variable_name Value
-Handler_read_key 4
-Handler_read_rnd_next 10
+Handler_read_key 7
+Handler_read_rnd_next 8
Handler_update 3
DROP TABLE t1, t2;
@@ -1079,14 +1084,14 @@ Warnings:
Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
EXPLAIN DELETE FROM t1 WHERE a1 IN (SELECT a2 FROM t2 WHERE a2 > 2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where
-2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 5 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5
+1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using where; FirstMatch(t1)
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED DELETE FROM t1 WHERE a1 IN (SELECT a2 FROM t2 WHERE a2 > 2);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 5 100.00 Using where
-2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5 100.00
+1 PRIMARY t2 ALL NULL NULL NULL NULL 5 100.00 Using where; FirstMatch(t1)
# Status of EXPLAIN EXTENDED query
Variable_name Value
Handler_read_key 4
@@ -3074,14 +3079,14 @@ Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be
EXPLAIN UPDATE t1 SET a = 10 WHERE a IN (SELECT * FROM (SELECT b FROM t2 ORDER BY b LIMIT 2,2) x);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
-2 DEPENDENT SUBQUERY <derived3> index_subquery key0 key0 5 func 2
+1 PRIMARY <derived3> ref key0 key0 5 test.t1.a 2 FirstMatch(t1)
3 DERIVED t2 ALL NULL NULL NULL NULL 3 Using filesort
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED UPDATE t1 SET a = 10 WHERE a IN (SELECT * FROM (SELECT b FROM t2 ORDER BY b LIMIT 2,2) x);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
-2 DEPENDENT SUBQUERY <derived3> index_subquery key0 key0 5 func 2 100.00
+1 PRIMARY <derived3> ref key0 key0 5 test.t1.a 2 100.00 FirstMatch(t1)
3 DERIVED t2 ALL NULL NULL NULL NULL 3 100.00 Using filesort
# Status of EXPLAIN EXTENDED query
Variable_name Value
diff --git a/mysql-test/main/opt_trace.result b/mysql-test/main/opt_trace.result
index 0555f72..e46bd80 100644
--- a/mysql-test/main/opt_trace.result
+++ b/mysql-test/main/opt_trace.result
@@ -3948,6 +3948,16 @@ explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3 {
}
},
{
+ "table": "t0",
+ "rowid_filters": [
+ {
+ "key": "a",
+ "build_cost": 0.174715752,
+ "rows": 3
+ }
+ ]
+ },
+ {
"selectivity_for_indexes": [
{
"index_name": "a",
@@ -4013,6 +4023,16 @@ explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3 {
}
},
{
+ "table": "t1",
+ "rowid_filters": [
+ {
+ "key": "a",
+ "build_cost": 0.174715752,
+ "rows": 3
+ }
+ ]
+ },
+ {
"selectivity_for_indexes": [
{
"index_name": "a",
diff --git a/mysql-test/main/update_single_to_multi.result b/mysql-test/main/update_single_to_multi.result
new file mode 100644
index 0000000..f7439f9
--- /dev/null
+++ b/mysql-test/main/update_single_to_multi.result
@@ -0,0 +1,2302 @@
+DROP DATABASE IF EXISTS dbt3_s001;
+CREATE DATABASE dbt3_s001;
+use dbt3_s001;
+create index i_n_name on nation(n_name);
+analyze table nation;
+Table Op Msg_type Msg_text
+dbt3_s001.nation analyze status Engine-independent statistics collected
+dbt3_s001.nation analyze status OK
+# Pullout
+# =======
+explain
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (7%) Using where; Using rowid filter
+explain format=json
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_n_name"],
+ "key": "i_n_name",
+ "key_length": "26",
+ "used_key_parts": ["n_name"],
+ "ref": ["const"],
+ "rows": 1,
+ "filtered": 100,
+ "index_condition": "nation.n_name = 'PERU'"
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "key": "i_c_nationkey",
+ "key_length": "5",
+ "used_key_parts": ["c_nationkey"],
+ "ref": ["dbt3_s001.nation.n_nationkey"],
+ "rows": 11,
+ "filtered": 100
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 108,
+ "selectivity_pct": 7.2
+ },
+ "rows": 11,
+ "filtered": 7.199999809,
+ "attached_condition": "orders.o_orderDATE between '1992-01-01' and '1992-06-30'"
+ }
+ }
+ ]
+ }
+}
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201268.06
+2880 145761.99
+3142 16030.15
+5382 138423.03
+5095 184583.99
+737 12984.85
+1729 12137.76
+5121 150334.57
+explain
+update orders set o_totalprice = o_totalprice-50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (7%) Using where; Using rowid filter
+explain format=json
+update orders set o_totalprice = o_totalprice-50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_n_name"],
+ "key": "i_n_name",
+ "key_length": "26",
+ "used_key_parts": ["n_name"],
+ "ref": ["const"],
+ "rows": 1,
+ "filtered": 100,
+ "index_condition": "nation.n_name = 'PERU'"
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "key": "i_c_nationkey",
+ "key_length": "5",
+ "used_key_parts": ["c_nationkey"],
+ "ref": ["dbt3_s001.nation.n_nationkey"],
+ "rows": 11,
+ "filtered": 100
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 108,
+ "selectivity_pct": 7.2
+ },
+ "rows": 11,
+ "filtered": 7.199999809,
+ "attached_condition": "orders.o_orderDATE between '1992-01-01' and '1992-06-30'"
+ }
+ }
+ ]
+ }
+}
+update orders set o_totalprice = o_totalprice-50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201218.06
+2880 145711.99
+3142 15980.15
+5382 138373.03
+5095 184533.99
+737 12934.85
+1729 12087.76
+5121 150284.57
+update orders set o_totalprice= o_totalprice+50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201268.06
+2880 145761.99
+3142 16030.15
+5382 138423.03
+5095 184583.99
+737 12984.85
+1729 12137.76
+5121 150334.57
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+4 1 444.37
+6 1 642.13
+8 1 957.34
+1 8 357.84
+3 8 645.4
+5 8 50.52
+7 8 763.98
+explain
+update partsupp set ps_supplycost = ps_supplycost+2 where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+update partsupp set ps_supplycost = ps_supplycost+2 where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+4 1 446.37
+6 1 644.13
+8 1 959.34
+1 8 359.84
+3 8 647.4
+5 8 52.52
+7 8 765.98
+update partsupp set ps_supplycost = ps_supplycost-2 where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+4 1 444.37
+6 1 642.13
+8 1 957.34
+1 8 357.84
+3 8 645.4
+5 8 50.52
+7 8 763.98
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+4 1 444.37
+6 1 642.13
+8 1 957.34
+1 8 357.84
+3 8 645.4
+5 8 50.52
+7 8 763.98
+explain
+update partsupp set ps_supplycost = ps_supplycost+10 where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+update partsupp set ps_supplycost = ps_supplycost+10 where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+4 1 454.37
+6 1 652.13
+8 1 967.34
+1 8 367.84
+3 8 655.4
+5 8 60.52
+7 8 773.98
+update partsupp set ps_supplycost = ps_supplycost-10 where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+4 1 444.37
+6 1 642.13
+8 1 957.34
+1 8 357.84
+3 8 645.4
+5 8 50.52
+7 8 763.98
+explain
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY lineitem ref PRIMARY,i_l_suppkey_partkey,i_l_partkey,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity i_l_suppkey 5 dbt3_s001.supplier.s_suppkey 100 Using where
+1 PRIMARY orders eq_ref|filter PRIMARY,i_o_orderdate,i_o_custkey PRIMARY|i_o_orderdate 4|4 dbt3_s001.lineitem.l_orderkey 1 (7%) Using where; Using rowid filter
+1 PRIMARY customer eq_ref PRIMARY,i_c_nationkey PRIMARY 4 dbt3_s001.orders.o_custkey 1 Using where
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.lineitem.l_partkey 1 Using where
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+l_orderkey l_linenumber l_tax
+4996 1 0.01
+933 1 0.04
+2500 2 0.02
+2500 4 0.02
+explain
+update lineitem set l_tax = (l_tax*100+1)/100 where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY lineitem ref PRIMARY,i_l_suppkey_partkey,i_l_partkey,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity i_l_suppkey 5 dbt3_s001.supplier.s_suppkey 100 Using where
+1 PRIMARY orders eq_ref|filter PRIMARY,i_o_orderdate,i_o_custkey PRIMARY|i_o_orderdate 4|4 dbt3_s001.lineitem.l_orderkey 1 (7%) Using where; Using rowid filter
+1 PRIMARY customer eq_ref PRIMARY,i_c_nationkey PRIMARY 4 dbt3_s001.orders.o_custkey 1 Using where
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.lineitem.l_partkey 1 Using where
+update lineitem set l_tax = (l_tax*100+1)/100 where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+l_orderkey l_linenumber l_tax
+4996 1 0.02
+933 1 0.05
+2500 2 0.03
+2500 4 0.03
+update lineitem set l_tax = (l_tax*100-1)/100 where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+l_orderkey l_linenumber l_tax
+4996 1 0.01
+933 1 0.04
+2500 2 0.02
+2500 4 0.02
+# FirstMatch
+# ==========
+explain
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY,i_c_nationkey NULL NULL NULL 150 Using where
+1 PRIMARY nation eq_ref|filter PRIMARY,i_n_regionkey PRIMARY|i_n_regionkey 4|5 dbt3_s001.customer.c_nationkey 1 (40%) Using where; Using rowid filter
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (6%) Using where; FirstMatch(nation); Using rowid filter
+explain format=json
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ALL",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "rows": 150,
+ "filtered": 100,
+ "attached_condition": "customer.c_nationkey is not null"
+ }
+ },
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY", "i_n_regionkey"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["n_nationkey"],
+ "ref": ["dbt3_s001.customer.c_nationkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_n_regionkey",
+ "used_key_parts": ["n_regionkey"]
+ },
+ "rows": 10,
+ "selectivity_pct": 40
+ },
+ "rows": 1,
+ "filtered": 40,
+ "attached_condition": "nation.n_regionkey in (1,2)"
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 89,
+ "selectivity_pct": 5.933333333
+ },
+ "rows": 11,
+ "filtered": 5.933333397,
+ "attached_condition": "orders.o_orderDATE between '1992-10-09' and '1993-03-08'",
+ "first_match": "nation"
+ }
+ }
+ ]
+ }
+}
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+explain
+update customer set c_acctbal = c_acctbal+10 where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY,i_c_nationkey NULL NULL NULL 150 Using where
+1 PRIMARY nation eq_ref|filter PRIMARY,i_n_regionkey PRIMARY|i_n_regionkey 4|5 dbt3_s001.customer.c_nationkey 1 (40%) Using where; Using rowid filter
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (6%) Using where; FirstMatch(nation); Using rowid filter
+explain format=json
+update customer set c_acctbal = c_acctbal+10 where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ALL",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "rows": 150,
+ "filtered": 100,
+ "attached_condition": "customer.c_nationkey is not null"
+ }
+ },
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY", "i_n_regionkey"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["n_nationkey"],
+ "ref": ["dbt3_s001.customer.c_nationkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_n_regionkey",
+ "used_key_parts": ["n_regionkey"]
+ },
+ "rows": 10,
+ "selectivity_pct": 40
+ },
+ "rows": 1,
+ "filtered": 40,
+ "attached_condition": "nation.n_regionkey in (1,2)"
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 89,
+ "selectivity_pct": 5.933333333
+ },
+ "rows": 11,
+ "filtered": 5.933333397,
+ "attached_condition": "orders.o_orderDATE between '1992-10-09' and '1993-03-08'",
+ "first_match": "nation"
+ }
+ }
+ ]
+ }
+}
+update customer set c_acctbal = c_acctbal+10 where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9571.95
+Customer#000000019 8924.71
+Customer#000000022 601.98
+Customer#000000025 7143.7
+Customer#000000028 1017.18
+Customer#000000037 -907.75
+Customer#000000040 1345.3
+Customer#000000047 284.58
+Customer#000000059 3468.6
+Customer#000000061 1546.24
+Customer#000000064 -636.64
+Customer#000000067 8176.59
+Customer#000000082 9478.34
+Customer#000000091 4653.14
+Customer#000000094 5510.11
+Customer#000000097 2174.48
+Customer#000000101 7480.96
+Customer#000000103 2767.45
+Customer#000000106 3298.42
+Customer#000000115 7518.92
+Customer#000000121 6438.32
+Customer#000000122 7875.46
+Customer#000000127 9290.71
+Customer#000000130 5083.58
+Customer#000000133 2324.67
+Customer#000000139 7907.78
+update customer set c_acctbal = c_acctbal-10 where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+explain
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (14%) Using where; FirstMatch(customer); Using rowid filter
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+c_name c_acctbal
+Customer#000000008 6819.74
+Customer#000000035 1228.24
+Customer#000000061 1536.24
+Customer#000000097 2164.48
+Customer#000000121 6428.32
+Customer#000000133 2314.67
+explain
+update customer set c_acctbal = c_acctbal+20 where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (14%) Using where; FirstMatch(customer); Using rowid filter
+update customer set c_acctbal = c_acctbal+20 where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+c_name c_acctbal
+Customer#000000008 6839.74
+Customer#000000035 1248.24
+Customer#000000061 1556.24
+Customer#000000097 2184.48
+Customer#000000121 6448.32
+Customer#000000133 2334.67
+update customer set c_acctbal = c_acctbal-20 where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+c_name c_acctbal
+Customer#000000008 6819.74
+Customer#000000035 1228.24
+Customer#000000061 1536.24
+Customer#000000097 2164.48
+Customer#000000121 6428.32
+Customer#000000133 2314.67
+# Materialization
+# ===============
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 dbt3_s001.orders.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 28 Using index condition; Using where
+explain format=json
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'",
+ "attached_condition": "orders.o_custkey is not null"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["dbt3_s001.orders.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7133.7
+Customer#000000013 3857.34
+Customer#000000065 8795.16
+Customer#000000032 3471.53
+Customer#000000023 3332.02
+Customer#000000035 1228.24
+Customer#000000091 4643.14
+Customer#000000016 4681.03
+Customer#000000098 -551.37
+Customer#000000037 -917.75
+Customer#000000136 -842.39
+Customer#000000118 3582.37
+Customer#000000022 591.98
+Customer#000000005 794.47
+Customer#000000109 -716.1
+Customer#000000038 6345.11
+Customer#000000076 5745.33
+Customer#000000056 6530.86
+Customer#000000040 1335.3
+Customer#000000116 8403.99
+Customer#000000115 7508.92
+Customer#000000140 9963.15
+Customer#000000017 6.34
+Customer#000000052 5630.28
+explain
+update customer set c_acctbal = c_acctbal+5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 dbt3_s001.orders.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 28 Using index condition; Using where
+explain format=json
+update customer set c_acctbal = c_acctbal+5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'",
+ "attached_condition": "orders.o_custkey is not null"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["dbt3_s001.orders.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+update customer set c_acctbal = c_acctbal+5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7138.7
+Customer#000000013 3862.34
+Customer#000000065 8800.16
+Customer#000000032 3476.53
+Customer#000000023 3337.02
+Customer#000000035 1233.24
+Customer#000000091 4648.14
+Customer#000000016 4686.03
+Customer#000000098 -546.37
+Customer#000000037 -912.75
+Customer#000000136 -837.39
+Customer#000000118 3587.37
+Customer#000000022 596.98
+Customer#000000005 799.47
+Customer#000000109 -711.1
+Customer#000000038 6350.11
+Customer#000000076 5750.33
+Customer#000000056 6535.86
+Customer#000000040 1340.3
+Customer#000000116 8408.99
+Customer#000000115 7513.92
+Customer#000000140 9968.15
+Customer#000000017 11.34
+Customer#000000052 5635.28
+update customer set c_acctbal = c_acctbal-5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7133.7
+Customer#000000013 3857.34
+Customer#000000065 8795.16
+Customer#000000032 3471.53
+Customer#000000023 3332.02
+Customer#000000035 1228.24
+Customer#000000091 4643.14
+Customer#000000016 4681.03
+Customer#000000098 -551.37
+Customer#000000037 -917.75
+Customer#000000136 -842.39
+Customer#000000118 3582.37
+Customer#000000022 591.98
+Customer#000000005 794.47
+Customer#000000109 -716.1
+Customer#000000038 6345.11
+Customer#000000076 5745.33
+Customer#000000056 6530.86
+Customer#000000040 1335.3
+Customer#000000116 8403.99
+Customer#000000115 7508.92
+Customer#000000140 9963.15
+Customer#000000017 6.34
+Customer#000000052 5630.28
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 114 Using index condition; Using where
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+c_name c_acctbal
+Customer#000000001 711.56
+Customer#000000002 121.65
+Customer#000000007 9561.95
+Customer#000000008 6819.74
+Customer#000000010 2753.54
+Customer#000000011 -272.6
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000029 7618.27
+Customer#000000031 5236.89
+Customer#000000034 8589.7
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000043 9904.28
+Customer#000000044 7315.94
+Customer#000000046 5744.59
+Customer#000000047 274.58
+Customer#000000049 4573.94
+Customer#000000053 4113.64
+Customer#000000055 4572.11
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000070 4867.52
+Customer#000000071 -611.19
+Customer#000000073 4288.5
+Customer#000000074 2764.43
+Customer#000000076 5745.33
+Customer#000000079 5121.28
+Customer#000000080 7383.53
+Customer#000000082 9468.34
+Customer#000000083 6463.51
+Customer#000000085 3386.64
+Customer#000000086 3306.32
+Customer#000000088 8031.44
+Customer#000000091 4643.14
+Customer#000000092 1182.91
+Customer#000000095 5327.38
+Customer#000000097 2164.48
+Customer#000000100 9889.89
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000104 -588.38
+Customer#000000106 3288.42
+Customer#000000109 -716.1
+Customer#000000110 7462.99
+Customer#000000112 2953.35
+Customer#000000118 3582.37
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000131 8595.53
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+Customer#000000136 -842.39
+Customer#000000137 7838.3
+Customer#000000139 7897.78
+Customer#000000142 2209.81
+Customer#000000143 2186.5
+Customer#000000148 2135.6
+Customer#000000149 8959.65
+explain
+update customer set c_acctbal = c_acctbal+1 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 114 Using index condition; Using where
+update customer set c_acctbal = c_acctbal+1 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+c_name c_acctbal
+Customer#000000001 712.56
+Customer#000000002 122.65
+Customer#000000007 9562.95
+Customer#000000008 6820.74
+Customer#000000010 2754.54
+Customer#000000011 -271.6
+Customer#000000016 4682.03
+Customer#000000017 7.34
+Customer#000000019 8915.71
+Customer#000000022 592.98
+Customer#000000023 3333.02
+Customer#000000025 7134.7
+Customer#000000028 1008.18
+Customer#000000029 7619.27
+Customer#000000031 5237.89
+Customer#000000034 8590.7
+Customer#000000037 -916.75
+Customer#000000040 1336.3
+Customer#000000043 9905.28
+Customer#000000044 7316.94
+Customer#000000046 5745.59
+Customer#000000047 275.58
+Customer#000000049 4574.94
+Customer#000000053 4114.64
+Customer#000000055 4573.11
+Customer#000000061 1537.24
+Customer#000000064 -645.64
+Customer#000000067 8167.59
+Customer#000000070 4868.52
+Customer#000000071 -610.19
+Customer#000000073 4289.5
+Customer#000000074 2765.43
+Customer#000000076 5746.33
+Customer#000000079 5122.28
+Customer#000000080 7384.53
+Customer#000000082 9469.34
+Customer#000000083 6464.51
+Customer#000000085 3387.64
+Customer#000000086 3307.32
+Customer#000000088 8032.44
+Customer#000000091 4644.14
+Customer#000000092 1183.91
+Customer#000000095 5328.38
+Customer#000000097 2165.48
+Customer#000000100 9890.89
+Customer#000000101 7471.96
+Customer#000000103 2758.45
+Customer#000000104 -587.38
+Customer#000000106 3289.42
+Customer#000000109 -715.1
+Customer#000000110 7463.99
+Customer#000000112 2954.35
+Customer#000000118 3583.37
+Customer#000000121 6429.32
+Customer#000000122 7866.46
+Customer#000000127 9281.71
+Customer#000000130 5074.58
+Customer#000000131 8596.53
+Customer#000000133 2315.67
+Customer#000000134 4609.9
+Customer#000000136 -841.39
+Customer#000000137 7839.3
+Customer#000000139 7898.78
+Customer#000000142 2210.81
+Customer#000000143 2187.5
+Customer#000000148 2136.6
+Customer#000000149 8960.65
+update customer set c_acctbal = c_acctbal-1 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+c_name c_acctbal
+Customer#000000001 711.56
+Customer#000000002 121.65
+Customer#000000007 9561.95
+Customer#000000008 6819.74
+Customer#000000010 2753.54
+Customer#000000011 -272.6
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000029 7618.27
+Customer#000000031 5236.89
+Customer#000000034 8589.7
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000043 9904.28
+Customer#000000044 7315.94
+Customer#000000046 5744.59
+Customer#000000047 274.58
+Customer#000000049 4573.94
+Customer#000000053 4113.64
+Customer#000000055 4572.11
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000070 4867.52
+Customer#000000071 -611.19
+Customer#000000073 4288.5
+Customer#000000074 2764.43
+Customer#000000076 5745.33
+Customer#000000079 5121.28
+Customer#000000080 7383.53
+Customer#000000082 9468.34
+Customer#000000083 6463.51
+Customer#000000085 3386.64
+Customer#000000086 3306.32
+Customer#000000088 8031.44
+Customer#000000091 4643.14
+Customer#000000092 1182.91
+Customer#000000095 5327.38
+Customer#000000097 2164.48
+Customer#000000100 9889.89
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000104 -588.38
+Customer#000000106 3288.42
+Customer#000000109 -716.1
+Customer#000000110 7462.99
+Customer#000000112 2953.35
+Customer#000000118 3582.37
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000131 8595.53
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+Customer#000000136 -842.39
+Customer#000000137 7838.3
+Customer#000000139 7897.78
+Customer#000000142 2209.81
+Customer#000000143 2186.5
+Customer#000000148 2135.6
+Customer#000000149 8959.65
+# Materialization SJM
+# ===================
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 <subquery2>.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 28 Using index condition; Using temporary
+explain format=json
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "having_condition": "count(orders.o_custkey) > 1",
+ "temporary_table": {
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'"
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["<subquery2>.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000118 3582.37
+Customer#000000056 6530.86
+explain
+update customer set c_acctbal = c_acctbal-5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 <subquery2>.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 28 Using index condition; Using temporary
+explain format=json
+update customer set c_acctbal = c_acctbal-5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "having_condition": "count(orders.o_custkey) > 1",
+ "temporary_table": {
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'"
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["<subquery2>.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+update customer set c_acctbal = c_acctbal-5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3852.34
+Customer#000000032 3466.53
+Customer#000000037 -922.75
+Customer#000000118 3577.37
+Customer#000000056 6525.86
+update customer set c_acctbal = c_acctbal+5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000118 3582.37
+Customer#000000056 6530.86
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 dbt3_s001.customer.c_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 242 Using index condition; Using temporary
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000016 4681.03
+Customer#000000037 -917.75
+Customer#000000046 5744.59
+Customer#000000091 4643.14
+Customer#000000103 2757.45
+Customer#000000118 3582.37
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+explain
+update customer set c_acctbal = c_acctbal-1 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 dbt3_s001.customer.c_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 242 Using index condition; Using temporary
+update customer set c_acctbal = c_acctbal-1 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+c_name c_acctbal
+Customer#000000007 9560.95
+Customer#000000016 4680.03
+Customer#000000037 -918.75
+Customer#000000046 5743.59
+Customer#000000091 4642.14
+Customer#000000103 2756.45
+Customer#000000118 3581.37
+Customer#000000133 2313.67
+Customer#000000134 4607.9
+update customer set c_acctbal = c_acctbal+1 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000016 4681.03
+Customer#000000037 -917.75
+Customer#000000046 5744.59
+Customer#000000091 4643.14
+Customer#000000103 2757.45
+Customer#000000118 3582.37
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+# Pullout PS
+# ==========
+prepare stmt from "
+update orders set o_totalprice = o_totalprice+? where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+";
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201268.06
+2880 145761.99
+3142 16030.15
+5382 138423.03
+5095 184583.99
+737 12984.85
+1729 12137.76
+5121 150334.57
+set @a1=-20;
+execute stmt using @a1;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201248.06
+2880 145741.99
+3142 16010.15
+5382 138403.03
+5095 184563.99
+737 12964.85
+1729 12117.76
+5121 150314.57
+set @a2=-10;
+execute stmt using @a2;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201238.06
+2880 145731.99
+3142 16000.15
+5382 138393.03
+5095 184553.99
+737 12954.85
+1729 12107.76
+5121 150304.57
+execute stmt using -(@a1+@a2);
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201268.06
+2880 145761.99
+3142 16030.15
+5382 138423.03
+5095 184583.99
+737 12984.85
+1729 12137.76
+5121 150334.57
+deallocate prepare stmt;
+# FirstMatch PS
+# =============
+prepare stmt from "
+update customer set c_acctbal = c_acctbal+? where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+";
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+set @a1=15;
+execute stmt using @a1;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9576.95
+Customer#000000019 8929.71
+Customer#000000022 606.98
+Customer#000000025 7148.7
+Customer#000000028 1022.18
+Customer#000000037 -902.75
+Customer#000000040 1350.3
+Customer#000000047 289.58
+Customer#000000059 3473.6
+Customer#000000061 1551.24
+Customer#000000064 -631.64
+Customer#000000067 8181.59
+Customer#000000082 9483.34
+Customer#000000091 4658.14
+Customer#000000094 5515.11
+Customer#000000097 2179.48
+Customer#000000101 7485.96
+Customer#000000103 2772.45
+Customer#000000106 3303.42
+Customer#000000115 7523.92
+Customer#000000121 6443.32
+Customer#000000122 7880.46
+Customer#000000127 9295.71
+Customer#000000130 5088.58
+Customer#000000133 2329.67
+Customer#000000139 7912.78
+set @a2=5;
+execute stmt using @a2;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9581.95
+Customer#000000019 8934.71
+Customer#000000022 611.98
+Customer#000000025 7153.7
+Customer#000000028 1027.1799999999998
+Customer#000000037 -897.75
+Customer#000000040 1355.3
+Customer#000000047 294.58
+Customer#000000059 3478.6
+Customer#000000061 1556.24
+Customer#000000064 -626.64
+Customer#000000067 8186.59
+Customer#000000082 9488.34
+Customer#000000091 4663.14
+Customer#000000094 5520.11
+Customer#000000097 2184.48
+Customer#000000101 7490.96
+Customer#000000103 2777.45
+Customer#000000106 3308.42
+Customer#000000115 7528.92
+Customer#000000121 6448.32
+Customer#000000122 7885.46
+Customer#000000127 9300.71
+Customer#000000130 5093.58
+Customer#000000133 2334.67
+Customer#000000139 7917.78
+execute stmt using -(@a1+@a2);
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.1799999999998
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+deallocate prepare stmt;
+# Materialization PS
+# ==================
+prepare stmt from "
+update customer set c_acctbal = c_acctbal+? where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+";
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7133.7
+Customer#000000013 3857.34
+Customer#000000065 8795.16
+Customer#000000032 3471.53
+Customer#000000023 3332.02
+Customer#000000035 1228.24
+Customer#000000091 4643.14
+Customer#000000016 4681.03
+Customer#000000098 -551.37
+Customer#000000037 -917.75
+Customer#000000136 -842.39
+Customer#000000118 3582.37
+Customer#000000022 591.98
+Customer#000000005 794.47
+Customer#000000109 -716.1
+Customer#000000038 6345.11
+Customer#000000076 5745.33
+Customer#000000056 6530.86
+Customer#000000040 1335.3
+Customer#000000116 8403.99
+Customer#000000115 7508.92
+Customer#000000140 9963.15
+Customer#000000017 6.34
+Customer#000000052 5630.28
+set @a1=7;
+execute stmt using @a1;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7140.7
+Customer#000000013 3864.34
+Customer#000000065 8802.16
+Customer#000000032 3478.53
+Customer#000000023 3339.02
+Customer#000000035 1235.24
+Customer#000000091 4650.14
+Customer#000000016 4688.03
+Customer#000000098 -544.37
+Customer#000000037 -910.75
+Customer#000000136 -835.39
+Customer#000000118 3589.37
+Customer#000000022 598.98
+Customer#000000005 801.47
+Customer#000000109 -709.1
+Customer#000000038 6352.11
+Customer#000000076 5752.33
+Customer#000000056 6537.86
+Customer#000000040 1342.3
+Customer#000000116 8410.99
+Customer#000000115 7515.92
+Customer#000000140 9970.15
+Customer#000000017 13.34
+Customer#000000052 5637.28
+set @a2=3;
+execute stmt using @a2;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7143.7
+Customer#000000013 3867.34
+Customer#000000065 8805.16
+Customer#000000032 3481.53
+Customer#000000023 3342.02
+Customer#000000035 1238.24
+Customer#000000091 4653.14
+Customer#000000016 4691.03
+Customer#000000098 -541.37
+Customer#000000037 -907.75
+Customer#000000136 -832.39
+Customer#000000118 3592.37
+Customer#000000022 601.98
+Customer#000000005 804.47
+Customer#000000109 -706.1
+Customer#000000038 6355.11
+Customer#000000076 5755.33
+Customer#000000056 6540.86
+Customer#000000040 1345.3
+Customer#000000116 8413.99
+Customer#000000115 7518.92
+Customer#000000140 9973.15
+Customer#000000017 16.34
+Customer#000000052 5640.28
+execute stmt using -(@a1+@a2);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7133.7
+Customer#000000013 3857.34
+Customer#000000065 8795.16
+Customer#000000032 3471.53
+Customer#000000023 3332.02
+Customer#000000035 1228.24
+Customer#000000091 4643.14
+Customer#000000016 4681.03
+Customer#000000098 -551.37
+Customer#000000037 -917.75
+Customer#000000136 -842.39
+Customer#000000118 3582.37
+Customer#000000022 591.98
+Customer#000000005 794.47
+Customer#000000109 -716.1
+Customer#000000038 6345.11
+Customer#000000076 5745.33
+Customer#000000056 6530.86
+Customer#000000040 1335.3
+Customer#000000116 8403.99
+Customer#000000115 7508.92
+Customer#000000140 9963.15
+Customer#000000017 6.34
+Customer#000000052 5630.28
+deallocate prepare stmt;
+# Materialization SJM PS
+# ======================
+prepare stmt from "
+update customer set c_acctbal = c_acctbal+? where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+";
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000118 3582.37
+Customer#000000056 6530.86
+set @a1=-2;
+execute stmt using @a1;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3855.34
+Customer#000000032 3469.53
+Customer#000000037 -919.75
+Customer#000000118 3580.37
+Customer#000000056 6528.86
+set @a2=-1;
+execute stmt using @a2;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3854.34
+Customer#000000032 3468.53
+Customer#000000037 -920.75
+Customer#000000118 3579.37
+Customer#000000056 6527.86
+execute stmt using -(@a1+@a2);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000118 3582.37
+Customer#000000056 6530.86
+deallocate prepare stmt;
+# Pullout SP
+# ==========
+create procedure p(d int)
+update orders set o_totalprice = o_totalprice+d where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201268.06
+2880 145761.99
+3142 16030.15
+5382 138423.03
+5095 184583.99
+737 12984.85
+1729 12137.76
+5121 150334.57
+call p(-10);
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201258.06
+2880 145751.99
+3142 16020.15
+5382 138413.03
+5095 184573.99
+737 12974.85
+1729 12127.76
+5121 150324.57
+call p(-20);
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201238.06
+2880 145731.99
+3142 16000.15
+5382 138393.03
+5095 184553.99
+737 12954.85
+1729 12107.76
+5121 150304.57
+call p(10+20);
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201268.06
+2880 145761.99
+3142 16030.15
+5382 138423.03
+5095 184583.99
+737 12984.85
+1729 12137.76
+5121 150334.57
+drop procedure p;
+# FirstMatch SP
+# =============
+create procedure p(d int)
+update customer set c_acctbal = c_acctbal+d where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.1799999999998
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+call p(5);
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9566.95
+Customer#000000019 8919.71
+Customer#000000022 596.98
+Customer#000000025 7138.7
+Customer#000000028 1012.1799999999998
+Customer#000000037 -912.75
+Customer#000000040 1340.3
+Customer#000000047 279.58
+Customer#000000059 3463.6
+Customer#000000061 1541.24
+Customer#000000064 -641.64
+Customer#000000067 8171.59
+Customer#000000082 9473.34
+Customer#000000091 4648.14
+Customer#000000094 5505.11
+Customer#000000097 2169.48
+Customer#000000101 7475.96
+Customer#000000103 2762.45
+Customer#000000106 3293.42
+Customer#000000115 7513.92
+Customer#000000121 6433.32
+Customer#000000122 7870.46
+Customer#000000127 9285.71
+Customer#000000130 5078.58
+Customer#000000133 2319.67
+Customer#000000139 7902.78
+call p(15);
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9581.95
+Customer#000000019 8934.71
+Customer#000000022 611.98
+Customer#000000025 7153.7
+Customer#000000028 1027.1799999999998
+Customer#000000037 -897.75
+Customer#000000040 1355.3
+Customer#000000047 294.58
+Customer#000000059 3478.6
+Customer#000000061 1556.24
+Customer#000000064 -626.64
+Customer#000000067 8186.59
+Customer#000000082 9488.34
+Customer#000000091 4663.14
+Customer#000000094 5520.11
+Customer#000000097 2184.48
+Customer#000000101 7490.96
+Customer#000000103 2777.45
+Customer#000000106 3308.42
+Customer#000000115 7528.92
+Customer#000000121 6448.32
+Customer#000000122 7885.46
+Customer#000000127 9300.71
+Customer#000000130 5093.58
+Customer#000000133 2334.67
+Customer#000000139 7917.78
+call p(-(5+15));
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.1799999999998
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+drop procedure p;
+# Materialization SP
+# ==================
+create procedure p(d int)
+update customer set c_acctbal = c_acctbal+d where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7133.7
+Customer#000000013 3857.34
+Customer#000000065 8795.16
+Customer#000000032 3471.53
+Customer#000000023 3332.02
+Customer#000000035 1228.24
+Customer#000000091 4643.14
+Customer#000000016 4681.03
+Customer#000000098 -551.37
+Customer#000000037 -917.75
+Customer#000000136 -842.39
+Customer#000000118 3582.37
+Customer#000000022 591.98
+Customer#000000005 794.47
+Customer#000000109 -716.1
+Customer#000000038 6345.11
+Customer#000000076 5745.33
+Customer#000000056 6530.86
+Customer#000000040 1335.3
+Customer#000000116 8403.99
+Customer#000000115 7508.92
+Customer#000000140 9963.15
+Customer#000000017 6.34
+Customer#000000052 5630.28
+call p(3);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7136.7
+Customer#000000013 3860.34
+Customer#000000065 8798.16
+Customer#000000032 3474.53
+Customer#000000023 3335.02
+Customer#000000035 1231.24
+Customer#000000091 4646.14
+Customer#000000016 4684.03
+Customer#000000098 -548.37
+Customer#000000037 -914.75
+Customer#000000136 -839.39
+Customer#000000118 3585.37
+Customer#000000022 594.98
+Customer#000000005 797.47
+Customer#000000109 -713.1
+Customer#000000038 6348.11
+Customer#000000076 5748.33
+Customer#000000056 6533.86
+Customer#000000040 1338.3
+Customer#000000116 8406.99
+Customer#000000115 7511.92
+Customer#000000140 9966.15
+Customer#000000017 9.34
+Customer#000000052 5633.28
+call p(7);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7143.7
+Customer#000000013 3867.34
+Customer#000000065 8805.16
+Customer#000000032 3481.53
+Customer#000000023 3342.02
+Customer#000000035 1238.24
+Customer#000000091 4653.14
+Customer#000000016 4691.03
+Customer#000000098 -541.37
+Customer#000000037 -907.75
+Customer#000000136 -832.39
+Customer#000000118 3592.37
+Customer#000000022 601.98
+Customer#000000005 804.47
+Customer#000000109 -706.1
+Customer#000000038 6355.11
+Customer#000000076 5755.33
+Customer#000000056 6540.86
+Customer#000000040 1345.3
+Customer#000000116 8413.99
+Customer#000000115 7518.92
+Customer#000000140 9973.15
+Customer#000000017 16.34
+Customer#000000052 5640.28
+call p(-(3+7));
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7133.7
+Customer#000000013 3857.34
+Customer#000000065 8795.16
+Customer#000000032 3471.53
+Customer#000000023 3332.02
+Customer#000000035 1228.24
+Customer#000000091 4643.14
+Customer#000000016 4681.03
+Customer#000000098 -551.37
+Customer#000000037 -917.75
+Customer#000000136 -842.39
+Customer#000000118 3582.37
+Customer#000000022 591.98
+Customer#000000005 794.47
+Customer#000000109 -716.1
+Customer#000000038 6345.11
+Customer#000000076 5745.33
+Customer#000000056 6530.86
+Customer#000000040 1335.3
+Customer#000000116 8403.99
+Customer#000000115 7508.92
+Customer#000000140 9963.15
+Customer#000000017 6.34
+Customer#000000052 5630.28
+drop procedure p;
+# Materialization SJM SP
+# ======================
+create procedure p(d int)
+update customer set c_acctbal = c_acctbal+d where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000118 3582.37
+Customer#000000056 6530.86
+call p(-1);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3856.34
+Customer#000000032 3470.53
+Customer#000000037 -918.75
+Customer#000000118 3581.37
+Customer#000000056 6529.86
+call p(-2);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3854.34
+Customer#000000032 3468.53
+Customer#000000037 -920.75
+Customer#000000118 3579.37
+Customer#000000056 6527.86
+call p(1+2);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000118 3582.37
+Customer#000000056 6530.86
+drop procedure p;
+# Checking limitations
+# ====================
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+o_orderkey o_totalprice
+1221 117397.16
+324 26868.85
+1856 189361.42
+1344 43809.37
+1925 146382.71
+3139 40975.96
+4903 34363.63
+5607 24660.06
+# Should not use semi-join conversion because has ORDER ... LIMIT
+explain
+update orders set o_totalprice = o_totalprice-50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2))
+order by o_totalprice limit 500;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY orders range i_o_orderdate i_o_orderdate 4 NULL 108 Using where; Using filesort
+2 DEPENDENT SUBQUERY customer unique_subquery|filter PRIMARY,i_c_nationkey PRIMARY|i_c_nationkey 4|5 func 1 (10%) Using where; Using rowid filter
+update orders set o_totalprice = o_totalprice-50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2))
+order by o_totalprice limit 500;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+o_orderkey o_totalprice
+1221 117347.16
+324 26818.85
+1856 189311.42
+1344 43759.37
+1925 146332.71
+3139 40925.96
+4903 34313.63
+5607 24610.06
+update orders set o_totalprice = o_totalprice+50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2))
+order by o_totalprice limit 500;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+o_orderkey o_totalprice
+1221 117397.16
+324 26868.85
+1856 189361.42
+1344 43809.37
+1925 146382.71
+3139 40975.96
+4903 34363.63
+5607 24660.06
+# Should use semi-join converion
+explain
+update orders set o_totalprice = o_totalprice-50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer range PRIMARY,i_c_nationkey i_c_nationkey 5 NULL 15 Using index condition
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (7%) Using where; Using rowid filter
+update orders set o_totalprice = o_totalprice-50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+o_orderkey o_totalprice
+1221 117347.16
+324 26818.85
+1856 189311.42
+1344 43759.37
+1925 146332.71
+3139 40925.96
+4903 34313.63
+5607 24610.06
+update orders set o_totalprice = o_totalprice+50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (1,2));
+o_orderkey o_totalprice
+1221 117397.16
+324 26868.85
+1856 189361.42
+1344 43809.37
+1925 146382.71
+3139 40975.96
+4903 34363.63
+5607 24660.06
+DROP DATABASE dbt3_s001;
diff --git a/mysql-test/main/update_single_to_multi.test b/mysql-test/main/update_single_to_multi.test
new file mode 100644
index 0000000..fe39e4d
--- /dev/null
+++ b/mysql-test/main/update_single_to_multi.test
@@ -0,0 +1,549 @@
+--disable_warnings
+DROP DATABASE IF EXISTS dbt3_s001;
+--enable_warnings
+
+CREATE DATABASE dbt3_s001;
+
+use dbt3_s001;
+
+--disable_query_log
+--disable_result_log
+--disable_warnings
+--source include/dbt3_s001.inc
+--enable_warnings
+--enable_result_log
+--enable_query_log
+
+create index i_n_name on nation(n_name);
+analyze table nation;
+
+
+--echo # Pullout
+--echo # =======
+
+let $c1=
+ o_orderDATE between '1992-01-01' and '1992-06-30' and
+ o_custkey in (select c_custkey from customer
+ where c_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+
+eval
+explain
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+explain format=json
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+
+eval
+explain
+update orders set o_totalprice = o_totalprice-50 where $c1;
+eval
+explain format=json
+update orders set o_totalprice = o_totalprice-50 where $c1;
+eval
+update orders set o_totalprice = o_totalprice-50 where $c1;
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+
+eval
+update orders set o_totalprice= o_totalprice+50 where $c1;
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+
+
+let $c2=
+ (ps_partkey, ps_suppkey) in
+ (select p_partkey, s_suppkey from part, supplier
+ where p_retailprice between 901 and 910 and
+ s_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+
+eval
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+
+eval
+explain
+update partsupp set ps_supplycost = ps_supplycost+2 where $c2;
+eval
+update partsupp set ps_supplycost = ps_supplycost+2 where $c2;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+
+eval
+update partsupp set ps_supplycost = ps_supplycost-2 where $c2;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+
+
+let $c3=
+ ps_partkey in (select p_partkey from part
+ where p_retailprice between 901 and 910) and
+ ps_suppkey in (select s_suppkey from supplier
+ where s_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+eval
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+
+eval
+explain
+update partsupp set ps_supplycost = ps_supplycost+10 where $c3;
+eval
+update partsupp set ps_supplycost = ps_supplycost+10 where $c3;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+
+eval
+update partsupp set ps_supplycost = ps_supplycost-10 where $c3;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+
+
+let $c4=
+ l_orderkey in (select o_orderkey from orders
+ where o_custkey in
+ (select c_custkey from customer
+ where c_nationkey in
+ (select n_nationkey from nation
+ where n_name='PERU'))
+ and
+ o_orderDATE between '1992-06-30' and '1992-12-31')
+ and
+ (l_partkey, l_suppkey) in
+ (select p_partkey, s_suppkey from part, supplier
+ where p_retailprice between 901 and 1000 and
+ s_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+
+eval
+explain
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+eval
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+
+eval
+explain
+update lineitem set l_tax = (l_tax*100+1)/100 where $c4;
+eval
+update lineitem set l_tax = (l_tax*100+1)/100 where $c4;
+eval
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+
+eval
+update lineitem set l_tax = (l_tax*100-1)/100 where $c4;
+eval
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+
+
+--echo # FirstMatch
+--echo # ==========
+
+let $c5=
+ c_nationkey in (select n_nationkey from nation
+ where n_regionkey in (1,2))
+ and
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-10-09' and '1993-03-08');
+
+eval
+explain
+select c_name, c_acctbal from customer where $c5;
+eval
+explain format=json
+select c_name, c_acctbal from customer where $c5;
+eval
+select c_name, c_acctbal from customer where $c5;
+
+eval
+explain
+update customer set c_acctbal = c_acctbal+10 where $c5;
+eval
+explain format=json
+update customer set c_acctbal = c_acctbal+10 where $c5;
+eval
+update customer set c_acctbal = c_acctbal+10 where $c5;
+eval
+select c_name, c_acctbal from customer where $c5;
+
+eval
+update customer set c_acctbal = c_acctbal-10 where $c5;
+eval
+select c_name, c_acctbal from customer where $c5;
+
+
+let $c6=
+ c_nationkey in (select n_nationkey from nation where n_name='PERU')
+ and
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between "1992-01-09" and "1993-01-08");
+
+eval
+explain
+select c_name, c_acctbal from customer where $c6;
+eval
+select c_name, c_acctbal from customer where $c6;
+
+eval
+explain
+update customer set c_acctbal = c_acctbal+20 where $c6;
+eval
+update customer set c_acctbal = c_acctbal+20 where $c6;
+eval
+select c_name, c_acctbal from customer where $c6;
+
+eval
+update customer set c_acctbal = c_acctbal-20 where $c6;
+eval
+select c_name, c_acctbal from customer where $c6;
+
+
+--echo # Materialization
+--echo # ===============
+
+let $c7=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-01-09' and '1992-03-08');
+
+eval
+explain
+select c_name, c_acctbal from customer where $c7;
+eval
+explain format=json
+select c_name, c_acctbal from customer where $c7;
+eval
+select c_name, c_acctbal from customer where $c7;
+
+eval
+explain
+update customer set c_acctbal = c_acctbal+5 where $c7;
+eval
+explain format=json
+update customer set c_acctbal = c_acctbal+5 where $c7;
+eval
+update customer set c_acctbal = c_acctbal+5 where $c7;
+eval
+select c_name, c_acctbal from customer where $c7;
+
+eval
+update customer set c_acctbal = c_acctbal-5 where $c7;
+eval
+select c_name, c_acctbal from customer where $c7;
+
+
+let $c8=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-06-09' and '1993-01-08');
+
+eval
+explain
+select c_name, c_acctbal from customer where $c8;
+eval
+select c_name, c_acctbal from customer where $c8;
+
+eval
+explain
+update customer set c_acctbal = c_acctbal+1 where $c8;
+eval
+update customer set c_acctbal = c_acctbal+1 where $c8;
+eval
+select c_name, c_acctbal from customer where $c8;
+
+eval
+update customer set c_acctbal = c_acctbal-1 where $c8;
+eval
+select c_name, c_acctbal from customer where $c8;
+
+
+--echo # Materialization SJM
+--echo # ===================
+
+let $c9=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+
+eval
+explain
+select c_name, c_acctbal from customer where $c9;
+eval
+explain format=json
+select c_name, c_acctbal from customer where $c9;
+eval
+select c_name, c_acctbal from customer where $c9;
+
+eval
+explain
+update customer set c_acctbal = c_acctbal-5 where $c9;
+eval
+explain format=json
+update customer set c_acctbal = c_acctbal-5 where $c9;
+eval
+update customer set c_acctbal = c_acctbal-5 where $c9;
+eval
+select c_name, c_acctbal from customer where $c9;
+
+eval
+update customer set c_acctbal = c_acctbal+5 where $c9;
+eval
+select c_name, c_acctbal from customer where $c9;
+
+
+let $c10=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+
+eval
+explain
+select c_name, c_acctbal from customer where $c10;
+eval
+select c_name, c_acctbal from customer where $c10;
+
+eval
+explain
+update customer set c_acctbal = c_acctbal-1 where $c10;
+eval
+update customer set c_acctbal = c_acctbal-1 where $c10;
+eval
+select c_name, c_acctbal from customer where $c10;
+
+eval
+update customer set c_acctbal = c_acctbal+1 where $c10;
+eval
+select c_name, c_acctbal from customer where $c10;
+
+
+--echo # Pullout PS
+--echo # ==========
+
+eval
+prepare stmt from "
+update orders set o_totalprice = o_totalprice+? where $c1;
+";
+
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+set @a1=-20;
+execute stmt using @a1;
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+set @a2=-10;
+execute stmt using @a2;
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+execute stmt using -(@a1+@a2);
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+
+deallocate prepare stmt;
+
+
+--echo # FirstMatch PS
+--echo # =============
+
+eval
+prepare stmt from "
+update customer set c_acctbal = c_acctbal+? where $c5;
+";
+
+eval
+select c_name, c_acctbal from customer where $c5;
+set @a1=15;
+execute stmt using @a1;
+eval
+select c_name, c_acctbal from customer where $c5;
+set @a2=5;
+execute stmt using @a2;
+eval
+select c_name, c_acctbal from customer where $c5;
+execute stmt using -(@a1+@a2);
+eval
+select c_name, c_acctbal from customer where $c5;
+
+deallocate prepare stmt;
+
+
+--echo # Materialization PS
+--echo # ==================
+
+eval
+prepare stmt from "
+update customer set c_acctbal = c_acctbal+? where $c7;
+";
+
+eval
+select c_name, c_acctbal from customer where $c7;
+set @a1=7;
+execute stmt using @a1;
+eval
+select c_name, c_acctbal from customer where $c7;
+set @a2=3;
+execute stmt using @a2;
+eval
+select c_name, c_acctbal from customer where $c7;
+execute stmt using -(@a1+@a2);
+eval
+select c_name, c_acctbal from customer where $c7;
+
+deallocate prepare stmt;
+
+
+--echo # Materialization SJM PS
+--echo # ======================
+
+eval
+prepare stmt from "
+update customer set c_acctbal = c_acctbal+? where $c9;
+";
+
+eval
+select c_name, c_acctbal from customer where $c9;
+set @a1=-2;
+execute stmt using @a1;
+eval
+select c_name, c_acctbal from customer where $c9;
+set @a2=-1;
+execute stmt using @a2;
+eval
+select c_name, c_acctbal from customer where $c9;
+execute stmt using -(@a1+@a2);
+eval
+select c_name, c_acctbal from customer where $c9;
+
+deallocate prepare stmt;
+
+
+--echo # Pullout SP
+--echo # ==========
+
+eval
+create procedure p(d int)
+update orders set o_totalprice = o_totalprice+d where $c1;
+
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+call p(-10);
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+call p(-20);
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+call p(10+20);
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+
+drop procedure p;
+
+
+--echo # FirstMatch SP
+--echo # =============
+
+eval
+create procedure p(d int)
+update customer set c_acctbal = c_acctbal+d where $c5;
+
+eval
+select c_name, c_acctbal from customer where $c5;
+call p(5);
+eval
+select c_name, c_acctbal from customer where $c5;
+call p(15);
+eval
+select c_name, c_acctbal from customer where $c5;
+call p(-(5+15));
+eval
+select c_name, c_acctbal from customer where $c5;
+
+drop procedure p;
+
+
+--echo # Materialization SP
+--echo # ==================
+
+eval
+create procedure p(d int)
+update customer set c_acctbal = c_acctbal+d where $c7;
+
+eval
+select c_name, c_acctbal from customer where $c7;
+call p(3);
+eval
+select c_name, c_acctbal from customer where $c7;
+call p(7);
+eval
+select c_name, c_acctbal from customer where $c7;
+call p(-(3+7));
+eval
+select c_name, c_acctbal from customer where $c7;
+
+drop procedure p;
+
+
+--echo # Materialization SJM SP
+--echo # ======================
+
+eval
+create procedure p(d int)
+update customer set c_acctbal = c_acctbal+d where $c9;
+
+eval
+select c_name, c_acctbal from customer where $c9;
+call p(-1);
+eval
+select c_name, c_acctbal from customer where $c9;
+call p(-2);
+eval
+select c_name, c_acctbal from customer where $c9;
+call p(1+2);
+eval
+select c_name, c_acctbal from customer where $c9;
+
+drop procedure p;
+
+--echo # Checking limitations
+--echo # ====================
+
+let $c11=
+ o_orderDATE between '1992-01-01' and '1992-06-30' and
+ o_custkey in (select c_custkey from customer
+ where c_nationkey in (1,2));
+
+eval
+select o_orderkey, o_totalprice from orders where $c11;
+--echo # Should not use semi-join conversion because has ORDER ... LIMIT
+eval
+explain
+update orders set o_totalprice = o_totalprice-50 where $c11
+order by o_totalprice limit 500;
+eval
+update orders set o_totalprice = o_totalprice-50 where $c11
+order by o_totalprice limit 500;
+eval
+select o_orderkey, o_totalprice from orders where $c11;
+eval
+update orders set o_totalprice = o_totalprice+50 where $c11
+order by o_totalprice limit 500;
+eval
+select o_orderkey, o_totalprice from orders where $c11;
+
+--echo # Should use semi-join converion
+eval
+explain
+update orders set o_totalprice = o_totalprice-50 where $c11;
+eval
+update orders set o_totalprice = o_totalprice-50 where $c11;
+eval
+select o_orderkey, o_totalprice from orders where $c11;
+eval
+update orders set o_totalprice = o_totalprice+50 where $c11;
+eval
+select o_orderkey, o_totalprice from orders where $c11;
+
+DROP DATABASE dbt3_s001;
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index fa338f0..cd88e78 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -533,6 +533,31 @@ bool is_materialization_applicable(THD *thd, Item_in_subselect *in_subs,
}
+/**
+ @brief Check whether an IN subquery must be excluded from conversion to SJ
+
+ @param thd global context the processed statement
+ @returns true if the IN subquery must be excluded from conversion to SJ
+
+ @note
+ Currently a top level IN subquery of an update/delete statement
+ is not converted to SJ if the statement contains ORDER BY ... LIMIT
+ or contains RETURNING.
+*/
+
+bool SELECT_LEX::is_sj_conversion_prohibited(THD *thd)
+{
+ DBUG_ASSERT(master_unit()->item->substype() == Item_subselect::IN_SUBS);
+ SELECT_LEX *outer_sl= outer_select();
+ return !outer_sl->outer_select() &&
+ (thd->lex->sql_command == SQLCOM_UPDATE ||
+ thd->lex->sql_command == SQLCOM_DELETE) &&
+ ((outer_sl->order_list.elements &&
+ outer_sl->get_limit() != HA_POS_ERROR) ||
+ (thd->lex->sql_command == SQLCOM_DELETE &&
+ thd->lex->has_returning()));
+}
+
/*
Check if we need JOIN::prepare()-phase subquery rewrites and if yes, do them
@@ -675,9 +700,9 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
3. Subquery does not have GROUP BY or ORDER BY
4. Subquery does not use aggregate functions or HAVING
5. Subquery predicate is at the AND-top-level of ON/WHERE clause
- 6. We are not in a subquery of a single table UPDATE/DELETE that
- doesn't have a JOIN (TODO: We should handle this at some
- point by switching to multi-table UPDATE/DELETE)
+ 6. We are not in a top level subquery of a single-table UPDATE or
+ DELETE with ORDER BY ... LIMIT and we are not in a top level
+ subquery of a single-table DELETE with returning
7. We're not in a table-less subquery like "SELECT 1"
8. No execution method was already chosen (by a prepared statement)
9. Parent select is not a table-less select
@@ -692,9 +717,7 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
!select_lex->group_list.elements && !join->order && // 3
!join->having && !select_lex->with_sum_func && // 4
in_subs->emb_on_expr_nest && // 5
- select_lex->outer_select()->join && // 6
- (!thd->lex->m_sql_cmd ||
- thd->lex->m_sql_cmd->sql_command_code() == SQLCOM_UPDATE_MULTI) &&
+ !select_lex->is_sj_conversion_prohibited(thd) && // 6
parent_unit->first_select()->leaf_tables.elements && // 7
!in_subs->has_strategy() && // 8
select_lex->outer_select()->table_list.first && // 9
@@ -754,7 +777,8 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
*/
if (in_subs && !in_subs->has_strategy())
{
- if (is_materialization_applicable(thd, in_subs, select_lex))
+ if (!select_lex->is_sj_conversion_prohibited(thd) &&
+ is_materialization_applicable(thd, in_subs, select_lex))
{
in_subs->add_strategy(SUBS_MATERIALIZATION);
@@ -7260,3 +7284,28 @@ bool TABLE_LIST::is_sjm_scan_table()
{
return is_active_sjm() && sj_mat_info->is_sj_scan;
}
+
+
+/**
+ @brief Check whether this subselect can be lifted to the top level
+ @returns true if the test is positive, false otherwise
+*/
+
+bool SELECT_LEX::is_sj_subselect_lifted_to_top()
+{
+ st_select_lex *sl= this;
+ st_select_lex *outer_sl= outer_select();
+ for ( ; outer_sl; sl= outer_sl, outer_sl= outer_sl->outer_select())
+ {
+ List_iterator_fast<Item_in_subselect> it(outer_sl->sj_subselects);
+ Item_in_subselect *in_subs;
+ while ((in_subs= it++))
+ {
+ if (in_subs->unit->first_select() == sl)
+ break;
+ }
+ if (!in_subs)
+ return false;
+ }
+ return true;
+}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 167df5b..3a2704f 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -7005,6 +7005,7 @@ class multi_delete :public select_result_interceptor
// Methods used by ColumnStore
uint get_num_of_tables() const { return num_of_tables; }
TABLE_LIST* get_tables() const { return delete_tables; }
+ void set_delete_tables (TABLE_LIST *tbl) { delete_tables= tbl; }
public:
multi_delete(THD *thd_arg, TABLE_LIST *dt, uint num_of_tables);
~multi_delete();
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 2ff4331..ed4b6be 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -1591,10 +1591,16 @@ bool Sql_cmd_delete::prepare_inner(THD *thd)
select_lex->order_list.first,
false, NULL, NULL, NULL,
select_lex, &lex->unit)))
-
{
goto err;
}
+
+ if (!multitable &&
+ select_lex->sj_subselects.elements)
+ multitable= true;
+
+ if (!multitable)
+ ((multi_delete *)result)->set_delete_tables(0);
}
if (multitable)
@@ -1638,7 +1644,8 @@ bool Sql_cmd_delete::prepare_inner(THD *thd)
{
TABLE_LIST *duplicate;
if ((duplicate= unique_table(thd, target_tbl->correspondent_table,
- lex->query_tables, 0)))
+ lex->query_tables, 0)) &&
+ !duplicate->select_lex->is_sj_subselect_lifted_to_top())
{
update_non_unique_table_error(target_tbl->correspondent_table,
"DELETE", duplicate);
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 0badc32..bb997cc 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -1642,6 +1642,8 @@ class st_select_lex: public st_select_lex_node
void lex_start(LEX *plex);
bool is_unit_nest() { return (nest_flags & UNIT_NEST_FL); }
void mark_as_unit_nest() { nest_flags= UNIT_NEST_FL; }
+ bool is_sj_conversion_prohibited(THD *thd);
+ bool is_sj_subselect_lifted_to_top();
};
typedef class st_select_lex SELECT_LEX;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index bf49d69..a7e5bc7 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -5834,8 +5834,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
s->needed_reg=select->needed_reg;
select->quick=0;
impossible_range= records == 0 && s->table->reginfo.impossible_range;
- if (join->thd->lex->sql_command == SQLCOM_SELECT &&
- optimizer_flag(join->thd, OPTIMIZER_SWITCH_USE_ROWID_FILTER))
+ if (optimizer_flag(join->thd, OPTIMIZER_SWITCH_USE_ROWID_FILTER))
s->table->init_cost_info_for_usable_range_rowid_filters(join->thd);
}
if (!impossible_range)
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 6b14c4f..b056b13 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -2471,6 +2471,8 @@ int multi_update::do_updates()
table = cur_table->table;
if (table == table_to_update)
continue; // Already updated
+ if (table->file->pushed_rowid_filter)
+ table->file->disable_pushed_rowid_filter();
org_updated= updated;
tmp_table= tmp_tables[cur_table->shared];
tmp_table->file->extra(HA_EXTRA_CACHE); // Change to read cache
@@ -2665,7 +2667,8 @@ int multi_update::do_updates()
check_opt_it.rewind();
while (TABLE *tbl= check_opt_it++)
tbl->file->ha_rnd_end();
-
+ if (table->file->save_pushed_rowid_filter)
+ table->file->enable_pushed_rowid_filter();
}
DBUG_RETURN(0);
@@ -2676,6 +2679,8 @@ int multi_update::do_updates()
}
err2:
+ if (table->file->save_pushed_rowid_filter)
+ table->file->enable_pushed_rowid_filter();
if (table->file->inited)
(void) table->file->ha_rnd_end();
if (tmp_table->file->inited)
@@ -2955,7 +2960,9 @@ bool Sql_cmd_update::prepare_inner(THD *thd)
{
goto err;
}
-
+ if (!multitable &&
+ select_lex->sj_subselects.elements)
+ multitable= true;
}
if (table_list->has_period())
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index a587a37..13dc602 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -13370,8 +13370,21 @@ delete_single_table:
YYPS->m_lock_type,
YYPS->m_mdl_type,
NULL,
+ 0)))
+ MYSQL_YYABORT;
+ Select->table_list.save_and_clear(&Lex->auxiliary_table_list);
+ Lex->table_count= 1;
+ Lex->query_tables= 0;
+ Lex->query_tables_last= &Lex->query_tables;
+ if (unlikely(!Select->
+ add_table_to_list(thd, $2, NULL, TL_OPTION_UPDATING,
+ YYPS->m_lock_type,
+ YYPS->m_mdl_type,
+ NULL,
$3)))
MYSQL_YYABORT;
+ Lex->auxiliary_table_list.first->correspondent_table=
+ Lex->query_tables;
YYPS->m_lock_type= TL_READ_DEFAULT;
YYPS->m_mdl_type= MDL_SHARED_READ;
}
1
0
[Commits] 6b21981: MDEV-7487 Semi-join optimization for single-table update/delete statements
by IgorBabaev 19 Jun '22
by IgorBabaev 19 Jun '22
19 Jun '22
revision-id: 6b21981eb1f61241cb4125a25e4e479164e213c0 (mariadb-10.6.1-472-g6b21981)
parent(s): 596cde07f17c490c43db10ce0a8cbb7bd4dbf5ae
author: Igor Babaev
committer: Igor Babaev
timestamp: 2022-06-18 21:44:00 -0700
message:
MDEV-7487 Semi-join optimization for single-table update/delete statements
This patch allows to use semi-join optimization at the top level of
single-table update and delete statements.
The problem of supporting such optimization became easy to resolve after
processing a single-table update/delete statement started using JOIN
structure. This allowed to use JOIN::prepare() not only for multi-table
updates/deletes but for single-table ones as well. This was done in the
patch for mdev-28883:
Re-design the upper level of handling UPDATE and DELETE statements.
Note that JOIN::prepare() detects all subqueries that can be considered
as candidates for semi-join optimization. The code added by this patch
looks for such candidates at the top level and if such candidates are found
in the processed single-table update/delete the statement is handled in
the same way as a multi-table update/delete.
Approved by Oleksandr Byelkin <sanja(a)mariadb.com>
---
mysql-test/main/delete_single_to_multi.result | 2216 ++++++++++++++++++++
mysql-test/main/delete_single_to_multi.test | 723 +++++++
mysql-test/main/log_state.result | 2 +-
.../main/myisam_explain_non_select_all.result | 45 +-
mysql-test/main/opt_trace.result | 20 +
mysql-test/main/update_single_to_multi.result | 2209 +++++++++++++++++++
mysql-test/main/update_single_to_multi.test | 511 +++++
sql/opt_subselect.cc | 36 +-
sql/sql_class.h | 1 +
sql/sql_delete.cc | 14 +-
sql/sql_lex.h | 1 +
sql/sql_select.cc | 3 +-
sql/sql_update.cc | 12 +-
sql/sql_yacc.yy | 13 +
14 files changed, 5774 insertions(+), 32 deletions(-)
diff --git a/mysql-test/main/delete_single_to_multi.result b/mysql-test/main/delete_single_to_multi.result
new file mode 100644
index 0000000..6cbc63f
--- /dev/null
+++ b/mysql-test/main/delete_single_to_multi.result
@@ -0,0 +1,2216 @@
+DROP DATABASE IF EXISTS dbt3_s001;
+CREATE DATABASE dbt3_s001;
+use dbt3_s001;
+create index i_n_name on nation(n_name);
+analyze table nation;
+Table Op Msg_type Msg_text
+dbt3_s001.nation analyze status Engine-independent statistics collected
+dbt3_s001.nation analyze status OK
+# Pullout
+# =======
+explain
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (7%) Using where; Using rowid filter
+explain format=json
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_n_name"],
+ "key": "i_n_name",
+ "key_length": "26",
+ "used_key_parts": ["n_name"],
+ "ref": ["const"],
+ "rows": 1,
+ "filtered": 100,
+ "index_condition": "nation.n_name = 'PERU'"
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "key": "i_c_nationkey",
+ "key_length": "5",
+ "used_key_parts": ["c_nationkey"],
+ "ref": ["dbt3_s001.nation.n_nationkey"],
+ "rows": 11,
+ "filtered": 100
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 108,
+ "selectivity_pct": 7.2
+ },
+ "rows": 11,
+ "filtered": 7.199999809,
+ "attached_condition": "orders.o_orderDATE between '1992-01-01' and '1992-06-30'"
+ }
+ }
+ ]
+ }
+}
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+5382 138423.03
+644 201268.06
+737 12984.85
+create table t as
+select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+explain
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (7%) Using where; Using rowid filter
+explain format=json
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_n_name"],
+ "key": "i_n_name",
+ "key_length": "26",
+ "used_key_parts": ["n_name"],
+ "ref": ["const"],
+ "rows": 1,
+ "filtered": 100,
+ "index_condition": "nation.n_name = 'PERU'"
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "key": "i_c_nationkey",
+ "key_length": "5",
+ "used_key_parts": ["c_nationkey"],
+ "ref": ["dbt3_s001.nation.n_nationkey"],
+ "rows": 11,
+ "filtered": 100
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 108,
+ "selectivity_pct": 7.2
+ },
+ "rows": 11,
+ "filtered": 7.199999809,
+ "attached_condition": "orders.o_orderDATE between '1992-01-01' and '1992-06-30'"
+ }
+ }
+ ]
+ }
+}
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+insert into orders select * from t;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+5382 138423.03
+644 201268.06
+737 12984.85
+drop table t;
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+1 8 357.84
+3 8 645.4
+4 1 444.37
+5 8 50.52
+6 1 642.13
+7 8 763.98
+8 1 957.34
+create table t as
+select * from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+explain
+delete from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+delete from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+insert into partsupp select * from t;
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+1 8 357.84
+3 8 645.4
+4 1 444.37
+5 8 50.52
+6 1 642.13
+7 8 763.98
+8 1 957.34
+drop table t;
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+1 8 357.84
+3 8 645.4
+4 1 444.37
+5 8 50.52
+6 1 642.13
+7 8 763.98
+8 1 957.34
+create table t as
+select * from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+explain
+delete from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+delete from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+insert into partsupp select * from t;
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+1 8 357.84
+3 8 645.4
+4 1 444.37
+5 8 50.52
+6 1 642.13
+7 8 763.98
+8 1 957.34
+drop table t;
+explain
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY lineitem ref PRIMARY,i_l_suppkey_partkey,i_l_partkey,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity i_l_suppkey 5 dbt3_s001.supplier.s_suppkey 100 Using where
+1 PRIMARY orders eq_ref|filter PRIMARY,i_o_orderdate,i_o_custkey PRIMARY|i_o_orderdate 4|4 dbt3_s001.lineitem.l_orderkey 1 (7%) Using where; Using rowid filter
+1 PRIMARY customer eq_ref PRIMARY,i_c_nationkey PRIMARY 4 dbt3_s001.orders.o_custkey 1 Using where
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.lineitem.l_partkey 1 Using where
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+l_orderkey l_linenumber l_tax
+2500 2 0.02
+2500 4 0.02
+4996 1 0.01
+933 1 0.04
+create table t as
+select * from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+explain
+delete from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY lineitem ref PRIMARY,i_l_suppkey_partkey,i_l_partkey,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity i_l_suppkey 5 dbt3_s001.supplier.s_suppkey 100 Using where
+1 PRIMARY orders eq_ref|filter PRIMARY,i_o_orderdate,i_o_custkey PRIMARY|i_o_orderdate 4|4 dbt3_s001.lineitem.l_orderkey 1 (7%) Using where; Using rowid filter
+1 PRIMARY customer eq_ref PRIMARY,i_c_nationkey PRIMARY 4 dbt3_s001.orders.o_custkey 1 Using where
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.lineitem.l_partkey 1 Using where
+delete from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+l_orderkey l_linenumber l_tax
+insert into lineitem select * from t;
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+l_orderkey l_linenumber l_tax
+2500 2 0.02
+2500 4 0.02
+4996 1 0.01
+933 1 0.04
+drop table t;
+# FirstMatch
+# ==========
+explain
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY,i_c_nationkey NULL NULL NULL 150 Using where
+1 PRIMARY nation eq_ref|filter PRIMARY,i_n_regionkey PRIMARY|i_n_regionkey 4|5 dbt3_s001.customer.c_nationkey 1 (40%) Using where; Using rowid filter
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (6%) Using where; FirstMatch(nation); Using rowid filter
+explain format=json
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ALL",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "rows": 150,
+ "filtered": 100,
+ "attached_condition": "customer.c_nationkey is not null"
+ }
+ },
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY", "i_n_regionkey"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["n_nationkey"],
+ "ref": ["dbt3_s001.customer.c_nationkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_n_regionkey",
+ "used_key_parts": ["n_regionkey"]
+ },
+ "rows": 10,
+ "selectivity_pct": 40
+ },
+ "rows": 1,
+ "filtered": 40,
+ "attached_condition": "nation.n_regionkey in (1,2)"
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 89,
+ "selectivity_pct": 5.933333333
+ },
+ "rows": 11,
+ "filtered": 5.933333397,
+ "attached_condition": "orders.o_orderDATE between '1992-10-09' and '1993-03-08'",
+ "first_match": "nation"
+ }
+ }
+ ]
+ }
+}
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+create table t as
+select * from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+explain
+delete from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY,i_c_nationkey NULL NULL NULL 150 Using where
+1 PRIMARY nation eq_ref|filter PRIMARY,i_n_regionkey PRIMARY|i_n_regionkey 4|5 dbt3_s001.customer.c_nationkey 1 (40%) Using where; Using rowid filter
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (6%) Using where; FirstMatch(nation); Using rowid filter
+explain format=json
+delete from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ALL",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "rows": 150,
+ "filtered": 100,
+ "attached_condition": "customer.c_nationkey is not null"
+ }
+ },
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY", "i_n_regionkey"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["n_nationkey"],
+ "ref": ["dbt3_s001.customer.c_nationkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_n_regionkey",
+ "used_key_parts": ["n_regionkey"]
+ },
+ "rows": 10,
+ "selectivity_pct": 40
+ },
+ "rows": 1,
+ "filtered": 40,
+ "attached_condition": "nation.n_regionkey in (1,2)"
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 89,
+ "selectivity_pct": 5.933333333
+ },
+ "rows": 11,
+ "filtered": 5.933333397,
+ "attached_condition": "orders.o_orderDATE between '1992-10-09' and '1993-03-08'",
+ "first_match": "nation"
+ }
+ }
+ ]
+ }
+}
+delete from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+drop table t;
+explain
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (14%) Using where; FirstMatch(customer); Using rowid filter
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+c_name c_acctbal
+Customer#000000008 6819.74
+Customer#000000035 1228.24
+Customer#000000061 1536.24
+Customer#000000097 2164.48
+Customer#000000121 6428.32
+Customer#000000133 2314.67
+create table t as
+select * from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+explain
+delete from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (14%) Using where; FirstMatch(customer); Using rowid filter
+delete from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+c_name c_acctbal
+Customer#000000008 6819.74
+Customer#000000035 1228.24
+Customer#000000061 1536.24
+Customer#000000097 2164.48
+Customer#000000121 6428.32
+Customer#000000133 2314.67
+drop table t;
+# Materialization
+# ===============
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 dbt3_s001.orders.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 28 Using index condition; Using where
+explain format=json
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'",
+ "attached_condition": "orders.o_custkey is not null"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["dbt3_s001.orders.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000005 794.47
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000035 1228.24
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000040 1335.3
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000098 -551.37
+Customer#000000109 -716.1
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000136 -842.39
+Customer#000000140 9963.15
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+explain
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 dbt3_s001.orders.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 28 Using index condition; Using where
+explain format=json
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'",
+ "attached_condition": "orders.o_custkey is not null"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["dbt3_s001.orders.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000005 794.47
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000035 1228.24
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000040 1335.3
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000098 -551.37
+Customer#000000109 -716.1
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000136 -842.39
+Customer#000000140 9963.15
+drop table t;
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 114 Using index condition; Using where
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+c_name c_acctbal
+Customer#000000001 711.56
+Customer#000000002 121.65
+Customer#000000007 9561.95
+Customer#000000008 6819.74
+Customer#000000010 2753.54
+Customer#000000011 -272.6
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000029 7618.27
+Customer#000000031 5236.89
+Customer#000000034 8589.7
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000043 9904.28
+Customer#000000044 7315.94
+Customer#000000046 5744.59
+Customer#000000047 274.58
+Customer#000000049 4573.94
+Customer#000000053 4113.64
+Customer#000000055 4572.11
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000070 4867.52
+Customer#000000071 -611.19
+Customer#000000073 4288.5
+Customer#000000074 2764.43
+Customer#000000076 5745.33
+Customer#000000079 5121.28
+Customer#000000080 7383.53
+Customer#000000082 9468.34
+Customer#000000083 6463.51
+Customer#000000085 3386.64
+Customer#000000086 3306.32
+Customer#000000088 8031.44
+Customer#000000091 4643.14
+Customer#000000092 1182.91
+Customer#000000095 5327.38
+Customer#000000097 2164.48
+Customer#000000100 9889.89
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000104 -588.38
+Customer#000000106 3288.42
+Customer#000000109 -716.1
+Customer#000000110 7462.99
+Customer#000000112 2953.35
+Customer#000000118 3582.37
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000131 8595.53
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+Customer#000000136 -842.39
+Customer#000000137 7838.3
+Customer#000000139 7897.78
+Customer#000000142 2209.81
+Customer#000000143 2186.5
+Customer#000000148 2135.6
+Customer#000000149 8959.65
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+explain
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 114 Using index condition; Using where
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+c_name c_acctbal
+Customer#000000001 711.56
+Customer#000000002 121.65
+Customer#000000007 9561.95
+Customer#000000008 6819.74
+Customer#000000010 2753.54
+Customer#000000011 -272.6
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000029 7618.27
+Customer#000000031 5236.89
+Customer#000000034 8589.7
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000043 9904.28
+Customer#000000044 7315.94
+Customer#000000046 5744.59
+Customer#000000047 274.58
+Customer#000000049 4573.94
+Customer#000000053 4113.64
+Customer#000000055 4572.11
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000070 4867.52
+Customer#000000071 -611.19
+Customer#000000073 4288.5
+Customer#000000074 2764.43
+Customer#000000076 5745.33
+Customer#000000079 5121.28
+Customer#000000080 7383.53
+Customer#000000082 9468.34
+Customer#000000083 6463.51
+Customer#000000085 3386.64
+Customer#000000086 3306.32
+Customer#000000088 8031.44
+Customer#000000091 4643.14
+Customer#000000092 1182.91
+Customer#000000095 5327.38
+Customer#000000097 2164.48
+Customer#000000100 9889.89
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000104 -588.38
+Customer#000000106 3288.42
+Customer#000000109 -716.1
+Customer#000000110 7462.99
+Customer#000000112 2953.35
+Customer#000000118 3582.37
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000131 8595.53
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+Customer#000000136 -842.39
+Customer#000000137 7838.3
+Customer#000000139 7897.78
+Customer#000000142 2209.81
+Customer#000000143 2186.5
+Customer#000000148 2135.6
+Customer#000000149 8959.65
+drop table t;
+# Materialization SJM
+# ===================
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 <subquery2>.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 28 Using index condition; Using temporary
+explain format=json
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "having_condition": "count(orders.o_custkey) > 1",
+ "temporary_table": {
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'"
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["<subquery2>.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+explain
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 <subquery2>.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 28 Using index condition; Using temporary
+explain format=json
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "having_condition": "count(orders.o_custkey) > 1",
+ "temporary_table": {
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'"
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["<subquery2>.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+drop table t;
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 dbt3_s001.customer.c_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 242 Using index condition; Using temporary
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000016 4681.03
+Customer#000000037 -917.75
+Customer#000000046 5744.59
+Customer#000000091 4643.14
+Customer#000000103 2757.45
+Customer#000000118 3582.37
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+explain
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 dbt3_s001.customer.c_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 242 Using index condition; Using temporary
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000016 4681.03
+Customer#000000037 -917.75
+Customer#000000046 5744.59
+Customer#000000091 4643.14
+Customer#000000103 2757.45
+Customer#000000118 3582.37
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+drop table t;
+# Pullout PS
+# ==========
+prepare stmt from "
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+";
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+5382 138423.03
+644 201268.06
+737 12984.85
+create table t as
+select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+execute stmt;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+insert into orders select * from t;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+5382 138423.03
+644 201268.06
+737 12984.85
+create table r as
+select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+execute stmt;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+insert into orders select * from r;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+5382 138423.03
+644 201268.06
+737 12984.85
+drop table t,r;
+deallocate prepare stmt;
+# FirstMatch PS
+# =============
+prepare stmt from "
+delete from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+";
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+create table t as
+select * from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+execute stmt;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+create table r as
+select * from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+execute stmt;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+insert into customer select * from r;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+drop table t,r;
+deallocate prepare stmt;
+# Materialization PS
+# ==================
+prepare stmt from "
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08') and c_name like ?;
+";
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000005 794.47
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000035 1228.24
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000040 1335.3
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000098 -551.37
+Customer#000000109 -716.1
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000136 -842.39
+Customer#000000140 9963.15
+set @a1='Customer#%1_';
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08') and c_name like @a1;
+execute stmt using @a1;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000005 794.47
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000035 1228.24
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000040 1335.3
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000098 -551.37
+Customer#000000109 -716.1
+Customer#000000136 -842.39
+Customer#000000140 9963.15
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000005 794.47
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000035 1228.24
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000040 1335.3
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000098 -551.37
+Customer#000000109 -716.1
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000136 -842.39
+Customer#000000140 9963.15
+set @a2='Customer#%3_';
+create table r as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08') and c_name like @a2;
+execute stmt using @a2;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000005 794.47
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000040 1335.3
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000098 -551.37
+Customer#000000109 -716.1
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000140 9963.15
+insert into customer select * from r;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000005 794.47
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000035 1228.24
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000040 1335.3
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000098 -551.37
+Customer#000000109 -716.1
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000136 -842.39
+Customer#000000140 9963.15
+drop table t,r;
+deallocate prepare stmt;
+# Materialization SJM PS
+# ======================
+prepare stmt from "
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08') and c_acctbal between ? and ?;
+";
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+set @a1=3500;
+set @a2=4000;
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1) and c_acctbal between @a1 and @a2;
+execute stmt using @a1, @a2;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+set @a3=-1000;
+set @a4=3500;
+create table r as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1) and c_acctbal between @a3 and @a4;
+execute stmt using @a3, @a4;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+insert into customer select * from r;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+drop table t,r;
+deallocate prepare stmt;
+# Pullout SP
+# ==========
+create procedure p(a1 int, a2 int)
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU')) and o_totalprice between a1 and a2;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+644 201268.06
+737 12984.85
+create table t as
+select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU')) and o_totalprice between 150000 and 200000;
+call p(150000, 200000);
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+644 201268.06
+737 12984.85
+insert into orders select * from t;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+644 201268.06
+737 12984.85
+create table r as
+select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU')) and o_totalprice between 180000 and 210000;
+call p(180000, 210000);
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5121 150334.57
+737 12984.85
+insert into orders select * from r;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+644 201268.06
+737 12984.85
+drop table t,r;
+drop procedure p;
+# FirstMatch SP
+# =============
+create procedure p(a int)
+delete from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08') and c_acctbal > a;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+create table t as
+select * from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08') and c_acctbal > 4000;
+call p(4000);
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000097 2164.48
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000133 2314.67
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+create table r as
+select * from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08') and c_acctbal > 2000;
+call p(2000);
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000047 274.58
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+insert into customer select * from r;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+drop table t,r;
+drop procedure p;
+# Materialization SP
+# ==================
+create procedure p()
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000140 9963.15
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+call p();
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000140 9963.15
+create table r as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+call p();
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+insert into customer select * from r;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000140 9963.15
+drop table t,r;
+drop procedure p;
+# Materialization SJM SP
+# ======================
+create procedure p()
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+call p();
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+create table r as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+call p();
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+insert into customer select * from r;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+drop table t,r;
+drop procedure p;
+# Check for DELETE ... RETURNING with SJ subquery in WHERE
+select c_name from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name
+Customer#000000013
+Customer#000000016
+Customer#000000025
+Customer#000000032
+Customer#000000037
+Customer#000000038
+Customer#000000052
+Customer#000000056
+Customer#000000065
+Customer#000000076
+Customer#000000091
+Customer#000000115
+Customer#000000116
+Customer#000000118
+Customer#000000140
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+explain
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08') returning c_name;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL NULL NULL NULL NULL 141 Using where
+2 DEPENDENT SUBQUERY orders index_subquery|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 func 175 (2%) Using where; Using rowid filter
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08') returning c_name;
+c_name
+Customer#000000013
+Customer#000000016
+Customer#000000025
+Customer#000000032
+Customer#000000037
+Customer#000000038
+Customer#000000052
+Customer#000000056
+Customer#000000065
+Customer#000000076
+Customer#000000091
+Customer#000000115
+Customer#000000116
+Customer#000000118
+Customer#000000140
+select c_name from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name
+insert into customer select * from t;
+select c_name from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name
+Customer#000000013
+Customer#000000016
+Customer#000000025
+Customer#000000032
+Customer#000000037
+Customer#000000038
+Customer#000000052
+Customer#000000056
+Customer#000000065
+Customer#000000076
+Customer#000000091
+Customer#000000115
+Customer#000000116
+Customer#000000118
+Customer#000000140
+drop table t;
+select c_name from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name
+Customer#000000013
+Customer#000000032
+Customer#000000037
+Customer#000000056
+Customer#000000118
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+explain
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1) returning c_name;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL NULL NULL NULL NULL 141 Using where
+2 DEPENDENT SUBQUERY orders range i_o_orderdate i_o_orderdate 4 NULL 28 Using index condition; Using temporary
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1) returning c_name;
+c_name
+Customer#000000013
+Customer#000000032
+Customer#000000037
+Customer#000000056
+Customer#000000118
+select c_name from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name
+insert into customer select * from t;
+select c_name from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name
+Customer#000000013
+Customer#000000032
+Customer#000000037
+Customer#000000056
+Customer#000000118
+drop table t;
+DROP DATABASE dbt3_s001;
diff --git a/mysql-test/main/delete_single_to_multi.test b/mysql-test/main/delete_single_to_multi.test
new file mode 100644
index 0000000..825da74
--- /dev/null
+++ b/mysql-test/main/delete_single_to_multi.test
@@ -0,0 +1,723 @@
+--disable_warnings
+DROP DATABASE IF EXISTS dbt3_s001;
+--enable_warnings
+
+CREATE DATABASE dbt3_s001;
+
+use dbt3_s001;
+
+--disable_query_log
+--disable_result_log
+--disable_warnings
+--source include/dbt3_s001.inc
+--enable_warnings
+--enable_result_log
+--enable_query_log
+
+create index i_n_name on nation(n_name);
+analyze table nation;
+
+
+--echo # Pullout
+--echo # =======
+
+let $c1=
+ o_orderDATE between '1992-01-01' and '1992-06-30' and
+ o_custkey in (select c_custkey from customer
+ where c_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+
+eval
+explain
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+explain format=json
+select o_orderkey, o_totalprice from orders where $c1;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+create table t as
+select * from orders where $c1;
+
+eval
+explain
+delete from orders where $c1;
+eval
+explain format=json
+delete from orders where $c1;
+eval
+delete from orders where $c1;
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+
+
+insert into orders select * from t;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+drop table t;
+
+
+let $c2=
+ (ps_partkey, ps_suppkey) in
+ (select p_partkey, s_suppkey from part, supplier
+ where p_retailprice between 901 and 910 and
+ s_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+
+eval
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+--sorted_result
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+eval
+create table t as
+select * from partsupp where $c2;
+
+eval
+explain
+delete from partsupp where $c2;
+eval
+delete from partsupp where $c2;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+
+insert into partsupp select * from t;
+--sorted_result
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+drop table t;
+
+
+let $c3=
+ ps_partkey in (select p_partkey from part
+ where p_retailprice between 901 and 910) and
+ ps_suppkey in (select s_suppkey from supplier
+ where s_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+eval
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+--sorted_result
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+eval
+create table t as
+select * from partsupp where $c3;
+
+eval
+explain
+delete from partsupp where $c3;
+eval
+delete from partsupp where $c3;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+
+insert into partsupp select * from t;
+--sorted_result
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+drop table t;
+
+
+let $c4=
+ l_orderkey in (select o_orderkey from orders
+ where o_custkey in
+ (select c_custkey from customer
+ where c_nationkey in
+ (select n_nationkey from nation
+ where n_name='PERU'))
+ and
+ o_orderDATE between '1992-06-30' and '1992-12-31')
+ and
+ (l_partkey, l_suppkey) in
+ (select p_partkey, s_suppkey from part, supplier
+ where p_retailprice between 901 and 1000 and
+ s_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+
+eval
+explain
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+--sorted_result
+eval
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+eval
+create table t as
+select * from lineitem where $c4;
+
+eval
+explain
+delete from lineitem where $c4;
+eval
+delete from lineitem where $c4;
+eval
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+
+insert into lineitem select * from t;
+--sorted_result
+eval
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+drop table t;
+
+
+--echo # FirstMatch
+--echo # ==========
+
+let $c5=
+ c_nationkey in (select n_nationkey from nation
+ where n_regionkey in (1,2))
+ and
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-10-09' and '1993-03-08');
+
+eval
+explain
+select c_name, c_acctbal from customer where $c5;
+eval
+explain format=json
+select c_name, c_acctbal from customer where $c5;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+eval
+create table t as
+select * from customer where $c5;
+
+eval
+explain
+delete from customer where $c5;
+eval
+explain format=json
+delete from customer where $c5;
+eval
+delete from customer where $c5;
+eval
+select c_name, c_acctbal from customer where $c5;
+
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+drop table t;
+
+
+let $c6=
+ c_nationkey in (select n_nationkey from nation where n_name='PERU')
+ and
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between "1992-01-09" and "1993-01-08");
+
+eval
+explain
+select c_name, c_acctbal from customer where $c6;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c6;
+eval
+create table t as
+select * from customer where $c6;
+
+eval
+explain
+delete from customer where $c6;
+eval
+delete from customer where $c6;
+eval
+select c_name, c_acctbal from customer where $c6;
+
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c6;
+drop table t;
+
+
+--echo # Materialization
+--echo # ===============
+
+let $c7=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-01-09' and '1992-03-08');
+
+eval
+explain
+select c_name, c_acctbal from customer where $c7;
+eval
+explain format=json
+select c_name, c_acctbal from customer where $c7;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+eval
+create table t as
+select * from customer where $c7;
+
+eval
+explain
+delete from customer where $c7;
+eval
+explain format=json
+delete from customer where $c7;
+eval
+delete from customer where $c7;
+eval
+select c_name, c_acctbal from customer where $c7;
+
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+drop table t;
+
+
+let $c8=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-06-09' and '1993-01-08');
+
+eval
+explain
+select c_name, c_acctbal from customer where $c8;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c8;
+eval
+create table t as
+select * from customer where $c8;
+
+eval
+explain
+delete from customer where $c8;
+eval
+delete from customer where $c8;
+eval
+select c_name, c_acctbal from customer where $c8;
+
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c8;
+drop table t;
+
+
+--echo # Materialization SJM
+--echo # ===================
+
+let $c9=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+
+eval
+explain
+select c_name, c_acctbal from customer where $c9;
+eval
+explain format=json
+select c_name, c_acctbal from customer where $c9;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+eval
+create table t as
+select * from customer where $c9;
+
+eval
+explain
+delete from customer where $c9;
+eval
+explain format=json
+delete from customer where $c9;
+eval
+delete from customer where $c9;
+eval
+select c_name, c_acctbal from customer where $c9;
+
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+drop table t;
+
+
+let $c10=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+
+eval
+explain
+select c_name, c_acctbal from customer where $c10;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c10;
+eval
+create table t as
+select * from customer where $c10;
+
+eval
+explain
+delete from customer where $c10;
+eval
+delete from customer where $c10;
+eval
+select c_name, c_acctbal from customer where $c10;
+
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c10;
+drop table t;
+
+
+--echo # Pullout PS
+--echo # ==========
+
+eval
+prepare stmt from "
+delete from orders where $c1;
+";
+
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+create table t as
+select * from orders where $c1;
+execute stmt;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+insert into orders select * from t;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+create table r as
+select * from orders where $c1;
+execute stmt;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+insert into orders select * from r;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+drop table t,r;
+
+deallocate prepare stmt;
+
+
+--echo # FirstMatch PS
+--echo # =============
+
+eval
+prepare stmt from "
+delete from customer where $c5;
+";
+
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+eval
+create table t as
+select * from customer where $c5;
+execute stmt;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+eval
+create table r as
+select * from customer where $c5;
+execute stmt;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+insert into customer select * from r;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+drop table t,r;
+
+deallocate prepare stmt;
+
+
+--echo # Materialization PS
+--echo # ==================
+
+eval
+prepare stmt from "
+delete from customer where $c7 and c_name like ?;
+";
+
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+set @a1='Customer#%1_';
+eval
+create table t as
+select * from customer where $c7 and c_name like @a1;
+execute stmt using @a1;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+set @a2='Customer#%3_';
+eval
+create table r as
+select * from customer where $c7 and c_name like @a2;
+execute stmt using @a2;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+insert into customer select * from r;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+drop table t,r;
+
+deallocate prepare stmt;
+
+
+--echo # Materialization SJM PS
+--echo # ======================
+
+eval
+prepare stmt from "
+delete from customer where $c7 and c_acctbal between ? and ?;
+";
+
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+set @a1=3500;
+set @a2=4000;
+eval
+create table t as
+select * from customer where $c9 and c_acctbal between @a1 and @a2;
+execute stmt using @a1, @a2;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+set @a3=-1000;
+set @a4=3500;
+eval
+create table r as
+select * from customer where $c9 and c_acctbal between @a3 and @a4;
+execute stmt using @a3, @a4;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+insert into customer select * from r;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+drop table t,r;
+
+deallocate prepare stmt;
+
+
+--echo # Pullout SP
+--echo # ==========
+
+eval
+create procedure p(a1 int, a2 int)
+delete from orders where $c1 and o_totalprice between a1 and a2;
+
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+create table t as
+select * from orders where $c1 and o_totalprice between 150000 and 200000;
+call p(150000, 200000);
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+insert into orders select * from t;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+create table r as
+select * from orders where $c1 and o_totalprice between 180000 and 210000;
+call p(180000, 210000);
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+insert into orders select * from r;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+drop table t,r;
+
+drop procedure p;
+
+
+--echo # FirstMatch SP
+--echo # =============
+
+eval
+create procedure p(a int)
+delete from customer where $c5 and c_acctbal > a;
+
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+eval
+create table t as
+select * from customer where $c5 and c_acctbal > 4000;
+call p(4000);
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+eval
+create table r as
+select * from customer where $c5 and c_acctbal > 2000;
+call p(2000);
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+insert into customer select * from r;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+drop table t,r;
+
+drop procedure p;
+
+
+--echo # Materialization SP
+--echo # ==================
+
+eval
+create procedure p()
+delete from customer where $c7;
+
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+eval
+create table t as
+select * from customer where $c7;
+call p();
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+eval
+create table r as
+select * from customer where $c7;
+call p();
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+insert into customer select * from r;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+drop table t,r;
+
+drop procedure p;
+
+
+--echo # Materialization SJM SP
+--echo # ======================
+
+eval
+create procedure p()
+delete from customer where $c9;
+
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+eval
+create table t as
+select * from customer where $c9;
+call p();
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+eval
+create table r as
+select * from customer where $c9;
+call p();
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+insert into customer select * from r;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+drop table t,r;
+
+drop procedure p;
+
+--echo # Check for DELETE ... RETURNING with SJ subquery in WHERE
+
+--sorted_result
+eval
+select c_name from customer where $c7;
+eval
+create table t as
+select * from customer where $c7;
+eval
+explain
+delete from customer where $c7 returning c_name;
+--sorted_result
+eval
+delete from customer where $c7 returning c_name;
+--sorted_result
+eval
+select c_name from customer where $c7;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name from customer where $c7;
+drop table t;
+
+--sorted_result
+eval
+select c_name from customer where $c9;
+eval
+create table t as
+select * from customer where $c9;
+eval
+explain
+delete from customer where $c9 returning c_name;
+--sorted_result
+eval
+delete from customer where $c9 returning c_name;
+--sorted_result
+eval
+select c_name from customer where $c9;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name from customer where $c9;
+drop table t;
+
+DROP DATABASE dbt3_s001;
diff --git a/mysql-test/main/log_state.result b/mysql-test/main/log_state.result
index 5e7aac8..1b1c737 100644
--- a/mysql-test/main/log_state.result
+++ b/mysql-test/main/log_state.result
@@ -243,7 +243,7 @@ rows_examined sql_text
4 UPDATE t1 SET a=a+sleep(.02) WHERE a>2
8 UPDATE t1 SET a=a+sleep(.02) ORDER BY a DESC
1 UPDATE t2 set b=b+sleep(.02) limit 1
-4 UPDATE t1 SET a=a+sleep(.02) WHERE a in (SELECT b from t2)
+10 UPDATE t1 SET a=a+sleep(.02) WHERE a in (SELECT b from t2)
6 DELETE FROM t1 WHERE a=a+sleep(.02) ORDER BY a LIMIT 2
disconnect con2;
connection default;
diff --git a/mysql-test/main/myisam_explain_non_select_all.result b/mysql-test/main/myisam_explain_non_select_all.result
index 20b769b..5df9ced 100644
--- a/mysql-test/main/myisam_explain_non_select_all.result
+++ b/mysql-test/main/myisam_explain_non_select_all.result
@@ -240,14 +240,16 @@ Warnings:
Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
EXPLAIN UPDATE t1 SET a = 10 WHERE 1 IN (SELECT 1 FROM t2 WHERE t2.b < 3);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
-2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED UPDATE t1 SET a = 10 WHERE 1 IN (SELECT 1 FROM t2 WHERE t2.b < 3);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
-2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 100.00 Using where
# Status of EXPLAIN EXTENDED query
Variable_name Value
Handler_read_key 4
@@ -271,8 +273,9 @@ Handler_read_key 5
Handler_read_rnd_next 8
# Status of testing query execution:
Variable_name Value
-Handler_read_key 4
-Handler_read_rnd_next 5
+Handler_read_key 5
+Handler_read_rnd 3
+Handler_read_rnd_next 12
Handler_update 3
DROP TABLE t1, t2;
@@ -290,13 +293,13 @@ Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be
EXPLAIN UPDATE t1 SET a = 10 WHERE a IN (SELECT b FROM t2 WHERE t1.a < 3);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
-2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY t2 ALL NULL NULL NULL NULL 3 Using where; FirstMatch(t1)
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED UPDATE t1 SET a = 10 WHERE a IN (SELECT b FROM t2 WHERE t1.a < 3);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
-2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where
+1 PRIMARY t2 ALL NULL NULL NULL NULL 3 100.00 Using where; FirstMatch(t1)
Warnings:
Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1
# Status of EXPLAIN EXTENDED query
@@ -984,14 +987,16 @@ Warnings:
Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
EXPLAIN UPDATE t1 SET a = 10 WHERE a IN (SELECT a FROM t2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
-2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED UPDATE t1 SET a = 10 WHERE a IN (SELECT a FROM t2);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
-2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 100.00
# Status of EXPLAIN EXTENDED query
Variable_name Value
Handler_read_key 4
@@ -1015,8 +1020,8 @@ Handler_read_key 7
Handler_read_rnd_next 8
# Status of testing query execution:
Variable_name Value
-Handler_read_key 4
-Handler_read_rnd_next 10
+Handler_read_key 7
+Handler_read_rnd_next 8
Handler_update 3
DROP TABLE t1, t2;
@@ -1079,14 +1084,14 @@ Warnings:
Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
EXPLAIN DELETE FROM t1 WHERE a1 IN (SELECT a2 FROM t2 WHERE a2 > 2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where
-2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 5 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5
+1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using where; FirstMatch(t1)
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED DELETE FROM t1 WHERE a1 IN (SELECT a2 FROM t2 WHERE a2 > 2);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 5 100.00 Using where
-2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5 100.00
+1 PRIMARY t2 ALL NULL NULL NULL NULL 5 100.00 Using where; FirstMatch(t1)
# Status of EXPLAIN EXTENDED query
Variable_name Value
Handler_read_key 4
@@ -3074,14 +3079,14 @@ Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be
EXPLAIN UPDATE t1 SET a = 10 WHERE a IN (SELECT * FROM (SELECT b FROM t2 ORDER BY b LIMIT 2,2) x);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
-2 DEPENDENT SUBQUERY <derived3> index_subquery key0 key0 5 func 2
+1 PRIMARY <derived3> ref key0 key0 5 test.t1.a 2 FirstMatch(t1)
3 DERIVED t2 ALL NULL NULL NULL NULL 3 Using filesort
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED UPDATE t1 SET a = 10 WHERE a IN (SELECT * FROM (SELECT b FROM t2 ORDER BY b LIMIT 2,2) x);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
-2 DEPENDENT SUBQUERY <derived3> index_subquery key0 key0 5 func 2 100.00
+1 PRIMARY <derived3> ref key0 key0 5 test.t1.a 2 100.00 FirstMatch(t1)
3 DERIVED t2 ALL NULL NULL NULL NULL 3 100.00 Using filesort
# Status of EXPLAIN EXTENDED query
Variable_name Value
diff --git a/mysql-test/main/opt_trace.result b/mysql-test/main/opt_trace.result
index 0555f72..e46bd80 100644
--- a/mysql-test/main/opt_trace.result
+++ b/mysql-test/main/opt_trace.result
@@ -3948,6 +3948,16 @@ explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3 {
}
},
{
+ "table": "t0",
+ "rowid_filters": [
+ {
+ "key": "a",
+ "build_cost": 0.174715752,
+ "rows": 3
+ }
+ ]
+ },
+ {
"selectivity_for_indexes": [
{
"index_name": "a",
@@ -4013,6 +4023,16 @@ explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3 {
}
},
{
+ "table": "t1",
+ "rowid_filters": [
+ {
+ "key": "a",
+ "build_cost": 0.174715752,
+ "rows": 3
+ }
+ ]
+ },
+ {
"selectivity_for_indexes": [
{
"index_name": "a",
diff --git a/mysql-test/main/update_single_to_multi.result b/mysql-test/main/update_single_to_multi.result
new file mode 100644
index 0000000..687132f
--- /dev/null
+++ b/mysql-test/main/update_single_to_multi.result
@@ -0,0 +1,2209 @@
+DROP DATABASE IF EXISTS dbt3_s001;
+CREATE DATABASE dbt3_s001;
+use dbt3_s001;
+create index i_n_name on nation(n_name);
+analyze table nation;
+Table Op Msg_type Msg_text
+dbt3_s001.nation analyze status Engine-independent statistics collected
+dbt3_s001.nation analyze status OK
+# Pullout
+# =======
+explain
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (7%) Using where; Using rowid filter
+explain format=json
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_n_name"],
+ "key": "i_n_name",
+ "key_length": "26",
+ "used_key_parts": ["n_name"],
+ "ref": ["const"],
+ "rows": 1,
+ "filtered": 100,
+ "index_condition": "nation.n_name = 'PERU'"
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "key": "i_c_nationkey",
+ "key_length": "5",
+ "used_key_parts": ["c_nationkey"],
+ "ref": ["dbt3_s001.nation.n_nationkey"],
+ "rows": 11,
+ "filtered": 100
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 108,
+ "selectivity_pct": 7.2
+ },
+ "rows": 11,
+ "filtered": 7.199999809,
+ "attached_condition": "orders.o_orderDATE between '1992-01-01' and '1992-06-30'"
+ }
+ }
+ ]
+ }
+}
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201268.06
+2880 145761.99
+3142 16030.15
+5382 138423.03
+5095 184583.99
+737 12984.85
+1729 12137.76
+5121 150334.57
+explain
+update orders set o_totalprice = o_totalprice-50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (7%) Using where; Using rowid filter
+explain format=json
+update orders set o_totalprice = o_totalprice-50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_n_name"],
+ "key": "i_n_name",
+ "key_length": "26",
+ "used_key_parts": ["n_name"],
+ "ref": ["const"],
+ "rows": 1,
+ "filtered": 100,
+ "index_condition": "nation.n_name = 'PERU'"
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "key": "i_c_nationkey",
+ "key_length": "5",
+ "used_key_parts": ["c_nationkey"],
+ "ref": ["dbt3_s001.nation.n_nationkey"],
+ "rows": 11,
+ "filtered": 100
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 108,
+ "selectivity_pct": 7.2
+ },
+ "rows": 11,
+ "filtered": 7.199999809,
+ "attached_condition": "orders.o_orderDATE between '1992-01-01' and '1992-06-30'"
+ }
+ }
+ ]
+ }
+}
+update orders set o_totalprice = o_totalprice-50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201218.06
+2880 145711.99
+3142 15980.15
+5382 138373.03
+5095 184533.99
+737 12934.85
+1729 12087.76
+5121 150284.57
+update orders set o_totalprice= o_totalprice+50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201268.06
+2880 145761.99
+3142 16030.15
+5382 138423.03
+5095 184583.99
+737 12984.85
+1729 12137.76
+5121 150334.57
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+4 1 444.37
+6 1 642.13
+8 1 957.34
+1 8 357.84
+3 8 645.4
+5 8 50.52
+7 8 763.98
+explain
+update partsupp set ps_supplycost = ps_supplycost+2 where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+update partsupp set ps_supplycost = ps_supplycost+2 where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+4 1 446.37
+6 1 644.13
+8 1 959.34
+1 8 359.84
+3 8 647.4
+5 8 52.52
+7 8 765.98
+update partsupp set ps_supplycost = ps_supplycost-2 where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+4 1 444.37
+6 1 642.13
+8 1 957.34
+1 8 357.84
+3 8 645.4
+5 8 50.52
+7 8 763.98
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+4 1 444.37
+6 1 642.13
+8 1 957.34
+1 8 357.84
+3 8 645.4
+5 8 50.52
+7 8 763.98
+explain
+update partsupp set ps_supplycost = ps_supplycost+10 where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+update partsupp set ps_supplycost = ps_supplycost+10 where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+4 1 454.37
+6 1 652.13
+8 1 967.34
+1 8 367.84
+3 8 655.4
+5 8 60.52
+7 8 773.98
+update partsupp set ps_supplycost = ps_supplycost-10 where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+4 1 444.37
+6 1 642.13
+8 1 957.34
+1 8 357.84
+3 8 645.4
+5 8 50.52
+7 8 763.98
+explain
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY lineitem ref PRIMARY,i_l_suppkey_partkey,i_l_partkey,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity i_l_suppkey 5 dbt3_s001.supplier.s_suppkey 100 Using where
+1 PRIMARY orders eq_ref|filter PRIMARY,i_o_orderdate,i_o_custkey PRIMARY|i_o_orderdate 4|4 dbt3_s001.lineitem.l_orderkey 1 (7%) Using where; Using rowid filter
+1 PRIMARY customer eq_ref PRIMARY,i_c_nationkey PRIMARY 4 dbt3_s001.orders.o_custkey 1 Using where
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.lineitem.l_partkey 1 Using where
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+l_orderkey l_linenumber l_tax
+4996 1 0.01
+933 1 0.04
+2500 2 0.02
+2500 4 0.02
+explain
+update lineitem set l_tax = (l_tax*100+1)/100 where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY lineitem ref PRIMARY,i_l_suppkey_partkey,i_l_partkey,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity i_l_suppkey 5 dbt3_s001.supplier.s_suppkey 100 Using where
+1 PRIMARY orders eq_ref|filter PRIMARY,i_o_orderdate,i_o_custkey PRIMARY|i_o_orderdate 4|4 dbt3_s001.lineitem.l_orderkey 1 (7%) Using where; Using rowid filter
+1 PRIMARY customer eq_ref PRIMARY,i_c_nationkey PRIMARY 4 dbt3_s001.orders.o_custkey 1 Using where
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.lineitem.l_partkey 1 Using where
+update lineitem set l_tax = (l_tax*100+1)/100 where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+l_orderkey l_linenumber l_tax
+4996 1 0.02
+933 1 0.05
+2500 2 0.03
+2500 4 0.03
+update lineitem set l_tax = (l_tax*100-1)/100 where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+l_orderkey l_linenumber l_tax
+4996 1 0.01
+933 1 0.04
+2500 2 0.02
+2500 4 0.02
+# FirstMatch
+# ==========
+explain
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY,i_c_nationkey NULL NULL NULL 150 Using where
+1 PRIMARY nation eq_ref|filter PRIMARY,i_n_regionkey PRIMARY|i_n_regionkey 4|5 dbt3_s001.customer.c_nationkey 1 (40%) Using where; Using rowid filter
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (6%) Using where; FirstMatch(nation); Using rowid filter
+explain format=json
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ALL",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "rows": 150,
+ "filtered": 100,
+ "attached_condition": "customer.c_nationkey is not null"
+ }
+ },
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY", "i_n_regionkey"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["n_nationkey"],
+ "ref": ["dbt3_s001.customer.c_nationkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_n_regionkey",
+ "used_key_parts": ["n_regionkey"]
+ },
+ "rows": 10,
+ "selectivity_pct": 40
+ },
+ "rows": 1,
+ "filtered": 40,
+ "attached_condition": "nation.n_regionkey in (1,2)"
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 89,
+ "selectivity_pct": 5.933333333
+ },
+ "rows": 11,
+ "filtered": 5.933333397,
+ "attached_condition": "orders.o_orderDATE between '1992-10-09' and '1993-03-08'",
+ "first_match": "nation"
+ }
+ }
+ ]
+ }
+}
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+explain
+update customer set c_acctbal = c_acctbal+10 where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY,i_c_nationkey NULL NULL NULL 150 Using where
+1 PRIMARY nation eq_ref|filter PRIMARY,i_n_regionkey PRIMARY|i_n_regionkey 4|5 dbt3_s001.customer.c_nationkey 1 (40%) Using where; Using rowid filter
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (6%) Using where; FirstMatch(nation); Using rowid filter
+explain format=json
+update customer set c_acctbal = c_acctbal+10 where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ALL",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "rows": 150,
+ "filtered": 100,
+ "attached_condition": "customer.c_nationkey is not null"
+ }
+ },
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY", "i_n_regionkey"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["n_nationkey"],
+ "ref": ["dbt3_s001.customer.c_nationkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_n_regionkey",
+ "used_key_parts": ["n_regionkey"]
+ },
+ "rows": 10,
+ "selectivity_pct": 40
+ },
+ "rows": 1,
+ "filtered": 40,
+ "attached_condition": "nation.n_regionkey in (1,2)"
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 89,
+ "selectivity_pct": 5.933333333
+ },
+ "rows": 11,
+ "filtered": 5.933333397,
+ "attached_condition": "orders.o_orderDATE between '1992-10-09' and '1993-03-08'",
+ "first_match": "nation"
+ }
+ }
+ ]
+ }
+}
+update customer set c_acctbal = c_acctbal+10 where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9571.95
+Customer#000000019 8924.71
+Customer#000000022 601.98
+Customer#000000025 7143.7
+Customer#000000028 1017.18
+Customer#000000037 -907.75
+Customer#000000040 1345.3
+Customer#000000047 284.58
+Customer#000000059 3468.6
+Customer#000000061 1546.24
+Customer#000000064 -636.64
+Customer#000000067 8176.59
+Customer#000000082 9478.34
+Customer#000000091 4653.14
+Customer#000000094 5510.11
+Customer#000000097 2174.48
+Customer#000000101 7480.96
+Customer#000000103 2767.45
+Customer#000000106 3298.42
+Customer#000000115 7518.92
+Customer#000000121 6438.32
+Customer#000000122 7875.46
+Customer#000000127 9290.71
+Customer#000000130 5083.58
+Customer#000000133 2324.67
+Customer#000000139 7907.78
+update customer set c_acctbal = c_acctbal-10 where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+explain
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (14%) Using where; FirstMatch(customer); Using rowid filter
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+c_name c_acctbal
+Customer#000000008 6819.74
+Customer#000000035 1228.24
+Customer#000000061 1536.24
+Customer#000000097 2164.48
+Customer#000000121 6428.32
+Customer#000000133 2314.67
+explain
+update customer set c_acctbal = c_acctbal+20 where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (14%) Using where; FirstMatch(customer); Using rowid filter
+update customer set c_acctbal = c_acctbal+20 where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+c_name c_acctbal
+Customer#000000008 6839.74
+Customer#000000035 1248.24
+Customer#000000061 1556.24
+Customer#000000097 2184.48
+Customer#000000121 6448.32
+Customer#000000133 2334.67
+update customer set c_acctbal = c_acctbal-20 where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+c_name c_acctbal
+Customer#000000008 6819.74
+Customer#000000035 1228.24
+Customer#000000061 1536.24
+Customer#000000097 2164.48
+Customer#000000121 6428.32
+Customer#000000133 2314.67
+# Materialization
+# ===============
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 dbt3_s001.orders.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 28 Using index condition; Using where
+explain format=json
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'",
+ "attached_condition": "orders.o_custkey is not null"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["dbt3_s001.orders.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7133.7
+Customer#000000013 3857.34
+Customer#000000065 8795.16
+Customer#000000032 3471.53
+Customer#000000023 3332.02
+Customer#000000035 1228.24
+Customer#000000091 4643.14
+Customer#000000016 4681.03
+Customer#000000098 -551.37
+Customer#000000037 -917.75
+Customer#000000136 -842.39
+Customer#000000118 3582.37
+Customer#000000022 591.98
+Customer#000000005 794.47
+Customer#000000109 -716.1
+Customer#000000038 6345.11
+Customer#000000076 5745.33
+Customer#000000056 6530.86
+Customer#000000040 1335.3
+Customer#000000116 8403.99
+Customer#000000115 7508.92
+Customer#000000140 9963.15
+Customer#000000017 6.34
+Customer#000000052 5630.28
+explain
+update customer set c_acctbal = c_acctbal+5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 dbt3_s001.orders.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 28 Using index condition; Using where
+explain format=json
+update customer set c_acctbal = c_acctbal+5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'",
+ "attached_condition": "orders.o_custkey is not null"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["dbt3_s001.orders.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+update customer set c_acctbal = c_acctbal+5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7138.7
+Customer#000000013 3862.34
+Customer#000000065 8800.16
+Customer#000000032 3476.53
+Customer#000000023 3337.02
+Customer#000000035 1233.24
+Customer#000000091 4648.14
+Customer#000000016 4686.03
+Customer#000000098 -546.37
+Customer#000000037 -912.75
+Customer#000000136 -837.39
+Customer#000000118 3587.37
+Customer#000000022 596.98
+Customer#000000005 799.47
+Customer#000000109 -711.1
+Customer#000000038 6350.11
+Customer#000000076 5750.33
+Customer#000000056 6535.86
+Customer#000000040 1340.3
+Customer#000000116 8408.99
+Customer#000000115 7513.92
+Customer#000000140 9968.15
+Customer#000000017 11.34
+Customer#000000052 5635.28
+update customer set c_acctbal = c_acctbal-5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7133.7
+Customer#000000013 3857.34
+Customer#000000065 8795.16
+Customer#000000032 3471.53
+Customer#000000023 3332.02
+Customer#000000035 1228.24
+Customer#000000091 4643.14
+Customer#000000016 4681.03
+Customer#000000098 -551.37
+Customer#000000037 -917.75
+Customer#000000136 -842.39
+Customer#000000118 3582.37
+Customer#000000022 591.98
+Customer#000000005 794.47
+Customer#000000109 -716.1
+Customer#000000038 6345.11
+Customer#000000076 5745.33
+Customer#000000056 6530.86
+Customer#000000040 1335.3
+Customer#000000116 8403.99
+Customer#000000115 7508.92
+Customer#000000140 9963.15
+Customer#000000017 6.34
+Customer#000000052 5630.28
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 114 Using index condition; Using where
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+c_name c_acctbal
+Customer#000000001 711.56
+Customer#000000002 121.65
+Customer#000000007 9561.95
+Customer#000000008 6819.74
+Customer#000000010 2753.54
+Customer#000000011 -272.6
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000029 7618.27
+Customer#000000031 5236.89
+Customer#000000034 8589.7
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000043 9904.28
+Customer#000000044 7315.94
+Customer#000000046 5744.59
+Customer#000000047 274.58
+Customer#000000049 4573.94
+Customer#000000053 4113.64
+Customer#000000055 4572.11
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000070 4867.52
+Customer#000000071 -611.19
+Customer#000000073 4288.5
+Customer#000000074 2764.43
+Customer#000000076 5745.33
+Customer#000000079 5121.28
+Customer#000000080 7383.53
+Customer#000000082 9468.34
+Customer#000000083 6463.51
+Customer#000000085 3386.64
+Customer#000000086 3306.32
+Customer#000000088 8031.44
+Customer#000000091 4643.14
+Customer#000000092 1182.91
+Customer#000000095 5327.38
+Customer#000000097 2164.48
+Customer#000000100 9889.89
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000104 -588.38
+Customer#000000106 3288.42
+Customer#000000109 -716.1
+Customer#000000110 7462.99
+Customer#000000112 2953.35
+Customer#000000118 3582.37
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000131 8595.53
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+Customer#000000136 -842.39
+Customer#000000137 7838.3
+Customer#000000139 7897.78
+Customer#000000142 2209.81
+Customer#000000143 2186.5
+Customer#000000148 2135.6
+Customer#000000149 8959.65
+explain
+update customer set c_acctbal = c_acctbal+1 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 114 Using index condition; Using where
+update customer set c_acctbal = c_acctbal+1 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+c_name c_acctbal
+Customer#000000001 712.56
+Customer#000000002 122.65
+Customer#000000007 9562.95
+Customer#000000008 6820.74
+Customer#000000010 2754.54
+Customer#000000011 -271.6
+Customer#000000016 4682.03
+Customer#000000017 7.34
+Customer#000000019 8915.71
+Customer#000000022 592.98
+Customer#000000023 3333.02
+Customer#000000025 7134.7
+Customer#000000028 1008.18
+Customer#000000029 7619.27
+Customer#000000031 5237.89
+Customer#000000034 8590.7
+Customer#000000037 -916.75
+Customer#000000040 1336.3
+Customer#000000043 9905.28
+Customer#000000044 7316.94
+Customer#000000046 5745.59
+Customer#000000047 275.58
+Customer#000000049 4574.94
+Customer#000000053 4114.64
+Customer#000000055 4573.11
+Customer#000000061 1537.24
+Customer#000000064 -645.64
+Customer#000000067 8167.59
+Customer#000000070 4868.52
+Customer#000000071 -610.19
+Customer#000000073 4289.5
+Customer#000000074 2765.43
+Customer#000000076 5746.33
+Customer#000000079 5122.28
+Customer#000000080 7384.53
+Customer#000000082 9469.34
+Customer#000000083 6464.51
+Customer#000000085 3387.64
+Customer#000000086 3307.32
+Customer#000000088 8032.44
+Customer#000000091 4644.14
+Customer#000000092 1183.91
+Customer#000000095 5328.38
+Customer#000000097 2165.48
+Customer#000000100 9890.89
+Customer#000000101 7471.96
+Customer#000000103 2758.45
+Customer#000000104 -587.38
+Customer#000000106 3289.42
+Customer#000000109 -715.1
+Customer#000000110 7463.99
+Customer#000000112 2954.35
+Customer#000000118 3583.37
+Customer#000000121 6429.32
+Customer#000000122 7866.46
+Customer#000000127 9281.71
+Customer#000000130 5074.58
+Customer#000000131 8596.53
+Customer#000000133 2315.67
+Customer#000000134 4609.9
+Customer#000000136 -841.39
+Customer#000000137 7839.3
+Customer#000000139 7898.78
+Customer#000000142 2210.81
+Customer#000000143 2187.5
+Customer#000000148 2136.6
+Customer#000000149 8960.65
+update customer set c_acctbal = c_acctbal-1 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+c_name c_acctbal
+Customer#000000001 711.56
+Customer#000000002 121.65
+Customer#000000007 9561.95
+Customer#000000008 6819.74
+Customer#000000010 2753.54
+Customer#000000011 -272.6
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000029 7618.27
+Customer#000000031 5236.89
+Customer#000000034 8589.7
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000043 9904.28
+Customer#000000044 7315.94
+Customer#000000046 5744.59
+Customer#000000047 274.58
+Customer#000000049 4573.94
+Customer#000000053 4113.64
+Customer#000000055 4572.11
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000070 4867.52
+Customer#000000071 -611.19
+Customer#000000073 4288.5
+Customer#000000074 2764.43
+Customer#000000076 5745.33
+Customer#000000079 5121.28
+Customer#000000080 7383.53
+Customer#000000082 9468.34
+Customer#000000083 6463.51
+Customer#000000085 3386.64
+Customer#000000086 3306.32
+Customer#000000088 8031.44
+Customer#000000091 4643.14
+Customer#000000092 1182.91
+Customer#000000095 5327.38
+Customer#000000097 2164.48
+Customer#000000100 9889.89
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000104 -588.38
+Customer#000000106 3288.42
+Customer#000000109 -716.1
+Customer#000000110 7462.99
+Customer#000000112 2953.35
+Customer#000000118 3582.37
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000131 8595.53
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+Customer#000000136 -842.39
+Customer#000000137 7838.3
+Customer#000000139 7897.78
+Customer#000000142 2209.81
+Customer#000000143 2186.5
+Customer#000000148 2135.6
+Customer#000000149 8959.65
+# Materialization SJM
+# ===================
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 <subquery2>.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 28 Using index condition; Using temporary
+explain format=json
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "having_condition": "count(orders.o_custkey) > 1",
+ "temporary_table": {
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'"
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["<subquery2>.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000118 3582.37
+Customer#000000056 6530.86
+explain
+update customer set c_acctbal = c_acctbal-5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 <subquery2>.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 28 Using index condition; Using temporary
+explain format=json
+update customer set c_acctbal = c_acctbal-5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "having_condition": "count(orders.o_custkey) > 1",
+ "temporary_table": {
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'"
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["<subquery2>.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+update customer set c_acctbal = c_acctbal-5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3852.34
+Customer#000000032 3466.53
+Customer#000000037 -922.75
+Customer#000000118 3577.37
+Customer#000000056 6525.86
+update customer set c_acctbal = c_acctbal+5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000118 3582.37
+Customer#000000056 6530.86
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 dbt3_s001.customer.c_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 242 Using index condition; Using temporary
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000016 4681.03
+Customer#000000037 -917.75
+Customer#000000046 5744.59
+Customer#000000091 4643.14
+Customer#000000103 2757.45
+Customer#000000118 3582.37
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+explain
+update customer set c_acctbal = c_acctbal-1 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 dbt3_s001.customer.c_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 242 Using index condition; Using temporary
+update customer set c_acctbal = c_acctbal-1 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+c_name c_acctbal
+Customer#000000007 9560.95
+Customer#000000016 4680.03
+Customer#000000037 -918.75
+Customer#000000046 5743.59
+Customer#000000091 4642.14
+Customer#000000103 2756.45
+Customer#000000118 3581.37
+Customer#000000133 2313.67
+Customer#000000134 4607.9
+update customer set c_acctbal = c_acctbal+1 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000016 4681.03
+Customer#000000037 -917.75
+Customer#000000046 5744.59
+Customer#000000091 4643.14
+Customer#000000103 2757.45
+Customer#000000118 3582.37
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+# Pullout PS
+# ==========
+prepare stmt from "
+update orders set o_totalprice = o_totalprice+? where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+";
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201268.06
+2880 145761.99
+3142 16030.15
+5382 138423.03
+5095 184583.99
+737 12984.85
+1729 12137.76
+5121 150334.57
+set @a1=-20;
+execute stmt using @a1;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201248.06
+2880 145741.99
+3142 16010.15
+5382 138403.03
+5095 184563.99
+737 12964.85
+1729 12117.76
+5121 150314.57
+set @a2=-10;
+execute stmt using @a2;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201238.06
+2880 145731.99
+3142 16000.15
+5382 138393.03
+5095 184553.99
+737 12954.85
+1729 12107.76
+5121 150304.57
+execute stmt using -(@a1+@a2);
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201268.06
+2880 145761.99
+3142 16030.15
+5382 138423.03
+5095 184583.99
+737 12984.85
+1729 12137.76
+5121 150334.57
+deallocate prepare stmt;
+# FirstMatch PS
+# =============
+prepare stmt from "
+update customer set c_acctbal = c_acctbal+? where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+";
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+set @a1=15;
+execute stmt using @a1;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9576.95
+Customer#000000019 8929.71
+Customer#000000022 606.98
+Customer#000000025 7148.7
+Customer#000000028 1022.18
+Customer#000000037 -902.75
+Customer#000000040 1350.3
+Customer#000000047 289.58
+Customer#000000059 3473.6
+Customer#000000061 1551.24
+Customer#000000064 -631.64
+Customer#000000067 8181.59
+Customer#000000082 9483.34
+Customer#000000091 4658.14
+Customer#000000094 5515.11
+Customer#000000097 2179.48
+Customer#000000101 7485.96
+Customer#000000103 2772.45
+Customer#000000106 3303.42
+Customer#000000115 7523.92
+Customer#000000121 6443.32
+Customer#000000122 7880.46
+Customer#000000127 9295.71
+Customer#000000130 5088.58
+Customer#000000133 2329.67
+Customer#000000139 7912.78
+set @a2=5;
+execute stmt using @a2;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9581.95
+Customer#000000019 8934.71
+Customer#000000022 611.98
+Customer#000000025 7153.7
+Customer#000000028 1027.1799999999998
+Customer#000000037 -897.75
+Customer#000000040 1355.3
+Customer#000000047 294.58
+Customer#000000059 3478.6
+Customer#000000061 1556.24
+Customer#000000064 -626.64
+Customer#000000067 8186.59
+Customer#000000082 9488.34
+Customer#000000091 4663.14
+Customer#000000094 5520.11
+Customer#000000097 2184.48
+Customer#000000101 7490.96
+Customer#000000103 2777.45
+Customer#000000106 3308.42
+Customer#000000115 7528.92
+Customer#000000121 6448.32
+Customer#000000122 7885.46
+Customer#000000127 9300.71
+Customer#000000130 5093.58
+Customer#000000133 2334.67
+Customer#000000139 7917.78
+execute stmt using -(@a1+@a2);
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.1799999999998
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+deallocate prepare stmt;
+# Materialization PS
+# ==================
+prepare stmt from "
+update customer set c_acctbal = c_acctbal+? where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+";
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7133.7
+Customer#000000013 3857.34
+Customer#000000065 8795.16
+Customer#000000032 3471.53
+Customer#000000023 3332.02
+Customer#000000035 1228.24
+Customer#000000091 4643.14
+Customer#000000016 4681.03
+Customer#000000098 -551.37
+Customer#000000037 -917.75
+Customer#000000136 -842.39
+Customer#000000118 3582.37
+Customer#000000022 591.98
+Customer#000000005 794.47
+Customer#000000109 -716.1
+Customer#000000038 6345.11
+Customer#000000076 5745.33
+Customer#000000056 6530.86
+Customer#000000040 1335.3
+Customer#000000116 8403.99
+Customer#000000115 7508.92
+Customer#000000140 9963.15
+Customer#000000017 6.34
+Customer#000000052 5630.28
+set @a1=7;
+execute stmt using @a1;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7140.7
+Customer#000000013 3864.34
+Customer#000000065 8802.16
+Customer#000000032 3478.53
+Customer#000000023 3339.02
+Customer#000000035 1235.24
+Customer#000000091 4650.14
+Customer#000000016 4688.03
+Customer#000000098 -544.37
+Customer#000000037 -910.75
+Customer#000000136 -835.39
+Customer#000000118 3589.37
+Customer#000000022 598.98
+Customer#000000005 801.47
+Customer#000000109 -709.1
+Customer#000000038 6352.11
+Customer#000000076 5752.33
+Customer#000000056 6537.86
+Customer#000000040 1342.3
+Customer#000000116 8410.99
+Customer#000000115 7515.92
+Customer#000000140 9970.15
+Customer#000000017 13.34
+Customer#000000052 5637.28
+set @a2=3;
+execute stmt using @a2;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7143.7
+Customer#000000013 3867.34
+Customer#000000065 8805.16
+Customer#000000032 3481.53
+Customer#000000023 3342.02
+Customer#000000035 1238.24
+Customer#000000091 4653.14
+Customer#000000016 4691.03
+Customer#000000098 -541.37
+Customer#000000037 -907.75
+Customer#000000136 -832.39
+Customer#000000118 3592.37
+Customer#000000022 601.98
+Customer#000000005 804.47
+Customer#000000109 -706.1
+Customer#000000038 6355.11
+Customer#000000076 5755.33
+Customer#000000056 6540.86
+Customer#000000040 1345.3
+Customer#000000116 8413.99
+Customer#000000115 7518.92
+Customer#000000140 9973.15
+Customer#000000017 16.34
+Customer#000000052 5640.28
+execute stmt using -(@a1+@a2);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7133.7
+Customer#000000013 3857.34
+Customer#000000065 8795.16
+Customer#000000032 3471.53
+Customer#000000023 3332.02
+Customer#000000035 1228.24
+Customer#000000091 4643.14
+Customer#000000016 4681.03
+Customer#000000098 -551.37
+Customer#000000037 -917.75
+Customer#000000136 -842.39
+Customer#000000118 3582.37
+Customer#000000022 591.98
+Customer#000000005 794.47
+Customer#000000109 -716.1
+Customer#000000038 6345.11
+Customer#000000076 5745.33
+Customer#000000056 6530.86
+Customer#000000040 1335.3
+Customer#000000116 8403.99
+Customer#000000115 7508.92
+Customer#000000140 9963.15
+Customer#000000017 6.34
+Customer#000000052 5630.28
+deallocate prepare stmt;
+# Materialization SJM PS
+# ======================
+prepare stmt from "
+update customer set c_acctbal = c_acctbal+? where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+";
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000118 3582.37
+Customer#000000056 6530.86
+set @a1=-2;
+execute stmt using @a1;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3855.34
+Customer#000000032 3469.53
+Customer#000000037 -919.75
+Customer#000000118 3580.37
+Customer#000000056 6528.86
+set @a2=-1;
+execute stmt using @a2;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3854.34
+Customer#000000032 3468.53
+Customer#000000037 -920.75
+Customer#000000118 3579.37
+Customer#000000056 6527.86
+execute stmt using -(@a1+@a2);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000118 3582.37
+Customer#000000056 6530.86
+deallocate prepare stmt;
+# Pullout SP
+# ==========
+create procedure p(d int)
+update orders set o_totalprice = o_totalprice+d where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201268.06
+2880 145761.99
+3142 16030.15
+5382 138423.03
+5095 184583.99
+737 12984.85
+1729 12137.76
+5121 150334.57
+call p(-10);
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201258.06
+2880 145751.99
+3142 16020.15
+5382 138413.03
+5095 184573.99
+737 12974.85
+1729 12127.76
+5121 150324.57
+call p(-20);
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201238.06
+2880 145731.99
+3142 16000.15
+5382 138393.03
+5095 184553.99
+737 12954.85
+1729 12107.76
+5121 150304.57
+call p(10+20);
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201268.06
+2880 145761.99
+3142 16030.15
+5382 138423.03
+5095 184583.99
+737 12984.85
+1729 12137.76
+5121 150334.57
+drop procedure p;
+# FirstMatch SP
+# =============
+create procedure p(d int)
+update customer set c_acctbal = c_acctbal+d where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.1799999999998
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+call p(5);
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9566.95
+Customer#000000019 8919.71
+Customer#000000022 596.98
+Customer#000000025 7138.7
+Customer#000000028 1012.1799999999998
+Customer#000000037 -912.75
+Customer#000000040 1340.3
+Customer#000000047 279.58
+Customer#000000059 3463.6
+Customer#000000061 1541.24
+Customer#000000064 -641.64
+Customer#000000067 8171.59
+Customer#000000082 9473.34
+Customer#000000091 4648.14
+Customer#000000094 5505.11
+Customer#000000097 2169.48
+Customer#000000101 7475.96
+Customer#000000103 2762.45
+Customer#000000106 3293.42
+Customer#000000115 7513.92
+Customer#000000121 6433.32
+Customer#000000122 7870.46
+Customer#000000127 9285.71
+Customer#000000130 5078.58
+Customer#000000133 2319.67
+Customer#000000139 7902.78
+call p(15);
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9581.95
+Customer#000000019 8934.71
+Customer#000000022 611.98
+Customer#000000025 7153.7
+Customer#000000028 1027.1799999999998
+Customer#000000037 -897.75
+Customer#000000040 1355.3
+Customer#000000047 294.58
+Customer#000000059 3478.6
+Customer#000000061 1556.24
+Customer#000000064 -626.64
+Customer#000000067 8186.59
+Customer#000000082 9488.34
+Customer#000000091 4663.14
+Customer#000000094 5520.11
+Customer#000000097 2184.48
+Customer#000000101 7490.96
+Customer#000000103 2777.45
+Customer#000000106 3308.42
+Customer#000000115 7528.92
+Customer#000000121 6448.32
+Customer#000000122 7885.46
+Customer#000000127 9300.71
+Customer#000000130 5093.58
+Customer#000000133 2334.67
+Customer#000000139 7917.78
+call p(-(5+15));
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.1799999999998
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+drop procedure p;
+# Materialization SP
+# ==================
+create procedure p(d int)
+update customer set c_acctbal = c_acctbal+d where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7133.7
+Customer#000000013 3857.34
+Customer#000000065 8795.16
+Customer#000000032 3471.53
+Customer#000000023 3332.02
+Customer#000000035 1228.24
+Customer#000000091 4643.14
+Customer#000000016 4681.03
+Customer#000000098 -551.37
+Customer#000000037 -917.75
+Customer#000000136 -842.39
+Customer#000000118 3582.37
+Customer#000000022 591.98
+Customer#000000005 794.47
+Customer#000000109 -716.1
+Customer#000000038 6345.11
+Customer#000000076 5745.33
+Customer#000000056 6530.86
+Customer#000000040 1335.3
+Customer#000000116 8403.99
+Customer#000000115 7508.92
+Customer#000000140 9963.15
+Customer#000000017 6.34
+Customer#000000052 5630.28
+call p(3);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7136.7
+Customer#000000013 3860.34
+Customer#000000065 8798.16
+Customer#000000032 3474.53
+Customer#000000023 3335.02
+Customer#000000035 1231.24
+Customer#000000091 4646.14
+Customer#000000016 4684.03
+Customer#000000098 -548.37
+Customer#000000037 -914.75
+Customer#000000136 -839.39
+Customer#000000118 3585.37
+Customer#000000022 594.98
+Customer#000000005 797.47
+Customer#000000109 -713.1
+Customer#000000038 6348.11
+Customer#000000076 5748.33
+Customer#000000056 6533.86
+Customer#000000040 1338.3
+Customer#000000116 8406.99
+Customer#000000115 7511.92
+Customer#000000140 9966.15
+Customer#000000017 9.34
+Customer#000000052 5633.28
+call p(7);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7143.7
+Customer#000000013 3867.34
+Customer#000000065 8805.16
+Customer#000000032 3481.53
+Customer#000000023 3342.02
+Customer#000000035 1238.24
+Customer#000000091 4653.14
+Customer#000000016 4691.03
+Customer#000000098 -541.37
+Customer#000000037 -907.75
+Customer#000000136 -832.39
+Customer#000000118 3592.37
+Customer#000000022 601.98
+Customer#000000005 804.47
+Customer#000000109 -706.1
+Customer#000000038 6355.11
+Customer#000000076 5755.33
+Customer#000000056 6540.86
+Customer#000000040 1345.3
+Customer#000000116 8413.99
+Customer#000000115 7518.92
+Customer#000000140 9973.15
+Customer#000000017 16.34
+Customer#000000052 5640.28
+call p(-(3+7));
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7133.7
+Customer#000000013 3857.34
+Customer#000000065 8795.16
+Customer#000000032 3471.53
+Customer#000000023 3332.02
+Customer#000000035 1228.24
+Customer#000000091 4643.14
+Customer#000000016 4681.03
+Customer#000000098 -551.37
+Customer#000000037 -917.75
+Customer#000000136 -842.39
+Customer#000000118 3582.37
+Customer#000000022 591.98
+Customer#000000005 794.47
+Customer#000000109 -716.1
+Customer#000000038 6345.11
+Customer#000000076 5745.33
+Customer#000000056 6530.86
+Customer#000000040 1335.3
+Customer#000000116 8403.99
+Customer#000000115 7508.92
+Customer#000000140 9963.15
+Customer#000000017 6.34
+Customer#000000052 5630.28
+drop procedure p;
+# Materialization SJM SP
+# ======================
+create procedure p(d int)
+update customer set c_acctbal = c_acctbal+d where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000118 3582.37
+Customer#000000056 6530.86
+call p(-1);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3856.34
+Customer#000000032 3470.53
+Customer#000000037 -918.75
+Customer#000000118 3581.37
+Customer#000000056 6529.86
+call p(-2);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3854.34
+Customer#000000032 3468.53
+Customer#000000037 -920.75
+Customer#000000118 3579.37
+Customer#000000056 6527.86
+call p(1+2);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000118 3582.37
+Customer#000000056 6530.86
+drop procedure p;
+DROP DATABASE dbt3_s001;
diff --git a/mysql-test/main/update_single_to_multi.test b/mysql-test/main/update_single_to_multi.test
new file mode 100644
index 0000000..f018365
--- /dev/null
+++ b/mysql-test/main/update_single_to_multi.test
@@ -0,0 +1,511 @@
+--disable_warnings
+DROP DATABASE IF EXISTS dbt3_s001;
+--enable_warnings
+
+CREATE DATABASE dbt3_s001;
+
+use dbt3_s001;
+
+--disable_query_log
+--disable_result_log
+--disable_warnings
+--source include/dbt3_s001.inc
+--enable_warnings
+--enable_result_log
+--enable_query_log
+
+create index i_n_name on nation(n_name);
+analyze table nation;
+
+
+--echo # Pullout
+--echo # =======
+
+let $c1=
+ o_orderDATE between '1992-01-01' and '1992-06-30' and
+ o_custkey in (select c_custkey from customer
+ where c_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+
+eval
+explain
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+explain format=json
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+
+eval
+explain
+update orders set o_totalprice = o_totalprice-50 where $c1;
+eval
+explain format=json
+update orders set o_totalprice = o_totalprice-50 where $c1;
+eval
+update orders set o_totalprice = o_totalprice-50 where $c1;
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+
+eval
+update orders set o_totalprice= o_totalprice+50 where $c1;
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+
+
+let $c2=
+ (ps_partkey, ps_suppkey) in
+ (select p_partkey, s_suppkey from part, supplier
+ where p_retailprice between 901 and 910 and
+ s_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+
+eval
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+
+eval
+explain
+update partsupp set ps_supplycost = ps_supplycost+2 where $c2;
+eval
+update partsupp set ps_supplycost = ps_supplycost+2 where $c2;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+
+eval
+update partsupp set ps_supplycost = ps_supplycost-2 where $c2;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+
+
+let $c3=
+ ps_partkey in (select p_partkey from part
+ where p_retailprice between 901 and 910) and
+ ps_suppkey in (select s_suppkey from supplier
+ where s_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+eval
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+
+eval
+explain
+update partsupp set ps_supplycost = ps_supplycost+10 where $c3;
+eval
+update partsupp set ps_supplycost = ps_supplycost+10 where $c3;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+
+eval
+update partsupp set ps_supplycost = ps_supplycost-10 where $c3;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+
+
+let $c4=
+ l_orderkey in (select o_orderkey from orders
+ where o_custkey in
+ (select c_custkey from customer
+ where c_nationkey in
+ (select n_nationkey from nation
+ where n_name='PERU'))
+ and
+ o_orderDATE between '1992-06-30' and '1992-12-31')
+ and
+ (l_partkey, l_suppkey) in
+ (select p_partkey, s_suppkey from part, supplier
+ where p_retailprice between 901 and 1000 and
+ s_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+
+eval
+explain
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+eval
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+
+eval
+explain
+update lineitem set l_tax = (l_tax*100+1)/100 where $c4;
+eval
+update lineitem set l_tax = (l_tax*100+1)/100 where $c4;
+eval
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+
+eval
+update lineitem set l_tax = (l_tax*100-1)/100 where $c4;
+eval
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+
+
+--echo # FirstMatch
+--echo # ==========
+
+let $c5=
+ c_nationkey in (select n_nationkey from nation
+ where n_regionkey in (1,2))
+ and
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-10-09' and '1993-03-08');
+
+eval
+explain
+select c_name, c_acctbal from customer where $c5;
+eval
+explain format=json
+select c_name, c_acctbal from customer where $c5;
+eval
+select c_name, c_acctbal from customer where $c5;
+
+eval
+explain
+update customer set c_acctbal = c_acctbal+10 where $c5;
+eval
+explain format=json
+update customer set c_acctbal = c_acctbal+10 where $c5;
+eval
+update customer set c_acctbal = c_acctbal+10 where $c5;
+eval
+select c_name, c_acctbal from customer where $c5;
+
+eval
+update customer set c_acctbal = c_acctbal-10 where $c5;
+eval
+select c_name, c_acctbal from customer where $c5;
+
+
+let $c6=
+ c_nationkey in (select n_nationkey from nation where n_name='PERU')
+ and
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between "1992-01-09" and "1993-01-08");
+
+eval
+explain
+select c_name, c_acctbal from customer where $c6;
+eval
+select c_name, c_acctbal from customer where $c6;
+
+eval
+explain
+update customer set c_acctbal = c_acctbal+20 where $c6;
+eval
+update customer set c_acctbal = c_acctbal+20 where $c6;
+eval
+select c_name, c_acctbal from customer where $c6;
+
+eval
+update customer set c_acctbal = c_acctbal-20 where $c6;
+eval
+select c_name, c_acctbal from customer where $c6;
+
+
+--echo # Materialization
+--echo # ===============
+
+let $c7=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-01-09' and '1992-03-08');
+
+eval
+explain
+select c_name, c_acctbal from customer where $c7;
+eval
+explain format=json
+select c_name, c_acctbal from customer where $c7;
+eval
+select c_name, c_acctbal from customer where $c7;
+
+eval
+explain
+update customer set c_acctbal = c_acctbal+5 where $c7;
+eval
+explain format=json
+update customer set c_acctbal = c_acctbal+5 where $c7;
+eval
+update customer set c_acctbal = c_acctbal+5 where $c7;
+eval
+select c_name, c_acctbal from customer where $c7;
+
+eval
+update customer set c_acctbal = c_acctbal-5 where $c7;
+eval
+select c_name, c_acctbal from customer where $c7;
+
+
+let $c8=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-06-09' and '1993-01-08');
+
+eval
+explain
+select c_name, c_acctbal from customer where $c8;
+eval
+select c_name, c_acctbal from customer where $c8;
+
+eval
+explain
+update customer set c_acctbal = c_acctbal+1 where $c8;
+eval
+update customer set c_acctbal = c_acctbal+1 where $c8;
+eval
+select c_name, c_acctbal from customer where $c8;
+
+eval
+update customer set c_acctbal = c_acctbal-1 where $c8;
+eval
+select c_name, c_acctbal from customer where $c8;
+
+
+--echo # Materialization SJM
+--echo # ===================
+
+let $c9=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+
+eval
+explain
+select c_name, c_acctbal from customer where $c9;
+eval
+explain format=json
+select c_name, c_acctbal from customer where $c9;
+eval
+select c_name, c_acctbal from customer where $c9;
+
+eval
+explain
+update customer set c_acctbal = c_acctbal-5 where $c9;
+eval
+explain format=json
+update customer set c_acctbal = c_acctbal-5 where $c9;
+eval
+update customer set c_acctbal = c_acctbal-5 where $c9;
+eval
+select c_name, c_acctbal from customer where $c9;
+
+eval
+update customer set c_acctbal = c_acctbal+5 where $c9;
+eval
+select c_name, c_acctbal from customer where $c9;
+
+
+let $c10=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+
+eval
+explain
+select c_name, c_acctbal from customer where $c10;
+eval
+select c_name, c_acctbal from customer where $c10;
+
+eval
+explain
+update customer set c_acctbal = c_acctbal-1 where $c10;
+eval
+update customer set c_acctbal = c_acctbal-1 where $c10;
+eval
+select c_name, c_acctbal from customer where $c10;
+
+eval
+update customer set c_acctbal = c_acctbal+1 where $c10;
+eval
+select c_name, c_acctbal from customer where $c10;
+
+
+--echo # Pullout PS
+--echo # ==========
+
+eval
+prepare stmt from "
+update orders set o_totalprice = o_totalprice+? where $c1;
+";
+
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+set @a1=-20;
+execute stmt using @a1;
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+set @a2=-10;
+execute stmt using @a2;
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+execute stmt using -(@a1+@a2);
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+
+deallocate prepare stmt;
+
+
+--echo # FirstMatch PS
+--echo # =============
+
+eval
+prepare stmt from "
+update customer set c_acctbal = c_acctbal+? where $c5;
+";
+
+eval
+select c_name, c_acctbal from customer where $c5;
+set @a1=15;
+execute stmt using @a1;
+eval
+select c_name, c_acctbal from customer where $c5;
+set @a2=5;
+execute stmt using @a2;
+eval
+select c_name, c_acctbal from customer where $c5;
+execute stmt using -(@a1+@a2);
+eval
+select c_name, c_acctbal from customer where $c5;
+
+deallocate prepare stmt;
+
+
+--echo # Materialization PS
+--echo # ==================
+
+eval
+prepare stmt from "
+update customer set c_acctbal = c_acctbal+? where $c7;
+";
+
+eval
+select c_name, c_acctbal from customer where $c7;
+set @a1=7;
+execute stmt using @a1;
+eval
+select c_name, c_acctbal from customer where $c7;
+set @a2=3;
+execute stmt using @a2;
+eval
+select c_name, c_acctbal from customer where $c7;
+execute stmt using -(@a1+@a2);
+eval
+select c_name, c_acctbal from customer where $c7;
+
+deallocate prepare stmt;
+
+
+--echo # Materialization SJM PS
+--echo # ======================
+
+eval
+prepare stmt from "
+update customer set c_acctbal = c_acctbal+? where $c9;
+";
+
+eval
+select c_name, c_acctbal from customer where $c9;
+set @a1=-2;
+execute stmt using @a1;
+eval
+select c_name, c_acctbal from customer where $c9;
+set @a2=-1;
+execute stmt using @a2;
+eval
+select c_name, c_acctbal from customer where $c9;
+execute stmt using -(@a1+@a2);
+eval
+select c_name, c_acctbal from customer where $c9;
+
+deallocate prepare stmt;
+
+
+--echo # Pullout SP
+--echo # ==========
+
+eval
+create procedure p(d int)
+update orders set o_totalprice = o_totalprice+d where $c1;
+
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+call p(-10);
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+call p(-20);
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+call p(10+20);
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+
+drop procedure p;
+
+
+--echo # FirstMatch SP
+--echo # =============
+
+eval
+create procedure p(d int)
+update customer set c_acctbal = c_acctbal+d where $c5;
+
+eval
+select c_name, c_acctbal from customer where $c5;
+call p(5);
+eval
+select c_name, c_acctbal from customer where $c5;
+call p(15);
+eval
+select c_name, c_acctbal from customer where $c5;
+call p(-(5+15));
+eval
+select c_name, c_acctbal from customer where $c5;
+
+drop procedure p;
+
+
+--echo # Materialization SP
+--echo # ==================
+
+eval
+create procedure p(d int)
+update customer set c_acctbal = c_acctbal+d where $c7;
+
+eval
+select c_name, c_acctbal from customer where $c7;
+call p(3);
+eval
+select c_name, c_acctbal from customer where $c7;
+call p(7);
+eval
+select c_name, c_acctbal from customer where $c7;
+call p(-(3+7));
+eval
+select c_name, c_acctbal from customer where $c7;
+
+drop procedure p;
+
+
+--echo # Materialization SJM SP
+--echo # ======================
+
+eval
+create procedure p(d int)
+update customer set c_acctbal = c_acctbal+d where $c9;
+
+eval
+select c_name, c_acctbal from customer where $c9;
+call p(-1);
+eval
+select c_name, c_acctbal from customer where $c9;
+call p(-2);
+eval
+select c_name, c_acctbal from customer where $c9;
+call p(1+2);
+eval
+select c_name, c_acctbal from customer where $c9;
+
+drop procedure p;
+
+
+DROP DATABASE dbt3_s001;
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index fa338f0..4379378 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -675,9 +675,8 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
3. Subquery does not have GROUP BY or ORDER BY
4. Subquery does not use aggregate functions or HAVING
5. Subquery predicate is at the AND-top-level of ON/WHERE clause
- 6. We are not in a subquery of a single table UPDATE/DELETE that
- doesn't have a JOIN (TODO: We should handle this at some
- point by switching to multi-table UPDATE/DELETE)
+ 6. We are not in a top level subquery of a single-table DELETE
+ with RETURNING
7. We're not in a table-less subquery like "SELECT 1"
8. No execution method was already chosen (by a prepared statement)
9. Parent select is not a table-less select
@@ -692,9 +691,9 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
!select_lex->group_list.elements && !join->order && // 3
!join->having && !select_lex->with_sum_func && // 4
in_subs->emb_on_expr_nest && // 5
- select_lex->outer_select()->join && // 6
- (!thd->lex->m_sql_cmd ||
- thd->lex->m_sql_cmd->sql_command_code() == SQLCOM_UPDATE_MULTI) &&
+ !(thd->lex->sql_command == SQLCOM_DELETE && // 6
+ thd->lex->has_returning() && // 6
+ !select_lex->outer_select()->outer_select()) && // 6
parent_unit->first_select()->leaf_tables.elements && // 7
!in_subs->has_strategy() && // 8
select_lex->outer_select()->table_list.first && // 9
@@ -7260,3 +7259,28 @@ bool TABLE_LIST::is_sjm_scan_table()
{
return is_active_sjm() && sj_mat_info->is_sj_scan;
}
+
+
+/**
+ @brief Check whether this subselect can be lifted to the top level
+ @returns true if the test is positive, false otherwise
+*/
+
+bool SELECT_LEX::is_sj_subselect_lifted_to_top()
+{
+ st_select_lex *sl= this;
+ st_select_lex *outer_sl= outer_select();
+ for ( ; outer_sl; sl= outer_sl, outer_sl= outer_sl->outer_select())
+ {
+ List_iterator_fast<Item_in_subselect> it(outer_sl->sj_subselects);
+ Item_in_subselect *in_subs;
+ while ((in_subs= it++))
+ {
+ if (in_subs->unit->first_select() == sl)
+ break;
+ }
+ if (!in_subs)
+ return false;
+ }
+ return true;
+}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 167df5b..3a2704f 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -7005,6 +7005,7 @@ class multi_delete :public select_result_interceptor
// Methods used by ColumnStore
uint get_num_of_tables() const { return num_of_tables; }
TABLE_LIST* get_tables() const { return delete_tables; }
+ void set_delete_tables (TABLE_LIST *tbl) { delete_tables= tbl; }
public:
multi_delete(THD *thd_arg, TABLE_LIST *dt, uint num_of_tables);
~multi_delete();
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 2ff4331..52efab3 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -1591,10 +1591,19 @@ bool Sql_cmd_delete::prepare_inner(THD *thd)
select_lex->order_list.first,
false, NULL, NULL, NULL,
select_lex, &lex->unit)))
-
{
goto err;
}
+
+ if (!multitable &&
+ select_lex->sj_subselects.elements &&
+ !select_lex->order_list.elements &&
+ select_lex->master_unit()->lim.get_select_limit() == HA_POS_ERROR &&
+ !thd->lex->has_returning())
+ multitable= true;
+
+ if (!multitable)
+ ((multi_delete *)result)->set_delete_tables(0);
}
if (multitable)
@@ -1638,7 +1647,8 @@ bool Sql_cmd_delete::prepare_inner(THD *thd)
{
TABLE_LIST *duplicate;
if ((duplicate= unique_table(thd, target_tbl->correspondent_table,
- lex->query_tables, 0)))
+ lex->query_tables, 0)) &&
+ !duplicate->select_lex->is_sj_subselect_lifted_to_top())
{
update_non_unique_table_error(target_tbl->correspondent_table,
"DELETE", duplicate);
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 0badc32..582ca53 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -1642,6 +1642,7 @@ class st_select_lex: public st_select_lex_node
void lex_start(LEX *plex);
bool is_unit_nest() { return (nest_flags & UNIT_NEST_FL); }
void mark_as_unit_nest() { nest_flags= UNIT_NEST_FL; }
+ bool is_sj_subselect_lifted_to_top();
};
typedef class st_select_lex SELECT_LEX;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index bf49d69..a7e5bc7 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -5834,8 +5834,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
s->needed_reg=select->needed_reg;
select->quick=0;
impossible_range= records == 0 && s->table->reginfo.impossible_range;
- if (join->thd->lex->sql_command == SQLCOM_SELECT &&
- optimizer_flag(join->thd, OPTIMIZER_SWITCH_USE_ROWID_FILTER))
+ if (optimizer_flag(join->thd, OPTIMIZER_SWITCH_USE_ROWID_FILTER))
s->table->init_cost_info_for_usable_range_rowid_filters(join->thd);
}
if (!impossible_range)
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 6b14c4f..b614291 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -2471,6 +2471,8 @@ int multi_update::do_updates()
table = cur_table->table;
if (table == table_to_update)
continue; // Already updated
+ if (table->file->pushed_rowid_filter)
+ table->file->disable_pushed_rowid_filter();
org_updated= updated;
tmp_table= tmp_tables[cur_table->shared];
tmp_table->file->extra(HA_EXTRA_CACHE); // Change to read cache
@@ -2665,7 +2667,8 @@ int multi_update::do_updates()
check_opt_it.rewind();
while (TABLE *tbl= check_opt_it++)
tbl->file->ha_rnd_end();
-
+ if (table->file->save_pushed_rowid_filter)
+ table->file->enable_pushed_rowid_filter();
}
DBUG_RETURN(0);
@@ -2676,6 +2679,8 @@ int multi_update::do_updates()
}
err2:
+ if (table->file->save_pushed_rowid_filter)
+ table->file->enable_pushed_rowid_filter();
if (table->file->inited)
(void) table->file->ha_rnd_end();
if (tmp_table->file->inited)
@@ -2956,6 +2961,11 @@ bool Sql_cmd_update::prepare_inner(THD *thd)
goto err;
}
+ if (!multitable &&
+ select_lex->sj_subselects.elements &&
+ !select_lex->order_list.elements &&
+ select_lex->master_unit()->lim.get_select_limit() == HA_POS_ERROR)
+ multitable= true;
}
if (table_list->has_period())
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index a587a37..13dc602 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -13370,8 +13370,21 @@ delete_single_table:
YYPS->m_lock_type,
YYPS->m_mdl_type,
NULL,
+ 0)))
+ MYSQL_YYABORT;
+ Select->table_list.save_and_clear(&Lex->auxiliary_table_list);
+ Lex->table_count= 1;
+ Lex->query_tables= 0;
+ Lex->query_tables_last= &Lex->query_tables;
+ if (unlikely(!Select->
+ add_table_to_list(thd, $2, NULL, TL_OPTION_UPDATING,
+ YYPS->m_lock_type,
+ YYPS->m_mdl_type,
+ NULL,
$3)))
MYSQL_YYABORT;
+ Lex->auxiliary_table_list.first->correspondent_table=
+ Lex->query_tables;
YYPS->m_lock_type= TL_READ_DEFAULT;
YYPS->m_mdl_type= MDL_SHARED_READ;
}
1
0
[Commits] cb0f445: MDEV-7487 Semi-join optimization for single-table UPDATE/DELETEs
by IgorBabaev 19 Jun '22
by IgorBabaev 19 Jun '22
19 Jun '22
revision-id: cb0f44570b9b38c60c37c649cb0a0ec963b3860a (mariadb-10.6.1-472-gcb0f445)
parent(s): 596cde07f17c490c43db10ce0a8cbb7bd4dbf5ae
author: Igor Babaev
committer: Igor Babaev
timestamp: 2022-06-18 20:18:50 -0700
message:
MDEV-7487 Semi-join optimization for single-table UPDATE/DELETEs
This is a preliminary patch.
# Conflicts:
# mysql-test/main/myisam_explain_non_select_all.result
# sql/sql_delete.cc
---
mysql-test/main/delete_single_to_multi.result | 2216 ++++++++++++++++++++
mysql-test/main/delete_single_to_multi.test | 723 +++++++
mysql-test/main/log_state.result | 2 +-
.../main/myisam_explain_non_select_all.result | 45 +-
mysql-test/main/opt_trace.result | 20 +
mysql-test/main/update_single_to_multi.result | 2209 +++++++++++++++++++
mysql-test/main/update_single_to_multi.test | 511 +++++
sql/opt_subselect.cc | 31 +-
sql/sql_class.h | 1 +
sql/sql_delete.cc | 14 +-
sql/sql_lex.h | 1 +
sql/sql_select.cc | 3 +-
sql/sql_update.cc | 12 +-
sql/sql_yacc.yy | 13 +
14 files changed, 5769 insertions(+), 32 deletions(-)
diff --git a/mysql-test/main/delete_single_to_multi.result b/mysql-test/main/delete_single_to_multi.result
new file mode 100644
index 0000000..6cbc63f
--- /dev/null
+++ b/mysql-test/main/delete_single_to_multi.result
@@ -0,0 +1,2216 @@
+DROP DATABASE IF EXISTS dbt3_s001;
+CREATE DATABASE dbt3_s001;
+use dbt3_s001;
+create index i_n_name on nation(n_name);
+analyze table nation;
+Table Op Msg_type Msg_text
+dbt3_s001.nation analyze status Engine-independent statistics collected
+dbt3_s001.nation analyze status OK
+# Pullout
+# =======
+explain
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (7%) Using where; Using rowid filter
+explain format=json
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_n_name"],
+ "key": "i_n_name",
+ "key_length": "26",
+ "used_key_parts": ["n_name"],
+ "ref": ["const"],
+ "rows": 1,
+ "filtered": 100,
+ "index_condition": "nation.n_name = 'PERU'"
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "key": "i_c_nationkey",
+ "key_length": "5",
+ "used_key_parts": ["c_nationkey"],
+ "ref": ["dbt3_s001.nation.n_nationkey"],
+ "rows": 11,
+ "filtered": 100
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 108,
+ "selectivity_pct": 7.2
+ },
+ "rows": 11,
+ "filtered": 7.199999809,
+ "attached_condition": "orders.o_orderDATE between '1992-01-01' and '1992-06-30'"
+ }
+ }
+ ]
+ }
+}
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+5382 138423.03
+644 201268.06
+737 12984.85
+create table t as
+select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+explain
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (7%) Using where; Using rowid filter
+explain format=json
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_n_name"],
+ "key": "i_n_name",
+ "key_length": "26",
+ "used_key_parts": ["n_name"],
+ "ref": ["const"],
+ "rows": 1,
+ "filtered": 100,
+ "index_condition": "nation.n_name = 'PERU'"
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "key": "i_c_nationkey",
+ "key_length": "5",
+ "used_key_parts": ["c_nationkey"],
+ "ref": ["dbt3_s001.nation.n_nationkey"],
+ "rows": 11,
+ "filtered": 100
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 108,
+ "selectivity_pct": 7.2
+ },
+ "rows": 11,
+ "filtered": 7.199999809,
+ "attached_condition": "orders.o_orderDATE between '1992-01-01' and '1992-06-30'"
+ }
+ }
+ ]
+ }
+}
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+insert into orders select * from t;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+5382 138423.03
+644 201268.06
+737 12984.85
+drop table t;
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+1 8 357.84
+3 8 645.4
+4 1 444.37
+5 8 50.52
+6 1 642.13
+7 8 763.98
+8 1 957.34
+create table t as
+select * from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+explain
+delete from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+delete from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+insert into partsupp select * from t;
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+1 8 357.84
+3 8 645.4
+4 1 444.37
+5 8 50.52
+6 1 642.13
+7 8 763.98
+8 1 957.34
+drop table t;
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+1 8 357.84
+3 8 645.4
+4 1 444.37
+5 8 50.52
+6 1 642.13
+7 8 763.98
+8 1 957.34
+create table t as
+select * from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+explain
+delete from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+delete from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+insert into partsupp select * from t;
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+1 8 357.84
+3 8 645.4
+4 1 444.37
+5 8 50.52
+6 1 642.13
+7 8 763.98
+8 1 957.34
+drop table t;
+explain
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY lineitem ref PRIMARY,i_l_suppkey_partkey,i_l_partkey,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity i_l_suppkey 5 dbt3_s001.supplier.s_suppkey 100 Using where
+1 PRIMARY orders eq_ref|filter PRIMARY,i_o_orderdate,i_o_custkey PRIMARY|i_o_orderdate 4|4 dbt3_s001.lineitem.l_orderkey 1 (7%) Using where; Using rowid filter
+1 PRIMARY customer eq_ref PRIMARY,i_c_nationkey PRIMARY 4 dbt3_s001.orders.o_custkey 1 Using where
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.lineitem.l_partkey 1 Using where
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+l_orderkey l_linenumber l_tax
+2500 2 0.02
+2500 4 0.02
+4996 1 0.01
+933 1 0.04
+create table t as
+select * from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+explain
+delete from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY lineitem ref PRIMARY,i_l_suppkey_partkey,i_l_partkey,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity i_l_suppkey 5 dbt3_s001.supplier.s_suppkey 100 Using where
+1 PRIMARY orders eq_ref|filter PRIMARY,i_o_orderdate,i_o_custkey PRIMARY|i_o_orderdate 4|4 dbt3_s001.lineitem.l_orderkey 1 (7%) Using where; Using rowid filter
+1 PRIMARY customer eq_ref PRIMARY,i_c_nationkey PRIMARY 4 dbt3_s001.orders.o_custkey 1 Using where
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.lineitem.l_partkey 1 Using where
+delete from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+l_orderkey l_linenumber l_tax
+insert into lineitem select * from t;
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+l_orderkey l_linenumber l_tax
+2500 2 0.02
+2500 4 0.02
+4996 1 0.01
+933 1 0.04
+drop table t;
+# FirstMatch
+# ==========
+explain
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY,i_c_nationkey NULL NULL NULL 150 Using where
+1 PRIMARY nation eq_ref|filter PRIMARY,i_n_regionkey PRIMARY|i_n_regionkey 4|5 dbt3_s001.customer.c_nationkey 1 (40%) Using where; Using rowid filter
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (6%) Using where; FirstMatch(nation); Using rowid filter
+explain format=json
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ALL",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "rows": 150,
+ "filtered": 100,
+ "attached_condition": "customer.c_nationkey is not null"
+ }
+ },
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY", "i_n_regionkey"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["n_nationkey"],
+ "ref": ["dbt3_s001.customer.c_nationkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_n_regionkey",
+ "used_key_parts": ["n_regionkey"]
+ },
+ "rows": 10,
+ "selectivity_pct": 40
+ },
+ "rows": 1,
+ "filtered": 40,
+ "attached_condition": "nation.n_regionkey in (1,2)"
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 89,
+ "selectivity_pct": 5.933333333
+ },
+ "rows": 11,
+ "filtered": 5.933333397,
+ "attached_condition": "orders.o_orderDATE between '1992-10-09' and '1993-03-08'",
+ "first_match": "nation"
+ }
+ }
+ ]
+ }
+}
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+create table t as
+select * from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+explain
+delete from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY,i_c_nationkey NULL NULL NULL 150 Using where
+1 PRIMARY nation eq_ref|filter PRIMARY,i_n_regionkey PRIMARY|i_n_regionkey 4|5 dbt3_s001.customer.c_nationkey 1 (40%) Using where; Using rowid filter
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (6%) Using where; FirstMatch(nation); Using rowid filter
+explain format=json
+delete from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ALL",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "rows": 150,
+ "filtered": 100,
+ "attached_condition": "customer.c_nationkey is not null"
+ }
+ },
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY", "i_n_regionkey"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["n_nationkey"],
+ "ref": ["dbt3_s001.customer.c_nationkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_n_regionkey",
+ "used_key_parts": ["n_regionkey"]
+ },
+ "rows": 10,
+ "selectivity_pct": 40
+ },
+ "rows": 1,
+ "filtered": 40,
+ "attached_condition": "nation.n_regionkey in (1,2)"
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 89,
+ "selectivity_pct": 5.933333333
+ },
+ "rows": 11,
+ "filtered": 5.933333397,
+ "attached_condition": "orders.o_orderDATE between '1992-10-09' and '1993-03-08'",
+ "first_match": "nation"
+ }
+ }
+ ]
+ }
+}
+delete from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+drop table t;
+explain
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (14%) Using where; FirstMatch(customer); Using rowid filter
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+c_name c_acctbal
+Customer#000000008 6819.74
+Customer#000000035 1228.24
+Customer#000000061 1536.24
+Customer#000000097 2164.48
+Customer#000000121 6428.32
+Customer#000000133 2314.67
+create table t as
+select * from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+explain
+delete from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (14%) Using where; FirstMatch(customer); Using rowid filter
+delete from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+c_name c_acctbal
+Customer#000000008 6819.74
+Customer#000000035 1228.24
+Customer#000000061 1536.24
+Customer#000000097 2164.48
+Customer#000000121 6428.32
+Customer#000000133 2314.67
+drop table t;
+# Materialization
+# ===============
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 dbt3_s001.orders.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 28 Using index condition; Using where
+explain format=json
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'",
+ "attached_condition": "orders.o_custkey is not null"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["dbt3_s001.orders.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000005 794.47
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000035 1228.24
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000040 1335.3
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000098 -551.37
+Customer#000000109 -716.1
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000136 -842.39
+Customer#000000140 9963.15
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+explain
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 dbt3_s001.orders.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 28 Using index condition; Using where
+explain format=json
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'",
+ "attached_condition": "orders.o_custkey is not null"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["dbt3_s001.orders.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000005 794.47
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000035 1228.24
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000040 1335.3
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000098 -551.37
+Customer#000000109 -716.1
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000136 -842.39
+Customer#000000140 9963.15
+drop table t;
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 114 Using index condition; Using where
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+c_name c_acctbal
+Customer#000000001 711.56
+Customer#000000002 121.65
+Customer#000000007 9561.95
+Customer#000000008 6819.74
+Customer#000000010 2753.54
+Customer#000000011 -272.6
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000029 7618.27
+Customer#000000031 5236.89
+Customer#000000034 8589.7
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000043 9904.28
+Customer#000000044 7315.94
+Customer#000000046 5744.59
+Customer#000000047 274.58
+Customer#000000049 4573.94
+Customer#000000053 4113.64
+Customer#000000055 4572.11
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000070 4867.52
+Customer#000000071 -611.19
+Customer#000000073 4288.5
+Customer#000000074 2764.43
+Customer#000000076 5745.33
+Customer#000000079 5121.28
+Customer#000000080 7383.53
+Customer#000000082 9468.34
+Customer#000000083 6463.51
+Customer#000000085 3386.64
+Customer#000000086 3306.32
+Customer#000000088 8031.44
+Customer#000000091 4643.14
+Customer#000000092 1182.91
+Customer#000000095 5327.38
+Customer#000000097 2164.48
+Customer#000000100 9889.89
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000104 -588.38
+Customer#000000106 3288.42
+Customer#000000109 -716.1
+Customer#000000110 7462.99
+Customer#000000112 2953.35
+Customer#000000118 3582.37
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000131 8595.53
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+Customer#000000136 -842.39
+Customer#000000137 7838.3
+Customer#000000139 7897.78
+Customer#000000142 2209.81
+Customer#000000143 2186.5
+Customer#000000148 2135.6
+Customer#000000149 8959.65
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+explain
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 114 Using index condition; Using where
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+c_name c_acctbal
+Customer#000000001 711.56
+Customer#000000002 121.65
+Customer#000000007 9561.95
+Customer#000000008 6819.74
+Customer#000000010 2753.54
+Customer#000000011 -272.6
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000029 7618.27
+Customer#000000031 5236.89
+Customer#000000034 8589.7
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000043 9904.28
+Customer#000000044 7315.94
+Customer#000000046 5744.59
+Customer#000000047 274.58
+Customer#000000049 4573.94
+Customer#000000053 4113.64
+Customer#000000055 4572.11
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000070 4867.52
+Customer#000000071 -611.19
+Customer#000000073 4288.5
+Customer#000000074 2764.43
+Customer#000000076 5745.33
+Customer#000000079 5121.28
+Customer#000000080 7383.53
+Customer#000000082 9468.34
+Customer#000000083 6463.51
+Customer#000000085 3386.64
+Customer#000000086 3306.32
+Customer#000000088 8031.44
+Customer#000000091 4643.14
+Customer#000000092 1182.91
+Customer#000000095 5327.38
+Customer#000000097 2164.48
+Customer#000000100 9889.89
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000104 -588.38
+Customer#000000106 3288.42
+Customer#000000109 -716.1
+Customer#000000110 7462.99
+Customer#000000112 2953.35
+Customer#000000118 3582.37
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000131 8595.53
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+Customer#000000136 -842.39
+Customer#000000137 7838.3
+Customer#000000139 7897.78
+Customer#000000142 2209.81
+Customer#000000143 2186.5
+Customer#000000148 2135.6
+Customer#000000149 8959.65
+drop table t;
+# Materialization SJM
+# ===================
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 <subquery2>.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 28 Using index condition; Using temporary
+explain format=json
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "having_condition": "count(orders.o_custkey) > 1",
+ "temporary_table": {
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'"
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["<subquery2>.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+explain
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 <subquery2>.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 28 Using index condition; Using temporary
+explain format=json
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "having_condition": "count(orders.o_custkey) > 1",
+ "temporary_table": {
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'"
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["<subquery2>.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+drop table t;
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 dbt3_s001.customer.c_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 242 Using index condition; Using temporary
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000016 4681.03
+Customer#000000037 -917.75
+Customer#000000046 5744.59
+Customer#000000091 4643.14
+Customer#000000103 2757.45
+Customer#000000118 3582.37
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+explain
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 dbt3_s001.customer.c_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 242 Using index condition; Using temporary
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000016 4681.03
+Customer#000000037 -917.75
+Customer#000000046 5744.59
+Customer#000000091 4643.14
+Customer#000000103 2757.45
+Customer#000000118 3582.37
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+drop table t;
+# Pullout PS
+# ==========
+prepare stmt from "
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+";
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+5382 138423.03
+644 201268.06
+737 12984.85
+create table t as
+select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+execute stmt;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+insert into orders select * from t;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+5382 138423.03
+644 201268.06
+737 12984.85
+create table r as
+select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+execute stmt;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+insert into orders select * from r;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+5382 138423.03
+644 201268.06
+737 12984.85
+drop table t,r;
+deallocate prepare stmt;
+# FirstMatch PS
+# =============
+prepare stmt from "
+delete from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+";
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+create table t as
+select * from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+execute stmt;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+create table r as
+select * from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+execute stmt;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+insert into customer select * from r;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+drop table t,r;
+deallocate prepare stmt;
+# Materialization PS
+# ==================
+prepare stmt from "
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08') and c_name like ?;
+";
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000005 794.47
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000035 1228.24
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000040 1335.3
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000098 -551.37
+Customer#000000109 -716.1
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000136 -842.39
+Customer#000000140 9963.15
+set @a1='Customer#%1_';
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08') and c_name like @a1;
+execute stmt using @a1;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000005 794.47
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000035 1228.24
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000040 1335.3
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000098 -551.37
+Customer#000000109 -716.1
+Customer#000000136 -842.39
+Customer#000000140 9963.15
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000005 794.47
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000035 1228.24
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000040 1335.3
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000098 -551.37
+Customer#000000109 -716.1
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000136 -842.39
+Customer#000000140 9963.15
+set @a2='Customer#%3_';
+create table r as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08') and c_name like @a2;
+execute stmt using @a2;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000005 794.47
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000040 1335.3
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000098 -551.37
+Customer#000000109 -716.1
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000140 9963.15
+insert into customer select * from r;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000005 794.47
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000035 1228.24
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000040 1335.3
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000098 -551.37
+Customer#000000109 -716.1
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000136 -842.39
+Customer#000000140 9963.15
+drop table t,r;
+deallocate prepare stmt;
+# Materialization SJM PS
+# ======================
+prepare stmt from "
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08') and c_acctbal between ? and ?;
+";
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+set @a1=3500;
+set @a2=4000;
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1) and c_acctbal between @a1 and @a2;
+execute stmt using @a1, @a2;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+set @a3=-1000;
+set @a4=3500;
+create table r as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1) and c_acctbal between @a3 and @a4;
+execute stmt using @a3, @a4;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+insert into customer select * from r;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+drop table t,r;
+deallocate prepare stmt;
+# Pullout SP
+# ==========
+create procedure p(a1 int, a2 int)
+delete from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU')) and o_totalprice between a1 and a2;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+644 201268.06
+737 12984.85
+create table t as
+select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU')) and o_totalprice between 150000 and 200000;
+call p(150000, 200000);
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+644 201268.06
+737 12984.85
+insert into orders select * from t;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+644 201268.06
+737 12984.85
+create table r as
+select * from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU')) and o_totalprice between 180000 and 210000;
+call p(180000, 210000);
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5121 150334.57
+737 12984.85
+insert into orders select * from r;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+1729 12137.76
+2880 145761.99
+3142 16030.15
+5095 184583.99
+5121 150334.57
+644 201268.06
+737 12984.85
+drop table t,r;
+drop procedure p;
+# FirstMatch SP
+# =============
+create procedure p(a int)
+delete from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08') and c_acctbal > a;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+create table t as
+select * from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08') and c_acctbal > 4000;
+call p(4000);
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000097 2164.48
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000133 2314.67
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+create table r as
+select * from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08') and c_acctbal > 2000;
+call p(2000);
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000047 274.58
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+insert into customer select * from r;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+drop table t,r;
+drop procedure p;
+# Materialization SP
+# ==================
+create procedure p()
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000140 9963.15
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+call p();
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000140 9963.15
+create table r as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+call p();
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+insert into customer select * from r;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000016 4681.03
+Customer#000000025 7133.7
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000038 6345.11
+Customer#000000052 5630.28
+Customer#000000056 6530.86
+Customer#000000065 8795.16
+Customer#000000076 5745.33
+Customer#000000091 4643.14
+Customer#000000115 7508.92
+Customer#000000116 8403.99
+Customer#000000118 3582.37
+Customer#000000140 9963.15
+drop table t,r;
+drop procedure p;
+# Materialization SJM SP
+# ======================
+create procedure p()
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+call p();
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+insert into customer select * from t;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+create table r as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+call p();
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+insert into customer select * from r;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000056 6530.86
+Customer#000000118 3582.37
+drop table t,r;
+drop procedure p;
+# Check for DELETE ... RETURNING with SJ subquery in WHERE
+select c_name from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name
+Customer#000000013
+Customer#000000016
+Customer#000000025
+Customer#000000032
+Customer#000000037
+Customer#000000038
+Customer#000000052
+Customer#000000056
+Customer#000000065
+Customer#000000076
+Customer#000000091
+Customer#000000115
+Customer#000000116
+Customer#000000118
+Customer#000000140
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+explain
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08') returning c_name;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL NULL NULL NULL NULL 141 Using where
+2 DEPENDENT SUBQUERY orders index_subquery|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 func 175 (2%) Using where; Using rowid filter
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08') returning c_name;
+c_name
+Customer#000000013
+Customer#000000016
+Customer#000000025
+Customer#000000032
+Customer#000000037
+Customer#000000038
+Customer#000000052
+Customer#000000056
+Customer#000000065
+Customer#000000076
+Customer#000000091
+Customer#000000115
+Customer#000000116
+Customer#000000118
+Customer#000000140
+select c_name from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name
+insert into customer select * from t;
+select c_name from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name
+Customer#000000013
+Customer#000000016
+Customer#000000025
+Customer#000000032
+Customer#000000037
+Customer#000000038
+Customer#000000052
+Customer#000000056
+Customer#000000065
+Customer#000000076
+Customer#000000091
+Customer#000000115
+Customer#000000116
+Customer#000000118
+Customer#000000140
+drop table t;
+select c_name from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name
+Customer#000000013
+Customer#000000032
+Customer#000000037
+Customer#000000056
+Customer#000000118
+create table t as
+select * from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+explain
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1) returning c_name;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL NULL NULL NULL NULL 141 Using where
+2 DEPENDENT SUBQUERY orders range i_o_orderdate i_o_orderdate 4 NULL 28 Using index condition; Using temporary
+delete from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1) returning c_name;
+c_name
+Customer#000000013
+Customer#000000032
+Customer#000000037
+Customer#000000056
+Customer#000000118
+select c_name from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name
+insert into customer select * from t;
+select c_name from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name
+Customer#000000013
+Customer#000000032
+Customer#000000037
+Customer#000000056
+Customer#000000118
+drop table t;
+DROP DATABASE dbt3_s001;
diff --git a/mysql-test/main/delete_single_to_multi.test b/mysql-test/main/delete_single_to_multi.test
new file mode 100644
index 0000000..825da74
--- /dev/null
+++ b/mysql-test/main/delete_single_to_multi.test
@@ -0,0 +1,723 @@
+--disable_warnings
+DROP DATABASE IF EXISTS dbt3_s001;
+--enable_warnings
+
+CREATE DATABASE dbt3_s001;
+
+use dbt3_s001;
+
+--disable_query_log
+--disable_result_log
+--disable_warnings
+--source include/dbt3_s001.inc
+--enable_warnings
+--enable_result_log
+--enable_query_log
+
+create index i_n_name on nation(n_name);
+analyze table nation;
+
+
+--echo # Pullout
+--echo # =======
+
+let $c1=
+ o_orderDATE between '1992-01-01' and '1992-06-30' and
+ o_custkey in (select c_custkey from customer
+ where c_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+
+eval
+explain
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+explain format=json
+select o_orderkey, o_totalprice from orders where $c1;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+create table t as
+select * from orders where $c1;
+
+eval
+explain
+delete from orders where $c1;
+eval
+explain format=json
+delete from orders where $c1;
+eval
+delete from orders where $c1;
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+
+
+insert into orders select * from t;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+drop table t;
+
+
+let $c2=
+ (ps_partkey, ps_suppkey) in
+ (select p_partkey, s_suppkey from part, supplier
+ where p_retailprice between 901 and 910 and
+ s_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+
+eval
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+--sorted_result
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+eval
+create table t as
+select * from partsupp where $c2;
+
+eval
+explain
+delete from partsupp where $c2;
+eval
+delete from partsupp where $c2;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+
+insert into partsupp select * from t;
+--sorted_result
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+drop table t;
+
+
+let $c3=
+ ps_partkey in (select p_partkey from part
+ where p_retailprice between 901 and 910) and
+ ps_suppkey in (select s_suppkey from supplier
+ where s_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+eval
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+--sorted_result
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+eval
+create table t as
+select * from partsupp where $c3;
+
+eval
+explain
+delete from partsupp where $c3;
+eval
+delete from partsupp where $c3;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+
+insert into partsupp select * from t;
+--sorted_result
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+drop table t;
+
+
+let $c4=
+ l_orderkey in (select o_orderkey from orders
+ where o_custkey in
+ (select c_custkey from customer
+ where c_nationkey in
+ (select n_nationkey from nation
+ where n_name='PERU'))
+ and
+ o_orderDATE between '1992-06-30' and '1992-12-31')
+ and
+ (l_partkey, l_suppkey) in
+ (select p_partkey, s_suppkey from part, supplier
+ where p_retailprice between 901 and 1000 and
+ s_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+
+eval
+explain
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+--sorted_result
+eval
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+eval
+create table t as
+select * from lineitem where $c4;
+
+eval
+explain
+delete from lineitem where $c4;
+eval
+delete from lineitem where $c4;
+eval
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+
+insert into lineitem select * from t;
+--sorted_result
+eval
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+drop table t;
+
+
+--echo # FirstMatch
+--echo # ==========
+
+let $c5=
+ c_nationkey in (select n_nationkey from nation
+ where n_regionkey in (1,2))
+ and
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-10-09' and '1993-03-08');
+
+eval
+explain
+select c_name, c_acctbal from customer where $c5;
+eval
+explain format=json
+select c_name, c_acctbal from customer where $c5;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+eval
+create table t as
+select * from customer where $c5;
+
+eval
+explain
+delete from customer where $c5;
+eval
+explain format=json
+delete from customer where $c5;
+eval
+delete from customer where $c5;
+eval
+select c_name, c_acctbal from customer where $c5;
+
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+drop table t;
+
+
+let $c6=
+ c_nationkey in (select n_nationkey from nation where n_name='PERU')
+ and
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between "1992-01-09" and "1993-01-08");
+
+eval
+explain
+select c_name, c_acctbal from customer where $c6;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c6;
+eval
+create table t as
+select * from customer where $c6;
+
+eval
+explain
+delete from customer where $c6;
+eval
+delete from customer where $c6;
+eval
+select c_name, c_acctbal from customer where $c6;
+
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c6;
+drop table t;
+
+
+--echo # Materialization
+--echo # ===============
+
+let $c7=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-01-09' and '1992-03-08');
+
+eval
+explain
+select c_name, c_acctbal from customer where $c7;
+eval
+explain format=json
+select c_name, c_acctbal from customer where $c7;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+eval
+create table t as
+select * from customer where $c7;
+
+eval
+explain
+delete from customer where $c7;
+eval
+explain format=json
+delete from customer where $c7;
+eval
+delete from customer where $c7;
+eval
+select c_name, c_acctbal from customer where $c7;
+
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+drop table t;
+
+
+let $c8=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-06-09' and '1993-01-08');
+
+eval
+explain
+select c_name, c_acctbal from customer where $c8;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c8;
+eval
+create table t as
+select * from customer where $c8;
+
+eval
+explain
+delete from customer where $c8;
+eval
+delete from customer where $c8;
+eval
+select c_name, c_acctbal from customer where $c8;
+
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c8;
+drop table t;
+
+
+--echo # Materialization SJM
+--echo # ===================
+
+let $c9=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+
+eval
+explain
+select c_name, c_acctbal from customer where $c9;
+eval
+explain format=json
+select c_name, c_acctbal from customer where $c9;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+eval
+create table t as
+select * from customer where $c9;
+
+eval
+explain
+delete from customer where $c9;
+eval
+explain format=json
+delete from customer where $c9;
+eval
+delete from customer where $c9;
+eval
+select c_name, c_acctbal from customer where $c9;
+
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+drop table t;
+
+
+let $c10=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+
+eval
+explain
+select c_name, c_acctbal from customer where $c10;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c10;
+eval
+create table t as
+select * from customer where $c10;
+
+eval
+explain
+delete from customer where $c10;
+eval
+delete from customer where $c10;
+eval
+select c_name, c_acctbal from customer where $c10;
+
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c10;
+drop table t;
+
+
+--echo # Pullout PS
+--echo # ==========
+
+eval
+prepare stmt from "
+delete from orders where $c1;
+";
+
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+create table t as
+select * from orders where $c1;
+execute stmt;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+insert into orders select * from t;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+create table r as
+select * from orders where $c1;
+execute stmt;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+insert into orders select * from r;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+drop table t,r;
+
+deallocate prepare stmt;
+
+
+--echo # FirstMatch PS
+--echo # =============
+
+eval
+prepare stmt from "
+delete from customer where $c5;
+";
+
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+eval
+create table t as
+select * from customer where $c5;
+execute stmt;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+eval
+create table r as
+select * from customer where $c5;
+execute stmt;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+insert into customer select * from r;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+drop table t,r;
+
+deallocate prepare stmt;
+
+
+--echo # Materialization PS
+--echo # ==================
+
+eval
+prepare stmt from "
+delete from customer where $c7 and c_name like ?;
+";
+
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+set @a1='Customer#%1_';
+eval
+create table t as
+select * from customer where $c7 and c_name like @a1;
+execute stmt using @a1;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+set @a2='Customer#%3_';
+eval
+create table r as
+select * from customer where $c7 and c_name like @a2;
+execute stmt using @a2;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+insert into customer select * from r;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+drop table t,r;
+
+deallocate prepare stmt;
+
+
+--echo # Materialization SJM PS
+--echo # ======================
+
+eval
+prepare stmt from "
+delete from customer where $c7 and c_acctbal between ? and ?;
+";
+
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+set @a1=3500;
+set @a2=4000;
+eval
+create table t as
+select * from customer where $c9 and c_acctbal between @a1 and @a2;
+execute stmt using @a1, @a2;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+set @a3=-1000;
+set @a4=3500;
+eval
+create table r as
+select * from customer where $c9 and c_acctbal between @a3 and @a4;
+execute stmt using @a3, @a4;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+insert into customer select * from r;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+drop table t,r;
+
+deallocate prepare stmt;
+
+
+--echo # Pullout SP
+--echo # ==========
+
+eval
+create procedure p(a1 int, a2 int)
+delete from orders where $c1 and o_totalprice between a1 and a2;
+
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+create table t as
+select * from orders where $c1 and o_totalprice between 150000 and 200000;
+call p(150000, 200000);
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+insert into orders select * from t;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+create table r as
+select * from orders where $c1 and o_totalprice between 180000 and 210000;
+call p(180000, 210000);
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+insert into orders select * from r;
+--sorted_result
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+drop table t,r;
+
+drop procedure p;
+
+
+--echo # FirstMatch SP
+--echo # =============
+
+eval
+create procedure p(a int)
+delete from customer where $c5 and c_acctbal > a;
+
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+eval
+create table t as
+select * from customer where $c5 and c_acctbal > 4000;
+call p(4000);
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+eval
+create table r as
+select * from customer where $c5 and c_acctbal > 2000;
+call p(2000);
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+insert into customer select * from r;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c5;
+drop table t,r;
+
+drop procedure p;
+
+
+--echo # Materialization SP
+--echo # ==================
+
+eval
+create procedure p()
+delete from customer where $c7;
+
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+eval
+create table t as
+select * from customer where $c7;
+call p();
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+eval
+create table r as
+select * from customer where $c7;
+call p();
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+insert into customer select * from r;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c7;
+drop table t,r;
+
+drop procedure p;
+
+
+--echo # Materialization SJM SP
+--echo # ======================
+
+eval
+create procedure p()
+delete from customer where $c9;
+
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+eval
+create table t as
+select * from customer where $c9;
+call p();
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+eval
+create table r as
+select * from customer where $c9;
+call p();
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+insert into customer select * from r;
+--sorted_result
+eval
+select c_name, c_acctbal from customer where $c9;
+drop table t,r;
+
+drop procedure p;
+
+--echo # Check for DELETE ... RETURNING with SJ subquery in WHERE
+
+--sorted_result
+eval
+select c_name from customer where $c7;
+eval
+create table t as
+select * from customer where $c7;
+eval
+explain
+delete from customer where $c7 returning c_name;
+--sorted_result
+eval
+delete from customer where $c7 returning c_name;
+--sorted_result
+eval
+select c_name from customer where $c7;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name from customer where $c7;
+drop table t;
+
+--sorted_result
+eval
+select c_name from customer where $c9;
+eval
+create table t as
+select * from customer where $c9;
+eval
+explain
+delete from customer where $c9 returning c_name;
+--sorted_result
+eval
+delete from customer where $c9 returning c_name;
+--sorted_result
+eval
+select c_name from customer where $c9;
+insert into customer select * from t;
+--sorted_result
+eval
+select c_name from customer where $c9;
+drop table t;
+
+DROP DATABASE dbt3_s001;
diff --git a/mysql-test/main/log_state.result b/mysql-test/main/log_state.result
index 5e7aac8..1b1c737 100644
--- a/mysql-test/main/log_state.result
+++ b/mysql-test/main/log_state.result
@@ -243,7 +243,7 @@ rows_examined sql_text
4 UPDATE t1 SET a=a+sleep(.02) WHERE a>2
8 UPDATE t1 SET a=a+sleep(.02) ORDER BY a DESC
1 UPDATE t2 set b=b+sleep(.02) limit 1
-4 UPDATE t1 SET a=a+sleep(.02) WHERE a in (SELECT b from t2)
+10 UPDATE t1 SET a=a+sleep(.02) WHERE a in (SELECT b from t2)
6 DELETE FROM t1 WHERE a=a+sleep(.02) ORDER BY a LIMIT 2
disconnect con2;
connection default;
diff --git a/mysql-test/main/myisam_explain_non_select_all.result b/mysql-test/main/myisam_explain_non_select_all.result
index 20b769b..5df9ced 100644
--- a/mysql-test/main/myisam_explain_non_select_all.result
+++ b/mysql-test/main/myisam_explain_non_select_all.result
@@ -240,14 +240,16 @@ Warnings:
Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
EXPLAIN UPDATE t1 SET a = 10 WHERE 1 IN (SELECT 1 FROM t2 WHERE t2.b < 3);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
-2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED UPDATE t1 SET a = 10 WHERE 1 IN (SELECT 1 FROM t2 WHERE t2.b < 3);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
-2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 100.00 Using where
# Status of EXPLAIN EXTENDED query
Variable_name Value
Handler_read_key 4
@@ -271,8 +273,9 @@ Handler_read_key 5
Handler_read_rnd_next 8
# Status of testing query execution:
Variable_name Value
-Handler_read_key 4
-Handler_read_rnd_next 5
+Handler_read_key 5
+Handler_read_rnd 3
+Handler_read_rnd_next 12
Handler_update 3
DROP TABLE t1, t2;
@@ -290,13 +293,13 @@ Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be
EXPLAIN UPDATE t1 SET a = 10 WHERE a IN (SELECT b FROM t2 WHERE t1.a < 3);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
-2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY t2 ALL NULL NULL NULL NULL 3 Using where; FirstMatch(t1)
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED UPDATE t1 SET a = 10 WHERE a IN (SELECT b FROM t2 WHERE t1.a < 3);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
-2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where
+1 PRIMARY t2 ALL NULL NULL NULL NULL 3 100.00 Using where; FirstMatch(t1)
Warnings:
Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1
# Status of EXPLAIN EXTENDED query
@@ -984,14 +987,16 @@ Warnings:
Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
EXPLAIN UPDATE t1 SET a = 10 WHERE a IN (SELECT a FROM t2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
-2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED UPDATE t1 SET a = 10 WHERE a IN (SELECT a FROM t2);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
-2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 100.00
# Status of EXPLAIN EXTENDED query
Variable_name Value
Handler_read_key 4
@@ -1015,8 +1020,8 @@ Handler_read_key 7
Handler_read_rnd_next 8
# Status of testing query execution:
Variable_name Value
-Handler_read_key 4
-Handler_read_rnd_next 10
+Handler_read_key 7
+Handler_read_rnd_next 8
Handler_update 3
DROP TABLE t1, t2;
@@ -1079,14 +1084,14 @@ Warnings:
Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
EXPLAIN DELETE FROM t1 WHERE a1 IN (SELECT a2 FROM t2 WHERE a2 > 2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where
-2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 5 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5
+1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using where; FirstMatch(t1)
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED DELETE FROM t1 WHERE a1 IN (SELECT a2 FROM t2 WHERE a2 > 2);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 5 100.00 Using where
-2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5 100.00
+1 PRIMARY t2 ALL NULL NULL NULL NULL 5 100.00 Using where; FirstMatch(t1)
# Status of EXPLAIN EXTENDED query
Variable_name Value
Handler_read_key 4
@@ -3074,14 +3079,14 @@ Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be
EXPLAIN UPDATE t1 SET a = 10 WHERE a IN (SELECT * FROM (SELECT b FROM t2 ORDER BY b LIMIT 2,2) x);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
-2 DEPENDENT SUBQUERY <derived3> index_subquery key0 key0 5 func 2
+1 PRIMARY <derived3> ref key0 key0 5 test.t1.a 2 FirstMatch(t1)
3 DERIVED t2 ALL NULL NULL NULL NULL 3 Using filesort
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED UPDATE t1 SET a = 10 WHERE a IN (SELECT * FROM (SELECT b FROM t2 ORDER BY b LIMIT 2,2) x);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
-2 DEPENDENT SUBQUERY <derived3> index_subquery key0 key0 5 func 2 100.00
+1 PRIMARY <derived3> ref key0 key0 5 test.t1.a 2 100.00 FirstMatch(t1)
3 DERIVED t2 ALL NULL NULL NULL NULL 3 100.00 Using filesort
# Status of EXPLAIN EXTENDED query
Variable_name Value
diff --git a/mysql-test/main/opt_trace.result b/mysql-test/main/opt_trace.result
index 0555f72..e46bd80 100644
--- a/mysql-test/main/opt_trace.result
+++ b/mysql-test/main/opt_trace.result
@@ -3948,6 +3948,16 @@ explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3 {
}
},
{
+ "table": "t0",
+ "rowid_filters": [
+ {
+ "key": "a",
+ "build_cost": 0.174715752,
+ "rows": 3
+ }
+ ]
+ },
+ {
"selectivity_for_indexes": [
{
"index_name": "a",
@@ -4013,6 +4023,16 @@ explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3 {
}
},
{
+ "table": "t1",
+ "rowid_filters": [
+ {
+ "key": "a",
+ "build_cost": 0.174715752,
+ "rows": 3
+ }
+ ]
+ },
+ {
"selectivity_for_indexes": [
{
"index_name": "a",
diff --git a/mysql-test/main/update_single_to_multi.result b/mysql-test/main/update_single_to_multi.result
new file mode 100644
index 0000000..687132f
--- /dev/null
+++ b/mysql-test/main/update_single_to_multi.result
@@ -0,0 +1,2209 @@
+DROP DATABASE IF EXISTS dbt3_s001;
+CREATE DATABASE dbt3_s001;
+use dbt3_s001;
+create index i_n_name on nation(n_name);
+analyze table nation;
+Table Op Msg_type Msg_text
+dbt3_s001.nation analyze status Engine-independent statistics collected
+dbt3_s001.nation analyze status OK
+# Pullout
+# =======
+explain
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (7%) Using where; Using rowid filter
+explain format=json
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_n_name"],
+ "key": "i_n_name",
+ "key_length": "26",
+ "used_key_parts": ["n_name"],
+ "ref": ["const"],
+ "rows": 1,
+ "filtered": 100,
+ "index_condition": "nation.n_name = 'PERU'"
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "key": "i_c_nationkey",
+ "key_length": "5",
+ "used_key_parts": ["c_nationkey"],
+ "ref": ["dbt3_s001.nation.n_nationkey"],
+ "rows": 11,
+ "filtered": 100
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 108,
+ "selectivity_pct": 7.2
+ },
+ "rows": 11,
+ "filtered": 7.199999809,
+ "attached_condition": "orders.o_orderDATE between '1992-01-01' and '1992-06-30'"
+ }
+ }
+ ]
+ }
+}
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201268.06
+2880 145761.99
+3142 16030.15
+5382 138423.03
+5095 184583.99
+737 12984.85
+1729 12137.76
+5121 150334.57
+explain
+update orders set o_totalprice = o_totalprice-50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (7%) Using where; Using rowid filter
+explain format=json
+update orders set o_totalprice = o_totalprice-50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_n_name"],
+ "key": "i_n_name",
+ "key_length": "26",
+ "used_key_parts": ["n_name"],
+ "ref": ["const"],
+ "rows": 1,
+ "filtered": 100,
+ "index_condition": "nation.n_name = 'PERU'"
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ref",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "key": "i_c_nationkey",
+ "key_length": "5",
+ "used_key_parts": ["c_nationkey"],
+ "ref": ["dbt3_s001.nation.n_nationkey"],
+ "rows": 11,
+ "filtered": 100
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 108,
+ "selectivity_pct": 7.2
+ },
+ "rows": 11,
+ "filtered": 7.199999809,
+ "attached_condition": "orders.o_orderDATE between '1992-01-01' and '1992-06-30'"
+ }
+ }
+ ]
+ }
+}
+update orders set o_totalprice = o_totalprice-50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201218.06
+2880 145711.99
+3142 15980.15
+5382 138373.03
+5095 184533.99
+737 12934.85
+1729 12087.76
+5121 150284.57
+update orders set o_totalprice= o_totalprice+50 where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201268.06
+2880 145761.99
+3142 16030.15
+5382 138423.03
+5095 184583.99
+737 12984.85
+1729 12137.76
+5121 150334.57
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+4 1 444.37
+6 1 642.13
+8 1 957.34
+1 8 357.84
+3 8 645.4
+5 8 50.52
+7 8 763.98
+explain
+update partsupp set ps_supplycost = ps_supplycost+2 where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+update partsupp set ps_supplycost = ps_supplycost+2 where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+4 1 446.37
+6 1 644.13
+8 1 959.34
+1 8 359.84
+3 8 647.4
+5 8 52.52
+7 8 765.98
+update partsupp set ps_supplycost = ps_supplycost-2 where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where (ps_partkey, ps_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 910 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+4 1 444.37
+6 1 642.13
+8 1 957.34
+1 8 357.84
+3 8 645.4
+5 8 50.52
+7 8 763.98
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+4 1 444.37
+6 1 642.13
+8 1 957.34
+1 8 357.84
+3 8 645.4
+5 8 50.52
+7 8 763.98
+explain
+update partsupp set ps_supplycost = ps_supplycost+10 where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey i_ps_suppkey 4 dbt3_s001.supplier.s_suppkey 16
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.partsupp.ps_partkey 1 Using where
+update partsupp set ps_supplycost = ps_supplycost+10 where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+4 1 454.37
+6 1 652.13
+8 1 967.34
+1 8 367.84
+3 8 655.4
+5 8 60.52
+7 8 773.98
+update partsupp set ps_supplycost = ps_supplycost-10 where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where ps_partkey in (select p_partkey from part
+where p_retailprice between 901 and 910) and
+ps_suppkey in (select s_suppkey from supplier
+where s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+ps_partkey ps_suppkey ps_supplycost
+4 1 444.37
+6 1 642.13
+8 1 957.34
+1 8 357.84
+3 8 645.4
+5 8 50.52
+7 8 763.98
+explain
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY lineitem ref PRIMARY,i_l_suppkey_partkey,i_l_partkey,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity i_l_suppkey 5 dbt3_s001.supplier.s_suppkey 100 Using where
+1 PRIMARY orders eq_ref|filter PRIMARY,i_o_orderdate,i_o_custkey PRIMARY|i_o_orderdate 4|4 dbt3_s001.lineitem.l_orderkey 1 (7%) Using where; Using rowid filter
+1 PRIMARY customer eq_ref PRIMARY,i_c_nationkey PRIMARY 4 dbt3_s001.orders.o_custkey 1 Using where
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.lineitem.l_partkey 1 Using where
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+l_orderkey l_linenumber l_tax
+4996 1 0.01
+933 1 0.04
+2500 2 0.02
+2500 4 0.02
+explain
+update lineitem set l_tax = (l_tax*100+1)/100 where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 2
+1 PRIMARY lineitem ref PRIMARY,i_l_suppkey_partkey,i_l_partkey,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity i_l_suppkey 5 dbt3_s001.supplier.s_suppkey 100 Using where
+1 PRIMARY orders eq_ref|filter PRIMARY,i_o_orderdate,i_o_custkey PRIMARY|i_o_orderdate 4|4 dbt3_s001.lineitem.l_orderkey 1 (7%) Using where; Using rowid filter
+1 PRIMARY customer eq_ref PRIMARY,i_c_nationkey PRIMARY 4 dbt3_s001.orders.o_custkey 1 Using where
+1 PRIMARY part eq_ref PRIMARY PRIMARY 4 dbt3_s001.lineitem.l_partkey 1 Using where
+update lineitem set l_tax = (l_tax*100+1)/100 where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+l_orderkey l_linenumber l_tax
+4996 1 0.02
+933 1 0.05
+2500 2 0.03
+2500 4 0.03
+update lineitem set l_tax = (l_tax*100-1)/100 where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select l_orderkey, l_linenumber, l_tax from lineitem where l_orderkey in (select o_orderkey from orders
+where o_custkey in
+(select c_custkey from customer
+where c_nationkey in
+(select n_nationkey from nation
+where n_name='PERU'))
+and
+o_orderDATE between '1992-06-30' and '1992-12-31')
+and
+(l_partkey, l_suppkey) in
+(select p_partkey, s_suppkey from part, supplier
+where p_retailprice between 901 and 1000 and
+s_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+l_orderkey l_linenumber l_tax
+4996 1 0.01
+933 1 0.04
+2500 2 0.02
+2500 4 0.02
+# FirstMatch
+# ==========
+explain
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY,i_c_nationkey NULL NULL NULL 150 Using where
+1 PRIMARY nation eq_ref|filter PRIMARY,i_n_regionkey PRIMARY|i_n_regionkey 4|5 dbt3_s001.customer.c_nationkey 1 (40%) Using where; Using rowid filter
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (6%) Using where; FirstMatch(nation); Using rowid filter
+explain format=json
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ALL",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "rows": 150,
+ "filtered": 100,
+ "attached_condition": "customer.c_nationkey is not null"
+ }
+ },
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY", "i_n_regionkey"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["n_nationkey"],
+ "ref": ["dbt3_s001.customer.c_nationkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_n_regionkey",
+ "used_key_parts": ["n_regionkey"]
+ },
+ "rows": 10,
+ "selectivity_pct": 40
+ },
+ "rows": 1,
+ "filtered": 40,
+ "attached_condition": "nation.n_regionkey in (1,2)"
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 89,
+ "selectivity_pct": 5.933333333
+ },
+ "rows": 11,
+ "filtered": 5.933333397,
+ "attached_condition": "orders.o_orderDATE between '1992-10-09' and '1993-03-08'",
+ "first_match": "nation"
+ }
+ }
+ ]
+ }
+}
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+explain
+update customer set c_acctbal = c_acctbal+10 where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY,i_c_nationkey NULL NULL NULL 150 Using where
+1 PRIMARY nation eq_ref|filter PRIMARY,i_n_regionkey PRIMARY|i_n_regionkey 4|5 dbt3_s001.customer.c_nationkey 1 (40%) Using where; Using rowid filter
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (6%) Using where; FirstMatch(nation); Using rowid filter
+explain format=json
+update customer set c_acctbal = c_acctbal+10 where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "ALL",
+ "possible_keys": ["PRIMARY", "i_c_nationkey"],
+ "rows": 150,
+ "filtered": 100,
+ "attached_condition": "customer.c_nationkey is not null"
+ }
+ },
+ {
+ "table": {
+ "table_name": "nation",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY", "i_n_regionkey"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["n_nationkey"],
+ "ref": ["dbt3_s001.customer.c_nationkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_n_regionkey",
+ "used_key_parts": ["n_regionkey"]
+ },
+ "rows": 10,
+ "selectivity_pct": 40
+ },
+ "rows": 1,
+ "filtered": 40,
+ "attached_condition": "nation.n_regionkey in (1,2)"
+ }
+ },
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "ref",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_custkey",
+ "key_length": "5",
+ "used_key_parts": ["o_custkey"],
+ "ref": ["dbt3_s001.customer.c_custkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_orderdate",
+ "used_key_parts": ["o_orderDATE"]
+ },
+ "rows": 89,
+ "selectivity_pct": 5.933333333
+ },
+ "rows": 11,
+ "filtered": 5.933333397,
+ "attached_condition": "orders.o_orderDATE between '1992-10-09' and '1993-03-08'",
+ "first_match": "nation"
+ }
+ }
+ ]
+ }
+}
+update customer set c_acctbal = c_acctbal+10 where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9571.95
+Customer#000000019 8924.71
+Customer#000000022 601.98
+Customer#000000025 7143.7
+Customer#000000028 1017.18
+Customer#000000037 -907.75
+Customer#000000040 1345.3
+Customer#000000047 284.58
+Customer#000000059 3468.6
+Customer#000000061 1546.24
+Customer#000000064 -636.64
+Customer#000000067 8176.59
+Customer#000000082 9478.34
+Customer#000000091 4653.14
+Customer#000000094 5510.11
+Customer#000000097 2174.48
+Customer#000000101 7480.96
+Customer#000000103 2767.45
+Customer#000000106 3298.42
+Customer#000000115 7518.92
+Customer#000000121 6438.32
+Customer#000000122 7875.46
+Customer#000000127 9290.71
+Customer#000000130 5083.58
+Customer#000000133 2324.67
+Customer#000000139 7907.78
+update customer set c_acctbal = c_acctbal-10 where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+explain
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (14%) Using where; FirstMatch(customer); Using rowid filter
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+c_name c_acctbal
+Customer#000000008 6819.74
+Customer#000000035 1228.24
+Customer#000000061 1536.24
+Customer#000000097 2164.48
+Customer#000000121 6428.32
+Customer#000000133 2314.67
+explain
+update customer set c_acctbal = c_acctbal+20 where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY nation ref PRIMARY,i_n_name i_n_name 26 const 1 Using index condition
+1 PRIMARY customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 11
+1 PRIMARY orders ref|filter i_o_orderdate,i_o_custkey i_o_custkey|i_o_orderdate 5|4 dbt3_s001.customer.c_custkey 11 (14%) Using where; FirstMatch(customer); Using rowid filter
+update customer set c_acctbal = c_acctbal+20 where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+c_name c_acctbal
+Customer#000000008 6839.74
+Customer#000000035 1248.24
+Customer#000000061 1556.24
+Customer#000000097 2184.48
+Customer#000000121 6448.32
+Customer#000000133 2334.67
+update customer set c_acctbal = c_acctbal-20 where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation where n_name='PERU')
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between "1992-01-09" and "1993-01-08");
+c_name c_acctbal
+Customer#000000008 6819.74
+Customer#000000035 1228.24
+Customer#000000061 1536.24
+Customer#000000097 2164.48
+Customer#000000121 6428.32
+Customer#000000133 2314.67
+# Materialization
+# ===============
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 dbt3_s001.orders.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 28 Using index condition; Using where
+explain format=json
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'",
+ "attached_condition": "orders.o_custkey is not null"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["dbt3_s001.orders.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7133.7
+Customer#000000013 3857.34
+Customer#000000065 8795.16
+Customer#000000032 3471.53
+Customer#000000023 3332.02
+Customer#000000035 1228.24
+Customer#000000091 4643.14
+Customer#000000016 4681.03
+Customer#000000098 -551.37
+Customer#000000037 -917.75
+Customer#000000136 -842.39
+Customer#000000118 3582.37
+Customer#000000022 591.98
+Customer#000000005 794.47
+Customer#000000109 -716.1
+Customer#000000038 6345.11
+Customer#000000076 5745.33
+Customer#000000056 6530.86
+Customer#000000040 1335.3
+Customer#000000116 8403.99
+Customer#000000115 7508.92
+Customer#000000140 9963.15
+Customer#000000017 6.34
+Customer#000000052 5630.28
+explain
+update customer set c_acctbal = c_acctbal+5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 dbt3_s001.orders.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 28 Using index condition; Using where
+explain format=json
+update customer set c_acctbal = c_acctbal+5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate", "i_o_custkey"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'",
+ "attached_condition": "orders.o_custkey is not null"
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["dbt3_s001.orders.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+update customer set c_acctbal = c_acctbal+5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7138.7
+Customer#000000013 3862.34
+Customer#000000065 8800.16
+Customer#000000032 3476.53
+Customer#000000023 3337.02
+Customer#000000035 1233.24
+Customer#000000091 4648.14
+Customer#000000016 4686.03
+Customer#000000098 -546.37
+Customer#000000037 -912.75
+Customer#000000136 -837.39
+Customer#000000118 3587.37
+Customer#000000022 596.98
+Customer#000000005 799.47
+Customer#000000109 -711.1
+Customer#000000038 6350.11
+Customer#000000076 5750.33
+Customer#000000056 6535.86
+Customer#000000040 1340.3
+Customer#000000116 8408.99
+Customer#000000115 7513.92
+Customer#000000140 9968.15
+Customer#000000017 11.34
+Customer#000000052 5635.28
+update customer set c_acctbal = c_acctbal-5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7133.7
+Customer#000000013 3857.34
+Customer#000000065 8795.16
+Customer#000000032 3471.53
+Customer#000000023 3332.02
+Customer#000000035 1228.24
+Customer#000000091 4643.14
+Customer#000000016 4681.03
+Customer#000000098 -551.37
+Customer#000000037 -917.75
+Customer#000000136 -842.39
+Customer#000000118 3582.37
+Customer#000000022 591.98
+Customer#000000005 794.47
+Customer#000000109 -716.1
+Customer#000000038 6345.11
+Customer#000000076 5745.33
+Customer#000000056 6530.86
+Customer#000000040 1335.3
+Customer#000000116 8403.99
+Customer#000000115 7508.92
+Customer#000000140 9963.15
+Customer#000000017 6.34
+Customer#000000052 5630.28
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 114 Using index condition; Using where
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+c_name c_acctbal
+Customer#000000001 711.56
+Customer#000000002 121.65
+Customer#000000007 9561.95
+Customer#000000008 6819.74
+Customer#000000010 2753.54
+Customer#000000011 -272.6
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000029 7618.27
+Customer#000000031 5236.89
+Customer#000000034 8589.7
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000043 9904.28
+Customer#000000044 7315.94
+Customer#000000046 5744.59
+Customer#000000047 274.58
+Customer#000000049 4573.94
+Customer#000000053 4113.64
+Customer#000000055 4572.11
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000070 4867.52
+Customer#000000071 -611.19
+Customer#000000073 4288.5
+Customer#000000074 2764.43
+Customer#000000076 5745.33
+Customer#000000079 5121.28
+Customer#000000080 7383.53
+Customer#000000082 9468.34
+Customer#000000083 6463.51
+Customer#000000085 3386.64
+Customer#000000086 3306.32
+Customer#000000088 8031.44
+Customer#000000091 4643.14
+Customer#000000092 1182.91
+Customer#000000095 5327.38
+Customer#000000097 2164.48
+Customer#000000100 9889.89
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000104 -588.38
+Customer#000000106 3288.42
+Customer#000000109 -716.1
+Customer#000000110 7462.99
+Customer#000000112 2953.35
+Customer#000000118 3582.37
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000131 8595.53
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+Customer#000000136 -842.39
+Customer#000000137 7838.3
+Customer#000000139 7897.78
+Customer#000000142 2209.81
+Customer#000000143 2186.5
+Customer#000000148 2135.6
+Customer#000000149 8959.65
+explain
+update customer set c_acctbal = c_acctbal+1 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED orders range i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 114 Using index condition; Using where
+update customer set c_acctbal = c_acctbal+1 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+c_name c_acctbal
+Customer#000000001 712.56
+Customer#000000002 122.65
+Customer#000000007 9562.95
+Customer#000000008 6820.74
+Customer#000000010 2754.54
+Customer#000000011 -271.6
+Customer#000000016 4682.03
+Customer#000000017 7.34
+Customer#000000019 8915.71
+Customer#000000022 592.98
+Customer#000000023 3333.02
+Customer#000000025 7134.7
+Customer#000000028 1008.18
+Customer#000000029 7619.27
+Customer#000000031 5237.89
+Customer#000000034 8590.7
+Customer#000000037 -916.75
+Customer#000000040 1336.3
+Customer#000000043 9905.28
+Customer#000000044 7316.94
+Customer#000000046 5745.59
+Customer#000000047 275.58
+Customer#000000049 4574.94
+Customer#000000053 4114.64
+Customer#000000055 4573.11
+Customer#000000061 1537.24
+Customer#000000064 -645.64
+Customer#000000067 8167.59
+Customer#000000070 4868.52
+Customer#000000071 -610.19
+Customer#000000073 4289.5
+Customer#000000074 2765.43
+Customer#000000076 5746.33
+Customer#000000079 5122.28
+Customer#000000080 7384.53
+Customer#000000082 9469.34
+Customer#000000083 6464.51
+Customer#000000085 3387.64
+Customer#000000086 3307.32
+Customer#000000088 8032.44
+Customer#000000091 4644.14
+Customer#000000092 1183.91
+Customer#000000095 5328.38
+Customer#000000097 2165.48
+Customer#000000100 9890.89
+Customer#000000101 7471.96
+Customer#000000103 2758.45
+Customer#000000104 -587.38
+Customer#000000106 3289.42
+Customer#000000109 -715.1
+Customer#000000110 7463.99
+Customer#000000112 2954.35
+Customer#000000118 3583.37
+Customer#000000121 6429.32
+Customer#000000122 7866.46
+Customer#000000127 9281.71
+Customer#000000130 5074.58
+Customer#000000131 8596.53
+Customer#000000133 2315.67
+Customer#000000134 4609.9
+Customer#000000136 -841.39
+Customer#000000137 7839.3
+Customer#000000139 7898.78
+Customer#000000142 2210.81
+Customer#000000143 2187.5
+Customer#000000148 2136.6
+Customer#000000149 8960.65
+update customer set c_acctbal = c_acctbal-1 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-06-09' and '1993-01-08');
+c_name c_acctbal
+Customer#000000001 711.56
+Customer#000000002 121.65
+Customer#000000007 9561.95
+Customer#000000008 6819.74
+Customer#000000010 2753.54
+Customer#000000011 -272.6
+Customer#000000016 4681.03
+Customer#000000017 6.34
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000023 3332.02
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000029 7618.27
+Customer#000000031 5236.89
+Customer#000000034 8589.7
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000043 9904.28
+Customer#000000044 7315.94
+Customer#000000046 5744.59
+Customer#000000047 274.58
+Customer#000000049 4573.94
+Customer#000000053 4113.64
+Customer#000000055 4572.11
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000070 4867.52
+Customer#000000071 -611.19
+Customer#000000073 4288.5
+Customer#000000074 2764.43
+Customer#000000076 5745.33
+Customer#000000079 5121.28
+Customer#000000080 7383.53
+Customer#000000082 9468.34
+Customer#000000083 6463.51
+Customer#000000085 3386.64
+Customer#000000086 3306.32
+Customer#000000088 8031.44
+Customer#000000091 4643.14
+Customer#000000092 1182.91
+Customer#000000095 5327.38
+Customer#000000097 2164.48
+Customer#000000100 9889.89
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000104 -588.38
+Customer#000000106 3288.42
+Customer#000000109 -716.1
+Customer#000000110 7462.99
+Customer#000000112 2953.35
+Customer#000000118 3582.37
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000131 8595.53
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+Customer#000000136 -842.39
+Customer#000000137 7838.3
+Customer#000000139 7897.78
+Customer#000000142 2209.81
+Customer#000000143 2186.5
+Customer#000000148 2135.6
+Customer#000000149 8959.65
+# Materialization SJM
+# ===================
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 <subquery2>.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 28 Using index condition; Using temporary
+explain format=json
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "having_condition": "count(orders.o_custkey) > 1",
+ "temporary_table": {
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'"
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["<subquery2>.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000118 3582.37
+Customer#000000056 6530.86
+explain
+update customer set c_acctbal = c_acctbal-5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 28
+1 PRIMARY customer eq_ref PRIMARY PRIMARY 4 <subquery2>.o_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 28 Using index condition; Using temporary
+explain format=json
+update customer set c_acctbal = c_acctbal-5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "ALL",
+ "possible_keys": ["distinct_key"],
+ "rows": 28,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "having_condition": "count(orders.o_custkey) > 1",
+ "temporary_table": {
+ "nested_loop": [
+ {
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["i_o_orderdate"],
+ "key": "i_o_orderdate",
+ "key_length": "4",
+ "used_key_parts": ["o_orderDATE"],
+ "rows": 28,
+ "filtered": 100,
+ "index_condition": "orders.o_orderDATE between '1992-01-09' and '1992-03-08'"
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ {
+ "table": {
+ "table_name": "customer",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["c_custkey"],
+ "ref": ["<subquery2>.o_custkey"],
+ "rows": 1,
+ "filtered": 100
+ }
+ }
+ ]
+ }
+}
+update customer set c_acctbal = c_acctbal-5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3852.34
+Customer#000000032 3466.53
+Customer#000000037 -922.75
+Customer#000000118 3577.37
+Customer#000000056 6525.86
+update customer set c_acctbal = c_acctbal+5 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000118 3582.37
+Customer#000000056 6530.86
+explain
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 dbt3_s001.customer.c_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 242 Using index condition; Using temporary
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000016 4681.03
+Customer#000000037 -917.75
+Customer#000000046 5744.59
+Customer#000000091 4643.14
+Customer#000000103 2757.45
+Customer#000000118 3582.37
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+explain
+update customer set c_acctbal = c_acctbal-1 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY customer ALL PRIMARY NULL NULL NULL 150
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 dbt3_s001.customer.c_custkey 1
+2 MATERIALIZED orders range i_o_orderdate i_o_orderdate 4 NULL 242 Using index condition; Using temporary
+update customer set c_acctbal = c_acctbal-1 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+c_name c_acctbal
+Customer#000000007 9560.95
+Customer#000000016 4680.03
+Customer#000000037 -918.75
+Customer#000000046 5743.59
+Customer#000000091 4642.14
+Customer#000000103 2756.45
+Customer#000000118 3581.37
+Customer#000000133 2313.67
+Customer#000000134 4607.9
+update customer set c_acctbal = c_acctbal+1 where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000016 4681.03
+Customer#000000037 -917.75
+Customer#000000046 5744.59
+Customer#000000091 4643.14
+Customer#000000103 2757.45
+Customer#000000118 3582.37
+Customer#000000133 2314.67
+Customer#000000134 4608.9
+# Pullout PS
+# ==========
+prepare stmt from "
+update orders set o_totalprice = o_totalprice+? where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+";
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201268.06
+2880 145761.99
+3142 16030.15
+5382 138423.03
+5095 184583.99
+737 12984.85
+1729 12137.76
+5121 150334.57
+set @a1=-20;
+execute stmt using @a1;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201248.06
+2880 145741.99
+3142 16010.15
+5382 138403.03
+5095 184563.99
+737 12964.85
+1729 12117.76
+5121 150314.57
+set @a2=-10;
+execute stmt using @a2;
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201238.06
+2880 145731.99
+3142 16000.15
+5382 138393.03
+5095 184553.99
+737 12954.85
+1729 12107.76
+5121 150304.57
+execute stmt using -(@a1+@a2);
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201268.06
+2880 145761.99
+3142 16030.15
+5382 138423.03
+5095 184583.99
+737 12984.85
+1729 12137.76
+5121 150334.57
+deallocate prepare stmt;
+# FirstMatch PS
+# =============
+prepare stmt from "
+update customer set c_acctbal = c_acctbal+? where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+";
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.18
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+set @a1=15;
+execute stmt using @a1;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9576.95
+Customer#000000019 8929.71
+Customer#000000022 606.98
+Customer#000000025 7148.7
+Customer#000000028 1022.18
+Customer#000000037 -902.75
+Customer#000000040 1350.3
+Customer#000000047 289.58
+Customer#000000059 3473.6
+Customer#000000061 1551.24
+Customer#000000064 -631.64
+Customer#000000067 8181.59
+Customer#000000082 9483.34
+Customer#000000091 4658.14
+Customer#000000094 5515.11
+Customer#000000097 2179.48
+Customer#000000101 7485.96
+Customer#000000103 2772.45
+Customer#000000106 3303.42
+Customer#000000115 7523.92
+Customer#000000121 6443.32
+Customer#000000122 7880.46
+Customer#000000127 9295.71
+Customer#000000130 5088.58
+Customer#000000133 2329.67
+Customer#000000139 7912.78
+set @a2=5;
+execute stmt using @a2;
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9581.95
+Customer#000000019 8934.71
+Customer#000000022 611.98
+Customer#000000025 7153.7
+Customer#000000028 1027.1799999999998
+Customer#000000037 -897.75
+Customer#000000040 1355.3
+Customer#000000047 294.58
+Customer#000000059 3478.6
+Customer#000000061 1556.24
+Customer#000000064 -626.64
+Customer#000000067 8186.59
+Customer#000000082 9488.34
+Customer#000000091 4663.14
+Customer#000000094 5520.11
+Customer#000000097 2184.48
+Customer#000000101 7490.96
+Customer#000000103 2777.45
+Customer#000000106 3308.42
+Customer#000000115 7528.92
+Customer#000000121 6448.32
+Customer#000000122 7885.46
+Customer#000000127 9300.71
+Customer#000000130 5093.58
+Customer#000000133 2334.67
+Customer#000000139 7917.78
+execute stmt using -(@a1+@a2);
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.1799999999998
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+deallocate prepare stmt;
+# Materialization PS
+# ==================
+prepare stmt from "
+update customer set c_acctbal = c_acctbal+? where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+";
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7133.7
+Customer#000000013 3857.34
+Customer#000000065 8795.16
+Customer#000000032 3471.53
+Customer#000000023 3332.02
+Customer#000000035 1228.24
+Customer#000000091 4643.14
+Customer#000000016 4681.03
+Customer#000000098 -551.37
+Customer#000000037 -917.75
+Customer#000000136 -842.39
+Customer#000000118 3582.37
+Customer#000000022 591.98
+Customer#000000005 794.47
+Customer#000000109 -716.1
+Customer#000000038 6345.11
+Customer#000000076 5745.33
+Customer#000000056 6530.86
+Customer#000000040 1335.3
+Customer#000000116 8403.99
+Customer#000000115 7508.92
+Customer#000000140 9963.15
+Customer#000000017 6.34
+Customer#000000052 5630.28
+set @a1=7;
+execute stmt using @a1;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7140.7
+Customer#000000013 3864.34
+Customer#000000065 8802.16
+Customer#000000032 3478.53
+Customer#000000023 3339.02
+Customer#000000035 1235.24
+Customer#000000091 4650.14
+Customer#000000016 4688.03
+Customer#000000098 -544.37
+Customer#000000037 -910.75
+Customer#000000136 -835.39
+Customer#000000118 3589.37
+Customer#000000022 598.98
+Customer#000000005 801.47
+Customer#000000109 -709.1
+Customer#000000038 6352.11
+Customer#000000076 5752.33
+Customer#000000056 6537.86
+Customer#000000040 1342.3
+Customer#000000116 8410.99
+Customer#000000115 7515.92
+Customer#000000140 9970.15
+Customer#000000017 13.34
+Customer#000000052 5637.28
+set @a2=3;
+execute stmt using @a2;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7143.7
+Customer#000000013 3867.34
+Customer#000000065 8805.16
+Customer#000000032 3481.53
+Customer#000000023 3342.02
+Customer#000000035 1238.24
+Customer#000000091 4653.14
+Customer#000000016 4691.03
+Customer#000000098 -541.37
+Customer#000000037 -907.75
+Customer#000000136 -832.39
+Customer#000000118 3592.37
+Customer#000000022 601.98
+Customer#000000005 804.47
+Customer#000000109 -706.1
+Customer#000000038 6355.11
+Customer#000000076 5755.33
+Customer#000000056 6540.86
+Customer#000000040 1345.3
+Customer#000000116 8413.99
+Customer#000000115 7518.92
+Customer#000000140 9973.15
+Customer#000000017 16.34
+Customer#000000052 5640.28
+execute stmt using -(@a1+@a2);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7133.7
+Customer#000000013 3857.34
+Customer#000000065 8795.16
+Customer#000000032 3471.53
+Customer#000000023 3332.02
+Customer#000000035 1228.24
+Customer#000000091 4643.14
+Customer#000000016 4681.03
+Customer#000000098 -551.37
+Customer#000000037 -917.75
+Customer#000000136 -842.39
+Customer#000000118 3582.37
+Customer#000000022 591.98
+Customer#000000005 794.47
+Customer#000000109 -716.1
+Customer#000000038 6345.11
+Customer#000000076 5745.33
+Customer#000000056 6530.86
+Customer#000000040 1335.3
+Customer#000000116 8403.99
+Customer#000000115 7508.92
+Customer#000000140 9963.15
+Customer#000000017 6.34
+Customer#000000052 5630.28
+deallocate prepare stmt;
+# Materialization SJM PS
+# ======================
+prepare stmt from "
+update customer set c_acctbal = c_acctbal+? where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+";
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000118 3582.37
+Customer#000000056 6530.86
+set @a1=-2;
+execute stmt using @a1;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3855.34
+Customer#000000032 3469.53
+Customer#000000037 -919.75
+Customer#000000118 3580.37
+Customer#000000056 6528.86
+set @a2=-1;
+execute stmt using @a2;
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3854.34
+Customer#000000032 3468.53
+Customer#000000037 -920.75
+Customer#000000118 3579.37
+Customer#000000056 6527.86
+execute stmt using -(@a1+@a2);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000118 3582.37
+Customer#000000056 6530.86
+deallocate prepare stmt;
+# Pullout SP
+# ==========
+create procedure p(d int)
+update orders set o_totalprice = o_totalprice+d where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201268.06
+2880 145761.99
+3142 16030.15
+5382 138423.03
+5095 184583.99
+737 12984.85
+1729 12137.76
+5121 150334.57
+call p(-10);
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201258.06
+2880 145751.99
+3142 16020.15
+5382 138413.03
+5095 184573.99
+737 12974.85
+1729 12127.76
+5121 150324.57
+call p(-20);
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201238.06
+2880 145731.99
+3142 16000.15
+5382 138393.03
+5095 184553.99
+737 12954.85
+1729 12107.76
+5121 150304.57
+call p(10+20);
+select o_orderkey, o_totalprice from orders where o_orderDATE between '1992-01-01' and '1992-06-30' and
+o_custkey in (select c_custkey from customer
+where c_nationkey in (select n_nationkey from nation
+where n_name='PERU'));
+o_orderkey o_totalprice
+644 201268.06
+2880 145761.99
+3142 16030.15
+5382 138423.03
+5095 184583.99
+737 12984.85
+1729 12137.76
+5121 150334.57
+drop procedure p;
+# FirstMatch SP
+# =============
+create procedure p(d int)
+update customer set c_acctbal = c_acctbal+d where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.1799999999998
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+call p(5);
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9566.95
+Customer#000000019 8919.71
+Customer#000000022 596.98
+Customer#000000025 7138.7
+Customer#000000028 1012.1799999999998
+Customer#000000037 -912.75
+Customer#000000040 1340.3
+Customer#000000047 279.58
+Customer#000000059 3463.6
+Customer#000000061 1541.24
+Customer#000000064 -641.64
+Customer#000000067 8171.59
+Customer#000000082 9473.34
+Customer#000000091 4648.14
+Customer#000000094 5505.11
+Customer#000000097 2169.48
+Customer#000000101 7475.96
+Customer#000000103 2762.45
+Customer#000000106 3293.42
+Customer#000000115 7513.92
+Customer#000000121 6433.32
+Customer#000000122 7870.46
+Customer#000000127 9285.71
+Customer#000000130 5078.58
+Customer#000000133 2319.67
+Customer#000000139 7902.78
+call p(15);
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9581.95
+Customer#000000019 8934.71
+Customer#000000022 611.98
+Customer#000000025 7153.7
+Customer#000000028 1027.1799999999998
+Customer#000000037 -897.75
+Customer#000000040 1355.3
+Customer#000000047 294.58
+Customer#000000059 3478.6
+Customer#000000061 1556.24
+Customer#000000064 -626.64
+Customer#000000067 8186.59
+Customer#000000082 9488.34
+Customer#000000091 4663.14
+Customer#000000094 5520.11
+Customer#000000097 2184.48
+Customer#000000101 7490.96
+Customer#000000103 2777.45
+Customer#000000106 3308.42
+Customer#000000115 7528.92
+Customer#000000121 6448.32
+Customer#000000122 7885.46
+Customer#000000127 9300.71
+Customer#000000130 5093.58
+Customer#000000133 2334.67
+Customer#000000139 7917.78
+call p(-(5+15));
+select c_name, c_acctbal from customer where c_nationkey in (select n_nationkey from nation
+where n_regionkey in (1,2))
+and
+c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-10-09' and '1993-03-08');
+c_name c_acctbal
+Customer#000000007 9561.95
+Customer#000000019 8914.71
+Customer#000000022 591.98
+Customer#000000025 7133.7
+Customer#000000028 1007.1799999999998
+Customer#000000037 -917.75
+Customer#000000040 1335.3
+Customer#000000047 274.58
+Customer#000000059 3458.6
+Customer#000000061 1536.24
+Customer#000000064 -646.64
+Customer#000000067 8166.59
+Customer#000000082 9468.34
+Customer#000000091 4643.14
+Customer#000000094 5500.11
+Customer#000000097 2164.48
+Customer#000000101 7470.96
+Customer#000000103 2757.45
+Customer#000000106 3288.42
+Customer#000000115 7508.92
+Customer#000000121 6428.32
+Customer#000000122 7865.46
+Customer#000000127 9280.71
+Customer#000000130 5073.58
+Customer#000000133 2314.67
+Customer#000000139 7897.78
+drop procedure p;
+# Materialization SP
+# ==================
+create procedure p(d int)
+update customer set c_acctbal = c_acctbal+d where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7133.7
+Customer#000000013 3857.34
+Customer#000000065 8795.16
+Customer#000000032 3471.53
+Customer#000000023 3332.02
+Customer#000000035 1228.24
+Customer#000000091 4643.14
+Customer#000000016 4681.03
+Customer#000000098 -551.37
+Customer#000000037 -917.75
+Customer#000000136 -842.39
+Customer#000000118 3582.37
+Customer#000000022 591.98
+Customer#000000005 794.47
+Customer#000000109 -716.1
+Customer#000000038 6345.11
+Customer#000000076 5745.33
+Customer#000000056 6530.86
+Customer#000000040 1335.3
+Customer#000000116 8403.99
+Customer#000000115 7508.92
+Customer#000000140 9963.15
+Customer#000000017 6.34
+Customer#000000052 5630.28
+call p(3);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7136.7
+Customer#000000013 3860.34
+Customer#000000065 8798.16
+Customer#000000032 3474.53
+Customer#000000023 3335.02
+Customer#000000035 1231.24
+Customer#000000091 4646.14
+Customer#000000016 4684.03
+Customer#000000098 -548.37
+Customer#000000037 -914.75
+Customer#000000136 -839.39
+Customer#000000118 3585.37
+Customer#000000022 594.98
+Customer#000000005 797.47
+Customer#000000109 -713.1
+Customer#000000038 6348.11
+Customer#000000076 5748.33
+Customer#000000056 6533.86
+Customer#000000040 1338.3
+Customer#000000116 8406.99
+Customer#000000115 7511.92
+Customer#000000140 9966.15
+Customer#000000017 9.34
+Customer#000000052 5633.28
+call p(7);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7143.7
+Customer#000000013 3867.34
+Customer#000000065 8805.16
+Customer#000000032 3481.53
+Customer#000000023 3342.02
+Customer#000000035 1238.24
+Customer#000000091 4653.14
+Customer#000000016 4691.03
+Customer#000000098 -541.37
+Customer#000000037 -907.75
+Customer#000000136 -832.39
+Customer#000000118 3592.37
+Customer#000000022 601.98
+Customer#000000005 804.47
+Customer#000000109 -706.1
+Customer#000000038 6355.11
+Customer#000000076 5755.33
+Customer#000000056 6540.86
+Customer#000000040 1345.3
+Customer#000000116 8413.99
+Customer#000000115 7518.92
+Customer#000000140 9973.15
+Customer#000000017 16.34
+Customer#000000052 5640.28
+call p(-(3+7));
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08');
+c_name c_acctbal
+Customer#000000025 7133.7
+Customer#000000013 3857.34
+Customer#000000065 8795.16
+Customer#000000032 3471.53
+Customer#000000023 3332.02
+Customer#000000035 1228.24
+Customer#000000091 4643.14
+Customer#000000016 4681.03
+Customer#000000098 -551.37
+Customer#000000037 -917.75
+Customer#000000136 -842.39
+Customer#000000118 3582.37
+Customer#000000022 591.98
+Customer#000000005 794.47
+Customer#000000109 -716.1
+Customer#000000038 6345.11
+Customer#000000076 5745.33
+Customer#000000056 6530.86
+Customer#000000040 1335.3
+Customer#000000116 8403.99
+Customer#000000115 7508.92
+Customer#000000140 9963.15
+Customer#000000017 6.34
+Customer#000000052 5630.28
+drop procedure p;
+# Materialization SJM SP
+# ======================
+create procedure p(d int)
+update customer set c_acctbal = c_acctbal+d where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000118 3582.37
+Customer#000000056 6530.86
+call p(-1);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3856.34
+Customer#000000032 3470.53
+Customer#000000037 -918.75
+Customer#000000118 3581.37
+Customer#000000056 6529.86
+call p(-2);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3854.34
+Customer#000000032 3468.53
+Customer#000000037 -920.75
+Customer#000000118 3579.37
+Customer#000000056 6527.86
+call p(1+2);
+select c_name, c_acctbal from customer where c_custkey in (select o_custkey from orders
+where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+c_name c_acctbal
+Customer#000000013 3857.34
+Customer#000000032 3471.53
+Customer#000000037 -917.75
+Customer#000000118 3582.37
+Customer#000000056 6530.86
+drop procedure p;
+DROP DATABASE dbt3_s001;
diff --git a/mysql-test/main/update_single_to_multi.test b/mysql-test/main/update_single_to_multi.test
new file mode 100644
index 0000000..f018365
--- /dev/null
+++ b/mysql-test/main/update_single_to_multi.test
@@ -0,0 +1,511 @@
+--disable_warnings
+DROP DATABASE IF EXISTS dbt3_s001;
+--enable_warnings
+
+CREATE DATABASE dbt3_s001;
+
+use dbt3_s001;
+
+--disable_query_log
+--disable_result_log
+--disable_warnings
+--source include/dbt3_s001.inc
+--enable_warnings
+--enable_result_log
+--enable_query_log
+
+create index i_n_name on nation(n_name);
+analyze table nation;
+
+
+--echo # Pullout
+--echo # =======
+
+let $c1=
+ o_orderDATE between '1992-01-01' and '1992-06-30' and
+ o_custkey in (select c_custkey from customer
+ where c_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+
+eval
+explain
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+explain format=json
+select o_orderkey, o_totalprice from orders where $c1;
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+
+eval
+explain
+update orders set o_totalprice = o_totalprice-50 where $c1;
+eval
+explain format=json
+update orders set o_totalprice = o_totalprice-50 where $c1;
+eval
+update orders set o_totalprice = o_totalprice-50 where $c1;
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+
+eval
+update orders set o_totalprice= o_totalprice+50 where $c1;
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+
+
+let $c2=
+ (ps_partkey, ps_suppkey) in
+ (select p_partkey, s_suppkey from part, supplier
+ where p_retailprice between 901 and 910 and
+ s_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+
+eval
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+
+eval
+explain
+update partsupp set ps_supplycost = ps_supplycost+2 where $c2;
+eval
+update partsupp set ps_supplycost = ps_supplycost+2 where $c2;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+
+eval
+update partsupp set ps_supplycost = ps_supplycost-2 where $c2;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c2;
+
+
+let $c3=
+ ps_partkey in (select p_partkey from part
+ where p_retailprice between 901 and 910) and
+ ps_suppkey in (select s_suppkey from supplier
+ where s_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+eval
+explain
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+
+eval
+explain
+update partsupp set ps_supplycost = ps_supplycost+10 where $c3;
+eval
+update partsupp set ps_supplycost = ps_supplycost+10 where $c3;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+
+eval
+update partsupp set ps_supplycost = ps_supplycost-10 where $c3;
+eval
+select ps_partkey, ps_suppkey, ps_supplycost from partsupp where $c3;
+
+
+let $c4=
+ l_orderkey in (select o_orderkey from orders
+ where o_custkey in
+ (select c_custkey from customer
+ where c_nationkey in
+ (select n_nationkey from nation
+ where n_name='PERU'))
+ and
+ o_orderDATE between '1992-06-30' and '1992-12-31')
+ and
+ (l_partkey, l_suppkey) in
+ (select p_partkey, s_suppkey from part, supplier
+ where p_retailprice between 901 and 1000 and
+ s_nationkey in (select n_nationkey from nation
+ where n_name='PERU'));
+
+eval
+explain
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+eval
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+
+eval
+explain
+update lineitem set l_tax = (l_tax*100+1)/100 where $c4;
+eval
+update lineitem set l_tax = (l_tax*100+1)/100 where $c4;
+eval
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+
+eval
+update lineitem set l_tax = (l_tax*100-1)/100 where $c4;
+eval
+select l_orderkey, l_linenumber, l_tax from lineitem where $c4;
+
+
+--echo # FirstMatch
+--echo # ==========
+
+let $c5=
+ c_nationkey in (select n_nationkey from nation
+ where n_regionkey in (1,2))
+ and
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-10-09' and '1993-03-08');
+
+eval
+explain
+select c_name, c_acctbal from customer where $c5;
+eval
+explain format=json
+select c_name, c_acctbal from customer where $c5;
+eval
+select c_name, c_acctbal from customer where $c5;
+
+eval
+explain
+update customer set c_acctbal = c_acctbal+10 where $c5;
+eval
+explain format=json
+update customer set c_acctbal = c_acctbal+10 where $c5;
+eval
+update customer set c_acctbal = c_acctbal+10 where $c5;
+eval
+select c_name, c_acctbal from customer where $c5;
+
+eval
+update customer set c_acctbal = c_acctbal-10 where $c5;
+eval
+select c_name, c_acctbal from customer where $c5;
+
+
+let $c6=
+ c_nationkey in (select n_nationkey from nation where n_name='PERU')
+ and
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between "1992-01-09" and "1993-01-08");
+
+eval
+explain
+select c_name, c_acctbal from customer where $c6;
+eval
+select c_name, c_acctbal from customer where $c6;
+
+eval
+explain
+update customer set c_acctbal = c_acctbal+20 where $c6;
+eval
+update customer set c_acctbal = c_acctbal+20 where $c6;
+eval
+select c_name, c_acctbal from customer where $c6;
+
+eval
+update customer set c_acctbal = c_acctbal-20 where $c6;
+eval
+select c_name, c_acctbal from customer where $c6;
+
+
+--echo # Materialization
+--echo # ===============
+
+let $c7=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-01-09' and '1992-03-08');
+
+eval
+explain
+select c_name, c_acctbal from customer where $c7;
+eval
+explain format=json
+select c_name, c_acctbal from customer where $c7;
+eval
+select c_name, c_acctbal from customer where $c7;
+
+eval
+explain
+update customer set c_acctbal = c_acctbal+5 where $c7;
+eval
+explain format=json
+update customer set c_acctbal = c_acctbal+5 where $c7;
+eval
+update customer set c_acctbal = c_acctbal+5 where $c7;
+eval
+select c_name, c_acctbal from customer where $c7;
+
+eval
+update customer set c_acctbal = c_acctbal-5 where $c7;
+eval
+select c_name, c_acctbal from customer where $c7;
+
+
+let $c8=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-06-09' and '1993-01-08');
+
+eval
+explain
+select c_name, c_acctbal from customer where $c8;
+eval
+select c_name, c_acctbal from customer where $c8;
+
+eval
+explain
+update customer set c_acctbal = c_acctbal+1 where $c8;
+eval
+update customer set c_acctbal = c_acctbal+1 where $c8;
+eval
+select c_name, c_acctbal from customer where $c8;
+
+eval
+update customer set c_acctbal = c_acctbal-1 where $c8;
+eval
+select c_name, c_acctbal from customer where $c8;
+
+
+--echo # Materialization SJM
+--echo # ===================
+
+let $c9=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-01-09' and '1992-03-08'
+ group by o_custkey having count(o_custkey) > 1);
+
+eval
+explain
+select c_name, c_acctbal from customer where $c9;
+eval
+explain format=json
+select c_name, c_acctbal from customer where $c9;
+eval
+select c_name, c_acctbal from customer where $c9;
+
+eval
+explain
+update customer set c_acctbal = c_acctbal-5 where $c9;
+eval
+explain format=json
+update customer set c_acctbal = c_acctbal-5 where $c9;
+eval
+update customer set c_acctbal = c_acctbal-5 where $c9;
+eval
+select c_name, c_acctbal from customer where $c9;
+
+eval
+update customer set c_acctbal = c_acctbal+5 where $c9;
+eval
+select c_name, c_acctbal from customer where $c9;
+
+
+let $c10=
+ c_custkey in (select o_custkey from orders
+ where o_orderDATE between '1992-01-09' and '1993-03-08'
+ group by o_custkey having count(o_custkey) > 5);
+
+eval
+explain
+select c_name, c_acctbal from customer where $c10;
+eval
+select c_name, c_acctbal from customer where $c10;
+
+eval
+explain
+update customer set c_acctbal = c_acctbal-1 where $c10;
+eval
+update customer set c_acctbal = c_acctbal-1 where $c10;
+eval
+select c_name, c_acctbal from customer where $c10;
+
+eval
+update customer set c_acctbal = c_acctbal+1 where $c10;
+eval
+select c_name, c_acctbal from customer where $c10;
+
+
+--echo # Pullout PS
+--echo # ==========
+
+eval
+prepare stmt from "
+update orders set o_totalprice = o_totalprice+? where $c1;
+";
+
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+set @a1=-20;
+execute stmt using @a1;
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+set @a2=-10;
+execute stmt using @a2;
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+execute stmt using -(@a1+@a2);
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+
+deallocate prepare stmt;
+
+
+--echo # FirstMatch PS
+--echo # =============
+
+eval
+prepare stmt from "
+update customer set c_acctbal = c_acctbal+? where $c5;
+";
+
+eval
+select c_name, c_acctbal from customer where $c5;
+set @a1=15;
+execute stmt using @a1;
+eval
+select c_name, c_acctbal from customer where $c5;
+set @a2=5;
+execute stmt using @a2;
+eval
+select c_name, c_acctbal from customer where $c5;
+execute stmt using -(@a1+@a2);
+eval
+select c_name, c_acctbal from customer where $c5;
+
+deallocate prepare stmt;
+
+
+--echo # Materialization PS
+--echo # ==================
+
+eval
+prepare stmt from "
+update customer set c_acctbal = c_acctbal+? where $c7;
+";
+
+eval
+select c_name, c_acctbal from customer where $c7;
+set @a1=7;
+execute stmt using @a1;
+eval
+select c_name, c_acctbal from customer where $c7;
+set @a2=3;
+execute stmt using @a2;
+eval
+select c_name, c_acctbal from customer where $c7;
+execute stmt using -(@a1+@a2);
+eval
+select c_name, c_acctbal from customer where $c7;
+
+deallocate prepare stmt;
+
+
+--echo # Materialization SJM PS
+--echo # ======================
+
+eval
+prepare stmt from "
+update customer set c_acctbal = c_acctbal+? where $c9;
+";
+
+eval
+select c_name, c_acctbal from customer where $c9;
+set @a1=-2;
+execute stmt using @a1;
+eval
+select c_name, c_acctbal from customer where $c9;
+set @a2=-1;
+execute stmt using @a2;
+eval
+select c_name, c_acctbal from customer where $c9;
+execute stmt using -(@a1+@a2);
+eval
+select c_name, c_acctbal from customer where $c9;
+
+deallocate prepare stmt;
+
+
+--echo # Pullout SP
+--echo # ==========
+
+eval
+create procedure p(d int)
+update orders set o_totalprice = o_totalprice+d where $c1;
+
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+call p(-10);
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+call p(-20);
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+call p(10+20);
+eval
+select o_orderkey, o_totalprice from orders where $c1;
+
+drop procedure p;
+
+
+--echo # FirstMatch SP
+--echo # =============
+
+eval
+create procedure p(d int)
+update customer set c_acctbal = c_acctbal+d where $c5;
+
+eval
+select c_name, c_acctbal from customer where $c5;
+call p(5);
+eval
+select c_name, c_acctbal from customer where $c5;
+call p(15);
+eval
+select c_name, c_acctbal from customer where $c5;
+call p(-(5+15));
+eval
+select c_name, c_acctbal from customer where $c5;
+
+drop procedure p;
+
+
+--echo # Materialization SP
+--echo # ==================
+
+eval
+create procedure p(d int)
+update customer set c_acctbal = c_acctbal+d where $c7;
+
+eval
+select c_name, c_acctbal from customer where $c7;
+call p(3);
+eval
+select c_name, c_acctbal from customer where $c7;
+call p(7);
+eval
+select c_name, c_acctbal from customer where $c7;
+call p(-(3+7));
+eval
+select c_name, c_acctbal from customer where $c7;
+
+drop procedure p;
+
+
+--echo # Materialization SJM SP
+--echo # ======================
+
+eval
+create procedure p(d int)
+update customer set c_acctbal = c_acctbal+d where $c9;
+
+eval
+select c_name, c_acctbal from customer where $c9;
+call p(-1);
+eval
+select c_name, c_acctbal from customer where $c9;
+call p(-2);
+eval
+select c_name, c_acctbal from customer where $c9;
+call p(1+2);
+eval
+select c_name, c_acctbal from customer where $c9;
+
+drop procedure p;
+
+
+DROP DATABASE dbt3_s001;
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index fa338f0..96bdaf3 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -675,9 +675,8 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
3. Subquery does not have GROUP BY or ORDER BY
4. Subquery does not use aggregate functions or HAVING
5. Subquery predicate is at the AND-top-level of ON/WHERE clause
- 6. We are not in a subquery of a single table UPDATE/DELETE that
- doesn't have a JOIN (TODO: We should handle this at some
- point by switching to multi-table UPDATE/DELETE)
+ 6. We are not in a top level subquery of a single table DELETE
+ with RETURNING
7. We're not in a table-less subquery like "SELECT 1"
8. No execution method was already chosen (by a prepared statement)
9. Parent select is not a table-less select
@@ -692,9 +691,9 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
!select_lex->group_list.elements && !join->order && // 3
!join->having && !select_lex->with_sum_func && // 4
in_subs->emb_on_expr_nest && // 5
- select_lex->outer_select()->join && // 6
- (!thd->lex->m_sql_cmd ||
- thd->lex->m_sql_cmd->sql_command_code() == SQLCOM_UPDATE_MULTI) &&
+ !(thd->lex->sql_command == SQLCOM_DELETE && // 6
+ thd->lex->has_returning() && // 6
+ !select_lex->outer_select()->outer_select()) && // 6
parent_unit->first_select()->leaf_tables.elements && // 7
!in_subs->has_strategy() && // 8
select_lex->outer_select()->table_list.first && // 9
@@ -7260,3 +7259,23 @@ bool TABLE_LIST::is_sjm_scan_table()
{
return is_active_sjm() && sj_mat_info->is_sj_scan;
}
+
+
+bool SELECT_LEX::is_sj_subselect_lifted_to_top()
+{
+ st_select_lex *sl= this;
+ st_select_lex *outer_sl= outer_select();
+ for ( ; outer_sl; sl= outer_sl, outer_sl= outer_sl->outer_select())
+ {
+ List_iterator_fast<Item_in_subselect> it(outer_sl->sj_subselects);
+ Item_in_subselect *in_subs;
+ while ((in_subs= it++))
+ {
+ if (in_subs->unit->first_select() == sl)
+ break;
+ }
+ if (!in_subs)
+ return false;
+ }
+ return true;
+}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 167df5b..3a2704f 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -7005,6 +7005,7 @@ class multi_delete :public select_result_interceptor
// Methods used by ColumnStore
uint get_num_of_tables() const { return num_of_tables; }
TABLE_LIST* get_tables() const { return delete_tables; }
+ void set_delete_tables (TABLE_LIST *tbl) { delete_tables= tbl; }
public:
multi_delete(THD *thd_arg, TABLE_LIST *dt, uint num_of_tables);
~multi_delete();
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 2ff4331..52efab3 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -1591,10 +1591,19 @@ bool Sql_cmd_delete::prepare_inner(THD *thd)
select_lex->order_list.first,
false, NULL, NULL, NULL,
select_lex, &lex->unit)))
-
{
goto err;
}
+
+ if (!multitable &&
+ select_lex->sj_subselects.elements &&
+ !select_lex->order_list.elements &&
+ select_lex->master_unit()->lim.get_select_limit() == HA_POS_ERROR &&
+ !thd->lex->has_returning())
+ multitable= true;
+
+ if (!multitable)
+ ((multi_delete *)result)->set_delete_tables(0);
}
if (multitable)
@@ -1638,7 +1647,8 @@ bool Sql_cmd_delete::prepare_inner(THD *thd)
{
TABLE_LIST *duplicate;
if ((duplicate= unique_table(thd, target_tbl->correspondent_table,
- lex->query_tables, 0)))
+ lex->query_tables, 0)) &&
+ !duplicate->select_lex->is_sj_subselect_lifted_to_top())
{
update_non_unique_table_error(target_tbl->correspondent_table,
"DELETE", duplicate);
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 0badc32..582ca53 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -1642,6 +1642,7 @@ class st_select_lex: public st_select_lex_node
void lex_start(LEX *plex);
bool is_unit_nest() { return (nest_flags & UNIT_NEST_FL); }
void mark_as_unit_nest() { nest_flags= UNIT_NEST_FL; }
+ bool is_sj_subselect_lifted_to_top();
};
typedef class st_select_lex SELECT_LEX;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index bf49d69..a7e5bc7 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -5834,8 +5834,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
s->needed_reg=select->needed_reg;
select->quick=0;
impossible_range= records == 0 && s->table->reginfo.impossible_range;
- if (join->thd->lex->sql_command == SQLCOM_SELECT &&
- optimizer_flag(join->thd, OPTIMIZER_SWITCH_USE_ROWID_FILTER))
+ if (optimizer_flag(join->thd, OPTIMIZER_SWITCH_USE_ROWID_FILTER))
s->table->init_cost_info_for_usable_range_rowid_filters(join->thd);
}
if (!impossible_range)
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 6b14c4f..b614291 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -2471,6 +2471,8 @@ int multi_update::do_updates()
table = cur_table->table;
if (table == table_to_update)
continue; // Already updated
+ if (table->file->pushed_rowid_filter)
+ table->file->disable_pushed_rowid_filter();
org_updated= updated;
tmp_table= tmp_tables[cur_table->shared];
tmp_table->file->extra(HA_EXTRA_CACHE); // Change to read cache
@@ -2665,7 +2667,8 @@ int multi_update::do_updates()
check_opt_it.rewind();
while (TABLE *tbl= check_opt_it++)
tbl->file->ha_rnd_end();
-
+ if (table->file->save_pushed_rowid_filter)
+ table->file->enable_pushed_rowid_filter();
}
DBUG_RETURN(0);
@@ -2676,6 +2679,8 @@ int multi_update::do_updates()
}
err2:
+ if (table->file->save_pushed_rowid_filter)
+ table->file->enable_pushed_rowid_filter();
if (table->file->inited)
(void) table->file->ha_rnd_end();
if (tmp_table->file->inited)
@@ -2956,6 +2961,11 @@ bool Sql_cmd_update::prepare_inner(THD *thd)
goto err;
}
+ if (!multitable &&
+ select_lex->sj_subselects.elements &&
+ !select_lex->order_list.elements &&
+ select_lex->master_unit()->lim.get_select_limit() == HA_POS_ERROR)
+ multitable= true;
}
if (table_list->has_period())
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index a587a37..13dc602 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -13370,8 +13370,21 @@ delete_single_table:
YYPS->m_lock_type,
YYPS->m_mdl_type,
NULL,
+ 0)))
+ MYSQL_YYABORT;
+ Select->table_list.save_and_clear(&Lex->auxiliary_table_list);
+ Lex->table_count= 1;
+ Lex->query_tables= 0;
+ Lex->query_tables_last= &Lex->query_tables;
+ if (unlikely(!Select->
+ add_table_to_list(thd, $2, NULL, TL_OPTION_UPDATING,
+ YYPS->m_lock_type,
+ YYPS->m_mdl_type,
+ NULL,
$3)))
MYSQL_YYABORT;
+ Lex->auxiliary_table_list.first->correspondent_table=
+ Lex->query_tables;
YYPS->m_lock_type= TL_READ_DEFAULT;
YYPS->m_mdl_type= MDL_SHARED_READ;
}
1
0
[Commits] 596cde0: MDEV-28883 Re-design the upper level of handling UPDATE and DELETE statements
by IgorBabaev 19 Jun '22
by IgorBabaev 19 Jun '22
19 Jun '22
revision-id: 596cde07f17c490c43db10ce0a8cbb7bd4dbf5ae (mariadb-10.6.1-471-g596cde0)
parent(s): d371e35257c45895318c4efbed20e5bfdcc7cee9
author: Igor Babaev
committer: Igor Babaev
timestamp: 2022-06-18 16:28:48 -0700
message:
MDEV-28883 Re-design the upper level of handling UPDATE and DELETE statements
This patch introduces a new way of handling UPDATE and DELETE commands at
the top level after the parsing phase. This new way of processing update
and delete statements can be seen in the implementation of the prepare()
and execute() methods from the new Sql_cmd_dml class. This class derived
from the Sql_cmd class can be considered as an interface class for processing
such commands as SELECT, INSERT, UPDATE, DELETE and other comands
manipulating data in tables.
With this patch processing of update and delete statements after parsing
proceeds by the following schema:
- precheck of the access rights is performed for the used tables
- the used tables are opened
- context analysis phase is performed for the statement
- the used tables are locked
- the statement is optimized and executed
- clean-up is performed for the statement
The implementation of the method Sql_cmd_dml::execute() adheres this schema.
The virtual functions of the class Sql_cmd_dml used for precheck of the
access rights, context analysis, optimization and execution allow to adjust
this schema for processing data manipulation statements of any types.
This schema of processing data manipulation statements is taken from the
current MySQL code. Moreover the definition the class Sql_cmd_dml introduced
in this patch is almost a full replica of such class in the existing MySQL.
However the implementation of the derived classes for update and delete
statements is quite different. This implementation employs the JOIN class
for all kinds of update and delete statements. It allows to perform main
bulk of context analysis actions by the function JOIN::prepare(). This
guarantees that characteristics and properties of the statement tree
discovered for optimization phase when doing context analysis are the same
for single-table and multi-table updates and deletes.
With this patch the following functions are gone:
mysql_prepare_update(), mysql_multi_update_prepare(),
mysql_update(), mysql_multi_update(),
mysql_prepare_delete(), mysql_multi_delete_prepare(), mysql_delete().
The code within these functions have been used as much as possible though.
The functions mysql_test_update() and mysql_test_delete() are also not
needed anymore. The method Sql_cmd_dml::prepare() serves processing
- update/delete statement
- PREPARE stmt FROM "<update/delete statement>"
- EXECUTE stmt when stmt is prepared from update/delete statement.
Approved by Oleksandr Byelkin <sanja(a)mariadb.com>
---
mysql-test/main/analyze_stmt_privileges2.result | 9 +-
mysql-test/main/analyze_stmt_privileges2.test | 15 +-
.../main/myisam_explain_non_select_all.result | 9 +-
mysql-test/main/opt_trace.result | 14 +-
mysql-test/main/opt_trace_security.result | 5 -
mysql-test/main/opt_trace_security.test | 6 +-
mysql-test/main/order_by.result | 8 +-
mysql-test/main/update.result | 2 +-
mysql-test/main/update_use_source.result | 7 +-
mysql-test/main/update_use_source.test | 2 +-
mysql-test/main/view_grant.result | 1 +
mysql-test/main/view_grant.test | 1 +
mysql-test/suite/funcs_1/r/is_collations.result | 2 +-
mysql-test/suite/funcs_1/t/is_collations.test | 2 +-
mysql-test/suite/period/r/update.result | 2 +-
mysql-test/suite/period/t/update.test | 2 +-
sql/ha_partition.cc | 6 +-
sql/handler.h | 5 +-
sql/opt_range.cc | 2 +-
sql/opt_subselect.cc | 2 +
sql/opt_trace.cc | 3 +-
sql/sql_base.cc | 34 +-
sql/sql_base.h | 15 +
sql/sql_class.h | 3 +
sql/sql_cmd.h | 206 ++++++-
sql/sql_delete.cc | 629 +++++++++++--------
sql/sql_delete.h | 69 ++-
sql/sql_lex.cc | 39 +-
sql/sql_lex.h | 26 +
sql/sql_parse.cc | 261 +-------
sql/sql_parse.h | 1 +
sql/sql_prepare.cc | 245 +-------
sql/sql_select.cc | 267 +++++++-
sql/sql_update.cc | 669 +++++++++------------
sql/sql_update.h | 81 ++-
sql/sql_yacc.yy | 85 ++-
sql/table.h | 1 +
.../mysql-test/spider/r/error_row_number.result | 2 +-
38 files changed, 1452 insertions(+), 1286 deletions(-)
diff --git a/mysql-test/main/analyze_stmt_privileges2.result b/mysql-test/main/analyze_stmt_privileges2.result
index f269aaf..d40dd63 100644
--- a/mysql-test/main/analyze_stmt_privileges2.result
+++ b/mysql-test/main/analyze_stmt_privileges2.result
@@ -3034,6 +3034,7 @@ ERROR HY000: ANALYZE/EXPLAIN/SHOW can not be issued; lacking privileges for unde
ANALYZE UPDATE v1 SET a = 10;
ERROR HY000: ANALYZE/EXPLAIN/SHOW can not be issued; lacking privileges for underlying table
UPDATE v1 SET a = a + 1;
+ERROR 42000: SELECT command denied to user 'privtest'@'localhost' for column 'a' in table 'v1'
EXPLAIN UPDATE v1 SET a = a + 1;
ERROR HY000: ANALYZE/EXPLAIN/SHOW can not be issued; lacking privileges for underlying table
ANALYZE UPDATE v1 SET a = a + 1;
@@ -4767,6 +4768,7 @@ ERROR HY000: ANALYZE/EXPLAIN/SHOW can not be issued; lacking privileges for unde
ANALYZE UPDATE v2 SET a = 10;
ERROR HY000: ANALYZE/EXPLAIN/SHOW can not be issued; lacking privileges for underlying table
UPDATE v2 SET a = a + 1;
+ERROR 42000: SELECT command denied to user 'privtest'@'localhost' for column 'a' in table 'v2'
EXPLAIN UPDATE v2 SET a = a + 1;
ERROR HY000: ANALYZE/EXPLAIN/SHOW can not be issued; lacking privileges for underlying table
ANALYZE UPDATE v2 SET a = a + 1;
@@ -4865,12 +4867,11 @@ ANALYZE UPDATE v2 SET a = 10;
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 43 43.00 100.00 6.98 Using where
UPDATE v2 SET a = a + 1;
+ERROR 42000: SELECT command denied to user 'privtest'@'localhost' for column 'a' in table 'v2'
EXPLAIN UPDATE v2 SET a = a + 1;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ALL NULL NULL NULL NULL 43 Using where
+ERROR 42000: SELECT command denied to user 'privtest'@'localhost' for column 'a' in table 'v2'
ANALYZE UPDATE v2 SET a = a + 1;
-id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 SIMPLE t1 ALL NULL NULL NULL NULL 43 43.00 100.00 6.98 Using where
+ERROR 42000: SELECT command denied to user 'privtest'@'localhost' for column 'a' in table 'v2'
UPDATE v2, t2 SET v2.a = v2.a + 1 WHERE v2.a = t2.a;
ERROR 42000: SELECT command denied to user 'privtest'@'localhost' for column 'a' in table 'v2'
EXPLAIN UPDATE v2, t2 SET v2.a = v2.a + 1 WHERE v2.a = t2.a;
diff --git a/mysql-test/main/analyze_stmt_privileges2.test b/mysql-test/main/analyze_stmt_privileges2.test
index a0f1f49..8b011c2 100644
--- a/mysql-test/main/analyze_stmt_privileges2.test
+++ b/mysql-test/main/analyze_stmt_privileges2.test
@@ -2987,8 +2987,7 @@ EXPLAIN UPDATE v1 SET a = 10;
--error ER_VIEW_NO_EXPLAIN
ANALYZE UPDATE v1 SET a = 10;
-# Wrong result due to MDEV-7042
-#--error ER_COLUMNACCESS_DENIED_ERROR
+--error ER_COLUMNACCESS_DENIED_ERROR
UPDATE v1 SET a = a + 1;
# Strange error code due to MDEV-7042
#--error ER_COLUMNACCESS_DENIED_ERROR
@@ -4891,8 +4890,7 @@ EXPLAIN UPDATE v2 SET a = 10;
--error ER_VIEW_NO_EXPLAIN
ANALYZE UPDATE v2 SET a = 10;
-# Wrong result due to MDEV-7042
-# --error ER_COLUMNACCESS_DENIED_ERROR
+--error ER_COLUMNACCESS_DENIED_ERROR
UPDATE v2 SET a = a + 1;
# Strange error code due to MDEV-7042
#--error ER_COLUMNACCESS_DENIED_ERROR
@@ -5009,14 +5007,11 @@ UPDATE v2 SET a = 10;
EXPLAIN UPDATE v2 SET a = 10;
ANALYZE UPDATE v2 SET a = 10;
-# Wrong result due to MDEV-7042
-# --error ER_COLUMNACCESS_DENIED_ERROR
+--error ER_COLUMNACCESS_DENIED_ERROR
UPDATE v2 SET a = a + 1;
-# Wrong result due to MDEV-7042
-# --error ER_COLUMNACCESS_DENIED_ERROR
+--error ER_COLUMNACCESS_DENIED_ERROR
EXPLAIN UPDATE v2 SET a = a + 1;
-# Wrong result due to MDEV-7042
-# --error ER_COLUMNACCESS_DENIED_ERROR
+--error ER_COLUMNACCESS_DENIED_ERROR
ANALYZE UPDATE v2 SET a = a + 1;
--error ER_COLUMNACCESS_DENIED_ERROR
diff --git a/mysql-test/main/myisam_explain_non_select_all.result b/mysql-test/main/myisam_explain_non_select_all.result
index 2ff966f..20b769b 100644
--- a/mysql-test/main/myisam_explain_non_select_all.result
+++ b/mysql-test/main/myisam_explain_non_select_all.result
@@ -240,18 +240,17 @@ Warnings:
Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
EXPLAIN UPDATE t1 SET a = 10 WHERE 1 IN (SELECT 1 FROM t2 WHERE t2.b < 3);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 Using where
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED UPDATE t1 SET a = 10 WHERE 1 IN (SELECT 1 FROM t2 WHERE t2.b < 3);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where
# Status of EXPLAIN EXTENDED query
Variable_name Value
Handler_read_key 4
-Handler_read_rnd_next 1
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1 IN (SELECT 1 FROM t2 WHERE t2.b < 3);
@@ -2723,9 +2722,9 @@ DROP TABLE t1;
#57
CREATE TABLE t1(f1 INT);
EXPLAIN EXTENDED UPDATE t1 SET f2=1 ORDER BY f2;
-ERROR 42S22: Unknown column 'f2' in 'order clause'
+ERROR 42S22: Unknown column 'f2' in 'field list'
UPDATE t1 SET f2=1 ORDER BY f2;
-ERROR 42S22: Unknown column 'f2' in 'order clause'
+ERROR 42S22: Unknown column 'f2' in 'field list'
DROP TABLE t1;
#62
CREATE TABLE t1 (a INT);
diff --git a/mysql-test/main/opt_trace.result b/mysql-test/main/opt_trace.result
index 6f0d134..0555f72 100644
--- a/mysql-test/main/opt_trace.result
+++ b/mysql-test/main/opt_trace.result
@@ -3743,6 +3743,16 @@ QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
explain delete from t0 where t0.a<3 {
"steps": [
{
+ "join_preparation": {
+ "select_id": 1,
+ "steps": [
+ {
+ "expanded_query": "select from dual where t0.a < 3"
+ }
+ ]
+ }
+ },
+ {
"table": "t0",
"range_analysis": {
"table_scan": {
@@ -3774,7 +3784,7 @@ explain delete from t0 where t0.a<3 {
},
"group_index_range": {
"chosen": false,
- "cause": "no join"
+ "cause": "no group by or distinct"
},
"chosen_range_access_summary": {
"range_access_plan": {
@@ -3817,7 +3827,7 @@ explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3 {
"select_id": 1,
"steps": [
{
- "expanded_query": "select NULL AS `NULL` from t0 join t1 where t0.a = t1.a and t1.a < 3"
+ "expanded_query": "select from t0 join t1 where t0.a = t1.a and t1.a < 3"
}
]
}
diff --git a/mysql-test/main/opt_trace_security.result b/mysql-test/main/opt_trace_security.result
index 83d98c4..32f89ac 100644
--- a/mysql-test/main/opt_trace_security.result
+++ b/mysql-test/main/opt_trace_security.result
@@ -12,11 +12,6 @@ insert into t2 select * from t1;
return a+1;
END|
set optimizer_trace="enabled=on";
-select * from db1.t1;
-ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 't1'
-select * from information_schema.OPTIMIZER_TRACE;
-QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
- 0 1
set optimizer_trace="enabled=off";
grant select(a) on db1.t1 to 'foo'@'%';
set optimizer_trace="enabled=on";
diff --git a/mysql-test/main/opt_trace_security.test b/mysql-test/main/opt_trace_security.test
index 9fa4919..6890b58 100644
--- a/mysql-test/main/opt_trace_security.test
+++ b/mysql-test/main/opt_trace_security.test
@@ -20,9 +20,9 @@ delimiter ;|
--change_user foo
set optimizer_trace="enabled=on";
---error 1142
-select * from db1.t1;
-select * from information_schema.OPTIMIZER_TRACE;
+# --error 1142
+# select * from db1.t1;
+# select * from information_schema.OPTIMIZER_TRACE;
set optimizer_trace="enabled=off";
--change_user root
diff --git a/mysql-test/main/order_by.result b/mysql-test/main/order_by.result
index b6345cd..08cd73c 100644
--- a/mysql-test/main/order_by.result
+++ b/mysql-test/main/order_by.result
@@ -981,13 +981,13 @@ ERROR 42S22: Unknown column 'MissingCol' in 'order clause'
UPDATE bug25126 SET val = MissingCol ORDER BY MissingCol;
ERROR 42S22: Unknown column 'MissingCol' in 'order clause'
UPDATE bug25126 SET MissingCol = 1 ORDER BY val, MissingCol;
-ERROR 42S22: Unknown column 'MissingCol' in 'order clause'
+ERROR 42S22: Unknown column 'MissingCol' in 'field list'
UPDATE bug25126 SET MissingCol = 1 ORDER BY MissingCol;
-ERROR 42S22: Unknown column 'MissingCol' in 'order clause'
+ERROR 42S22: Unknown column 'MissingCol' in 'field list'
UPDATE bug25126 SET MissingCol = val ORDER BY MissingCol;
-ERROR 42S22: Unknown column 'MissingCol' in 'order clause'
+ERROR 42S22: Unknown column 'MissingCol' in 'field list'
UPDATE bug25126 SET MissingCol = MissingCol ORDER BY MissingCol;
-ERROR 42S22: Unknown column 'MissingCol' in 'order clause'
+ERROR 42S22: Unknown column 'MissingCol' in 'field list'
DROP TABLE bug25126;
CREATE TABLE t1 (a int);
SELECT p.a AS val, q.a AS val1 FROM t1 p, t1 q ORDER BY val > 1;
diff --git a/mysql-test/main/update.result b/mysql-test/main/update.result
index f5edf1c..15efd7e 100644
--- a/mysql-test/main/update.result
+++ b/mysql-test/main/update.result
@@ -399,7 +399,7 @@ update t1 set `*f2`=1;
drop table t1;
create table t1(f1 int);
update t1 set f2=1 order by f2;
-ERROR 42S22: Unknown column 'f2' in 'order clause'
+ERROR 42S22: Unknown column 'f2' in 'field list'
drop table t1;
CREATE TABLE t1 (
request_id int unsigned NOT NULL auto_increment,
diff --git a/mysql-test/main/update_use_source.result b/mysql-test/main/update_use_source.result
index 2774e7e..320f5b6 100644
--- a/mysql-test/main/update_use_source.result
+++ b/mysql-test/main/update_use_source.result
@@ -316,7 +316,7 @@ rollback;
#
explain update t1 set c1=0 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 > 3;
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 range t1_c2 t1_c2 5 NULL 2 Using where
+1 PRIMARY t1 range t1_c2 t1_c2 5 NULL 2 Using index condition; Using where
2 DEPENDENT SUBQUERY a ref t1_c2 t1_c2 5 test.t1.c2 4 Using index
start transaction;
update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3;
@@ -557,7 +557,7 @@ rollback;
#
explain update t1 set c1=0 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 > 3;
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 range t1_c2 t1_c2 5 NULL 2 Using where
+1 PRIMARY t1 range t1_c2 t1_c2 5 NULL 2 Using index condition; Using where
2 DEPENDENT SUBQUERY a ref t1_c2 t1_c2 5 test.t1.c2 1 Using index
start transaction;
update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3;
@@ -799,7 +799,7 @@ rollback;
#
explain update t1 set c1=0 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 > 3;
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 range t1_c2 t1_c2 5 NULL 2 Using where
+1 PRIMARY t1 range t1_c2 t1_c2 5 NULL 2 Using index condition; Using where
2 DEPENDENT SUBQUERY a ref t1_c2 t1_c2 5 test.t1.c2 1 Using index
start transaction;
update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3;
@@ -1195,7 +1195,6 @@ create table t1 (c1 integer) engine=InnoDb;
create table t2 (c1 integer) engine=InnoDb;
create view v1 as select t1.c1 as "t1c1" ,t2.c1 as "t2c1" from t1,t2 where t1.c1=t2.c1;
update v1 set t1c1=2 order by 1;
-ERROR 42S22: Unknown column '1' in 'order clause'
update v1 set t1c1=2 limit 1;
drop table t1;
drop table t2;
diff --git a/mysql-test/main/update_use_source.test b/mysql-test/main/update_use_source.test
index d446bd5..8e104a5 100644
--- a/mysql-test/main/update_use_source.test
+++ b/mysql-test/main/update_use_source.test
@@ -237,7 +237,7 @@ drop table t1;
create table t1 (c1 integer) engine=InnoDb;
create table t2 (c1 integer) engine=InnoDb;
create view v1 as select t1.c1 as "t1c1" ,t2.c1 as "t2c1" from t1,t2 where t1.c1=t2.c1;
---error ER_BAD_FIELD_ERROR
+# 'order by 1' should be considered as in 'select * from v1 order 1'
update v1 set t1c1=2 order by 1;
update v1 set t1c1=2 limit 1;
drop table t1;
diff --git a/mysql-test/main/view_grant.result b/mysql-test/main/view_grant.result
index c31ba88..6167c1f 100644
--- a/mysql-test/main/view_grant.result
+++ b/mysql-test/main/view_grant.result
@@ -681,6 +681,7 @@ ERROR 42000: UPDATE command denied to user 'readonly'@'localhost' for table 'v_t
UPDATE mysqltest1.v_ts SET x= 200;
ERROR 42000: UPDATE command denied to user 'readonly'@'localhost' for table 'v_ts'
UPDATE mysqltest1.v_tu SET x= 200 WHERE x = 100;
+ERROR 42000: SELECT command denied to user 'readonly'@'localhost' for column 'x' in table 'v_tu'
UPDATE mysqltest1.v_tus SET x= 200 WHERE x = 100;
UPDATE mysqltest1.v_tu SET x= 200;
DELETE FROM mysqltest1.v_ts WHERE x= 200;
diff --git a/mysql-test/main/view_grant.test b/mysql-test/main/view_grant.test
index 83bbeb3..538342c 100644
--- a/mysql-test/main/view_grant.test
+++ b/mysql-test/main/view_grant.test
@@ -810,6 +810,7 @@ INSERT INTO mysqltest1.v_ti VALUES (100);
UPDATE mysqltest1.v_ts SET x= 200 WHERE x = 100;
--error ER_TABLEACCESS_DENIED_ERROR
UPDATE mysqltest1.v_ts SET x= 200;
+--error ER_COLUMNACCESS_DENIED_ERROR
UPDATE mysqltest1.v_tu SET x= 200 WHERE x = 100;
UPDATE mysqltest1.v_tus SET x= 200 WHERE x = 100;
UPDATE mysqltest1.v_tu SET x= 200;
diff --git a/mysql-test/suite/funcs_1/r/is_collations.result b/mysql-test/suite/funcs_1/r/is_collations.result
index f4054af..013a267 100644
--- a/mysql-test/suite/funcs_1/r/is_collations.result
+++ b/mysql-test/suite/funcs_1/r/is_collations.result
@@ -66,7 +66,7 @@ INSERT INTO information_schema.collations
(collation_name,character_set_name,id,is_default,is_compiled,sortlen)
VALUES ( 'cp1251_bin', 'cp1251',50, '', '',0);
ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema'
-UPDATE information_schema.collations SET description = 'just updated';
+UPDATE information_schema.collations SET collation_name = 'just updated';
Got one of the listed errors
DELETE FROM information_schema.collations WHERE table_name = 't1';
ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema'
diff --git a/mysql-test/suite/funcs_1/t/is_collations.test b/mysql-test/suite/funcs_1/t/is_collations.test
index db34a7b..aa199b5 100644
--- a/mysql-test/suite/funcs_1/t/is_collations.test
+++ b/mysql-test/suite/funcs_1/t/is_collations.test
@@ -83,7 +83,7 @@ INSERT INTO information_schema.collations
VALUES ( 'cp1251_bin', 'cp1251',50, '', '',0);
--error ER_DBACCESS_DENIED_ERROR,ER_NON_UPDATABLE_TABLE
-UPDATE information_schema.collations SET description = 'just updated';
+UPDATE information_schema.collations SET collation_name = 'just updated';
--error ER_DBACCESS_DENIED_ERROR
DELETE FROM information_schema.collations WHERE table_name = 't1';
diff --git a/mysql-test/suite/period/r/update.result b/mysql-test/suite/period/r/update.result
index f726b4c..004b997 100644
--- a/mysql-test/suite/period/r/update.result
+++ b/mysql-test/suite/period/r/update.result
@@ -229,8 +229,8 @@ update t for portion of apptime from @s to g() set t.id= t.id + 5;
ERROR HY000: Expression in FOR PORTION OF must be constant
# success
update t for portion of apptime from @s to h() set t.id= t.id + 5;
-# select value is cached
update t for portion of apptime from (select s from t2 limit 1) to h() set t.id= t.id + 5;
+ERROR HY000: Expression in FOR PORTION OF must be constant
# auto_inrement field is updated
create or replace table t (id int primary key auto_increment, x int,
s date, e date, period for apptime(s, e));
diff --git a/mysql-test/suite/period/t/update.test b/mysql-test/suite/period/t/update.test
index 3f4dd2b..fd67dc3 100644
--- a/mysql-test/suite/period/t/update.test
+++ b/mysql-test/suite/period/t/update.test
@@ -123,7 +123,7 @@ update t for portion of apptime from @s to g() set t.id= t.id + 5;
--echo # success
update t for portion of apptime from @s to h() set t.id= t.id + 5;
---echo # select value is cached
+--error ER_NOT_CONSTANT_EXPRESSION
update t for portion of apptime from (select s from t2 limit 1) to h() set t.id= t.id + 5;
--echo # auto_inrement field is updated
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index e85ce02..22fc115 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -4681,8 +4681,8 @@ int ha_partition::update_row(const uchar *old_data, const uchar *new_data)
part_share->next_auto_inc_val if needed.
(not to be used if auto_increment on secondary field in a multi-column
index)
- mysql_update does not set table->next_number_field, so we use
- table->found_next_number_field instead.
+ Sql_cmd_update::update_single_table() does not set table->next_number_field,
+ so we use table->found_next_number_field instead.
Also checking that the field is marked in the write set.
*/
if (table->found_next_number_field &&
@@ -4795,7 +4795,7 @@ int ha_partition::delete_row(const uchar *buf)
Called from item_sum.cc by Item_func_group_concat::clear(),
Item_sum_count::clear(), and Item_func_group_concat::clear().
- Called from sql_delete.cc by mysql_delete().
+ Called from sql_delete.cc by Sql_cmd_delete::delete_single_table().
Called from sql_select.cc by JOIN::reset().
Called from sql_union.cc by st_select_lex_unit::exec().
*/
diff --git a/sql/handler.h b/sql/handler.h
index 60c6195..efc75d7 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -246,7 +246,7 @@ enum chf_create_flags {
Example:
UPDATE a=1 WHERE pk IN (<keys>)
- mysql_update()
+ Sql_cmd_update::update_single_table()
{
if (<conditions for starting read removal>)
start_read_removal()
@@ -1800,7 +1800,8 @@ struct THD_TRANS
modified non-transactional tables of top-level statements. At
the end of the previous statement and at the beginning of the session,
it is reset to FALSE. If such functions
- as mysql_insert, mysql_update, mysql_delete etc modify a
+ as mysql_insert(), Sql_cmd_update::update_single_table,
+ Sql_cmd_delete::delete_single_table modify a
non-transactional table, they set this flag to TRUE. At the
end of the statement, the value of stmt.modified_non_trans_table
is merged with all.modified_non_trans_table and gets reset.
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 391a04c..f70122f 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -11599,7 +11599,7 @@ ha_rows check_quick_select(PARAM *param, uint idx, bool index_only,
Skip materialized derived table/view result table from MRR check as
they aren't contain any data yet.
*/
- if (param->table->pos_in_table_list->is_non_derived())
+ if (!param->table->pos_in_table_list->is_materialized_derived())
rows= file->multi_range_read_info_const(keynr, &seq_if, (void*)&seq, 0,
bufsize, mrr_flags, cost);
param->quick_rows[keynr]= rows;
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 3e58a27..fa338f0 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -693,6 +693,8 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
!join->having && !select_lex->with_sum_func && // 4
in_subs->emb_on_expr_nest && // 5
select_lex->outer_select()->join && // 6
+ (!thd->lex->m_sql_cmd ||
+ thd->lex->m_sql_cmd->sql_command_code() == SQLCOM_UPDATE_MULTI) &&
parent_unit->first_select()->leaf_tables.elements && // 7
!in_subs->has_strategy() && // 8
select_lex->outer_select()->table_list.first && // 9
diff --git a/sql/opt_trace.cc b/sql/opt_trace.cc
index 4bc4939..33209ff 100644
--- a/sql/opt_trace.cc
+++ b/sql/opt_trace.cc
@@ -491,7 +491,8 @@ void Opt_trace_start::init(THD *thd,
!list_has_optimizer_trace_table(tbl) &&
!sets_var_optimizer_trace(sql_command, set_vars) &&
!thd->system_thread &&
- !ctx->disable_tracing_if_required())
+ !ctx->disable_tracing_if_required() &&
+ !(thd->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_PREPARE))
{
ctx->start(thd, tbl, sql_command, query, query_length, query_charset,
thd->variables.optimizer_trace_max_mem_size);
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 18ffdc9..2b41b78 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1087,7 +1087,11 @@ TABLE_LIST* find_dup_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list,
(table->table equal to 0) and right names is in current TABLE_LIST
object.
*/
- if (table->table)
+ if (table->table &&
+ thd->lex->sql_command != SQLCOM_UPDATE &&
+ thd->lex->sql_command != SQLCOM_UPDATE_MULTI &&
+ thd->lex->sql_command != SQLCOM_DELETE &&
+ thd->lex->sql_command != SQLCOM_DELETE_MULTI)
{
/* All MyISAMMRG children are plain MyISAM tables. */
DBUG_ASSERT(table->table->file->ht->db_type != DB_TYPE_MRG_MYISAM);
@@ -5675,6 +5679,28 @@ bool open_tables_only_view_structure(THD *thd, TABLE_LIST *table_list,
}
+bool open_tables_for_query(THD *thd, TABLE_LIST *tables,
+ uint *table_count, uint flags,
+ DML_prelocking_strategy *prelocking_strategy)
+{
+ MDL_savepoint mdl_savepoint = thd->mdl_context.mdl_savepoint();
+
+ DBUG_ASSERT(tables == thd->lex->query_tables);
+
+ if (open_tables(thd, &tables, table_count,
+ thd->stmt_arena->is_stmt_prepare() ? MYSQL_OPEN_FORCE_SHARED_MDL : 0,
+ prelocking_strategy))
+ {
+ close_thread_tables(thd);
+ /* Don't keep locks for a failed statement. */
+ thd->mdl_context.rollback_to_savepoint(mdl_savepoint);
+ return true;
+ }
+
+ return false;
+}
+
+
/*
Mark all real tables in the list as free for reuse.
@@ -7818,6 +7844,9 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
if (!select_lex->with_wild)
DBUG_RETURN(0);
+ if (!fields.elements)
+ DBUG_RETURN(0);
+
/*
Don't use arena if we are not in prepared statements or stored procedures
For PS/SP we have to use arena to remember the changes
@@ -8120,7 +8149,7 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
while ((table_list= ti++))
{
TABLE *table= table_list->table;
- if (table)
+ if (table && !table->pos_in_table_list)
table->pos_in_table_list= table_list;
if (first_select_table &&
table_list->top_table() == first_select_table)
@@ -8136,7 +8165,6 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
}
else if (table)
{
- table->pos_in_table_list= table_list;
setup_table_map(table, table_list, tablenr);
if (table_list->process_index_hints(table))
diff --git a/sql/sql_base.h b/sql/sql_base.h
index 06d7559..370e0f3 100644
--- a/sql/sql_base.h
+++ b/sql/sql_base.h
@@ -28,6 +28,7 @@ struct Name_resolution_context;
class Open_table_context;
class Open_tables_state;
class Prelocking_strategy;
+class DML_prelocking_strategy;
struct TABLE_LIST;
class THD;
struct handlerton;
@@ -288,6 +289,9 @@ bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags,
bool open_tables_only_view_structure(THD *thd, TABLE_LIST *tables,
bool can_deadlock);
bool open_and_lock_internal_tables(TABLE *table, bool lock);
+bool open_tables_for_query(THD *thd, TABLE_LIST *tables,
+ uint *table_count, uint flags,
+ DML_prelocking_strategy *prelocking_strategy);
bool lock_tables(THD *thd, TABLE_LIST *tables, uint counter, uint flags);
int decide_logging_format(THD *thd, TABLE_LIST *tables);
void close_thread_table(THD *thd, TABLE **table_ptr);
@@ -430,6 +434,17 @@ class DML_prelocking_strategy : public Prelocking_strategy
};
+
+class Multiupdate_prelocking_strategy : public DML_prelocking_strategy
+{
+ bool done;
+ bool has_prelocking_list;
+public:
+ void reset(THD *thd);
+ bool handle_end(THD *thd);
+};
+
+
/**
A strategy for prelocking algorithm to be used for LOCK TABLES
statement.
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 806f77c..167df5b 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -7063,6 +7063,7 @@ class multi_update :public select_result_interceptor
enum_duplicates handle_duplicates, bool ignore);
~multi_update();
bool init(THD *thd);
+ bool init_for_single_table(THD *thd);
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
int send_data(List<Item> &items);
bool initialize_tables (JOIN *join);
@@ -7071,6 +7072,8 @@ class multi_update :public select_result_interceptor
bool send_eof();
inline ha_rows num_found() const { return found; }
inline ha_rows num_updated() const { return updated; }
+ inline void set_found (ha_rows n) { found= n; }
+ inline void set_updated (ha_rows n) { updated= n; }
virtual void abort_result_set();
void update_used_tables();
void prepare_to_read_rows();
diff --git a/sql/sql_cmd.h b/sql/sql_cmd.h
index 1a01caa..9852886 100644
--- a/sql/sql_cmd.h
+++ b/sql/sql_cmd.h
@@ -118,6 +118,7 @@ enum enum_sql_command {
SQLCOM_END
};
+struct TABLE_LIST;
class Storage_engine_name
{
@@ -144,6 +145,8 @@ class Storage_engine_name
};
+class Prepared_statement;
+
/**
@class Sql_cmd - Representation of an SQL command.
@@ -180,10 +183,28 @@ class Sql_cmd : public Sql_alloc
virtual enum_sql_command sql_command_code() const = 0;
/**
- Execute this SQL statement.
- @param thd the current thread.
- @retval false on success.
- @retval true on error
+ @brief Check whether the statement has been prepared
+ @returns true if this statement is prepared, false otherwise
+ */
+ bool is_prepared() const { return m_prepared; }
+
+ /**
+ @brief Prepare this SQL statement
+ @param thd global context the processed statement
+ @returns false if success, true if error
+ */
+ virtual bool prepare(THD *thd)
+ {
+ /* Default behavior for a statement is to have no preparation code. */
+ DBUG_ASSERT(!is_prepared());
+ set_prepared();
+ return false;
+ }
+
+ /**
+ @brief Execute this SQL statement
+ @param thd global context the processed statement
+ @returns false if success, true if error
*/
virtual bool execute(THD *thd) = 0;
@@ -192,8 +213,39 @@ class Sql_cmd : public Sql_alloc
return NULL;
}
+ /**
+ @brief Set the owning prepared statement
+ */
+ void set_owner(Prepared_statement *stmt) { m_owner = stmt; }
+
+ /**
+ @breaf Get the owning prepared statement
+ */
+ Prepared_statement *get_owner() { return m_owner; }
+
+ /**
+ @brief Check whether this command is a DML statement
+ @return true if SQL command is a DML statement, false otherwise
+ */
+ virtual bool is_dml() const { return false; }
+
+ /**
+ @brief Unprepare prepared statement for the command
+ @param thd global context of the processed statement
+
+ @notes
+ Temporary function used to "unprepare" a prepared statement after
+ preparation, so that a subsequent execute statement will reprepare it.
+ This is done because UNIT::cleanup() will un-resolve all resolved QBs.
+ */
+ virtual void unprepare(THD *thd)
+ {
+ DBUG_ASSERT(is_prepared());
+ m_prepared = false;
+ }
+
protected:
- Sql_cmd()
+ Sql_cmd() : m_prepared(false), m_owner(nullptr)
{}
virtual ~Sql_cmd()
@@ -204,10 +256,152 @@ class Sql_cmd : public Sql_alloc
simply destroyed instead.
Do not rely on the destructor for any cleanup.
*/
- DBUG_ASSERT(FALSE);
+ DBUG_ASSERT(false);
+ }
+
+ /**
+ @brief Set this statement as prepared
+ */
+ void set_prepared() { m_prepared = true; }
+
+ private:
+ /* True when statement has been prepared */
+ bool m_prepared;
+ /* Owning prepared statement, nullptr if not prepared */
+ Prepared_statement *m_owner;
+
+};
+
+struct LEX;
+class select_result;
+class Prelocking_strategy;
+class DML_prelocking_strategy;
+class Protocol;
+
+/**
+ @class Sql_cmd_dml - derivative abstract class used for DML statements
+
+ This class is a class derived from Sql_cmd used when processing such
+ data manipulation commands as SELECT, INSERT, UPDATE, DELETE and others
+ that operate over some tables.
+ After the parser phase all these commands are supposed to be processed
+ by the same schema:
+ - precheck of the access rights is performed for the used tables
+ - the used tables are opened
+ - context analysis phase is performed for the statement
+ - the used tables are locked
+ - the statement is optimized and executed
+ - clean-up is performed for the statement.
+ This schema is reflected in the function Sql_cmd_dml::execute() that
+ uses Sql_cmd_dml::prepare is the statement has not been prepared yet.
+ Precheck of the access right, context analysis are specific for statements
+ of a certain type. That's why the methods implementing this operations are
+ declared as abstract in this class.
+
+ @note
+ Currently this class is used only for UPDATE and DELETE commands.
+*/
+class Sql_cmd_dml : public Sql_cmd
+{
+public:
+
+ /**
+ @brief Check whether the statement changes the contents of used tables
+ @return true if this is data change statement, false otherwise
+ */
+ virtual bool is_data_change_stmt() const { return true; }
+
+ /**
+ @brief Perform context analysis of the statement
+ @param thd global context the processed statement
+ @returns false on success, true on error
+ */
+ virtual bool prepare(THD *thd);
+
+ /**
+ Execute the processed statement once
+ @param thd global context the processed statement
+ @returns false on success, true on error
+ */
+ virtual bool execute(THD *thd);
+
+ virtual bool is_dml() const { return true; }
+
+ select_result *get_result() { return result; }
+
+protected:
+ Sql_cmd_dml()
+ : Sql_cmd(), lex(nullptr), result(nullptr),
+ m_empty_query(false)
+ {}
+
+ /**
+ @brief Check whether query is guaranteed to return no data
+ @return true if query is guaranteed to return no data, false otherwise
+
+ @todo Also check this for the following cases:
+ - Empty source for multi-table UPDATE and DELETE.
+ - Check empty query expression for INSERT
+ */
+ bool is_empty_query() const
+ {
+ DBUG_ASSERT(is_prepared());
+ return m_empty_query;
}
+
+ /**
+ @brief Set statement as returning no data
+ */
+ void set_empty_query() { m_empty_query = true; }
+
+ /**
+ @brief Perform precheck of table privileges for the specific command
+ @param thd global context the processed statement
+ @returns false if success, true if false
+
+ @details
+ Check that user has some relevant privileges for all tables involved in
+ the statement, e.g. SELECT privileges for tables selected from, INSERT
+ privileges for tables inserted into, etc. This function will also populate
+ TABLE_LIST::grant with all privileges the user has for each table, which
+ is later used during checking of column privileges.
+ Note that at preparation time, views are not expanded yet. Privilege
+ checking is thus rudimentary and must be complemented with later calls to
+ SELECT_LEX::check_view_privileges().
+ The reason to call this function at such an early stage is to be able to
+ quickly reject statements for which the user obviously has insufficient
+ privileges.
+ */
+ virtual bool precheck(THD *thd) = 0;
+
+ /**
+ @brief Perform the command-specific actions of the context analysis
+ @param thd global context the processed statement
+ @returns false if success, true if error
+
+ @note
+ This function is called from prepare()
+ */
+ virtual bool prepare_inner(THD *thd) = 0;
+
+ /**
+ @brief Perform the command-specific actions of optimization and excution
+ @param thd global context the processed statement
+ @returns false on success, true on error
+ */
+ virtual bool execute_inner(THD *thd);
+
+ virtual DML_prelocking_strategy *get_dml_prelocking_strategy() = 0;
+
+ uint table_count;
+
+ protected:
+ LEX *lex; /**< Pointer to LEX for this statement */
+ select_result *result; /**< Pointer to object for handling of the result */
+ bool m_empty_query; /**< True if query will produce no rows */
};
+
class Sql_cmd_show_slave_status: public Sql_cmd
{
protected:
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 65a3a76..2ff4331 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -103,7 +103,7 @@ bool Update_plan::save_explain_data_intern(MEM_ROOT *mem_root,
bool is_analyze)
{
explain->select_type= "SIMPLE";
- explain->table_name.append(&table->pos_in_table_list->alias);
+ explain->table_name.append(table->alias);
explain->impossible_where= false;
explain->no_partitions= false;
@@ -295,123 +295,86 @@ int TABLE::delete_row()
/**
- Implement DELETE SQL word.
+ @brief Special handling of single-table deletes after prepare phase
- @note Like implementations of other DDL/DML in MySQL, this function
- relies on the caller to close the thread tables. This is done in the
- end of dispatch_command().
+ @param thd global context the processed statement
+ @returns false on success, true on error
*/
-bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
- SQL_I_List<ORDER> *order_list, ha_rows limit,
- ulonglong options, select_result *result)
+bool Sql_cmd_delete::delete_from_single_table(THD *thd)
{
- bool will_batch= FALSE;
- int error, loc_error;
- TABLE *table;
- SQL_SELECT *select=0;
- SORT_INFO *file_sort= 0;
- READ_RECORD info;
- bool using_limit=limit != HA_POS_ERROR;
- bool transactional_table, safe_update, const_cond;
- bool const_cond_result;
- bool return_error= 0;
- ha_rows deleted= 0;
- bool reverse= FALSE;
- bool has_triggers= false;
- ORDER *order= (ORDER *) ((order_list && order_list->elements) ?
- order_list->first : NULL);
- SELECT_LEX *select_lex= thd->lex->first_select_lex();
- SELECT_LEX *returning= thd->lex->has_returning() ? thd->lex->returning() : 0;
+ int error;
+ int loc_error;
+ bool transactional_table;
+ bool const_cond;
+ bool safe_update;
+ bool const_cond_result;
+ bool return_error= 0;
+ TABLE *table;
+ SQL_SELECT *select= 0;
+ SORT_INFO *file_sort= 0;
+ READ_RECORD info;
+ ha_rows deleted= 0;
+ bool reverse= FALSE;
+ bool binlog_is_row;
killed_state killed_status= NOT_KILLED;
THD::enum_binlog_query_type query_type= THD::ROW_QUERY_TYPE;
- bool binlog_is_row;
- Explain_delete *explain;
+ bool will_batch= FALSE;
+
+ bool has_triggers= false;
+ SELECT_LEX_UNIT *unit = &lex->unit;
+ SELECT_LEX *select_lex= unit->first_select();
+ SELECT_LEX *returning= thd->lex->has_returning() ? thd->lex->returning() : 0;
+ TABLE_LIST *const table_list = select_lex->get_table_list();
+ ulonglong options= select_lex->options;
+ ORDER *order= select_lex->order_list.first;
+ COND *conds= select_lex->join->conds;
+ ha_rows limit= unit->lim.get_select_limit();
+ bool using_limit= limit != HA_POS_ERROR;
+
Delete_plan query_plan(thd->mem_root);
+ Explain_delete *explain;
Unique * deltempfile= NULL;
bool delete_record= false;
- bool delete_while_scanning;
+ bool delete_while_scanning= table_list->delete_while_scanning;
bool portion_of_time_through_update;
- DBUG_ENTER("mysql_delete");
+
+ DBUG_ENTER("Sql_cmd_delete::delete_single_table");
query_plan.index= MAX_KEY;
query_plan.using_filesort= FALSE;
- create_explain_query(thd->lex, thd->mem_root);
- if (open_and_lock_tables(thd, table_list, TRUE, 0))
- DBUG_RETURN(TRUE);
-
THD_STAGE_INFO(thd, stage_init_update);
+ create_explain_query(thd->lex, thd->mem_root);
const bool delete_history= table_list->vers_conditions.delete_history;
DBUG_ASSERT(!(delete_history && table_list->period_conditions.is_set()));
- if (thd->lex->handle_list_of_derived(table_list, DT_MERGE_FOR_INSERT))
- DBUG_RETURN(TRUE);
- if (thd->lex->handle_list_of_derived(table_list, DT_PREPARE))
- DBUG_RETURN(TRUE);
+ if (table_list->handle_derived(thd->lex, DT_MERGE_FOR_INSERT))
+ DBUG_RETURN(1);
+ if (table_list->handle_derived(thd->lex, DT_PREPARE))
+ DBUG_RETURN(1);
+
+ table= table_list->table;
if (!table_list->single_table_updatable())
{
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias.str, "DELETE");
DBUG_RETURN(TRUE);
}
- if (!(table= table_list->table) || !table->is_created())
+
+ if (!table || !table->is_created())
{
my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
table_list->view_db.str, table_list->view_name.str);
DBUG_RETURN(TRUE);
}
- table->map=1;
+
query_plan.select_lex= thd->lex->first_select_lex();
query_plan.table= table;
thd->lex->promote_select_describe_flag_if_needed();
- if (mysql_prepare_delete(thd, table_list, &conds, &delete_while_scanning))
- DBUG_RETURN(TRUE);
-
- if (table_list->has_period())
- {
- if (!table_list->period_conditions.start.item->const_item()
- || !table_list->period_conditions.end.item->const_item())
- {
- my_error(ER_NOT_CONSTANT_EXPRESSION, MYF(0), "FOR PORTION OF");
- DBUG_RETURN(true);
- }
- }
-
- if (delete_history)
- table->vers_write= false;
-
- if (returning)
- (void) result->prepare(returning->item_list, NULL);
-
- if (thd->lex->current_select->first_cond_optimization)
- {
- thd->lex->current_select->save_leaf_tables(thd);
- thd->lex->current_select->first_cond_optimization= 0;
- }
- /* check ORDER BY even if it can be ignored */
- if (order)
- {
- TABLE_LIST tables;
- List<Item> fields;
- List<Item> all_fields;
-
- bzero((char*) &tables,sizeof(tables));
- tables.table = table;
- tables.alias = table_list->alias;
-
- if (select_lex->setup_ref_array(thd, order_list->elements) ||
- setup_order(thd, select_lex->ref_pointer_array, &tables,
- fields, all_fields, order))
- {
- free_underlaid_joins(thd, thd->lex->first_select_lex());
- DBUG_RETURN(TRUE);
- }
- }
-
/* Apply the IN=>EXISTS transformation to all subqueries and optimize them. */
if (select_lex->optimize_unflattened_subqueries(false))
DBUG_RETURN(TRUE);
@@ -1011,90 +974,6 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
}
-/*
- Prepare items in DELETE statement
-
- SYNOPSIS
- mysql_prepare_delete()
- thd - thread handler
- table_list - global/local table list
- conds - conditions
-
- RETURN VALUE
- FALSE OK
- TRUE error
-*/
-int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds,
- bool *delete_while_scanning)
-{
- Item *fake_conds= 0;
- SELECT_LEX *select_lex= thd->lex->first_select_lex();
- DBUG_ENTER("mysql_prepare_delete");
- List<Item> all_fields;
-
- *delete_while_scanning= true;
- thd->lex->allow_sum_func.clear_all();
- if (setup_tables_and_check_access(thd, &select_lex->context,
- &select_lex->top_join_list, table_list,
- select_lex->leaf_tables, FALSE,
- DELETE_ACL, SELECT_ACL, TRUE))
- DBUG_RETURN(TRUE);
-
- if (table_list->vers_conditions.is_set() && table_list->is_view_or_derived())
- {
- my_error(ER_IT_IS_A_VIEW, MYF(0), table_list->table_name.str);
- DBUG_RETURN(true);
- }
-
- if (table_list->has_period())
- {
- if (table_list->is_view_or_derived())
- {
- my_error(ER_IT_IS_A_VIEW, MYF(0), table_list->table_name.str);
- DBUG_RETURN(true);
- }
-
- if (select_lex->period_setup_conds(thd, table_list))
- DBUG_RETURN(true);
- }
-
- DBUG_ASSERT(table_list->table);
- // conds could be cached from previous SP call
- DBUG_ASSERT(!table_list->vers_conditions.need_setup() ||
- !*conds || thd->stmt_arena->is_stmt_execute());
- if (select_lex->vers_setup_conds(thd, table_list))
- DBUG_RETURN(TRUE);
-
- *conds= select_lex->where;
-
- if (setup_returning_fields(thd, table_list) ||
- setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
- setup_ftfuncs(select_lex))
- DBUG_RETURN(TRUE);
- if (!table_list->single_table_updatable() ||
- check_key_in_view(thd, table_list))
- {
- my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias.str, "DELETE");
- DBUG_RETURN(TRUE);
- }
-
- /*
- Application-time periods: if FOR PORTION OF ... syntax used, DELETE
- statement could issue delete_row's mixed with write_row's. This causes
- problems for myisam and corrupts table, if deleting while scanning.
- */
- if (table_list->has_period()
- || unique_table(thd, table_list, table_list->next_global, 0))
- *delete_while_scanning= false;
-
- if (select_lex->inner_refs_list.elements &&
- fix_inner_refs(thd, all_fields, select_lex, select_lex->ref_pointer_array))
- DBUG_RETURN(TRUE);
-
- select_lex->fix_prepare_information(thd, conds, &fake_conds);
- DBUG_RETURN(FALSE);
-}
-
/***************************************************************************
Delete multiple tables from join
@@ -1107,106 +986,6 @@ extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b)
return file->cmp_ref((const uchar*)a, (const uchar*)b);
}
-/*
- make delete specific preparation and checks after opening tables
-
- SYNOPSIS
- mysql_multi_delete_prepare()
- thd thread handler
-
- RETURN
- FALSE OK
- TRUE Error
-*/
-
-int mysql_multi_delete_prepare(THD *thd)
-{
- LEX *lex= thd->lex;
- TABLE_LIST *aux_tables= lex->auxiliary_table_list.first;
- TABLE_LIST *target_tbl;
- DBUG_ENTER("mysql_multi_delete_prepare");
-
- if (mysql_handle_derived(lex, DT_INIT))
- DBUG_RETURN(TRUE);
- if (mysql_handle_derived(lex, DT_MERGE_FOR_INSERT))
- DBUG_RETURN(TRUE);
- if (mysql_handle_derived(lex, DT_PREPARE))
- DBUG_RETURN(TRUE);
- /*
- setup_tables() need for VIEWs. JOIN::prepare() will not do it second
- time.
-
- lex->query_tables also point on local list of DELETE SELECT_LEX
- */
- if (setup_tables_and_check_access(thd,
- &thd->lex->first_select_lex()->context,
- &thd->lex->first_select_lex()->
- top_join_list,
- lex->query_tables,
- lex->first_select_lex()->leaf_tables,
- FALSE, DELETE_ACL, SELECT_ACL, FALSE))
- DBUG_RETURN(TRUE);
-
- /*
- Multi-delete can't be constructed over-union => we always have
- single SELECT on top and have to check underlying SELECTs of it
- */
- lex->first_select_lex()->set_unique_exclude();
- /* Fix tables-to-be-deleted-from list to point at opened tables */
- for (target_tbl= (TABLE_LIST*) aux_tables;
- target_tbl;
- target_tbl= target_tbl->next_local)
- {
-
- target_tbl->table= target_tbl->correspondent_table->table;
- if (target_tbl->correspondent_table->is_multitable())
- {
- my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
- target_tbl->correspondent_table->view_db.str,
- target_tbl->correspondent_table->view_name.str);
- DBUG_RETURN(TRUE);
- }
-
- if (!target_tbl->correspondent_table->single_table_updatable() ||
- check_key_in_view(thd, target_tbl->correspondent_table))
- {
- my_error(ER_NON_UPDATABLE_TABLE, MYF(0),
- target_tbl->table_name.str, "DELETE");
- DBUG_RETURN(TRUE);
- }
- }
-
- for (target_tbl= (TABLE_LIST*) aux_tables;
- target_tbl;
- target_tbl= target_tbl->next_local)
- {
- /*
- Check that table from which we delete is not used somewhere
- inside subqueries/view.
- */
- {
- TABLE_LIST *duplicate;
- if ((duplicate= unique_table(thd, target_tbl->correspondent_table,
- lex->query_tables, 0)))
- {
- update_non_unique_table_error(target_tbl->correspondent_table,
- "DELETE", duplicate);
- DBUG_RETURN(TRUE);
- }
- }
- }
- /*
- Reset the exclude flag to false so it doesn't interfare
- with further calls to unique_table
- */
- lex->first_select_lex()->exclude_from_table_unique_test= FALSE;
-
- if (lex->save_prep_leaf_tables())
- DBUG_RETURN(TRUE);
-
- DBUG_RETURN(FALSE);
-}
-
multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt, uint num_of_tables_arg):
select_result_interceptor(thd_arg), delete_tables(dt), deleted(0), found(0),
@@ -1659,3 +1438,319 @@ bool multi_delete::send_eof()
}
return 0;
}
+
+
+bool Sql_cmd_delete::precheck(THD *thd)
+{
+ if (!multitable)
+ {
+ if (delete_precheck(thd, lex->query_tables))
+ return true;
+ }
+ else
+ {
+ if (multi_delete_precheck(thd, lex->query_tables))
+ return true;
+ }
+
+ WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
+
+ return false;
+
+#ifdef WITH_WSREP
+wsrep_error_label:
+#endif
+ return true;
+}
+
+
+/**
+ @brief Perform context analysis for delete statements
+
+ @param thd global context the processed statement
+ @returns false on success, true on error
+
+ @note
+ The main bulk of the context analysis actions for a delete statement
+ is performed by a call of JOIN::prepare().
+*/
+
+bool Sql_cmd_delete::prepare_inner(THD *thd)
+{
+ int err= 0;
+ TABLE_LIST *target_tbl;
+ JOIN *join;
+ SELECT_LEX *const select_lex = thd->lex->first_select_lex();
+ TABLE_LIST *const table_list = select_lex->get_table_list();
+ TABLE_LIST *aux_tables= thd->lex->auxiliary_table_list.first;
+ ulonglong select_options= select_lex->options;
+ bool free_join= 1;
+ SELECT_LEX *returning= thd->lex->has_returning() ? thd->lex->returning() : 0;
+ const bool delete_history= table_list->vers_conditions.delete_history;
+ DBUG_ASSERT(!(delete_history && table_list->period_conditions.is_set()));
+
+ DBUG_ENTER("Sql_cmd_delete::prepare_inner");
+
+ (void) read_statistics_for_tables_if_needed(thd, table_list);
+
+ THD_STAGE_INFO(thd, stage_init_update);
+
+ {
+ if (mysql_handle_derived(lex, DT_INIT))
+ DBUG_RETURN(TRUE);
+ if (mysql_handle_derived(lex, DT_MERGE_FOR_INSERT))
+ DBUG_RETURN(TRUE);
+ if (mysql_handle_derived(lex, DT_PREPARE))
+ DBUG_RETURN(TRUE);
+ }
+
+ if (!(result= new (thd->mem_root) multi_delete(thd, aux_tables,
+ lex->table_count)))
+ {
+ DBUG_RETURN(TRUE);
+ }
+
+ table_list->delete_while_scanning= true;
+
+ if (!multitable && !table_list->single_table_updatable())
+ {
+ my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias.str, "DELETE");
+ DBUG_RETURN(TRUE);
+ }
+
+ if (!multitable && (!table_list->table || !table_list->table->is_created()))
+ {
+ my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
+ table_list->view_db.str, table_list->view_name.str);
+ DBUG_RETURN(TRUE);
+ }
+
+ if (setup_tables_and_check_access(thd, &select_lex->context,
+ &select_lex->top_join_list,
+ table_list, select_lex->leaf_tables,
+ false, DELETE_ACL, SELECT_ACL, true))
+ DBUG_RETURN(TRUE);
+
+ if (setup_tables(thd, &select_lex->context, &select_lex->top_join_list,
+ table_list, select_lex->leaf_tables, false, false))
+ DBUG_RETURN(TRUE);
+
+ if (!multitable)
+ {
+ if (table_list->vers_conditions.is_set() && table_list->is_view_or_derived())
+ {
+ my_error(ER_IT_IS_A_VIEW, MYF(0), table_list->table_name.str);
+ DBUG_RETURN(true);
+ }
+
+ if (table_list->has_period())
+ {
+ if (table_list->is_view_or_derived())
+ {
+ my_error(ER_IT_IS_A_VIEW, MYF(0), table_list->table_name.str);
+ DBUG_RETURN(true);
+ }
+
+ if (select_lex->period_setup_conds(thd, table_list))
+ DBUG_RETURN(true);
+ }
+
+ if (select_lex->vers_setup_conds(thd, table_list))
+ DBUG_RETURN(TRUE);
+ /*
+ Application-time periods: if FOR PORTION OF ... syntax used, DELETE
+ statement could issue delete_row's mixed with write_row's. This causes
+ problems for myisam and corrupts table, if deleting while scanning.
+ */
+ if (table_list->has_period()
+ || unique_table(thd, table_list, table_list->next_global, 0))
+ table_list->delete_while_scanning= false;
+ }
+
+ {
+ if (thd->lex->describe)
+ select_options|= SELECT_DESCRIBE;
+
+ /*
+ When in EXPLAIN, delay deleting the joins so that they are still
+ available when we're producing EXPLAIN EXTENDED warning text.
+ */
+ if (select_options & SELECT_DESCRIBE)
+ free_join= 0;
+ select_options|=
+ SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK | OPTION_SETUP_TABLES_DONE;
+
+ if (!(join= new (thd->mem_root) JOIN(thd, empty_list,
+ select_options, result)))
+ DBUG_RETURN(TRUE);
+ THD_STAGE_INFO(thd, stage_init);
+ select_lex->join= join;
+ thd->lex->used_tables=0;
+ if ((err= join->prepare(table_list, select_lex->where,
+ select_lex->order_list.elements,
+ select_lex->order_list.first,
+ false, NULL, NULL, NULL,
+ select_lex, &lex->unit)))
+
+ {
+ goto err;
+ }
+ }
+
+ if (multitable)
+ {
+ /*
+ Multi-delete can't be constructed over-union => we always have
+ single SELECT on top and have to check underlying SELECTs of it
+ */
+ lex->first_select_lex()->set_unique_exclude();
+ /* Fix tables-to-be-deleted-from list to point at opened tables */
+ for (target_tbl= (TABLE_LIST*) aux_tables;
+ target_tbl;
+ target_tbl= target_tbl->next_local)
+ {
+ target_tbl->table= target_tbl->correspondent_table->table;
+ if (target_tbl->correspondent_table->is_multitable())
+ {
+ my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
+ target_tbl->correspondent_table->view_db.str,
+ target_tbl->correspondent_table->view_name.str);
+ DBUG_RETURN(TRUE);
+ }
+
+ if (!target_tbl->correspondent_table->single_table_updatable() ||
+ check_key_in_view(thd, target_tbl->correspondent_table))
+ {
+ my_error(ER_NON_UPDATABLE_TABLE, MYF(0),
+ target_tbl->table_name.str, "DELETE");
+ DBUG_RETURN(TRUE);
+ }
+ }
+
+ for (target_tbl= (TABLE_LIST*) aux_tables;
+ target_tbl;
+ target_tbl= target_tbl->next_local)
+ {
+ /*
+ Check that table from which we delete is not used somewhere
+ inside subqueries/view.
+ */
+ {
+ TABLE_LIST *duplicate;
+ if ((duplicate= unique_table(thd, target_tbl->correspondent_table,
+ lex->query_tables, 0)))
+ {
+ update_non_unique_table_error(target_tbl->correspondent_table,
+ "DELETE", duplicate);
+ DBUG_RETURN(TRUE);
+ }
+ }
+ }
+ /*
+ Reset the exclude flag to false so it doesn't interfare
+ with further calls to unique_table
+ */
+ lex->first_select_lex()->exclude_from_table_unique_test= FALSE;
+ }
+
+ if (!multitable && table_list->has_period())
+ {
+ if (!table_list->period_conditions.start.item->const_item()
+ || !table_list->period_conditions.end.item->const_item())
+ {
+ my_error(ER_NOT_CONSTANT_EXPRESSION, MYF(0), "FOR PORTION OF");
+ DBUG_RETURN(true);
+ }
+ }
+
+ if (delete_history)
+ table_list->table->vers_write= false;
+
+ if (setup_returning_fields(thd, table_list) ||
+ setup_ftfuncs(select_lex))
+ goto err;
+
+ free_join= false;
+
+ if (returning)
+ (void) result->prepare(returning->item_list, NULL);
+
+err:
+
+ if (free_join)
+ {
+ THD_STAGE_INFO(thd, stage_end);
+ err|= (int)(select_lex->cleanup());
+ DBUG_RETURN(err || thd->is_error());
+ }
+ DBUG_RETURN(err);
+
+}
+
+
+/**
+ @brief Perform optimization and execution actions needed for deletes
+
+ @param thd global context the processed statement
+ @returns false on success, true on error
+*/
+
+bool Sql_cmd_delete::execute_inner(THD *thd)
+{
+ if (!multitable)
+ {
+ if (lex->has_returning())
+ {
+ select_result *sel_result= NULL;
+ delete result;
+ /* This is DELETE ... RETURNING. It will return output to the client */
+ if (thd->lex->analyze_stmt)
+ {
+ /*
+ Actually, it is ANALYZE .. DELETE .. RETURNING. We need to produce
+ output and then discard it.
+ */
+ sel_result= new (thd->mem_root) select_send_analyze(thd);
+ save_protocol= thd->protocol;
+ thd->protocol= new Protocol_discard(thd);
+ }
+ else
+ {
+ if (!lex->result && !(sel_result= new (thd->mem_root) select_send(thd)))
+ return true;
+ }
+ result= lex->result ? lex->result : sel_result;
+ }
+ }
+
+ bool res= multitable ? Sql_cmd_dml::execute_inner(thd)
+ : delete_from_single_table(thd);
+
+ res|= thd->is_error();
+
+ if (save_protocol)
+ {
+ delete thd->protocol;
+ thd->protocol= save_protocol;
+ }
+ {
+ if (unlikely(res))
+ {
+ if (multitable)
+ result->abort_result_set();
+ }
+ else
+ {
+ if (thd->lex->describe || thd->lex->analyze_stmt)
+ res= thd->lex->explain->send_explain(thd);
+ }
+ }
+
+ if (result)
+ {
+ res= false;
+ delete result;
+ }
+
+ return res;
+}
diff --git a/sql/sql_delete.h b/sql/sql_delete.h
index 520524c..e1d5044 100644
--- a/sql/sql_delete.h
+++ b/sql/sql_delete.h
@@ -17,6 +17,9 @@
#define SQL_DELETE_INCLUDED
#include "my_base.h" /* ha_rows */
+#include "sql_class.h" /* enum_duplicates */
+#include "sql_cmd.h" // Sql_cmd_dml
+#include "sql_base.h"
class THD;
struct TABLE_LIST;
@@ -26,10 +29,66 @@ class select_result;
typedef class Item COND;
template <typename T> class SQL_I_List;
-int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds,
- bool *delete_while_scanning);
-bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
- SQL_I_List<ORDER> *order, ha_rows rows,
- ulonglong options, select_result *result);
+/**
+ @class Sql_cmd_delete - class used for any DELETE statements
+ This class is derived from Sql_cmd_dml and contains implementations
+ for abstract virtual function of the latter such as precheck() and
+ prepare_inner(). It also overrides the implementation of execute_inner()
+ providing a special handling for single-table delete statements that
+ are not converted to multi-table delete.
+ The class provides an object of the DML_prelocking_strategy class
+ for the virtual function get_dml_prelocking_strategy().
+*/
+class Sql_cmd_delete final : public Sql_cmd_dml
+{
+public:
+ Sql_cmd_delete(bool multitable_arg)
+ : multitable(multitable_arg), save_protocol(NULL) {}
+
+ enum_sql_command sql_command_code() const override
+ {
+ return multitable ? SQLCOM_DELETE_MULTI : SQLCOM_DELETE;
+ }
+
+ DML_prelocking_strategy *get_dml_prelocking_strategy()
+ {
+ return &dml_prelocking_strategy;
+ }
+
+protected:
+ /**
+ @brief Perform precheck of table privileges for delete statements
+ */
+ bool precheck(THD *thd) override;
+
+ /**
+ @brief Perform context analysis for delete statements
+ */
+ bool prepare_inner(THD *thd) override;
+
+ /**
+ @brief Perform optimization and execution actions needed for deletes
+ */
+ bool execute_inner(THD *thd) override;
+
+ private:
+ /**
+ @biefSpecial handling of single-table deletes after prepare phase
+ */
+ bool delete_from_single_table(THD *thd);
+
+ /*
+ True if the statement is a multitable delete or converted to such.
+ For a single-table delete this flag is set to true if the statement
+ is supposed to be converted to multi-table delete.
+ */
+ bool multitable;
+
+ /* The prelocking strategy used when opening the used tables */
+ DML_prelocking_strategy dml_prelocking_strategy;
+
+ List<Item> empty_list; /**< auxiliary empty list used by prepare_inner() */
+ Protocol *save_protocol; /**< needed for ANALYZE .. DELETE .. RETURNING */
+};
#endif /* SQL_DELETE_INCLUDED */
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 5f2f072..070cf52 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -1302,6 +1302,8 @@ void LEX::start(THD *thd_arg)
wild= 0;
exchange= 0;
+ table_count= 0;
+
DBUG_VOID_RETURN;
}
@@ -3029,6 +3031,7 @@ void st_select_lex::init_select()
curr_tvc_name= 0;
versioned_tables= 0;
nest_flags= 0;
+ item_list_usage= MARK_COLUMNS_READ;
}
/*
@@ -3299,34 +3302,6 @@ void st_select_lex_unit::exclude_level()
}
-#if 0
-/*
- Exclude subtree of current unit from tree of SELECTs
-
- SYNOPSYS
- st_select_lex_unit::exclude_tree()
-*/
-void st_select_lex_unit::exclude_tree()
-{
- for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
- {
- // unlink current level from global SELECTs list
- if (sl->link_prev && (*sl->link_prev= sl->link_next))
- sl->link_next->link_prev= sl->link_prev;
-
- // unlink underlay levels
- for (SELECT_LEX_UNIT *u= sl->first_inner_unit(); u; u= u->next_unit())
- {
- u->exclude_level();
- }
- }
- // exclude currect unit from list of nodes
- (*prev)= next;
- if (next)
- next->prev= prev;
-}
-#endif
-
/*
st_select_lex_node::mark_as_dependent mark all st_select_lex struct from
@@ -3548,7 +3523,7 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num)
select_n_where_fields +
order_group_num +
hidden_bit_fields +
- fields_in_window_functions) * (size_t) 5;
+ fields_in_window_functions + 1) * (size_t) 5;
DBUG_ASSERT(n_elems % 5 == 0);
if (!ref_pointer_array.is_null())
{
@@ -4094,6 +4069,12 @@ bool LEX::can_not_use_merged(bool no_update_or_delete)
return TRUE;
/* Fall through */
+ case SQLCOM_UPDATE:
+ if (no_update_or_delete && m_sql_cmd &&
+ (m_sql_cmd->sql_command_code() == SQLCOM_UPDATE_MULTI ||
+ query_tables->is_multitable()))
+ return TRUE;
+
default:
return FALSE;
}
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 4f2e775..0badc32 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -36,6 +36,7 @@
#include "sql_limit.h" // Select_limit_counters
#include "json_table.h" // Json_table_column
#include "sql_schema.h"
+#include "sql_class.h" // enum enum_column_usage
/* Used for flags of nesting constructs */
#define SELECT_NESTING_MAP_SIZE 64
@@ -873,6 +874,8 @@ class st_select_lex_unit: public st_select_lex_node {
{
}
+ void set_query_result(select_result *res) { result= res; }
+
TABLE *table; /* temporary table using for appending UNION results */
select_result *result;
st_select_lex *pre_last_parse;
@@ -1005,6 +1008,7 @@ class st_select_lex_unit: public st_select_lex_node {
bool add_fake_select_lex(THD *thd);
void init_prepare_fake_select_lex(THD *thd, bool first_execution);
+ void set_prepared() { prepared = true; }
inline bool is_prepared() { return prepared; }
bool change_result(select_result_interceptor *result,
select_result_interceptor *old_result);
@@ -1107,6 +1111,7 @@ class st_select_lex: public st_select_lex_node
Item *prep_having;/* saved HAVING clause for prepared statement processing */
Item *cond_pushed_into_where; /* condition pushed into WHERE */
Item *cond_pushed_into_having; /* condition pushed into HAVING */
+ Item *where_cond_after_prepare;
/*
nest_levels are local to the query or VIEW,
@@ -1215,6 +1220,7 @@ class st_select_lex: public st_select_lex_node
List<List_item> save_many_values;
List<Item> *save_insert_list;
+ enum_column_usage item_list_usage;
bool is_item_list_lookup:1;
/*
Needed to correctly generate 'PRIMARY' or 'SIMPLE' for select_type column
@@ -1745,6 +1751,25 @@ class Query_tables_list
uint sroutines_list_own_elements;
/**
+ Locking state of tables in this particular statement.
+
+ If we under LOCK TABLES or in prelocked mode we consider tables
+ for the statement to be "locked" if there was a call to lock_tables()
+ (which called handler::start_stmt()) for tables of this statement
+ and there was no matching close_thread_tables() call.
+
+ As result this state may differ significantly from one represented
+ by Open_tables_state::lock/locked_tables_mode more, which are always
+ "on" under LOCK TABLES or in prelocked mode.
+ */
+ enum enum_lock_tables_state { LTS_NOT_LOCKED = 0, LTS_LOCKED };
+ enum_lock_tables_state lock_tables_state;
+ bool is_query_tables_locked() const
+ {
+ return (lock_tables_state == LTS_LOCKED);
+ }
+
+ /**
Number of tables which were open by open_tables() and to be locked
by lock_tables().
Note that we set this member only in some cases, when this value
@@ -3391,6 +3416,7 @@ struct LEX: public Query_tables_list
bool default_used:1; /* using default() function */
bool with_rownum:1; /* Using rownum() function */
bool is_lex_started:1; /* If lex_start() did run. For debugging. */
+
/*
This variable is used in post-parse stage to declare that sum-functions,
or functions which have sense only if GROUP BY is present, are allowed.
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 0597b08..8b906be 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -34,9 +34,7 @@
#include "sql_locale.h" // my_locale_en_US
#include "log.h" // flush_error_log
#include "sql_view.h" // mysql_create_view, mysql_drop_view
-#include "sql_delete.h" // mysql_delete
#include "sql_insert.h" // mysql_insert
-#include "sql_update.h" // mysql_update, mysql_multi_update
#include "sql_partition.h" // struct partition_info
#include "sql_db.h" // mysql_change_db, mysql_create_db,
// mysql_rm_db, mysql_upgrade_db,
@@ -3442,7 +3440,6 @@ int
mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt)
{
int res= 0;
- int up_result= 0;
LEX *lex= thd->lex;
/* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */
SELECT_LEX *select_lex= lex->first_select_lex();
@@ -3454,7 +3451,6 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt)
SELECT_LEX_UNIT *unit= &lex->unit;
#ifdef HAVE_REPLICATION
/* have table map for update for multi-update statement (BUG#37051) */
- bool have_table_map_for_update= FALSE;
/* */
Rpl_filter *rpl_filter;
#endif
@@ -3576,7 +3572,6 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt)
if (lex->sql_command == SQLCOM_UPDATE_MULTI &&
thd->table_map_for_update)
{
- have_table_map_for_update= TRUE;
table_map table_map_for_update= thd->table_map_for_update;
uint nr= 0;
TABLE_LIST *table;
@@ -4381,130 +4376,15 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt)
break;
}
case SQLCOM_UPDATE:
- {
- WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
- ha_rows found= 0, updated= 0;
- DBUG_ASSERT(first_table == all_tables && first_table != 0);
- WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
-
- if (update_precheck(thd, all_tables))
- break;
-
- /*
- UPDATE IGNORE can be unsafe. We therefore use row based
- logging if mixed or row based logging is available.
- TODO: Check if the order of the output of the select statement is
- deterministic. Waiting for BUG#42415
- */
- if (lex->ignore)
- lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_UPDATE_IGNORE);
-
- DBUG_ASSERT(select_lex->limit_params.offset_limit == 0);
- unit->set_limit(select_lex);
- MYSQL_UPDATE_START(thd->query());
- res= up_result= mysql_update(thd, all_tables,
- select_lex->item_list,
- lex->value_list,
- select_lex->where,
- select_lex->order_list.elements,
- select_lex->order_list.first,
- unit->lim.get_select_limit(),
- lex->ignore, &found, &updated);
- MYSQL_UPDATE_DONE(res, found, updated);
- /* mysql_update return 2 if we need to switch to multi-update */
- if (up_result != 2)
- break;
- if (thd->lex->period_conditions.is_set())
- {
- DBUG_ASSERT(0); // Should never happen
- goto error;
- }
- }
- /* fall through */
case SQLCOM_UPDATE_MULTI:
+ case SQLCOM_DELETE:
+ case SQLCOM_DELETE_MULTI:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
- /* if we switched from normal update, rights are checked */
- if (up_result != 2)
- {
- WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
- if ((res= multi_update_precheck(thd, all_tables)))
- break;
- }
- else
- res= 0;
-
- unit->set_limit(select_lex);
- /*
- We can not use mysql_explain_union() because of parameters of
- mysql_select in mysql_multi_update so just set the option if needed
- */
- if (thd->lex->describe)
- {
- select_lex->set_explain_type(FALSE);
- select_lex->options|= SELECT_DESCRIBE;
- }
-
- res= mysql_multi_update_prepare(thd);
+ DBUG_ASSERT(lex->m_sql_cmd != NULL);
-#ifdef HAVE_REPLICATION
- /* Check slave filtering rules */
- if (unlikely(thd->slave_thread && !have_table_map_for_update))
- {
- if (all_tables_not_ok(thd, all_tables))
- {
- if (res!= 0)
- {
- res= 0; /* don't care of prev failure */
- thd->clear_error(); /* filters are of highest prior */
- }
- /* we warn the slave SQL thread */
- my_error(ER_SLAVE_IGNORED_TABLE, MYF(0));
- break;
- }
- if (res)
- break;
- }
- else
- {
-#endif /* HAVE_REPLICATION */
- if (res)
- break;
- if (opt_readonly &&
- !(thd->security_ctx->master_access & PRIV_IGNORE_READ_ONLY) &&
- some_non_temp_table_to_be_updated(thd, all_tables))
- {
- my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
- break;
- }
-#ifdef HAVE_REPLICATION
- } /* unlikely */
-#endif
- {
- multi_update *result_obj;
- MYSQL_MULTI_UPDATE_START(thd->query());
- res= mysql_multi_update(thd, all_tables,
- &select_lex->item_list,
- &lex->value_list,
- select_lex->where,
- select_lex->options,
- lex->duplicates,
- lex->ignore,
- unit,
- select_lex,
- &result_obj);
- if (result_obj)
- {
- MYSQL_MULTI_UPDATE_DONE(res, result_obj->num_found(),
- result_obj->num_updated());
- res= FALSE; /* Ignore errors here */
- delete result_obj;
- }
- else
- {
- MYSQL_MULTI_UPDATE_DONE(1, 0, 0);
- }
- }
+ res = lex->m_sql_cmd->execute(thd);
+ thd->abort_on_warning= 0;
break;
}
case SQLCOM_REPLACE:
@@ -4766,129 +4646,6 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt)
break;
}
- case SQLCOM_DELETE:
- {
- WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
- select_result *sel_result= NULL;
- DBUG_ASSERT(first_table == all_tables && first_table != 0);
- WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
-
- if ((res= delete_precheck(thd, all_tables)))
- break;
- DBUG_ASSERT(select_lex->limit_params.offset_limit == 0);
- unit->set_limit(select_lex);
-
- MYSQL_DELETE_START(thd->query());
- Protocol *save_protocol= NULL;
-
- if (lex->has_returning())
- {
- /* This is DELETE ... RETURNING. It will return output to the client */
- if (thd->lex->analyze_stmt)
- {
- /*
- Actually, it is ANALYZE .. DELETE .. RETURNING. We need to produce
- output and then discard it.
- */
- sel_result= new (thd->mem_root) select_send_analyze(thd);
- save_protocol= thd->protocol;
- thd->protocol= new Protocol_discard(thd);
- }
- else
- {
- if (!lex->result && !(sel_result= new (thd->mem_root) select_send(thd)))
- goto error;
- }
- }
-
- res = mysql_delete(thd, all_tables,
- select_lex->where, &select_lex->order_list,
- unit->lim.get_select_limit(), select_lex->options,
- lex->result ? lex->result : sel_result);
-
- if (save_protocol)
- {
- delete thd->protocol;
- thd->protocol= save_protocol;
- }
-
- if (thd->lex->analyze_stmt || thd->lex->describe)
- {
- if (!res)
- res= thd->lex->explain->send_explain(thd);
- }
-
- delete sel_result;
- MYSQL_DELETE_DONE(res, (ulong) thd->get_row_count_func());
- break;
- }
- case SQLCOM_DELETE_MULTI:
- {
- WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
- DBUG_ASSERT(first_table == all_tables && first_table != 0);
- TABLE_LIST *aux_tables= thd->lex->auxiliary_table_list.first;
- multi_delete *result;
- WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
-
- if ((res= multi_delete_precheck(thd, all_tables)))
- break;
-
- /* condition will be TRUE on SP re-excuting */
- if (select_lex->item_list.elements != 0)
- select_lex->item_list.empty();
- if (add_item_to_list(thd, new (thd->mem_root) Item_null(thd)))
- goto error;
-
- THD_STAGE_INFO(thd, stage_init);
- if ((res= open_and_lock_tables(thd, all_tables, TRUE, 0)))
- break;
-
- MYSQL_MULTI_DELETE_START(thd->query());
- if (unlikely(res= mysql_multi_delete_prepare(thd)))
- {
- MYSQL_MULTI_DELETE_DONE(1, 0);
- goto error;
- }
-
- if (likely(!thd->is_fatal_error))
- {
- result= new (thd->mem_root) multi_delete(thd, aux_tables,
- lex->table_count);
- if (likely(result))
- {
- if (unlikely(select_lex->vers_setup_conds(thd, aux_tables)))
- goto multi_delete_error;
- res= mysql_select(thd,
- select_lex->get_table_list(),
- select_lex->item_list,
- select_lex->where,
- 0, (ORDER *)NULL, (ORDER *)NULL, (Item *)NULL,
- (ORDER *)NULL,
- (select_lex->options | thd->variables.option_bits |
- SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK |
- OPTION_SETUP_TABLES_DONE) & ~OPTION_BUFFER_RESULT,
- result, unit, select_lex);
- res|= (int)(thd->is_error());
-
- MYSQL_MULTI_DELETE_DONE(res, result->num_deleted());
- if (res)
- result->abort_result_set(); /* for both DELETE and EXPLAIN DELETE */
- else
- {
- if (lex->describe || lex->analyze_stmt)
- res= thd->lex->explain->send_explain(thd);
- }
- multi_delete_error:
- delete result;
- }
- }
- else
- {
- res= TRUE; // Error
- MYSQL_MULTI_DELETE_DONE(1, 0);
- }
- break;
- }
case SQLCOM_DROP_SEQUENCE:
case SQLCOM_DROP_TABLE:
{
@@ -7772,12 +7529,16 @@ void create_select_for_variable(THD *thd, LEX_CSTRING *var_name)
}
-void mysql_init_multi_delete(LEX *lex)
+void mysql_init_delete(LEX *lex)
{
- lex->sql_command= SQLCOM_DELETE_MULTI;
mysql_init_select(lex);
lex->first_select_lex()->limit_params.clear();
lex->unit.lim.clear();
+}
+
+void mysql_init_multi_delete(LEX *lex)
+{
+ lex->sql_command= SQLCOM_DELETE_MULTI;
lex->first_select_lex()->table_list.
save_and_clear(&lex->auxiliary_table_list);
lex->query_tables= 0;
diff --git a/sql/sql_parse.h b/sql/sql_parse.h
index d3cf83b..3f3302b 100644
--- a/sql/sql_parse.h
+++ b/sql/sql_parse.h
@@ -93,6 +93,7 @@ void mysql_parse(THD *thd, char *rawbuf, uint length,
bool mysql_new_select(LEX *lex, bool move_down, SELECT_LEX *sel);
void create_select_for_variable(THD *thd, LEX_CSTRING *var_name);
void create_table_set_open_action_and_adjust_tables(LEX *lex);
+void mysql_init_delete(LEX *lex);
void mysql_init_multi_delete(LEX *lex);
bool multi_delete_set_locks_and_link_aux_tables(LEX *lex);
void create_table_set_open_action_and_adjust_tables(LEX *lex);
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index b10a81d..b9ae058 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -95,10 +95,8 @@ When one supplies long data for a placeholder:
#include "sql_base.h" // open_normal_and_derived_tables
#include "sql_cache.h" // query_cache_*
#include "sql_view.h" // create_view_precheck
-#include "sql_delete.h" // mysql_prepare_delete
#include "sql_select.h" // for JOIN
#include "sql_insert.h" // upgrade_lock_type_for_insert, mysql_prepare_insert
-#include "sql_update.h" // mysql_prepare_update
#include "sql_db.h" // mysql_opt_change_db, mysql_change_db
#include "sql_derived.h" // mysql_derived_prepare,
// mysql_handle_derived
@@ -1399,160 +1397,6 @@ static bool mysql_test_insert(Prepared_statement *stmt,
}
-/**
- Validate UPDATE statement.
-
- @param stmt prepared statement
- @param tables list of tables used in this query
-
- @todo
- - here we should send types of placeholders to the client.
-
- @retval
- 0 success
- @retval
- 1 error, error message is set in THD
- @retval
- 2 convert to multi_update
-*/
-
-static int mysql_test_update(Prepared_statement *stmt,
- TABLE_LIST *table_list)
-{
- int res;
- THD *thd= stmt->thd;
- uint table_count= 0;
- TABLE_LIST *update_source_table;
- SELECT_LEX *select= stmt->lex->first_select_lex();
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- privilege_t want_privilege(NO_ACL);
-#endif
- DBUG_ENTER("mysql_test_update");
-
- if (update_precheck(thd, table_list) ||
- open_tables(thd, &table_list, &table_count, MYSQL_OPEN_FORCE_SHARED_MDL))
- goto error;
-
- if (mysql_handle_derived(thd->lex, DT_INIT))
- goto error;
-
- if (((update_source_table= unique_table(thd, table_list,
- table_list->next_global, 0)) ||
- table_list->is_multitable()))
- {
- DBUG_ASSERT(update_source_table || table_list->view != 0);
- DBUG_PRINT("info", ("Switch to multi-update"));
- /* pass counter value */
- thd->lex->table_count= table_count;
- /* convert to multiupdate */
- DBUG_RETURN(2);
- }
-
- /*
- thd->fill_derived_tables() is false here for sure (because it is
- preparation of PS, so we even do not check it).
- */
- if (table_list->handle_derived(thd->lex, DT_MERGE_FOR_INSERT))
- goto error;
- if (table_list->handle_derived(thd->lex, DT_PREPARE))
- goto error;
-
- if (!table_list->single_table_updatable())
- {
- my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias.str, "UPDATE");
- goto error;
- }
-
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- /* Force privilege re-checking for views after they have been opened. */
- want_privilege= (table_list->view ? UPDATE_ACL :
- table_list->grant.want_privilege);
-#endif
-
- if (mysql_prepare_update(thd, table_list, &select->where,
- select->order_list.elements,
- select->order_list.first))
- goto error;
-
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- table_list->grant.want_privilege= want_privilege;
- table_list->table->grant.want_privilege= want_privilege;
- table_list->register_want_access(want_privilege);
-#endif
- thd->lex->first_select_lex()->no_wrap_view_item= TRUE;
- res= setup_fields(thd, Ref_ptr_array(),
- select->item_list, MARK_COLUMNS_READ, 0, NULL, 0);
- thd->lex->first_select_lex()->no_wrap_view_item= FALSE;
- if (res)
- goto error;
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- /* Check values */
- table_list->grant.want_privilege=
- table_list->table->grant.want_privilege=
- (SELECT_ACL & ~table_list->table->grant.privilege);
- table_list->register_want_access(SELECT_ACL);
-#endif
- if (setup_fields(thd, Ref_ptr_array(),
- stmt->lex->value_list, COLUMNS_READ, 0, NULL, 0) ||
- check_unique_table(thd, table_list))
- goto error;
- /* TODO: here we should send types of placeholders to the client. */
- DBUG_RETURN(0);
-error:
- DBUG_RETURN(1);
-}
-
-
-/**
- Validate DELETE statement.
-
- @param stmt prepared statement
- @param tables list of tables used in this query
-
- @retval
- FALSE success
- @retval
- TRUE error, error message is set in THD
-*/
-
-static bool mysql_test_delete(Prepared_statement *stmt,
- TABLE_LIST *table_list)
-{
- uint table_count= 0;
- THD *thd= stmt->thd;
- LEX *lex= stmt->lex;
- bool delete_while_scanning;
- DBUG_ENTER("mysql_test_delete");
-
- if (delete_precheck(thd, table_list) ||
- open_tables(thd, &table_list, &table_count, MYSQL_OPEN_FORCE_SHARED_MDL))
- goto error;
-
- if (mysql_handle_derived(thd->lex, DT_INIT))
- goto error;
- if (mysql_handle_derived(thd->lex, DT_MERGE_FOR_INSERT))
- goto error;
- if (mysql_handle_derived(thd->lex, DT_PREPARE))
- goto error;
-
- if (!table_list->single_table_updatable())
- {
- my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias.str, "DELETE");
- goto error;
- }
- if (!table_list->table || !table_list->table->is_created())
- {
- my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
- table_list->view_db.str, table_list->view_name.str);
- goto error;
- }
-
- DBUG_RETURN(mysql_prepare_delete(thd, table_list,
- &lex->first_select_lex()->where,
- &delete_while_scanning));
-error:
- DBUG_RETURN(TRUE);
-}
/**
@@ -2135,74 +1979,6 @@ static bool mysql_test_create_view(Prepared_statement *stmt)
}
-/*
- Validate and prepare for execution a multi update statement.
-
- @param stmt prepared statement
- @param tables list of tables used in this query
- @param converted converted to multi-update from usual update
-
- @retval
- FALSE success
- @retval
- TRUE error, error message is set in THD
-*/
-
-static bool mysql_test_multiupdate(Prepared_statement *stmt,
- TABLE_LIST *tables,
- bool converted)
-{
- /* if we switched from normal update, rights are checked */
- if (!converted && multi_update_precheck(stmt->thd, tables))
- return TRUE;
-
- return select_like_stmt_test(stmt, &mysql_multi_update_prepare,
- OPTION_SETUP_TABLES_DONE);
-}
-
-
-/**
- Validate and prepare for execution a multi delete statement.
-
- @param stmt prepared statement
- @param tables list of tables used in this query
-
- @retval
- FALSE success
- @retval
- TRUE error, error message in THD is set.
-*/
-
-static bool mysql_test_multidelete(Prepared_statement *stmt,
- TABLE_LIST *tables)
-{
- THD *thd= stmt->thd;
-
- thd->lex->current_select= thd->lex->first_select_lex();
- if (add_item_to_list(thd, new (thd->mem_root)
- Item_null(thd)))
- {
- my_error(ER_OUTOFMEMORY, MYF(ME_FATAL), 0);
- goto error;
- }
-
- if (multi_delete_precheck(thd, tables) ||
- select_like_stmt_test_with_open(stmt, tables,
- &mysql_multi_delete_prepare,
- OPTION_SETUP_TABLES_DONE))
- goto error;
- if (!tables->table)
- {
- my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
- tables->view_db.str, tables->view_name.str);
- goto error;
- }
- return FALSE;
-error:
- return TRUE;
-}
-
-
/**
Wrapper for mysql_insert_select_prepare, to make change of local tables
after open_normal_and_derived_tables() call.
@@ -2484,18 +2260,14 @@ static bool check_prepared_statement(Prepared_statement *stmt)
break;
case SQLCOM_UPDATE:
- res= mysql_test_update(stmt, tables);
- /* mysql_test_update returns 2 if we need to switch to multi-update */
- if (res != 2)
- break;
- /* fall through */
case SQLCOM_UPDATE_MULTI:
- res= mysql_test_multiupdate(stmt, tables, res == 2);
- break;
-
case SQLCOM_DELETE:
- res= mysql_test_delete(stmt, tables);
+ case SQLCOM_DELETE_MULTI:
+ res = lex->m_sql_cmd->prepare(thd);
+ if (!res)
+ lex->m_sql_cmd->unprepare(thd);
break;
+
/* The following allow WHERE clause, so they must be tested like SELECT */
case SQLCOM_SHOW_DATABASES:
case SQLCOM_SHOW_TABLES:
@@ -2632,10 +2404,6 @@ static bool check_prepared_statement(Prepared_statement *stmt)
res= mysql_test_set_fields(stmt, tables, &lex->var_list);
break;
- case SQLCOM_DELETE_MULTI:
- res= mysql_test_multidelete(stmt, tables);
- break;
-
case SQLCOM_INSERT_SELECT:
case SQLCOM_REPLACE_SELECT:
res= mysql_test_insert_select(stmt, tables);
@@ -4373,6 +4141,9 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
thd->is_error() ||
init_param_array(this));
+ if (lex->m_sql_cmd)
+ lex->m_sql_cmd->set_owner(this);
+
if (thd->security_ctx->password_expired &&
lex->sql_command != SQLCOM_SET_OPTION &&
lex->sql_command != SQLCOM_PREPARE &&
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 2a56292..bf49d69 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1430,7 +1430,7 @@ JOIN::prepare(TABLE_LIST *tables_init, COND *conds_init, uint og_num,
}
}
- if (setup_fields(thd, ref_ptrs, fields_list, MARK_COLUMNS_READ,
+ if (setup_fields(thd, ref_ptrs, fields_list, select_lex->item_list_usage,
&all_fields, &select_lex->pre_fix, 1))
DBUG_RETURN(-1);
thd->lex->current_select->context_analysis_place= save_place;
@@ -1720,6 +1720,8 @@ JOIN::prepare(TABLE_LIST *tables_init, COND *conds_init, uint og_num,
if (!procedure && result && result->prepare(fields_list, unit_arg))
goto err; /* purecov: inspected */
+ select_lex->where_cond_after_prepare= conds;
+
unit= unit_arg;
if (prepare_stage2())
goto err;
@@ -29028,7 +29030,8 @@ static bool get_range_limit_read_cost(const JOIN_TAB *tab,
@note
This function takes into account table->opt_range_condition_rows statistic
(that is calculated by the make_join_statistics function).
- However, single table procedures such as mysql_update() and mysql_delete()
+ However, single table procedures such as Sql_cmd_update:update_single_table()
+ and Sql_cmd_delete::delete_single_table()
never call make_join_statistics, so they have to update it manually
(@see get_index_for_order()).
*/
@@ -30463,6 +30466,266 @@ static bool process_direct_rownum_comparison(THD *thd, SELECT_LEX_UNIT *unit,
}
+static void MYSQL_DML_START(THD *thd)
+{
+ switch (thd->lex->sql_command) {
+
+ case SQLCOM_UPDATE:
+ MYSQL_UPDATE_START(thd->query());
+ break;
+ case SQLCOM_UPDATE_MULTI:
+ MYSQL_MULTI_UPDATE_START(thd->query());
+ break;
+ case SQLCOM_DELETE:
+ MYSQL_DELETE_START(thd->query());
+ break;
+ case SQLCOM_DELETE_MULTI:
+ MYSQL_MULTI_DELETE_START(thd->query());
+ break;
+ default:
+ DBUG_ASSERT(0);
+ }
+}
+
+
+static void MYSQL_DML_DONE(THD *thd, int rc)
+{
+ switch (thd->lex->sql_command) {
+
+ case SQLCOM_UPDATE:
+ MYSQL_UPDATE_DONE(
+ rc,
+ (rc ? 0 :
+ ((multi_update*)(((Sql_cmd_dml*)(thd->lex->m_sql_cmd))->get_result()))
+ ->num_found()),
+ (rc ? 0 :
+ ((multi_update*)(((Sql_cmd_dml*)(thd->lex->m_sql_cmd))->get_result()))
+ ->num_updated()));
+ break;
+ case SQLCOM_UPDATE_MULTI:
+ MYSQL_MULTI_UPDATE_DONE(
+ rc,
+ (rc ? 0 :
+ ((multi_update*)(((Sql_cmd_dml*)(thd->lex->m_sql_cmd))->get_result()))
+ ->num_found()),
+ (rc ? 0 :
+ ((multi_update*)(((Sql_cmd_dml*)(thd->lex->m_sql_cmd))->get_result()))
+ ->num_updated()));
+ break;
+ case SQLCOM_DELETE:
+ MYSQL_DELETE_DONE(rc, (rc ? 0 : (ulong) (thd->get_row_count_func())));
+ break;
+ case SQLCOM_DELETE_MULTI:
+ MYSQL_MULTI_DELETE_DONE(
+ rc,
+ (rc ? 0 :
+ ((multi_delete*)(((Sql_cmd_dml*)(thd->lex->m_sql_cmd))->get_result()))
+ ->num_deleted()));
+ break;
+ default:
+ DBUG_ASSERT(0);
+ }
+}
+
+/*
+ @brief Perform actions needed before locking tables for a DML statement
+
+ @param thd global context the processed statement
+ @returns false if success, true if error
+
+ @details
+ This function calls the precheck() procedure fo the processed statement,
+ then is opens tables used in the statement and finally it calls the function
+ prepare_inner() that is specific for the type of the statement.
+
+ @note
+ The function are used when processing:
+ - a DML statement
+ - PREPARE stmt FROM <DML "statement>"
+ - EXECUTE stmt when stmt is prepared from a DML statement.
+*/
+
+bool Sql_cmd_dml::prepare(THD *thd)
+{
+ lex= thd->lex;
+ SELECT_LEX_UNIT *unit= &lex->unit;
+
+ DBUG_ASSERT(!is_prepared());
+
+ // Perform a coarse statement-specific privilege check.
+ if (precheck(thd))
+ goto err;
+
+ MYSQL_DML_START(thd);
+
+ lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_DERIVED;
+
+ if (open_tables_for_query(thd, lex->query_tables, &table_count, 0,
+ get_dml_prelocking_strategy()))
+ {
+ if (thd->is_error())
+ goto err;
+ (void)unit->cleanup();
+ return true;
+ }
+
+ if (prepare_inner(thd))
+ goto err;
+
+ lex->context_analysis_only&= ~CONTEXT_ANALYSIS_ONLY_DERIVED;
+
+ set_prepared();
+ unit->set_prepared();
+
+ return false;
+
+err:
+ DBUG_ASSERT(thd->is_error());
+ DBUG_PRINT("info", ("report_error: %d", thd->is_error()));
+
+ (void)unit->cleanup();
+
+ return true;
+}
+
+
+/**
+ @brief Execute a DML statement
+
+ @param thd global context the processed statement
+ @returns false if success, true if error
+
+ @details
+ The function assumes that each type of a DML statement has its own
+ implementation of the virtunal functions precheck(). It is also
+ assumed that that the virtual function execute execute_inner() is to be
+ overridden by the implementations for specific commands.
+
+ @note
+ Currently only UPDATE and DELETE statement are executed using this function.
+*/
+
+bool Sql_cmd_dml::execute(THD *thd)
+{
+ lex = thd->lex;
+ bool res;
+
+ SELECT_LEX_UNIT *unit = &lex->unit;
+ SELECT_LEX *select_lex= lex->first_select_lex();
+
+ if (!is_prepared())
+ {
+ /*
+ This is called when processing
+ - a DML statement
+ - PREPARE stmt FROM <DML "statement>"
+ - EXECUTE stmt when stmt is prepared from a DML statement.
+ The call will invoke open_tables_for_query()
+ */
+ if (prepare(thd))
+ goto err;
+ }
+ else // This branch currently is never used for DML commands
+ {
+ if (precheck(thd))
+ goto err;
+
+ MYSQL_DML_START(thd);
+
+ if (open_tables_for_query(thd, lex->query_tables, &table_count, 0,
+ get_dml_prelocking_strategy()))
+ goto err;
+ }
+
+ THD_STAGE_INFO(thd, stage_init);
+
+ /*
+ Locking of tables is done after preparation but before optimization.
+ This allows to do better partition pruning and avoid locking unused
+ partitions. As a consequence, in such a case, prepare stage can rely only
+ on metadata about tables used and not data from them.
+ */
+ if (!is_empty_query())
+ {
+ if (lock_tables(thd, lex->query_tables, table_count, 0))
+ goto err;
+ }
+
+ unit->set_limit(select_lex);
+
+ /* Perform statement-specific execution */
+ res = execute_inner(thd);
+
+ if (res)
+ goto err;
+
+ res= unit->cleanup();
+
+ /* "Unprepare" this object since unit->cleanup actually unprepares */
+ unprepare(thd);
+
+ THD_STAGE_INFO(thd, stage_end);
+
+ MYSQL_DML_DONE(thd, res);
+
+ return res;
+
+err:
+ DBUG_ASSERT(thd->is_error() || thd->killed);
+ MYSQL_DML_DONE(thd, 1);
+ THD_STAGE_INFO(thd, stage_end);
+ (void)unit->cleanup();
+
+ return thd->is_error();
+}
+
+/**
+ @brief Generic implemention of optimization and execution phases
+ @param thd global context the processed statement
+ @returns false if success, true if error
+
+ @note
+ This implementation assumes that the processed DML statement is represented
+ as a SELECT_LEX or SELECT_LEX_UNIT tree with attached corresponding
+ JOIN structures. Any JOIN structure is constructed at the prepare phase.
+ When created at the top level join it is provided with an object of a class
+ derived from select_result_sink. The pointer to the object is saved in
+ the this->result field. For different types of DML statements different
+ derived classes are used for this object. The class of this object determines
+ additional specific actions performed at the phases of context analysis,
+ optimization and execution.
+*/
+
+bool Sql_cmd_dml::execute_inner(THD *thd)
+{
+ SELECT_LEX_UNIT *unit = &lex->unit;
+ SELECT_LEX *select_lex= unit->first_select();
+ JOIN *join= select_lex->join;
+
+ if (join->optimize())
+ goto err;
+
+ if (thd->lex->describe & DESCRIBE_EXTENDED)
+ {
+ join->conds_history= join->conds;
+ join->having_history= (join->having?join->having:join->tmp_having);
+ }
+
+ if (unlikely(thd->is_error()))
+ goto err;
+
+ join->exec();
+
+ if (thd->lex->describe & DESCRIBE_EXTENDED)
+ {
+ select_lex->where= join->conds_history;
+ select_lex->having= join->having_history;
+ }
+
+err:
+ return join->error;
+}
+
/**
@} (end of group Query_Optimizer)
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 74ed078..6b14c4f 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -197,22 +197,11 @@ static bool check_fields(THD *thd, TABLE_LIST *table, List<Item> &items,
return true;
}
- DBUG_ASSERT(thd->lex->sql_command == SQLCOM_UPDATE);
- for (List_iterator_fast<Item> it(items); (item=it++);)
- {
- Field *f= item->field_for_view_update()->field;
- vers_select_conds_t &period= table->period_conditions;
- if (period.field_start->field == f || period.field_end->field == f)
- {
- my_error(ER_PERIOD_COLUMNS_UPDATED, MYF(0),
- item->name.str, period.name.str);
- return true;
- }
- }
}
return FALSE;
}
+
bool TABLE::vers_check_update(List<Item> &items)
{
List_iterator<Item> it(items);
@@ -339,36 +328,25 @@ int cut_fields_for_portion_of_time(THD *thd, TABLE *table,
return res;
}
-/*
- Process usual UPDATE
-
- SYNOPSIS
- mysql_update()
- thd thread handler
- fields fields for update
- values values of fields for update
- conds WHERE clause expression
- order_num number of elemen in ORDER BY clause
- order ORDER BY clause list
- limit limit clause
+/**
+ @brief Special handling of single-table updates after prepare phase
- RETURN
- 0 - OK
- 2 - privilege check and openning table passed, but we need to convert to
- multi-update because of view substitution
- 1 - error
+ @param thd global context the processed statement
+ @returns false on success, true on error
*/
-int mysql_update(THD *thd,
- TABLE_LIST *table_list,
- List<Item> &fields,
- List<Item> &values,
- COND *conds,
- uint order_num, ORDER *order,
- ha_rows limit,
- bool ignore,
- ha_rows *found_return, ha_rows *updated_return)
+bool Sql_cmd_update::update_single_table(THD *thd)
{
+ SELECT_LEX_UNIT *unit = &lex->unit;
+ SELECT_LEX *select_lex= unit->first_select();
+ TABLE_LIST *const table_list = select_lex->get_table_list();
+ List<Item> *fields= &select_lex->item_list;
+ List<Item> *values= &lex->value_list;
+ COND *conds= select_lex->where_cond_after_prepare;
+ ORDER *order= select_lex->order_list.first;
+ ha_rows limit= unit->lim.get_select_limit();
+ bool ignore= lex->ignore;
+
bool using_limit= limit != HA_POS_ERROR;
bool safe_update= (thd->variables.option_bits & OPTION_SAFE_UPDATES)
&& !thd->lex->describe;
@@ -380,76 +358,39 @@ int mysql_update(THD *thd,
ha_rows dup_key_found;
bool need_sort= TRUE;
bool reverse= FALSE;
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- privilege_t want_privilege(NO_ACL);
-#endif
- uint table_count= 0;
ha_rows updated, updated_or_same, found;
key_map old_covering_keys;
TABLE *table;
SQL_SELECT *select= NULL;
SORT_INFO *file_sort= 0;
READ_RECORD info;
- SELECT_LEX *select_lex= thd->lex->first_select_lex();
ulonglong id;
List<Item> all_fields;
killed_state killed_status= NOT_KILLED;
bool has_triggers, binlog_is_row, do_direct_update= FALSE;
Update_plan query_plan(thd->mem_root);
Explain_update *explain;
- TABLE_LIST *update_source_table;
query_plan.index= MAX_KEY;
query_plan.using_filesort= FALSE;
// For System Versioning (may need to insert new fields to a table).
ha_rows rows_inserted= 0;
- DBUG_ENTER("mysql_update");
+ DBUG_ENTER("Sql_cmd_update::update_single_table");
+ THD_STAGE_INFO(thd, stage_init_update);
create_explain_query(thd->lex, thd->mem_root);
- if (open_tables(thd, &table_list, &table_count, 0))
- DBUG_RETURN(1);
-
- /* Prepare views so they are handled correctly */
- if (mysql_handle_derived(thd->lex, DT_INIT))
- DBUG_RETURN(1);
- if (table_list->has_period() && table_list->is_view_or_derived())
- {
- my_error(ER_IT_IS_A_VIEW, MYF(0), table_list->table_name.str);
- DBUG_RETURN(TRUE);
- }
-
- if (((update_source_table=unique_table(thd, table_list,
- table_list->next_global, 0)) ||
- table_list->is_multitable()))
- {
- DBUG_ASSERT(update_source_table || table_list->view != 0);
- DBUG_PRINT("info", ("Switch to multi-update"));
- /* pass counter value */
- thd->lex->table_count= table_count;
- if (thd->lex->period_conditions.is_set())
- {
- my_error(ER_NOT_SUPPORTED_YET, MYF(0),
- "updating and querying the same temporal periods table");
+ thd->table_map_for_update= 0;
- DBUG_RETURN(1);
- }
-
- /* convert to multiupdate */
- DBUG_RETURN(2);
- }
- if (lock_tables(thd, table_list, table_count, 0))
- DBUG_RETURN(1);
-
- (void) read_statistics_for_tables_if_needed(thd, table_list);
-
- THD_STAGE_INFO(thd, stage_init_update);
if (table_list->handle_derived(thd->lex, DT_MERGE_FOR_INSERT))
DBUG_RETURN(1);
if (table_list->handle_derived(thd->lex, DT_PREPARE))
DBUG_RETURN(1);
+ if (setup_ftfuncs(select_lex))
+ DBUG_RETURN(1);
+
table= table_list->table;
if (!table_list->single_table_updatable())
@@ -458,85 +399,26 @@ int mysql_update(THD *thd,
DBUG_RETURN(1);
}
- /* Calculate "table->covering_keys" based on the WHERE */
- table->covering_keys= table->s->keys_in_use;
table->opt_range_keys.clear_all();
query_plan.select_lex= thd->lex->first_select_lex();
query_plan.table= table;
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- /* Force privilege re-checking for views after they have been opened. */
- want_privilege= (table_list->view ? UPDATE_ACL :
- table_list->grant.want_privilege);
-#endif
thd->lex->promote_select_describe_flag_if_needed();
- if (mysql_prepare_update(thd, table_list, &conds, order_num, order))
- DBUG_RETURN(1);
-
- if (table_list->has_period())
- {
- if (!table_list->period_conditions.start.item->const_item()
- || !table_list->period_conditions.end.item->const_item())
- {
- my_error(ER_NOT_CONSTANT_EXPRESSION, MYF(0), "FOR PORTION OF");
- DBUG_RETURN(true);
- }
- table->no_cache= true;
- }
-
old_covering_keys= table->covering_keys; // Keys used in WHERE
- /* Check the fields we are going to modify */
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- table_list->grant.want_privilege= table->grant.want_privilege= want_privilege;
- table_list->register_want_access(want_privilege);
-#endif
- /* 'Unfix' fields to allow correct marking by the setup_fields function. */
- if (table_list->is_view())
- unfix_fields(fields);
- if (setup_fields_with_no_wrap(thd, Ref_ptr_array(),
- fields, MARK_COLUMNS_WRITE, 0, 0))
- DBUG_RETURN(1); /* purecov: inspected */
- if (check_fields(thd, table_list, fields, table_list->view))
- {
- DBUG_RETURN(1);
- }
- bool has_vers_fields= table->vers_check_update(fields);
- if (check_key_in_view(thd, table_list))
- {
- my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias.str, "UPDATE");
- DBUG_RETURN(1);
- }
+ bool has_vers_fields= table->vers_check_update(*fields);
if (table->default_field)
table->mark_default_fields_for_write(false);
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- /* Check values */
- table_list->grant.want_privilege= table->grant.want_privilege=
- (SELECT_ACL & ~table->grant.privilege);
-#endif
- if (setup_fields(thd, Ref_ptr_array(), values, MARK_COLUMNS_READ, 0, NULL, 0))
- {
- free_underlaid_joins(thd, select_lex);
- DBUG_RETURN(1); /* purecov: inspected */
- }
-
- if (check_unique_table(thd, table_list))
- DBUG_RETURN(TRUE);
-
- switch_to_nullable_trigger_fields(fields, table);
- switch_to_nullable_trigger_fields(values, table);
+ switch_to_nullable_trigger_fields(*fields, table);
+ switch_to_nullable_trigger_fields(*values, table);
/* Apply the IN=>EXISTS transformation to all subqueries and optimize them */
if (select_lex->optimize_unflattened_subqueries(false))
DBUG_RETURN(TRUE);
- if (select_lex->inner_refs_list.elements &&
- fix_inner_refs(thd, all_fields, select_lex, select_lex->ref_pointer_array))
- DBUG_RETURN(1);
-
if (conds)
{
Item::cond_result cond_value;
@@ -776,9 +658,9 @@ int mysql_update(THD *thd,
}
if (use_direct_update &&
- !table->file->info_push(INFO_KIND_UPDATE_FIELDS, &fields) &&
- !table->file->info_push(INFO_KIND_UPDATE_VALUES, &values) &&
- !table->file->direct_update_rows_init(&fields))
+ !table->file->info_push(INFO_KIND_UPDATE_FIELDS, fields) &&
+ !table->file->info_push(INFO_KIND_UPDATE_VALUES, values) &&
+ !table->file->direct_update_rows_init(fields))
{
do_direct_update= TRUE;
@@ -1027,7 +909,7 @@ int mysql_update(THD *thd,
cut_fields_for_portion_of_time(thd, table,
table_list->period_conditions);
- if (fill_record_n_invoke_before_triggers(thd, table, fields, values, 0,
+ if (fill_record_n_invoke_before_triggers(thd, table, *fields, *values, 0,
TRG_EVENT_UPDATE))
break; /* purecov: inspected */
@@ -1360,9 +1242,9 @@ int mysql_update(THD *thd,
thd->lex->current_select->save_leaf_tables(thd);
thd->lex->current_select->first_cond_optimization= 0;
}
- *found_return= found;
- *updated_return= updated;
-
+ ((multi_update *)result)->set_found(found);
+ ((multi_update *)result)->set_updated(updated);
+
if (unlikely(thd->lex->analyze_stmt))
goto emit_explain_and_leave;
@@ -1394,75 +1276,6 @@ int mysql_update(THD *thd,
DBUG_RETURN((err2 || thd->is_error()) ? 1 : 0);
}
-/*
- Prepare items in UPDATE statement
-
- SYNOPSIS
- mysql_prepare_update()
- thd - thread handler
- table_list - global/local table list
- conds - conditions
- order_num - number of ORDER BY list entries
- order - ORDER BY clause list
-
- RETURN VALUE
- FALSE OK
- TRUE error
-*/
-bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
- Item **conds, uint order_num, ORDER *order)
-{
- Item *fake_conds= 0;
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- TABLE *table= table_list->table;
-#endif
- List<Item> all_fields;
- SELECT_LEX *select_lex= thd->lex->first_select_lex();
- DBUG_ENTER("mysql_prepare_update");
-
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- table_list->grant.want_privilege= table->grant.want_privilege=
- (SELECT_ACL & ~table->grant.privilege);
- table_list->register_want_access(SELECT_ACL);
-#endif
-
- thd->lex->allow_sum_func.clear_all();
-
- if (table_list->has_period() &&
- select_lex->period_setup_conds(thd, table_list))
- DBUG_RETURN(true);
-
- DBUG_ASSERT(table_list->table);
- // conds could be cached from previous SP call
- DBUG_ASSERT(!table_list->vers_conditions.need_setup() ||
- !*conds || thd->stmt_arena->is_stmt_execute());
- if (select_lex->vers_setup_conds(thd, table_list))
- DBUG_RETURN(TRUE);
-
- *conds= select_lex->where;
-
- /*
- We do not call DT_MERGE_FOR_INSERT because it has no sense for simple
- (not multi-) update
- */
- if (mysql_handle_derived(thd->lex, DT_PREPARE))
- DBUG_RETURN(TRUE);
-
- if (setup_tables_and_check_access(thd, &select_lex->context,
- &select_lex->top_join_list, table_list,
- select_lex->leaf_tables,
- FALSE, UPDATE_ACL, SELECT_ACL, TRUE) ||
- setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
- select_lex->setup_ref_array(thd, order_num) ||
- setup_order(thd, select_lex->ref_pointer_array,
- table_list, all_fields, all_fields, order) ||
- setup_ftfuncs(select_lex))
- DBUG_RETURN(TRUE);
-
-
- select_lex->fix_prepare_information(thd, conds, &fake_conds);
- DBUG_RETURN(FALSE);
-}
/**
Check that we are not using table that we are updating in a sub select
@@ -1690,15 +1503,6 @@ static bool multi_update_check_table_access(THD *thd, TABLE_LIST *table,
}
-class Multiupdate_prelocking_strategy : public DML_prelocking_strategy
-{
- bool done;
- bool has_prelocking_list;
-public:
- void reset(THD *thd);
- bool handle_end(THD *thd);
-};
-
void Multiupdate_prelocking_strategy::reset(THD *thd)
{
done= false;
@@ -1728,7 +1532,13 @@ bool Multiupdate_prelocking_strategy::handle_end(THD *thd)
mysql_handle_derived(lex, DT_PREPARE))
DBUG_RETURN(1);
- /*
+ if (table_list->has_period() && table_list->is_view_or_derived())
+ {
+ my_error(ER_IT_IS_A_VIEW, MYF(0), table_list->table_name.str);
+ DBUG_RETURN(TRUE);
+ }
+
+ /*
setup_tables() need for VIEWs. JOIN::prepare() will call setup_tables()
second time, but this call will do nothing (there are check for second
call in setup_tables()).
@@ -1739,6 +1549,10 @@ bool Multiupdate_prelocking_strategy::handle_end(THD *thd)
FALSE, UPDATE_ACL, SELECT_ACL, TRUE))
DBUG_RETURN(1);
+ if (table_list->has_period() &&
+ select_lex->period_setup_conds(thd, table_list))
+ DBUG_RETURN(true);
+
List<Item> *fields= &lex->first_select_lex()->item_list;
if (setup_fields_with_no_wrap(thd, Ref_ptr_array(),
*fields, MARK_COLUMNS_WRITE, 0, 0))
@@ -1847,153 +1661,6 @@ bool Multiupdate_prelocking_strategy::handle_end(THD *thd)
DBUG_RETURN(0);
}
-/*
- make update specific preparation and checks after opening tables
-
- SYNOPSIS
- mysql_multi_update_prepare()
- thd thread handler
-
- RETURN
- FALSE OK
- TRUE Error
-*/
-
-int mysql_multi_update_prepare(THD *thd)
-{
- LEX *lex= thd->lex;
- TABLE_LIST *table_list= lex->query_tables;
- TABLE_LIST *tl;
- Multiupdate_prelocking_strategy prelocking_strategy;
- uint table_count= lex->table_count;
- DBUG_ENTER("mysql_multi_update_prepare");
-
- /*
- Open tables and create derived ones, but do not lock and fill them yet.
-
- During prepare phase acquire only S metadata locks instead of SW locks to
- keep prepare of multi-UPDATE compatible with concurrent LOCK TABLES WRITE
- and global read lock.
-
- Don't evaluate any subqueries even if constant, because
- tables aren't locked yet.
- */
- lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_DERIVED;
- if (thd->lex->sql_command == SQLCOM_UPDATE_MULTI)
- {
- if (open_tables(thd, &table_list, &table_count,
- thd->stmt_arena->is_stmt_prepare() ? MYSQL_OPEN_FORCE_SHARED_MDL : 0,
- &prelocking_strategy))
- DBUG_RETURN(TRUE);
- }
- else
- {
- /* following need for prepared statements, to run next time multi-update */
- thd->lex->sql_command= SQLCOM_UPDATE_MULTI;
- prelocking_strategy.reset(thd);
- if (prelocking_strategy.handle_end(thd))
- DBUG_RETURN(TRUE);
- }
-
- /* now lock and fill tables */
- if (!thd->stmt_arena->is_stmt_prepare() &&
- lock_tables(thd, table_list, table_count, 0))
- DBUG_RETURN(TRUE);
-
- lex->context_analysis_only&= ~CONTEXT_ANALYSIS_ONLY_DERIVED;
-
- (void) read_statistics_for_tables_if_needed(thd, table_list);
- /* @todo: downgrade the metadata locks here. */
-
- /*
- Check that we are not using table that we are updating, but we should
- skip all tables of UPDATE SELECT itself
- */
- lex->first_select_lex()->exclude_from_table_unique_test= TRUE;
- /* We only need SELECT privilege for columns in the values list */
- List_iterator<TABLE_LIST> ti(lex->first_select_lex()->leaf_tables);
- while ((tl= ti++))
- {
- if (tl->is_jtbm())
- continue;
- TABLE *table= tl->table;
- TABLE_LIST *tlist;
- if (!(tlist= tl->top_table())->derived)
- {
- tlist->grant.want_privilege=
- (SELECT_ACL & ~tlist->grant.privilege);
- table->grant.want_privilege= (SELECT_ACL & ~table->grant.privilege);
- }
- DBUG_PRINT("info", ("table: %s want_privilege: %llx", tl->alias.str,
- (longlong) table->grant.want_privilege));
- }
- /*
- Set exclude_from_table_unique_test value back to FALSE. It is needed for
- further check in multi_update::prepare whether to use record cache.
- */
- lex->first_select_lex()->exclude_from_table_unique_test= FALSE;
-
- if (lex->save_prep_leaf_tables())
- DBUG_RETURN(TRUE);
-
- DBUG_RETURN (FALSE);
-}
-
-
-/*
- Setup multi-update handling and call SELECT to do the join
-*/
-
-bool mysql_multi_update(THD *thd, TABLE_LIST *table_list, List<Item> *fields,
- List<Item> *values, COND *conds, ulonglong options,
- enum enum_duplicates handle_duplicates,
- bool ignore, SELECT_LEX_UNIT *unit,
- SELECT_LEX *select_lex, multi_update **result)
-{
- bool res;
- DBUG_ENTER("mysql_multi_update");
-
- if (!(*result= new (thd->mem_root) multi_update(thd, table_list,
- &thd->lex->first_select_lex()->leaf_tables,
- fields, values, handle_duplicates, ignore)))
- {
- DBUG_RETURN(TRUE);
- }
-
- if ((*result)->init(thd))
- DBUG_RETURN(1);
-
- thd->abort_on_warning= !ignore && thd->is_strict_mode();
- List<Item> total_list;
-
- if (setup_tables(thd, &select_lex->context, &select_lex->top_join_list,
- table_list, select_lex->leaf_tables, FALSE, FALSE))
- DBUG_RETURN(1);
-
- if (select_lex->vers_setup_conds(thd, table_list))
- DBUG_RETURN(1);
-
- res= mysql_select(thd,
- table_list, total_list, conds,
- select_lex->order_list.elements,
- select_lex->order_list.first, NULL, NULL, NULL,
- options | SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK |
- OPTION_SETUP_TABLES_DONE,
- *result, unit, select_lex);
-
- DBUG_PRINT("info",("res: %d report_error: %d", res, (int) thd->is_error()));
- res|= thd->is_error();
- if (unlikely(res))
- (*result)->abort_result_set();
- else
- {
- if (thd->lex->describe || thd->lex->analyze_stmt)
- res= thd->lex->explain->send_explain(thd);
- }
- thd->abort_on_warning= 0;
- DBUG_RETURN(res);
-}
-
multi_update::multi_update(THD *thd_arg, TABLE_LIST *table_list,
List<TABLE_LIST> *leaves_list,
@@ -2029,6 +1696,19 @@ bool multi_update::init(THD *thd)
}
+bool multi_update::init_for_single_table(THD *thd)
+{
+ List_iterator_fast<TABLE_LIST> li(*leaves);
+ TABLE_LIST *tbl;
+ while ((tbl =li++))
+ {
+ if (updated_leaves.push_back(tbl, thd->mem_root))
+ return true;
+ }
+ return false;
+}
+
+
/*
Connect fields with tables and create list of tables that are updated
*/
@@ -2102,7 +1782,8 @@ int multi_update::prepare(List<Item> ¬_used_values,
{
table->read_set= &table->def_read_set;
bitmap_union(table->read_set, &table->tmp_set);
- table->file->prepare_for_insert(1);
+ if (!(thd->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_PREPARE))
+ table->file->prepare_for_insert(1);
}
}
if (unlikely(error))
@@ -3123,3 +2804,237 @@ bool multi_update::send_eof()
}
DBUG_RETURN(FALSE);
}
+
+
+/**
+ @brief Perform precheck of table privileges for update statements
+
+ @param thd global context the processed statement
+ @returns false on success, true on error
+*/
+
+bool Sql_cmd_update::precheck(THD *thd)
+{
+ if (!multitable)
+ {
+ if (update_precheck(thd, lex->query_tables))
+ return true;
+ }
+ else
+ {
+ if (multi_update_precheck(thd, lex->query_tables))
+ return true;
+ }
+
+ WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
+
+ return false;
+
+#ifdef WITH_WSREP
+wsrep_error_label:
+#endif
+ return true;
+}
+
+
+/**
+ @brief Perform context analysis for update statements
+
+ @param thd global context the processed statement
+ @returns false on success, true on error
+
+ @note
+ The main bulk of the context analysis actions for and update statement
+ is performed by a call of JOIN::prepare().
+*/
+
+bool Sql_cmd_update::prepare_inner(THD *thd)
+{
+ JOIN *join;
+ int err= 0;
+ SELECT_LEX *const select_lex = thd->lex->first_select_lex();
+ TABLE_LIST *const table_list = select_lex->get_table_list();
+ ulonglong select_options= select_lex->options;
+ bool free_join= 1;
+ DBUG_ENTER("Sql_cmd_update::prepare_inner");
+
+ (void) read_statistics_for_tables_if_needed(thd, table_list);
+
+ THD_STAGE_INFO(thd, stage_init_update);
+
+ if (!multitable)
+ {
+ if (mysql_handle_derived(lex, DT_INIT))
+ DBUG_RETURN(TRUE);
+ }
+
+ if (table_list->has_period() && table_list->is_view_or_derived())
+ {
+ my_error(ER_IT_IS_A_VIEW, MYF(0), table_list->table_name.str);
+ DBUG_RETURN(TRUE);
+ }
+
+ if (!multitable)
+ {
+ TABLE_LIST *update_source_table= 0;
+
+ if (((update_source_table=unique_table(thd, table_list,
+ table_list->next_global, 0)) ||
+ table_list->is_multitable()))
+ {
+ DBUG_ASSERT(update_source_table || table_list->view != 0);
+ if (thd->lex->period_conditions.is_set())
+ {
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0),
+ "updating and querying the same temporal periods table");
+ DBUG_RETURN(TRUE);
+ }
+ multitable= true;
+ }
+ }
+
+ if(!multitable)
+ {
+ if (table_list->is_view_or_derived() &&
+ select_lex->leaf_tables.elements > 1)
+ multitable = true;
+ }
+
+ if (!multitable)
+ {
+ if (lex->ignore)
+ lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_UPDATE_IGNORE);
+ }
+
+ if (!(result= new (thd->mem_root) multi_update(thd, table_list,
+ &select_lex->leaf_tables,
+ &select_lex->item_list,
+ &lex->value_list,
+ lex->duplicates,
+ lex->ignore)))
+ {
+ DBUG_RETURN(TRUE);
+ }
+
+ if (((multi_update *)result)->init(thd))
+ DBUG_RETURN(TRUE);
+
+ if (setup_tables(thd, &select_lex->context, &select_lex->top_join_list,
+ table_list, select_lex->leaf_tables, false, false))
+ DBUG_RETURN(TRUE);
+
+ if (select_lex->vers_setup_conds(thd, table_list))
+ DBUG_RETURN(TRUE);
+
+ {
+ if (thd->lex->describe)
+ select_options|= SELECT_DESCRIBE;
+
+ /*
+ When in EXPLAIN, delay deleting the joins so that they are still
+ available when we're producing EXPLAIN EXTENDED warning text.
+ */
+ if (select_options & SELECT_DESCRIBE)
+ free_join= 0;
+
+ select_options|=
+ SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK | OPTION_SETUP_TABLES_DONE;
+
+ if (!(join= new (thd->mem_root) JOIN(thd, select_lex->item_list,
+ select_options, result)))
+ DBUG_RETURN(TRUE);
+ THD_STAGE_INFO(thd, stage_init);
+ select_lex->join= join;
+ thd->lex->used_tables=0;
+ select_lex->item_list_usage= MARK_COLUMNS_WRITE;
+ if ((err= join->prepare(table_list, select_lex->where,
+ select_lex->order_list.elements,
+ select_lex->order_list.first,
+ false, NULL, NULL, NULL,
+ select_lex, &lex->unit)))
+ {
+ goto err;
+ }
+
+ }
+
+ if (table_list->has_period())
+ {
+ Item *item;
+ for (List_iterator_fast<Item> it(select_lex->item_list); (item=it++);)
+ {
+ Field *f= item->field_for_view_update()->field;
+ vers_select_conds_t &period= table_list->period_conditions;
+ if (period.field_start->field == f || period.field_end->field == f)
+ {
+ my_error(ER_PERIOD_COLUMNS_UPDATED, MYF(0),
+ item->name.str, period.name.str);
+ DBUG_RETURN(true);
+ }
+ }
+
+ if (!table_list->period_conditions.start.item->const_item()
+ || !table_list->period_conditions.end.item->const_item())
+ {
+ my_error(ER_NOT_CONSTANT_EXPRESSION, MYF(0), "FOR PORTION OF");
+ DBUG_RETURN(true);
+ }
+ table_list->table->no_cache= true;
+ }
+
+
+ free_join= false;
+
+err:
+
+ if (free_join)
+ {
+ THD_STAGE_INFO(thd, stage_end);
+ err|= (int)(select_lex->cleanup());
+ DBUG_RETURN(err || thd->is_error());
+ }
+ DBUG_RETURN(err);
+
+}
+
+
+/**
+ @brief Perform optimization and execution actions needed for updates
+
+ @param thd global context the processed statement
+ @returns false on success, true on error
+*/
+
+bool Sql_cmd_update::execute_inner(THD *thd)
+{
+ bool res= 0;
+
+ thd->get_stmt_da()->reset_current_row_for_warning(1);
+ if (!multitable)
+ res= update_single_table(thd);
+ else
+ {
+ thd->abort_on_warning= !thd->lex->ignore && thd->is_strict_mode();
+ res= Sql_cmd_dml::execute_inner(thd);
+ }
+
+ res|= thd->is_error();
+ if (multitable)
+ {
+ if (unlikely(res))
+ result->abort_result_set();
+ else
+ {
+ if (thd->lex->describe || thd->lex->analyze_stmt)
+ res= thd->lex->explain->send_explain(thd);
+ }
+ }
+
+ if (result)
+ {
+ res= false;
+ delete result;
+ }
+
+ return res;
+}
diff --git a/sql/sql_update.h b/sql/sql_update.h
index 65e44d1..d0fc7cb 100644
--- a/sql/sql_update.h
+++ b/sql/sql_update.h
@@ -17,6 +17,8 @@
#define SQL_UPDATE_INCLUDED
#include "sql_class.h" /* enum_duplicates */
+#include "sql_cmd.h" // Sql_cmd_dml
+#include "sql_base.h"
class Item;
struct TABLE_LIST;
@@ -25,20 +27,75 @@ class THD;
typedef class st_select_lex SELECT_LEX;
typedef class st_select_lex_unit SELECT_LEX_UNIT;
-bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
- Item **conds, uint order_num, ORDER *order);
bool check_unique_table(THD *thd, TABLE_LIST *table_list);
-int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields,
- List<Item> &values,COND *conds,
- uint order_num, ORDER *order, ha_rows limit,
- bool ignore, ha_rows *found_return, ha_rows *updated_return);
-bool mysql_multi_update(THD *thd, TABLE_LIST *table_list,
- List<Item> *fields, List<Item> *values,
- COND *conds, ulonglong options,
- enum enum_duplicates handle_duplicates, bool ignore,
- SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex,
- multi_update **result);
bool records_are_comparable(const TABLE *table);
bool compare_record(const TABLE *table);
+/**
+ @class Sql_cmd_update - class used for any UPDATE statements
+
+ This class is derived from Sql_cmd_dml and contains implementations
+ for abstract virtual function of the latter such as precheck() and
+ prepare_inner(). It also overrides the implementation of execute_inner()
+ providing a special handling for single-table update statements that
+ are not converted to multi-table updates.
+ The class provides an object of the Multiupdate_prelocking_strategy class
+ for the virtual function get_dml_prelocking_strategy().
+*/
+class Sql_cmd_update final : public Sql_cmd_dml
+{
+public:
+ Sql_cmd_update(bool multitable_arg)
+ : multitable(multitable_arg)
+ { }
+
+ enum_sql_command sql_command_code() const override
+ {
+ return multitable ? SQLCOM_UPDATE_MULTI : SQLCOM_UPDATE;
+ }
+
+ DML_prelocking_strategy *get_dml_prelocking_strategy()
+ {
+ return &multiupdate_prelocking_strategy;
+ }
+
+protected:
+ /**
+ @brief Perform precheck of table privileges for update statements
+ */
+ bool precheck(THD *thd) override;
+
+ /**
+ @brief Perform context analysis for update statements
+ */
+ bool prepare_inner(THD *thd) override;
+
+ /**
+ @brief Perform optimization and execution actions needed for updates
+ */
+ bool execute_inner(THD *thd) override;
+
+private:
+
+ /**
+ @brief Special handling of single-table updates after prepare phase
+ */
+ bool update_single_table(THD *thd);
+
+ /*
+ True if the statement is a multi-table update or converted to such.
+ For a single-table update this flag is set to true if the statement
+ is supposed to be converted to multi-table update.
+ */
+ bool multitable;
+
+ /* The prelocking strategy used when opening the used tables */
+ Multiupdate_prelocking_strategy multiupdate_prelocking_strategy;
+
+ public:
+ /* The list of the updating expressions used in the set clause */
+ List<Item> *update_value_list;
+
+};
+
#endif /* SQL_UPDATE_INCLUDED */
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 5416cec..a587a37 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -69,6 +69,8 @@
#include "my_base.h"
#include "sql_type_json.h"
#include "json_table.h"
+#include "sql_update.h"
+#include "sql_delete.h"
/* this is to get the bison compilation windows warnings out */
#ifdef _MSC_VER
@@ -1682,7 +1684,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
opt_mi_check_type opt_to mi_check_types
table_to_table_list table_to_table opt_table_list opt_as
handler_rkey_function handler_read_or_scan
- single_multi table_wild_list table_wild_one opt_wild
+ single_multi opt_wild
opt_and
select_var_list select_var_list_init help
opt_extended_describe shutdown
@@ -13242,9 +13244,14 @@ update:
opt_low_priority opt_ignore update_table_list
SET update_list
{
+ bool is_multiupdate= false;
+ LEX *lex= Lex;
SELECT_LEX *slex= Lex->first_select_lex();
if (slex->table_list.elements > 1)
+ {
Lex->sql_command= SQLCOM_UPDATE_MULTI;
+ is_multiupdate= true;
+ }
else if (slex->get_table_list()->derived)
{
/* it is single table update and it is update of derived table */
@@ -13252,10 +13259,13 @@ update:
slex->get_table_list()->alias.str, "UPDATE");
MYSQL_YYABORT;
}
+ if (!(lex->m_sql_cmd=
+ new (thd->mem_root) Sql_cmd_update(is_multiupdate)))
+ MYSQL_YYABORT;
/*
In case of multi-update setting write lock for all tables may
- be too pessimistic. We will decrease lock level if possible in
- mysql_multi_update().
+ be too pessimistic. We will decrease lock level if possible
+ later while processing the statement.
*/
slex->set_lock_for_tables($3, slex->table_list.elements == 1, false);
}
@@ -13312,12 +13322,11 @@ delete:
DELETE_SYM
{
LEX *lex= Lex;
- lex->sql_command= SQLCOM_DELETE;
YYPS->m_lock_type= TL_WRITE_DEFAULT;
YYPS->m_mdl_type= MDL_SHARED_WRITE;
if (Lex->main_select_push())
MYSQL_YYABORT;
- mysql_init_select(lex);
+ mysql_init_delete(lex);
lex->ignore= 0;
lex->first_select_lex()->order_list.empty();
}
@@ -13343,8 +13352,13 @@ delete_part2:
opt_delete_options single_multi {}
| HISTORY_SYM delete_single_table opt_delete_system_time
{
- Lex->last_table()->vers_conditions= Lex->vers_conditions;
- Lex->pop_select(); //main select
+ LEX *lex= Lex;
+ lex->last_table()->vers_conditions= lex->vers_conditions;
+ lex->pop_select(); //main select
+ lex->sql_command= SQLCOM_DELETE;
+ if (!(lex->m_sql_cmd=
+ new (thd->mem_root) Sql_cmd_delete(false)))
+ MYSQL_YYABORT;
}
;
@@ -13378,12 +13392,22 @@ single_multi:
delete_limit_clause
opt_returning
{
+ LEX *lex= Lex;
if ($3)
Select->order_list= *($3);
- Lex->pop_select(); //main select
+ lex->pop_select(); //main select
+ lex->sql_command= SQLCOM_DELETE;
+ if (!(lex->m_sql_cmd=
+ new (thd->mem_root) Sql_cmd_delete(false)))
+ MYSQL_YYABORT;
}
- | table_wild_list
+ | table_alias_ref_list
{
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_DELETE_MULTI;
+ if (!(lex->m_sql_cmd=
+ new (thd->mem_root) Sql_cmd_delete(true)))
+ MYSQL_YYABORT;
mysql_init_multi_delete(Lex);
YYPS->m_lock_type= TL_READ_DEFAULT;
YYPS->m_mdl_type= MDL_SHARED_READ;
@@ -13395,6 +13419,11 @@ single_multi:
} stmt_end {}
| FROM table_alias_ref_list
{
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_DELETE_MULTI;
+ if (!(lex->m_sql_cmd=
+ new (thd->mem_root) Sql_cmd_delete(true)))
+ MYSQL_YYABORT;
mysql_init_multi_delete(Lex);
YYPS->m_lock_type= TL_READ_DEFAULT;
YYPS->m_mdl_type= MDL_SHARED_READ;
@@ -13430,44 +13459,6 @@ opt_returning:
}
;
-table_wild_list:
- table_wild_one
- | table_wild_list ',' table_wild_one
- ;
-
-table_wild_one:
- ident opt_wild
- {
- Table_ident *ti= new (thd->mem_root) Table_ident(&$1);
- if (unlikely(ti == NULL))
- MYSQL_YYABORT;
- if (unlikely(!Select->
- add_table_to_list(thd,
- ti,
- NULL,
- (TL_OPTION_UPDATING |
- TL_OPTION_ALIAS),
- YYPS->m_lock_type,
- YYPS->m_mdl_type)))
- MYSQL_YYABORT;
- }
- | ident '.' ident opt_wild
- {
- Table_ident *ti= new (thd->mem_root) Table_ident(thd, &$1, &$3, 0);
- if (unlikely(ti == NULL))
- MYSQL_YYABORT;
- if (unlikely(!Select->
- add_table_to_list(thd,
- ti,
- NULL,
- (TL_OPTION_UPDATING |
- TL_OPTION_ALIAS),
- YYPS->m_lock_type,
- YYPS->m_mdl_type)))
- MYSQL_YYABORT;
- }
- ;
-
opt_wild:
/* empty */ {}
| '.' '*' {}
diff --git a/sql/table.h b/sql/table.h
index 30517f8..5f8d299 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -2338,6 +2338,7 @@ struct TABLE_LIST
*/
select_unit *derived_result;
/* Stub used for materialized derived tables. */
+ bool delete_while_scanning;
table_map map; /* ID bit of table (1,2,4,8,16...) */
table_map get_map()
{
diff --git a/storage/spider/mysql-test/spider/r/error_row_number.result b/storage/spider/mysql-test/spider/r/error_row_number.result
index cc2b548..ad095fe 100644
--- a/storage/spider/mysql-test/spider/r/error_row_number.result
+++ b/storage/spider/mysql-test/spider/r/error_row_number.result
@@ -29,7 +29,7 @@ ERROR 23000: Duplicate entry '13' for key 'PRIMARY'
get diagnostics condition 1 @n = row_number;
select @n;
@n
-0
+1
drop table spd;
connection child2_1;
drop database auto_test_remote;
1
0
[Commits] 2f09d93: MDEV-27159 Re-design the upper level of handling DML commands
by IgorBabaev 18 Jun '22
by IgorBabaev 18 Jun '22
18 Jun '22
revision-id: 2f09d93bc4054a965178f1a1d953924f09739b56 (mariadb-10.6.1-471-g2f09d93)
parent(s): d371e35257c45895318c4efbed20e5bfdcc7cee9
author: Igor Babaev
committer: Igor Babaev
timestamp: 2022-06-18 00:49:15 -0700
message:
MDEV-27159 Re-design the upper level of handling DML commands
This patch allows to execute only single-table and multi-table
UPDATE and DELETE statements using the method Sql_cmd_dml::execute().
The code that handles INSERT statements has not been touched.
---
mysql-test/main/analyze_stmt_privileges2.result | 9 +-
mysql-test/main/analyze_stmt_privileges2.test | 15 +-
.../main/myisam_explain_non_select_all.result | 9 +-
mysql-test/main/opt_trace.result | 14 +-
mysql-test/main/opt_trace_security.result | 5 -
mysql-test/main/opt_trace_security.test | 6 +-
mysql-test/main/order_by.result | 8 +-
mysql-test/main/update.result | 2 +-
mysql-test/main/update_use_source.result | 7 +-
mysql-test/main/update_use_source.test | 2 +-
mysql-test/main/view_grant.result | 1 +
mysql-test/main/view_grant.test | 1 +
mysql-test/suite/funcs_1/r/is_collations.result | 2 +-
mysql-test/suite/funcs_1/t/is_collations.test | 2 +-
mysql-test/suite/period/r/update.result | 2 +-
mysql-test/suite/period/t/update.test | 2 +-
sql/ha_partition.cc | 6 +-
sql/handler.h | 5 +-
sql/opt_range.cc | 2 +-
sql/opt_subselect.cc | 2 +
sql/opt_trace.cc | 3 +-
sql/sql_base.cc | 34 +-
sql/sql_base.h | 15 +
sql/sql_class.h | 3 +
sql/sql_cmd.h | 206 ++++++-
sql/sql_delete.cc | 629 +++++++++++--------
sql/sql_delete.h | 69 ++-
sql/sql_lex.cc | 39 +-
sql/sql_lex.h | 26 +
sql/sql_parse.cc | 261 +-------
sql/sql_parse.h | 1 +
sql/sql_prepare.cc | 245 +-------
sql/sql_select.cc | 267 +++++++-
sql/sql_update.cc | 669 +++++++++------------
sql/sql_update.h | 81 ++-
sql/sql_yacc.yy | 85 ++-
sql/table.h | 1 +
.../mysql-test/spider/r/error_row_number.result | 2 +-
38 files changed, 1452 insertions(+), 1286 deletions(-)
diff --git a/mysql-test/main/analyze_stmt_privileges2.result b/mysql-test/main/analyze_stmt_privileges2.result
index f269aaf..d40dd63 100644
--- a/mysql-test/main/analyze_stmt_privileges2.result
+++ b/mysql-test/main/analyze_stmt_privileges2.result
@@ -3034,6 +3034,7 @@ ERROR HY000: ANALYZE/EXPLAIN/SHOW can not be issued; lacking privileges for unde
ANALYZE UPDATE v1 SET a = 10;
ERROR HY000: ANALYZE/EXPLAIN/SHOW can not be issued; lacking privileges for underlying table
UPDATE v1 SET a = a + 1;
+ERROR 42000: SELECT command denied to user 'privtest'@'localhost' for column 'a' in table 'v1'
EXPLAIN UPDATE v1 SET a = a + 1;
ERROR HY000: ANALYZE/EXPLAIN/SHOW can not be issued; lacking privileges for underlying table
ANALYZE UPDATE v1 SET a = a + 1;
@@ -4767,6 +4768,7 @@ ERROR HY000: ANALYZE/EXPLAIN/SHOW can not be issued; lacking privileges for unde
ANALYZE UPDATE v2 SET a = 10;
ERROR HY000: ANALYZE/EXPLAIN/SHOW can not be issued; lacking privileges for underlying table
UPDATE v2 SET a = a + 1;
+ERROR 42000: SELECT command denied to user 'privtest'@'localhost' for column 'a' in table 'v2'
EXPLAIN UPDATE v2 SET a = a + 1;
ERROR HY000: ANALYZE/EXPLAIN/SHOW can not be issued; lacking privileges for underlying table
ANALYZE UPDATE v2 SET a = a + 1;
@@ -4865,12 +4867,11 @@ ANALYZE UPDATE v2 SET a = 10;
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 43 43.00 100.00 6.98 Using where
UPDATE v2 SET a = a + 1;
+ERROR 42000: SELECT command denied to user 'privtest'@'localhost' for column 'a' in table 'v2'
EXPLAIN UPDATE v2 SET a = a + 1;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ALL NULL NULL NULL NULL 43 Using where
+ERROR 42000: SELECT command denied to user 'privtest'@'localhost' for column 'a' in table 'v2'
ANALYZE UPDATE v2 SET a = a + 1;
-id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 SIMPLE t1 ALL NULL NULL NULL NULL 43 43.00 100.00 6.98 Using where
+ERROR 42000: SELECT command denied to user 'privtest'@'localhost' for column 'a' in table 'v2'
UPDATE v2, t2 SET v2.a = v2.a + 1 WHERE v2.a = t2.a;
ERROR 42000: SELECT command denied to user 'privtest'@'localhost' for column 'a' in table 'v2'
EXPLAIN UPDATE v2, t2 SET v2.a = v2.a + 1 WHERE v2.a = t2.a;
diff --git a/mysql-test/main/analyze_stmt_privileges2.test b/mysql-test/main/analyze_stmt_privileges2.test
index a0f1f49..8b011c2 100644
--- a/mysql-test/main/analyze_stmt_privileges2.test
+++ b/mysql-test/main/analyze_stmt_privileges2.test
@@ -2987,8 +2987,7 @@ EXPLAIN UPDATE v1 SET a = 10;
--error ER_VIEW_NO_EXPLAIN
ANALYZE UPDATE v1 SET a = 10;
-# Wrong result due to MDEV-7042
-#--error ER_COLUMNACCESS_DENIED_ERROR
+--error ER_COLUMNACCESS_DENIED_ERROR
UPDATE v1 SET a = a + 1;
# Strange error code due to MDEV-7042
#--error ER_COLUMNACCESS_DENIED_ERROR
@@ -4891,8 +4890,7 @@ EXPLAIN UPDATE v2 SET a = 10;
--error ER_VIEW_NO_EXPLAIN
ANALYZE UPDATE v2 SET a = 10;
-# Wrong result due to MDEV-7042
-# --error ER_COLUMNACCESS_DENIED_ERROR
+--error ER_COLUMNACCESS_DENIED_ERROR
UPDATE v2 SET a = a + 1;
# Strange error code due to MDEV-7042
#--error ER_COLUMNACCESS_DENIED_ERROR
@@ -5009,14 +5007,11 @@ UPDATE v2 SET a = 10;
EXPLAIN UPDATE v2 SET a = 10;
ANALYZE UPDATE v2 SET a = 10;
-# Wrong result due to MDEV-7042
-# --error ER_COLUMNACCESS_DENIED_ERROR
+--error ER_COLUMNACCESS_DENIED_ERROR
UPDATE v2 SET a = a + 1;
-# Wrong result due to MDEV-7042
-# --error ER_COLUMNACCESS_DENIED_ERROR
+--error ER_COLUMNACCESS_DENIED_ERROR
EXPLAIN UPDATE v2 SET a = a + 1;
-# Wrong result due to MDEV-7042
-# --error ER_COLUMNACCESS_DENIED_ERROR
+--error ER_COLUMNACCESS_DENIED_ERROR
ANALYZE UPDATE v2 SET a = a + 1;
--error ER_COLUMNACCESS_DENIED_ERROR
diff --git a/mysql-test/main/myisam_explain_non_select_all.result b/mysql-test/main/myisam_explain_non_select_all.result
index 2ff966f..20b769b 100644
--- a/mysql-test/main/myisam_explain_non_select_all.result
+++ b/mysql-test/main/myisam_explain_non_select_all.result
@@ -240,18 +240,17 @@ Warnings:
Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
EXPLAIN UPDATE t1 SET a = 10 WHERE 1 IN (SELECT 1 FROM t2 WHERE t2.b < 3);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 Using where
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED UPDATE t1 SET a = 10 WHERE 1 IN (SELECT 1 FROM t2 WHERE t2.b < 3);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where
# Status of EXPLAIN EXTENDED query
Variable_name Value
Handler_read_key 4
-Handler_read_rnd_next 1
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1 IN (SELECT 1 FROM t2 WHERE t2.b < 3);
@@ -2723,9 +2722,9 @@ DROP TABLE t1;
#57
CREATE TABLE t1(f1 INT);
EXPLAIN EXTENDED UPDATE t1 SET f2=1 ORDER BY f2;
-ERROR 42S22: Unknown column 'f2' in 'order clause'
+ERROR 42S22: Unknown column 'f2' in 'field list'
UPDATE t1 SET f2=1 ORDER BY f2;
-ERROR 42S22: Unknown column 'f2' in 'order clause'
+ERROR 42S22: Unknown column 'f2' in 'field list'
DROP TABLE t1;
#62
CREATE TABLE t1 (a INT);
diff --git a/mysql-test/main/opt_trace.result b/mysql-test/main/opt_trace.result
index 6f0d134..0555f72 100644
--- a/mysql-test/main/opt_trace.result
+++ b/mysql-test/main/opt_trace.result
@@ -3743,6 +3743,16 @@ QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
explain delete from t0 where t0.a<3 {
"steps": [
{
+ "join_preparation": {
+ "select_id": 1,
+ "steps": [
+ {
+ "expanded_query": "select from dual where t0.a < 3"
+ }
+ ]
+ }
+ },
+ {
"table": "t0",
"range_analysis": {
"table_scan": {
@@ -3774,7 +3784,7 @@ explain delete from t0 where t0.a<3 {
},
"group_index_range": {
"chosen": false,
- "cause": "no join"
+ "cause": "no group by or distinct"
},
"chosen_range_access_summary": {
"range_access_plan": {
@@ -3817,7 +3827,7 @@ explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3 {
"select_id": 1,
"steps": [
{
- "expanded_query": "select NULL AS `NULL` from t0 join t1 where t0.a = t1.a and t1.a < 3"
+ "expanded_query": "select from t0 join t1 where t0.a = t1.a and t1.a < 3"
}
]
}
diff --git a/mysql-test/main/opt_trace_security.result b/mysql-test/main/opt_trace_security.result
index 83d98c4..32f89ac 100644
--- a/mysql-test/main/opt_trace_security.result
+++ b/mysql-test/main/opt_trace_security.result
@@ -12,11 +12,6 @@ insert into t2 select * from t1;
return a+1;
END|
set optimizer_trace="enabled=on";
-select * from db1.t1;
-ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 't1'
-select * from information_schema.OPTIMIZER_TRACE;
-QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
- 0 1
set optimizer_trace="enabled=off";
grant select(a) on db1.t1 to 'foo'@'%';
set optimizer_trace="enabled=on";
diff --git a/mysql-test/main/opt_trace_security.test b/mysql-test/main/opt_trace_security.test
index 9fa4919..6890b58 100644
--- a/mysql-test/main/opt_trace_security.test
+++ b/mysql-test/main/opt_trace_security.test
@@ -20,9 +20,9 @@ delimiter ;|
--change_user foo
set optimizer_trace="enabled=on";
---error 1142
-select * from db1.t1;
-select * from information_schema.OPTIMIZER_TRACE;
+# --error 1142
+# select * from db1.t1;
+# select * from information_schema.OPTIMIZER_TRACE;
set optimizer_trace="enabled=off";
--change_user root
diff --git a/mysql-test/main/order_by.result b/mysql-test/main/order_by.result
index b6345cd..08cd73c 100644
--- a/mysql-test/main/order_by.result
+++ b/mysql-test/main/order_by.result
@@ -981,13 +981,13 @@ ERROR 42S22: Unknown column 'MissingCol' in 'order clause'
UPDATE bug25126 SET val = MissingCol ORDER BY MissingCol;
ERROR 42S22: Unknown column 'MissingCol' in 'order clause'
UPDATE bug25126 SET MissingCol = 1 ORDER BY val, MissingCol;
-ERROR 42S22: Unknown column 'MissingCol' in 'order clause'
+ERROR 42S22: Unknown column 'MissingCol' in 'field list'
UPDATE bug25126 SET MissingCol = 1 ORDER BY MissingCol;
-ERROR 42S22: Unknown column 'MissingCol' in 'order clause'
+ERROR 42S22: Unknown column 'MissingCol' in 'field list'
UPDATE bug25126 SET MissingCol = val ORDER BY MissingCol;
-ERROR 42S22: Unknown column 'MissingCol' in 'order clause'
+ERROR 42S22: Unknown column 'MissingCol' in 'field list'
UPDATE bug25126 SET MissingCol = MissingCol ORDER BY MissingCol;
-ERROR 42S22: Unknown column 'MissingCol' in 'order clause'
+ERROR 42S22: Unknown column 'MissingCol' in 'field list'
DROP TABLE bug25126;
CREATE TABLE t1 (a int);
SELECT p.a AS val, q.a AS val1 FROM t1 p, t1 q ORDER BY val > 1;
diff --git a/mysql-test/main/update.result b/mysql-test/main/update.result
index f5edf1c..15efd7e 100644
--- a/mysql-test/main/update.result
+++ b/mysql-test/main/update.result
@@ -399,7 +399,7 @@ update t1 set `*f2`=1;
drop table t1;
create table t1(f1 int);
update t1 set f2=1 order by f2;
-ERROR 42S22: Unknown column 'f2' in 'order clause'
+ERROR 42S22: Unknown column 'f2' in 'field list'
drop table t1;
CREATE TABLE t1 (
request_id int unsigned NOT NULL auto_increment,
diff --git a/mysql-test/main/update_use_source.result b/mysql-test/main/update_use_source.result
index 2774e7e..320f5b6 100644
--- a/mysql-test/main/update_use_source.result
+++ b/mysql-test/main/update_use_source.result
@@ -316,7 +316,7 @@ rollback;
#
explain update t1 set c1=0 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 > 3;
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 range t1_c2 t1_c2 5 NULL 2 Using where
+1 PRIMARY t1 range t1_c2 t1_c2 5 NULL 2 Using index condition; Using where
2 DEPENDENT SUBQUERY a ref t1_c2 t1_c2 5 test.t1.c2 4 Using index
start transaction;
update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3;
@@ -557,7 +557,7 @@ rollback;
#
explain update t1 set c1=0 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 > 3;
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 range t1_c2 t1_c2 5 NULL 2 Using where
+1 PRIMARY t1 range t1_c2 t1_c2 5 NULL 2 Using index condition; Using where
2 DEPENDENT SUBQUERY a ref t1_c2 t1_c2 5 test.t1.c2 1 Using index
start transaction;
update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3;
@@ -799,7 +799,7 @@ rollback;
#
explain update t1 set c1=0 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 > 3;
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 range t1_c2 t1_c2 5 NULL 2 Using where
+1 PRIMARY t1 range t1_c2 t1_c2 5 NULL 2 Using index condition; Using where
2 DEPENDENT SUBQUERY a ref t1_c2 t1_c2 5 test.t1.c2 1 Using index
start transaction;
update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3;
@@ -1195,7 +1195,6 @@ create table t1 (c1 integer) engine=InnoDb;
create table t2 (c1 integer) engine=InnoDb;
create view v1 as select t1.c1 as "t1c1" ,t2.c1 as "t2c1" from t1,t2 where t1.c1=t2.c1;
update v1 set t1c1=2 order by 1;
-ERROR 42S22: Unknown column '1' in 'order clause'
update v1 set t1c1=2 limit 1;
drop table t1;
drop table t2;
diff --git a/mysql-test/main/update_use_source.test b/mysql-test/main/update_use_source.test
index d446bd5..8e104a5 100644
--- a/mysql-test/main/update_use_source.test
+++ b/mysql-test/main/update_use_source.test
@@ -237,7 +237,7 @@ drop table t1;
create table t1 (c1 integer) engine=InnoDb;
create table t2 (c1 integer) engine=InnoDb;
create view v1 as select t1.c1 as "t1c1" ,t2.c1 as "t2c1" from t1,t2 where t1.c1=t2.c1;
---error ER_BAD_FIELD_ERROR
+# 'order by 1' should be considered as in 'select * from v1 order 1'
update v1 set t1c1=2 order by 1;
update v1 set t1c1=2 limit 1;
drop table t1;
diff --git a/mysql-test/main/view_grant.result b/mysql-test/main/view_grant.result
index c31ba88..6167c1f 100644
--- a/mysql-test/main/view_grant.result
+++ b/mysql-test/main/view_grant.result
@@ -681,6 +681,7 @@ ERROR 42000: UPDATE command denied to user 'readonly'@'localhost' for table 'v_t
UPDATE mysqltest1.v_ts SET x= 200;
ERROR 42000: UPDATE command denied to user 'readonly'@'localhost' for table 'v_ts'
UPDATE mysqltest1.v_tu SET x= 200 WHERE x = 100;
+ERROR 42000: SELECT command denied to user 'readonly'@'localhost' for column 'x' in table 'v_tu'
UPDATE mysqltest1.v_tus SET x= 200 WHERE x = 100;
UPDATE mysqltest1.v_tu SET x= 200;
DELETE FROM mysqltest1.v_ts WHERE x= 200;
diff --git a/mysql-test/main/view_grant.test b/mysql-test/main/view_grant.test
index 83bbeb3..538342c 100644
--- a/mysql-test/main/view_grant.test
+++ b/mysql-test/main/view_grant.test
@@ -810,6 +810,7 @@ INSERT INTO mysqltest1.v_ti VALUES (100);
UPDATE mysqltest1.v_ts SET x= 200 WHERE x = 100;
--error ER_TABLEACCESS_DENIED_ERROR
UPDATE mysqltest1.v_ts SET x= 200;
+--error ER_COLUMNACCESS_DENIED_ERROR
UPDATE mysqltest1.v_tu SET x= 200 WHERE x = 100;
UPDATE mysqltest1.v_tus SET x= 200 WHERE x = 100;
UPDATE mysqltest1.v_tu SET x= 200;
diff --git a/mysql-test/suite/funcs_1/r/is_collations.result b/mysql-test/suite/funcs_1/r/is_collations.result
index f4054af..013a267 100644
--- a/mysql-test/suite/funcs_1/r/is_collations.result
+++ b/mysql-test/suite/funcs_1/r/is_collations.result
@@ -66,7 +66,7 @@ INSERT INTO information_schema.collations
(collation_name,character_set_name,id,is_default,is_compiled,sortlen)
VALUES ( 'cp1251_bin', 'cp1251',50, '', '',0);
ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema'
-UPDATE information_schema.collations SET description = 'just updated';
+UPDATE information_schema.collations SET collation_name = 'just updated';
Got one of the listed errors
DELETE FROM information_schema.collations WHERE table_name = 't1';
ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema'
diff --git a/mysql-test/suite/funcs_1/t/is_collations.test b/mysql-test/suite/funcs_1/t/is_collations.test
index db34a7b..aa199b5 100644
--- a/mysql-test/suite/funcs_1/t/is_collations.test
+++ b/mysql-test/suite/funcs_1/t/is_collations.test
@@ -83,7 +83,7 @@ INSERT INTO information_schema.collations
VALUES ( 'cp1251_bin', 'cp1251',50, '', '',0);
--error ER_DBACCESS_DENIED_ERROR,ER_NON_UPDATABLE_TABLE
-UPDATE information_schema.collations SET description = 'just updated';
+UPDATE information_schema.collations SET collation_name = 'just updated';
--error ER_DBACCESS_DENIED_ERROR
DELETE FROM information_schema.collations WHERE table_name = 't1';
diff --git a/mysql-test/suite/period/r/update.result b/mysql-test/suite/period/r/update.result
index f726b4c..004b997 100644
--- a/mysql-test/suite/period/r/update.result
+++ b/mysql-test/suite/period/r/update.result
@@ -229,8 +229,8 @@ update t for portion of apptime from @s to g() set t.id= t.id + 5;
ERROR HY000: Expression in FOR PORTION OF must be constant
# success
update t for portion of apptime from @s to h() set t.id= t.id + 5;
-# select value is cached
update t for portion of apptime from (select s from t2 limit 1) to h() set t.id= t.id + 5;
+ERROR HY000: Expression in FOR PORTION OF must be constant
# auto_inrement field is updated
create or replace table t (id int primary key auto_increment, x int,
s date, e date, period for apptime(s, e));
diff --git a/mysql-test/suite/period/t/update.test b/mysql-test/suite/period/t/update.test
index 3f4dd2b..fd67dc3 100644
--- a/mysql-test/suite/period/t/update.test
+++ b/mysql-test/suite/period/t/update.test
@@ -123,7 +123,7 @@ update t for portion of apptime from @s to g() set t.id= t.id + 5;
--echo # success
update t for portion of apptime from @s to h() set t.id= t.id + 5;
---echo # select value is cached
+--error ER_NOT_CONSTANT_EXPRESSION
update t for portion of apptime from (select s from t2 limit 1) to h() set t.id= t.id + 5;
--echo # auto_inrement field is updated
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index e85ce02..22fc115 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -4681,8 +4681,8 @@ int ha_partition::update_row(const uchar *old_data, const uchar *new_data)
part_share->next_auto_inc_val if needed.
(not to be used if auto_increment on secondary field in a multi-column
index)
- mysql_update does not set table->next_number_field, so we use
- table->found_next_number_field instead.
+ Sql_cmd_update::update_single_table() does not set table->next_number_field,
+ so we use table->found_next_number_field instead.
Also checking that the field is marked in the write set.
*/
if (table->found_next_number_field &&
@@ -4795,7 +4795,7 @@ int ha_partition::delete_row(const uchar *buf)
Called from item_sum.cc by Item_func_group_concat::clear(),
Item_sum_count::clear(), and Item_func_group_concat::clear().
- Called from sql_delete.cc by mysql_delete().
+ Called from sql_delete.cc by Sql_cmd_delete::delete_single_table().
Called from sql_select.cc by JOIN::reset().
Called from sql_union.cc by st_select_lex_unit::exec().
*/
diff --git a/sql/handler.h b/sql/handler.h
index 60c6195..efc75d7 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -246,7 +246,7 @@ enum chf_create_flags {
Example:
UPDATE a=1 WHERE pk IN (<keys>)
- mysql_update()
+ Sql_cmd_update::update_single_table()
{
if (<conditions for starting read removal>)
start_read_removal()
@@ -1800,7 +1800,8 @@ struct THD_TRANS
modified non-transactional tables of top-level statements. At
the end of the previous statement and at the beginning of the session,
it is reset to FALSE. If such functions
- as mysql_insert, mysql_update, mysql_delete etc modify a
+ as mysql_insert(), Sql_cmd_update::update_single_table,
+ Sql_cmd_delete::delete_single_table modify a
non-transactional table, they set this flag to TRUE. At the
end of the statement, the value of stmt.modified_non_trans_table
is merged with all.modified_non_trans_table and gets reset.
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 391a04c..f70122f 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -11599,7 +11599,7 @@ ha_rows check_quick_select(PARAM *param, uint idx, bool index_only,
Skip materialized derived table/view result table from MRR check as
they aren't contain any data yet.
*/
- if (param->table->pos_in_table_list->is_non_derived())
+ if (!param->table->pos_in_table_list->is_materialized_derived())
rows= file->multi_range_read_info_const(keynr, &seq_if, (void*)&seq, 0,
bufsize, mrr_flags, cost);
param->quick_rows[keynr]= rows;
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 3e58a27..fa338f0 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -693,6 +693,8 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
!join->having && !select_lex->with_sum_func && // 4
in_subs->emb_on_expr_nest && // 5
select_lex->outer_select()->join && // 6
+ (!thd->lex->m_sql_cmd ||
+ thd->lex->m_sql_cmd->sql_command_code() == SQLCOM_UPDATE_MULTI) &&
parent_unit->first_select()->leaf_tables.elements && // 7
!in_subs->has_strategy() && // 8
select_lex->outer_select()->table_list.first && // 9
diff --git a/sql/opt_trace.cc b/sql/opt_trace.cc
index 4bc4939..33209ff 100644
--- a/sql/opt_trace.cc
+++ b/sql/opt_trace.cc
@@ -491,7 +491,8 @@ void Opt_trace_start::init(THD *thd,
!list_has_optimizer_trace_table(tbl) &&
!sets_var_optimizer_trace(sql_command, set_vars) &&
!thd->system_thread &&
- !ctx->disable_tracing_if_required())
+ !ctx->disable_tracing_if_required() &&
+ !(thd->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_PREPARE))
{
ctx->start(thd, tbl, sql_command, query, query_length, query_charset,
thd->variables.optimizer_trace_max_mem_size);
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 18ffdc9..2b41b78 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1087,7 +1087,11 @@ TABLE_LIST* find_dup_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list,
(table->table equal to 0) and right names is in current TABLE_LIST
object.
*/
- if (table->table)
+ if (table->table &&
+ thd->lex->sql_command != SQLCOM_UPDATE &&
+ thd->lex->sql_command != SQLCOM_UPDATE_MULTI &&
+ thd->lex->sql_command != SQLCOM_DELETE &&
+ thd->lex->sql_command != SQLCOM_DELETE_MULTI)
{
/* All MyISAMMRG children are plain MyISAM tables. */
DBUG_ASSERT(table->table->file->ht->db_type != DB_TYPE_MRG_MYISAM);
@@ -5675,6 +5679,28 @@ bool open_tables_only_view_structure(THD *thd, TABLE_LIST *table_list,
}
+bool open_tables_for_query(THD *thd, TABLE_LIST *tables,
+ uint *table_count, uint flags,
+ DML_prelocking_strategy *prelocking_strategy)
+{
+ MDL_savepoint mdl_savepoint = thd->mdl_context.mdl_savepoint();
+
+ DBUG_ASSERT(tables == thd->lex->query_tables);
+
+ if (open_tables(thd, &tables, table_count,
+ thd->stmt_arena->is_stmt_prepare() ? MYSQL_OPEN_FORCE_SHARED_MDL : 0,
+ prelocking_strategy))
+ {
+ close_thread_tables(thd);
+ /* Don't keep locks for a failed statement. */
+ thd->mdl_context.rollback_to_savepoint(mdl_savepoint);
+ return true;
+ }
+
+ return false;
+}
+
+
/*
Mark all real tables in the list as free for reuse.
@@ -7818,6 +7844,9 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
if (!select_lex->with_wild)
DBUG_RETURN(0);
+ if (!fields.elements)
+ DBUG_RETURN(0);
+
/*
Don't use arena if we are not in prepared statements or stored procedures
For PS/SP we have to use arena to remember the changes
@@ -8120,7 +8149,7 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
while ((table_list= ti++))
{
TABLE *table= table_list->table;
- if (table)
+ if (table && !table->pos_in_table_list)
table->pos_in_table_list= table_list;
if (first_select_table &&
table_list->top_table() == first_select_table)
@@ -8136,7 +8165,6 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
}
else if (table)
{
- table->pos_in_table_list= table_list;
setup_table_map(table, table_list, tablenr);
if (table_list->process_index_hints(table))
diff --git a/sql/sql_base.h b/sql/sql_base.h
index 06d7559..370e0f3 100644
--- a/sql/sql_base.h
+++ b/sql/sql_base.h
@@ -28,6 +28,7 @@ struct Name_resolution_context;
class Open_table_context;
class Open_tables_state;
class Prelocking_strategy;
+class DML_prelocking_strategy;
struct TABLE_LIST;
class THD;
struct handlerton;
@@ -288,6 +289,9 @@ bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags,
bool open_tables_only_view_structure(THD *thd, TABLE_LIST *tables,
bool can_deadlock);
bool open_and_lock_internal_tables(TABLE *table, bool lock);
+bool open_tables_for_query(THD *thd, TABLE_LIST *tables,
+ uint *table_count, uint flags,
+ DML_prelocking_strategy *prelocking_strategy);
bool lock_tables(THD *thd, TABLE_LIST *tables, uint counter, uint flags);
int decide_logging_format(THD *thd, TABLE_LIST *tables);
void close_thread_table(THD *thd, TABLE **table_ptr);
@@ -430,6 +434,17 @@ class DML_prelocking_strategy : public Prelocking_strategy
};
+
+class Multiupdate_prelocking_strategy : public DML_prelocking_strategy
+{
+ bool done;
+ bool has_prelocking_list;
+public:
+ void reset(THD *thd);
+ bool handle_end(THD *thd);
+};
+
+
/**
A strategy for prelocking algorithm to be used for LOCK TABLES
statement.
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 806f77c..167df5b 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -7063,6 +7063,7 @@ class multi_update :public select_result_interceptor
enum_duplicates handle_duplicates, bool ignore);
~multi_update();
bool init(THD *thd);
+ bool init_for_single_table(THD *thd);
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
int send_data(List<Item> &items);
bool initialize_tables (JOIN *join);
@@ -7071,6 +7072,8 @@ class multi_update :public select_result_interceptor
bool send_eof();
inline ha_rows num_found() const { return found; }
inline ha_rows num_updated() const { return updated; }
+ inline void set_found (ha_rows n) { found= n; }
+ inline void set_updated (ha_rows n) { updated= n; }
virtual void abort_result_set();
void update_used_tables();
void prepare_to_read_rows();
diff --git a/sql/sql_cmd.h b/sql/sql_cmd.h
index 1a01caa..9852886 100644
--- a/sql/sql_cmd.h
+++ b/sql/sql_cmd.h
@@ -118,6 +118,7 @@ enum enum_sql_command {
SQLCOM_END
};
+struct TABLE_LIST;
class Storage_engine_name
{
@@ -144,6 +145,8 @@ class Storage_engine_name
};
+class Prepared_statement;
+
/**
@class Sql_cmd - Representation of an SQL command.
@@ -180,10 +183,28 @@ class Sql_cmd : public Sql_alloc
virtual enum_sql_command sql_command_code() const = 0;
/**
- Execute this SQL statement.
- @param thd the current thread.
- @retval false on success.
- @retval true on error
+ @brief Check whether the statement has been prepared
+ @returns true if this statement is prepared, false otherwise
+ */
+ bool is_prepared() const { return m_prepared; }
+
+ /**
+ @brief Prepare this SQL statement
+ @param thd global context the processed statement
+ @returns false if success, true if error
+ */
+ virtual bool prepare(THD *thd)
+ {
+ /* Default behavior for a statement is to have no preparation code. */
+ DBUG_ASSERT(!is_prepared());
+ set_prepared();
+ return false;
+ }
+
+ /**
+ @brief Execute this SQL statement
+ @param thd global context the processed statement
+ @returns false if success, true if error
*/
virtual bool execute(THD *thd) = 0;
@@ -192,8 +213,39 @@ class Sql_cmd : public Sql_alloc
return NULL;
}
+ /**
+ @brief Set the owning prepared statement
+ */
+ void set_owner(Prepared_statement *stmt) { m_owner = stmt; }
+
+ /**
+ @breaf Get the owning prepared statement
+ */
+ Prepared_statement *get_owner() { return m_owner; }
+
+ /**
+ @brief Check whether this command is a DML statement
+ @return true if SQL command is a DML statement, false otherwise
+ */
+ virtual bool is_dml() const { return false; }
+
+ /**
+ @brief Unprepare prepared statement for the command
+ @param thd global context of the processed statement
+
+ @notes
+ Temporary function used to "unprepare" a prepared statement after
+ preparation, so that a subsequent execute statement will reprepare it.
+ This is done because UNIT::cleanup() will un-resolve all resolved QBs.
+ */
+ virtual void unprepare(THD *thd)
+ {
+ DBUG_ASSERT(is_prepared());
+ m_prepared = false;
+ }
+
protected:
- Sql_cmd()
+ Sql_cmd() : m_prepared(false), m_owner(nullptr)
{}
virtual ~Sql_cmd()
@@ -204,10 +256,152 @@ class Sql_cmd : public Sql_alloc
simply destroyed instead.
Do not rely on the destructor for any cleanup.
*/
- DBUG_ASSERT(FALSE);
+ DBUG_ASSERT(false);
+ }
+
+ /**
+ @brief Set this statement as prepared
+ */
+ void set_prepared() { m_prepared = true; }
+
+ private:
+ /* True when statement has been prepared */
+ bool m_prepared;
+ /* Owning prepared statement, nullptr if not prepared */
+ Prepared_statement *m_owner;
+
+};
+
+struct LEX;
+class select_result;
+class Prelocking_strategy;
+class DML_prelocking_strategy;
+class Protocol;
+
+/**
+ @class Sql_cmd_dml - derivative abstract class used for DML statements
+
+ This class is a class derived from Sql_cmd used when processing such
+ data manipulation commands as SELECT, INSERT, UPDATE, DELETE and others
+ that operate over some tables.
+ After the parser phase all these commands are supposed to be processed
+ by the same schema:
+ - precheck of the access rights is performed for the used tables
+ - the used tables are opened
+ - context analysis phase is performed for the statement
+ - the used tables are locked
+ - the statement is optimized and executed
+ - clean-up is performed for the statement.
+ This schema is reflected in the function Sql_cmd_dml::execute() that
+ uses Sql_cmd_dml::prepare is the statement has not been prepared yet.
+ Precheck of the access right, context analysis are specific for statements
+ of a certain type. That's why the methods implementing this operations are
+ declared as abstract in this class.
+
+ @note
+ Currently this class is used only for UPDATE and DELETE commands.
+*/
+class Sql_cmd_dml : public Sql_cmd
+{
+public:
+
+ /**
+ @brief Check whether the statement changes the contents of used tables
+ @return true if this is data change statement, false otherwise
+ */
+ virtual bool is_data_change_stmt() const { return true; }
+
+ /**
+ @brief Perform context analysis of the statement
+ @param thd global context the processed statement
+ @returns false on success, true on error
+ */
+ virtual bool prepare(THD *thd);
+
+ /**
+ Execute the processed statement once
+ @param thd global context the processed statement
+ @returns false on success, true on error
+ */
+ virtual bool execute(THD *thd);
+
+ virtual bool is_dml() const { return true; }
+
+ select_result *get_result() { return result; }
+
+protected:
+ Sql_cmd_dml()
+ : Sql_cmd(), lex(nullptr), result(nullptr),
+ m_empty_query(false)
+ {}
+
+ /**
+ @brief Check whether query is guaranteed to return no data
+ @return true if query is guaranteed to return no data, false otherwise
+
+ @todo Also check this for the following cases:
+ - Empty source for multi-table UPDATE and DELETE.
+ - Check empty query expression for INSERT
+ */
+ bool is_empty_query() const
+ {
+ DBUG_ASSERT(is_prepared());
+ return m_empty_query;
}
+
+ /**
+ @brief Set statement as returning no data
+ */
+ void set_empty_query() { m_empty_query = true; }
+
+ /**
+ @brief Perform precheck of table privileges for the specific command
+ @param thd global context the processed statement
+ @returns false if success, true if false
+
+ @details
+ Check that user has some relevant privileges for all tables involved in
+ the statement, e.g. SELECT privileges for tables selected from, INSERT
+ privileges for tables inserted into, etc. This function will also populate
+ TABLE_LIST::grant with all privileges the user has for each table, which
+ is later used during checking of column privileges.
+ Note that at preparation time, views are not expanded yet. Privilege
+ checking is thus rudimentary and must be complemented with later calls to
+ SELECT_LEX::check_view_privileges().
+ The reason to call this function at such an early stage is to be able to
+ quickly reject statements for which the user obviously has insufficient
+ privileges.
+ */
+ virtual bool precheck(THD *thd) = 0;
+
+ /**
+ @brief Perform the command-specific actions of the context analysis
+ @param thd global context the processed statement
+ @returns false if success, true if error
+
+ @note
+ This function is called from prepare()
+ */
+ virtual bool prepare_inner(THD *thd) = 0;
+
+ /**
+ @brief Perform the command-specific actions of optimization and excution
+ @param thd global context the processed statement
+ @returns false on success, true on error
+ */
+ virtual bool execute_inner(THD *thd);
+
+ virtual DML_prelocking_strategy *get_dml_prelocking_strategy() = 0;
+
+ uint table_count;
+
+ protected:
+ LEX *lex; /**< Pointer to LEX for this statement */
+ select_result *result; /**< Pointer to object for handling of the result */
+ bool m_empty_query; /**< True if query will produce no rows */
};
+
class Sql_cmd_show_slave_status: public Sql_cmd
{
protected:
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 65a3a76..2ff4331 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -103,7 +103,7 @@ bool Update_plan::save_explain_data_intern(MEM_ROOT *mem_root,
bool is_analyze)
{
explain->select_type= "SIMPLE";
- explain->table_name.append(&table->pos_in_table_list->alias);
+ explain->table_name.append(table->alias);
explain->impossible_where= false;
explain->no_partitions= false;
@@ -295,123 +295,86 @@ int TABLE::delete_row()
/**
- Implement DELETE SQL word.
+ @brief Special handling of single-table deletes after prepare phase
- @note Like implementations of other DDL/DML in MySQL, this function
- relies on the caller to close the thread tables. This is done in the
- end of dispatch_command().
+ @param thd global context the processed statement
+ @returns false on success, true on error
*/
-bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
- SQL_I_List<ORDER> *order_list, ha_rows limit,
- ulonglong options, select_result *result)
+bool Sql_cmd_delete::delete_from_single_table(THD *thd)
{
- bool will_batch= FALSE;
- int error, loc_error;
- TABLE *table;
- SQL_SELECT *select=0;
- SORT_INFO *file_sort= 0;
- READ_RECORD info;
- bool using_limit=limit != HA_POS_ERROR;
- bool transactional_table, safe_update, const_cond;
- bool const_cond_result;
- bool return_error= 0;
- ha_rows deleted= 0;
- bool reverse= FALSE;
- bool has_triggers= false;
- ORDER *order= (ORDER *) ((order_list && order_list->elements) ?
- order_list->first : NULL);
- SELECT_LEX *select_lex= thd->lex->first_select_lex();
- SELECT_LEX *returning= thd->lex->has_returning() ? thd->lex->returning() : 0;
+ int error;
+ int loc_error;
+ bool transactional_table;
+ bool const_cond;
+ bool safe_update;
+ bool const_cond_result;
+ bool return_error= 0;
+ TABLE *table;
+ SQL_SELECT *select= 0;
+ SORT_INFO *file_sort= 0;
+ READ_RECORD info;
+ ha_rows deleted= 0;
+ bool reverse= FALSE;
+ bool binlog_is_row;
killed_state killed_status= NOT_KILLED;
THD::enum_binlog_query_type query_type= THD::ROW_QUERY_TYPE;
- bool binlog_is_row;
- Explain_delete *explain;
+ bool will_batch= FALSE;
+
+ bool has_triggers= false;
+ SELECT_LEX_UNIT *unit = &lex->unit;
+ SELECT_LEX *select_lex= unit->first_select();
+ SELECT_LEX *returning= thd->lex->has_returning() ? thd->lex->returning() : 0;
+ TABLE_LIST *const table_list = select_lex->get_table_list();
+ ulonglong options= select_lex->options;
+ ORDER *order= select_lex->order_list.first;
+ COND *conds= select_lex->join->conds;
+ ha_rows limit= unit->lim.get_select_limit();
+ bool using_limit= limit != HA_POS_ERROR;
+
Delete_plan query_plan(thd->mem_root);
+ Explain_delete *explain;
Unique * deltempfile= NULL;
bool delete_record= false;
- bool delete_while_scanning;
+ bool delete_while_scanning= table_list->delete_while_scanning;
bool portion_of_time_through_update;
- DBUG_ENTER("mysql_delete");
+
+ DBUG_ENTER("Sql_cmd_delete::delete_single_table");
query_plan.index= MAX_KEY;
query_plan.using_filesort= FALSE;
- create_explain_query(thd->lex, thd->mem_root);
- if (open_and_lock_tables(thd, table_list, TRUE, 0))
- DBUG_RETURN(TRUE);
-
THD_STAGE_INFO(thd, stage_init_update);
+ create_explain_query(thd->lex, thd->mem_root);
const bool delete_history= table_list->vers_conditions.delete_history;
DBUG_ASSERT(!(delete_history && table_list->period_conditions.is_set()));
- if (thd->lex->handle_list_of_derived(table_list, DT_MERGE_FOR_INSERT))
- DBUG_RETURN(TRUE);
- if (thd->lex->handle_list_of_derived(table_list, DT_PREPARE))
- DBUG_RETURN(TRUE);
+ if (table_list->handle_derived(thd->lex, DT_MERGE_FOR_INSERT))
+ DBUG_RETURN(1);
+ if (table_list->handle_derived(thd->lex, DT_PREPARE))
+ DBUG_RETURN(1);
+
+ table= table_list->table;
if (!table_list->single_table_updatable())
{
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias.str, "DELETE");
DBUG_RETURN(TRUE);
}
- if (!(table= table_list->table) || !table->is_created())
+
+ if (!table || !table->is_created())
{
my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
table_list->view_db.str, table_list->view_name.str);
DBUG_RETURN(TRUE);
}
- table->map=1;
+
query_plan.select_lex= thd->lex->first_select_lex();
query_plan.table= table;
thd->lex->promote_select_describe_flag_if_needed();
- if (mysql_prepare_delete(thd, table_list, &conds, &delete_while_scanning))
- DBUG_RETURN(TRUE);
-
- if (table_list->has_period())
- {
- if (!table_list->period_conditions.start.item->const_item()
- || !table_list->period_conditions.end.item->const_item())
- {
- my_error(ER_NOT_CONSTANT_EXPRESSION, MYF(0), "FOR PORTION OF");
- DBUG_RETURN(true);
- }
- }
-
- if (delete_history)
- table->vers_write= false;
-
- if (returning)
- (void) result->prepare(returning->item_list, NULL);
-
- if (thd->lex->current_select->first_cond_optimization)
- {
- thd->lex->current_select->save_leaf_tables(thd);
- thd->lex->current_select->first_cond_optimization= 0;
- }
- /* check ORDER BY even if it can be ignored */
- if (order)
- {
- TABLE_LIST tables;
- List<Item> fields;
- List<Item> all_fields;
-
- bzero((char*) &tables,sizeof(tables));
- tables.table = table;
- tables.alias = table_list->alias;
-
- if (select_lex->setup_ref_array(thd, order_list->elements) ||
- setup_order(thd, select_lex->ref_pointer_array, &tables,
- fields, all_fields, order))
- {
- free_underlaid_joins(thd, thd->lex->first_select_lex());
- DBUG_RETURN(TRUE);
- }
- }
-
/* Apply the IN=>EXISTS transformation to all subqueries and optimize them. */
if (select_lex->optimize_unflattened_subqueries(false))
DBUG_RETURN(TRUE);
@@ -1011,90 +974,6 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
}
-/*
- Prepare items in DELETE statement
-
- SYNOPSIS
- mysql_prepare_delete()
- thd - thread handler
- table_list - global/local table list
- conds - conditions
-
- RETURN VALUE
- FALSE OK
- TRUE error
-*/
-int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds,
- bool *delete_while_scanning)
-{
- Item *fake_conds= 0;
- SELECT_LEX *select_lex= thd->lex->first_select_lex();
- DBUG_ENTER("mysql_prepare_delete");
- List<Item> all_fields;
-
- *delete_while_scanning= true;
- thd->lex->allow_sum_func.clear_all();
- if (setup_tables_and_check_access(thd, &select_lex->context,
- &select_lex->top_join_list, table_list,
- select_lex->leaf_tables, FALSE,
- DELETE_ACL, SELECT_ACL, TRUE))
- DBUG_RETURN(TRUE);
-
- if (table_list->vers_conditions.is_set() && table_list->is_view_or_derived())
- {
- my_error(ER_IT_IS_A_VIEW, MYF(0), table_list->table_name.str);
- DBUG_RETURN(true);
- }
-
- if (table_list->has_period())
- {
- if (table_list->is_view_or_derived())
- {
- my_error(ER_IT_IS_A_VIEW, MYF(0), table_list->table_name.str);
- DBUG_RETURN(true);
- }
-
- if (select_lex->period_setup_conds(thd, table_list))
- DBUG_RETURN(true);
- }
-
- DBUG_ASSERT(table_list->table);
- // conds could be cached from previous SP call
- DBUG_ASSERT(!table_list->vers_conditions.need_setup() ||
- !*conds || thd->stmt_arena->is_stmt_execute());
- if (select_lex->vers_setup_conds(thd, table_list))
- DBUG_RETURN(TRUE);
-
- *conds= select_lex->where;
-
- if (setup_returning_fields(thd, table_list) ||
- setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
- setup_ftfuncs(select_lex))
- DBUG_RETURN(TRUE);
- if (!table_list->single_table_updatable() ||
- check_key_in_view(thd, table_list))
- {
- my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias.str, "DELETE");
- DBUG_RETURN(TRUE);
- }
-
- /*
- Application-time periods: if FOR PORTION OF ... syntax used, DELETE
- statement could issue delete_row's mixed with write_row's. This causes
- problems for myisam and corrupts table, if deleting while scanning.
- */
- if (table_list->has_period()
- || unique_table(thd, table_list, table_list->next_global, 0))
- *delete_while_scanning= false;
-
- if (select_lex->inner_refs_list.elements &&
- fix_inner_refs(thd, all_fields, select_lex, select_lex->ref_pointer_array))
- DBUG_RETURN(TRUE);
-
- select_lex->fix_prepare_information(thd, conds, &fake_conds);
- DBUG_RETURN(FALSE);
-}
-
/***************************************************************************
Delete multiple tables from join
@@ -1107,106 +986,6 @@ extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b)
return file->cmp_ref((const uchar*)a, (const uchar*)b);
}
-/*
- make delete specific preparation and checks after opening tables
-
- SYNOPSIS
- mysql_multi_delete_prepare()
- thd thread handler
-
- RETURN
- FALSE OK
- TRUE Error
-*/
-
-int mysql_multi_delete_prepare(THD *thd)
-{
- LEX *lex= thd->lex;
- TABLE_LIST *aux_tables= lex->auxiliary_table_list.first;
- TABLE_LIST *target_tbl;
- DBUG_ENTER("mysql_multi_delete_prepare");
-
- if (mysql_handle_derived(lex, DT_INIT))
- DBUG_RETURN(TRUE);
- if (mysql_handle_derived(lex, DT_MERGE_FOR_INSERT))
- DBUG_RETURN(TRUE);
- if (mysql_handle_derived(lex, DT_PREPARE))
- DBUG_RETURN(TRUE);
- /*
- setup_tables() need for VIEWs. JOIN::prepare() will not do it second
- time.
-
- lex->query_tables also point on local list of DELETE SELECT_LEX
- */
- if (setup_tables_and_check_access(thd,
- &thd->lex->first_select_lex()->context,
- &thd->lex->first_select_lex()->
- top_join_list,
- lex->query_tables,
- lex->first_select_lex()->leaf_tables,
- FALSE, DELETE_ACL, SELECT_ACL, FALSE))
- DBUG_RETURN(TRUE);
-
- /*
- Multi-delete can't be constructed over-union => we always have
- single SELECT on top and have to check underlying SELECTs of it
- */
- lex->first_select_lex()->set_unique_exclude();
- /* Fix tables-to-be-deleted-from list to point at opened tables */
- for (target_tbl= (TABLE_LIST*) aux_tables;
- target_tbl;
- target_tbl= target_tbl->next_local)
- {
-
- target_tbl->table= target_tbl->correspondent_table->table;
- if (target_tbl->correspondent_table->is_multitable())
- {
- my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
- target_tbl->correspondent_table->view_db.str,
- target_tbl->correspondent_table->view_name.str);
- DBUG_RETURN(TRUE);
- }
-
- if (!target_tbl->correspondent_table->single_table_updatable() ||
- check_key_in_view(thd, target_tbl->correspondent_table))
- {
- my_error(ER_NON_UPDATABLE_TABLE, MYF(0),
- target_tbl->table_name.str, "DELETE");
- DBUG_RETURN(TRUE);
- }
- }
-
- for (target_tbl= (TABLE_LIST*) aux_tables;
- target_tbl;
- target_tbl= target_tbl->next_local)
- {
- /*
- Check that table from which we delete is not used somewhere
- inside subqueries/view.
- */
- {
- TABLE_LIST *duplicate;
- if ((duplicate= unique_table(thd, target_tbl->correspondent_table,
- lex->query_tables, 0)))
- {
- update_non_unique_table_error(target_tbl->correspondent_table,
- "DELETE", duplicate);
- DBUG_RETURN(TRUE);
- }
- }
- }
- /*
- Reset the exclude flag to false so it doesn't interfare
- with further calls to unique_table
- */
- lex->first_select_lex()->exclude_from_table_unique_test= FALSE;
-
- if (lex->save_prep_leaf_tables())
- DBUG_RETURN(TRUE);
-
- DBUG_RETURN(FALSE);
-}
-
multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt, uint num_of_tables_arg):
select_result_interceptor(thd_arg), delete_tables(dt), deleted(0), found(0),
@@ -1659,3 +1438,319 @@ bool multi_delete::send_eof()
}
return 0;
}
+
+
+bool Sql_cmd_delete::precheck(THD *thd)
+{
+ if (!multitable)
+ {
+ if (delete_precheck(thd, lex->query_tables))
+ return true;
+ }
+ else
+ {
+ if (multi_delete_precheck(thd, lex->query_tables))
+ return true;
+ }
+
+ WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
+
+ return false;
+
+#ifdef WITH_WSREP
+wsrep_error_label:
+#endif
+ return true;
+}
+
+
+/**
+ @brief Perform context analysis for delete statements
+
+ @param thd global context the processed statement
+ @returns false on success, true on error
+
+ @note
+ The main bulk of the context analysis actions for a delete statement
+ is performed by a call of JOIN::prepare().
+*/
+
+bool Sql_cmd_delete::prepare_inner(THD *thd)
+{
+ int err= 0;
+ TABLE_LIST *target_tbl;
+ JOIN *join;
+ SELECT_LEX *const select_lex = thd->lex->first_select_lex();
+ TABLE_LIST *const table_list = select_lex->get_table_list();
+ TABLE_LIST *aux_tables= thd->lex->auxiliary_table_list.first;
+ ulonglong select_options= select_lex->options;
+ bool free_join= 1;
+ SELECT_LEX *returning= thd->lex->has_returning() ? thd->lex->returning() : 0;
+ const bool delete_history= table_list->vers_conditions.delete_history;
+ DBUG_ASSERT(!(delete_history && table_list->period_conditions.is_set()));
+
+ DBUG_ENTER("Sql_cmd_delete::prepare_inner");
+
+ (void) read_statistics_for_tables_if_needed(thd, table_list);
+
+ THD_STAGE_INFO(thd, stage_init_update);
+
+ {
+ if (mysql_handle_derived(lex, DT_INIT))
+ DBUG_RETURN(TRUE);
+ if (mysql_handle_derived(lex, DT_MERGE_FOR_INSERT))
+ DBUG_RETURN(TRUE);
+ if (mysql_handle_derived(lex, DT_PREPARE))
+ DBUG_RETURN(TRUE);
+ }
+
+ if (!(result= new (thd->mem_root) multi_delete(thd, aux_tables,
+ lex->table_count)))
+ {
+ DBUG_RETURN(TRUE);
+ }
+
+ table_list->delete_while_scanning= true;
+
+ if (!multitable && !table_list->single_table_updatable())
+ {
+ my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias.str, "DELETE");
+ DBUG_RETURN(TRUE);
+ }
+
+ if (!multitable && (!table_list->table || !table_list->table->is_created()))
+ {
+ my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
+ table_list->view_db.str, table_list->view_name.str);
+ DBUG_RETURN(TRUE);
+ }
+
+ if (setup_tables_and_check_access(thd, &select_lex->context,
+ &select_lex->top_join_list,
+ table_list, select_lex->leaf_tables,
+ false, DELETE_ACL, SELECT_ACL, true))
+ DBUG_RETURN(TRUE);
+
+ if (setup_tables(thd, &select_lex->context, &select_lex->top_join_list,
+ table_list, select_lex->leaf_tables, false, false))
+ DBUG_RETURN(TRUE);
+
+ if (!multitable)
+ {
+ if (table_list->vers_conditions.is_set() && table_list->is_view_or_derived())
+ {
+ my_error(ER_IT_IS_A_VIEW, MYF(0), table_list->table_name.str);
+ DBUG_RETURN(true);
+ }
+
+ if (table_list->has_period())
+ {
+ if (table_list->is_view_or_derived())
+ {
+ my_error(ER_IT_IS_A_VIEW, MYF(0), table_list->table_name.str);
+ DBUG_RETURN(true);
+ }
+
+ if (select_lex->period_setup_conds(thd, table_list))
+ DBUG_RETURN(true);
+ }
+
+ if (select_lex->vers_setup_conds(thd, table_list))
+ DBUG_RETURN(TRUE);
+ /*
+ Application-time periods: if FOR PORTION OF ... syntax used, DELETE
+ statement could issue delete_row's mixed with write_row's. This causes
+ problems for myisam and corrupts table, if deleting while scanning.
+ */
+ if (table_list->has_period()
+ || unique_table(thd, table_list, table_list->next_global, 0))
+ table_list->delete_while_scanning= false;
+ }
+
+ {
+ if (thd->lex->describe)
+ select_options|= SELECT_DESCRIBE;
+
+ /*
+ When in EXPLAIN, delay deleting the joins so that they are still
+ available when we're producing EXPLAIN EXTENDED warning text.
+ */
+ if (select_options & SELECT_DESCRIBE)
+ free_join= 0;
+ select_options|=
+ SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK | OPTION_SETUP_TABLES_DONE;
+
+ if (!(join= new (thd->mem_root) JOIN(thd, empty_list,
+ select_options, result)))
+ DBUG_RETURN(TRUE);
+ THD_STAGE_INFO(thd, stage_init);
+ select_lex->join= join;
+ thd->lex->used_tables=0;
+ if ((err= join->prepare(table_list, select_lex->where,
+ select_lex->order_list.elements,
+ select_lex->order_list.first,
+ false, NULL, NULL, NULL,
+ select_lex, &lex->unit)))
+
+ {
+ goto err;
+ }
+ }
+
+ if (multitable)
+ {
+ /*
+ Multi-delete can't be constructed over-union => we always have
+ single SELECT on top and have to check underlying SELECTs of it
+ */
+ lex->first_select_lex()->set_unique_exclude();
+ /* Fix tables-to-be-deleted-from list to point at opened tables */
+ for (target_tbl= (TABLE_LIST*) aux_tables;
+ target_tbl;
+ target_tbl= target_tbl->next_local)
+ {
+ target_tbl->table= target_tbl->correspondent_table->table;
+ if (target_tbl->correspondent_table->is_multitable())
+ {
+ my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
+ target_tbl->correspondent_table->view_db.str,
+ target_tbl->correspondent_table->view_name.str);
+ DBUG_RETURN(TRUE);
+ }
+
+ if (!target_tbl->correspondent_table->single_table_updatable() ||
+ check_key_in_view(thd, target_tbl->correspondent_table))
+ {
+ my_error(ER_NON_UPDATABLE_TABLE, MYF(0),
+ target_tbl->table_name.str, "DELETE");
+ DBUG_RETURN(TRUE);
+ }
+ }
+
+ for (target_tbl= (TABLE_LIST*) aux_tables;
+ target_tbl;
+ target_tbl= target_tbl->next_local)
+ {
+ /*
+ Check that table from which we delete is not used somewhere
+ inside subqueries/view.
+ */
+ {
+ TABLE_LIST *duplicate;
+ if ((duplicate= unique_table(thd, target_tbl->correspondent_table,
+ lex->query_tables, 0)))
+ {
+ update_non_unique_table_error(target_tbl->correspondent_table,
+ "DELETE", duplicate);
+ DBUG_RETURN(TRUE);
+ }
+ }
+ }
+ /*
+ Reset the exclude flag to false so it doesn't interfare
+ with further calls to unique_table
+ */
+ lex->first_select_lex()->exclude_from_table_unique_test= FALSE;
+ }
+
+ if (!multitable && table_list->has_period())
+ {
+ if (!table_list->period_conditions.start.item->const_item()
+ || !table_list->period_conditions.end.item->const_item())
+ {
+ my_error(ER_NOT_CONSTANT_EXPRESSION, MYF(0), "FOR PORTION OF");
+ DBUG_RETURN(true);
+ }
+ }
+
+ if (delete_history)
+ table_list->table->vers_write= false;
+
+ if (setup_returning_fields(thd, table_list) ||
+ setup_ftfuncs(select_lex))
+ goto err;
+
+ free_join= false;
+
+ if (returning)
+ (void) result->prepare(returning->item_list, NULL);
+
+err:
+
+ if (free_join)
+ {
+ THD_STAGE_INFO(thd, stage_end);
+ err|= (int)(select_lex->cleanup());
+ DBUG_RETURN(err || thd->is_error());
+ }
+ DBUG_RETURN(err);
+
+}
+
+
+/**
+ @brief Perform optimization and execution actions needed for deletes
+
+ @param thd global context the processed statement
+ @returns false on success, true on error
+*/
+
+bool Sql_cmd_delete::execute_inner(THD *thd)
+{
+ if (!multitable)
+ {
+ if (lex->has_returning())
+ {
+ select_result *sel_result= NULL;
+ delete result;
+ /* This is DELETE ... RETURNING. It will return output to the client */
+ if (thd->lex->analyze_stmt)
+ {
+ /*
+ Actually, it is ANALYZE .. DELETE .. RETURNING. We need to produce
+ output and then discard it.
+ */
+ sel_result= new (thd->mem_root) select_send_analyze(thd);
+ save_protocol= thd->protocol;
+ thd->protocol= new Protocol_discard(thd);
+ }
+ else
+ {
+ if (!lex->result && !(sel_result= new (thd->mem_root) select_send(thd)))
+ return true;
+ }
+ result= lex->result ? lex->result : sel_result;
+ }
+ }
+
+ bool res= multitable ? Sql_cmd_dml::execute_inner(thd)
+ : delete_from_single_table(thd);
+
+ res|= thd->is_error();
+
+ if (save_protocol)
+ {
+ delete thd->protocol;
+ thd->protocol= save_protocol;
+ }
+ {
+ if (unlikely(res))
+ {
+ if (multitable)
+ result->abort_result_set();
+ }
+ else
+ {
+ if (thd->lex->describe || thd->lex->analyze_stmt)
+ res= thd->lex->explain->send_explain(thd);
+ }
+ }
+
+ if (result)
+ {
+ res= false;
+ delete result;
+ }
+
+ return res;
+}
diff --git a/sql/sql_delete.h b/sql/sql_delete.h
index 520524c..e1d5044 100644
--- a/sql/sql_delete.h
+++ b/sql/sql_delete.h
@@ -17,6 +17,9 @@
#define SQL_DELETE_INCLUDED
#include "my_base.h" /* ha_rows */
+#include "sql_class.h" /* enum_duplicates */
+#include "sql_cmd.h" // Sql_cmd_dml
+#include "sql_base.h"
class THD;
struct TABLE_LIST;
@@ -26,10 +29,66 @@ class select_result;
typedef class Item COND;
template <typename T> class SQL_I_List;
-int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds,
- bool *delete_while_scanning);
-bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
- SQL_I_List<ORDER> *order, ha_rows rows,
- ulonglong options, select_result *result);
+/**
+ @class Sql_cmd_delete - class used for any DELETE statements
+ This class is derived from Sql_cmd_dml and contains implementations
+ for abstract virtual function of the latter such as precheck() and
+ prepare_inner(). It also overrides the implementation of execute_inner()
+ providing a special handling for single-table delete statements that
+ are not converted to multi-table delete.
+ The class provides an object of the DML_prelocking_strategy class
+ for the virtual function get_dml_prelocking_strategy().
+*/
+class Sql_cmd_delete final : public Sql_cmd_dml
+{
+public:
+ Sql_cmd_delete(bool multitable_arg)
+ : multitable(multitable_arg), save_protocol(NULL) {}
+
+ enum_sql_command sql_command_code() const override
+ {
+ return multitable ? SQLCOM_DELETE_MULTI : SQLCOM_DELETE;
+ }
+
+ DML_prelocking_strategy *get_dml_prelocking_strategy()
+ {
+ return &dml_prelocking_strategy;
+ }
+
+protected:
+ /**
+ @brief Perform precheck of table privileges for delete statements
+ */
+ bool precheck(THD *thd) override;
+
+ /**
+ @brief Perform context analysis for delete statements
+ */
+ bool prepare_inner(THD *thd) override;
+
+ /**
+ @brief Perform optimization and execution actions needed for deletes
+ */
+ bool execute_inner(THD *thd) override;
+
+ private:
+ /**
+ @biefSpecial handling of single-table deletes after prepare phase
+ */
+ bool delete_from_single_table(THD *thd);
+
+ /*
+ True if the statement is a multitable delete or converted to such.
+ For a single-table delete this flag is set to true if the statement
+ is supposed to be converted to multi-table delete.
+ */
+ bool multitable;
+
+ /* The prelocking strategy used when opening the used tables */
+ DML_prelocking_strategy dml_prelocking_strategy;
+
+ List<Item> empty_list; /**< auxiliary empty list used by prepare_inner() */
+ Protocol *save_protocol; /**< needed for ANALYZE .. DELETE .. RETURNING */
+};
#endif /* SQL_DELETE_INCLUDED */
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 5f2f072..070cf52 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -1302,6 +1302,8 @@ void LEX::start(THD *thd_arg)
wild= 0;
exchange= 0;
+ table_count= 0;
+
DBUG_VOID_RETURN;
}
@@ -3029,6 +3031,7 @@ void st_select_lex::init_select()
curr_tvc_name= 0;
versioned_tables= 0;
nest_flags= 0;
+ item_list_usage= MARK_COLUMNS_READ;
}
/*
@@ -3299,34 +3302,6 @@ void st_select_lex_unit::exclude_level()
}
-#if 0
-/*
- Exclude subtree of current unit from tree of SELECTs
-
- SYNOPSYS
- st_select_lex_unit::exclude_tree()
-*/
-void st_select_lex_unit::exclude_tree()
-{
- for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
- {
- // unlink current level from global SELECTs list
- if (sl->link_prev && (*sl->link_prev= sl->link_next))
- sl->link_next->link_prev= sl->link_prev;
-
- // unlink underlay levels
- for (SELECT_LEX_UNIT *u= sl->first_inner_unit(); u; u= u->next_unit())
- {
- u->exclude_level();
- }
- }
- // exclude currect unit from list of nodes
- (*prev)= next;
- if (next)
- next->prev= prev;
-}
-#endif
-
/*
st_select_lex_node::mark_as_dependent mark all st_select_lex struct from
@@ -3548,7 +3523,7 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num)
select_n_where_fields +
order_group_num +
hidden_bit_fields +
- fields_in_window_functions) * (size_t) 5;
+ fields_in_window_functions + 1) * (size_t) 5;
DBUG_ASSERT(n_elems % 5 == 0);
if (!ref_pointer_array.is_null())
{
@@ -4094,6 +4069,12 @@ bool LEX::can_not_use_merged(bool no_update_or_delete)
return TRUE;
/* Fall through */
+ case SQLCOM_UPDATE:
+ if (no_update_or_delete && m_sql_cmd &&
+ (m_sql_cmd->sql_command_code() == SQLCOM_UPDATE_MULTI ||
+ query_tables->is_multitable()))
+ return TRUE;
+
default:
return FALSE;
}
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 4f2e775..0badc32 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -36,6 +36,7 @@
#include "sql_limit.h" // Select_limit_counters
#include "json_table.h" // Json_table_column
#include "sql_schema.h"
+#include "sql_class.h" // enum enum_column_usage
/* Used for flags of nesting constructs */
#define SELECT_NESTING_MAP_SIZE 64
@@ -873,6 +874,8 @@ class st_select_lex_unit: public st_select_lex_node {
{
}
+ void set_query_result(select_result *res) { result= res; }
+
TABLE *table; /* temporary table using for appending UNION results */
select_result *result;
st_select_lex *pre_last_parse;
@@ -1005,6 +1008,7 @@ class st_select_lex_unit: public st_select_lex_node {
bool add_fake_select_lex(THD *thd);
void init_prepare_fake_select_lex(THD *thd, bool first_execution);
+ void set_prepared() { prepared = true; }
inline bool is_prepared() { return prepared; }
bool change_result(select_result_interceptor *result,
select_result_interceptor *old_result);
@@ -1107,6 +1111,7 @@ class st_select_lex: public st_select_lex_node
Item *prep_having;/* saved HAVING clause for prepared statement processing */
Item *cond_pushed_into_where; /* condition pushed into WHERE */
Item *cond_pushed_into_having; /* condition pushed into HAVING */
+ Item *where_cond_after_prepare;
/*
nest_levels are local to the query or VIEW,
@@ -1215,6 +1220,7 @@ class st_select_lex: public st_select_lex_node
List<List_item> save_many_values;
List<Item> *save_insert_list;
+ enum_column_usage item_list_usage;
bool is_item_list_lookup:1;
/*
Needed to correctly generate 'PRIMARY' or 'SIMPLE' for select_type column
@@ -1745,6 +1751,25 @@ class Query_tables_list
uint sroutines_list_own_elements;
/**
+ Locking state of tables in this particular statement.
+
+ If we under LOCK TABLES or in prelocked mode we consider tables
+ for the statement to be "locked" if there was a call to lock_tables()
+ (which called handler::start_stmt()) for tables of this statement
+ and there was no matching close_thread_tables() call.
+
+ As result this state may differ significantly from one represented
+ by Open_tables_state::lock/locked_tables_mode more, which are always
+ "on" under LOCK TABLES or in prelocked mode.
+ */
+ enum enum_lock_tables_state { LTS_NOT_LOCKED = 0, LTS_LOCKED };
+ enum_lock_tables_state lock_tables_state;
+ bool is_query_tables_locked() const
+ {
+ return (lock_tables_state == LTS_LOCKED);
+ }
+
+ /**
Number of tables which were open by open_tables() and to be locked
by lock_tables().
Note that we set this member only in some cases, when this value
@@ -3391,6 +3416,7 @@ struct LEX: public Query_tables_list
bool default_used:1; /* using default() function */
bool with_rownum:1; /* Using rownum() function */
bool is_lex_started:1; /* If lex_start() did run. For debugging. */
+
/*
This variable is used in post-parse stage to declare that sum-functions,
or functions which have sense only if GROUP BY is present, are allowed.
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 0597b08..8b906be 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -34,9 +34,7 @@
#include "sql_locale.h" // my_locale_en_US
#include "log.h" // flush_error_log
#include "sql_view.h" // mysql_create_view, mysql_drop_view
-#include "sql_delete.h" // mysql_delete
#include "sql_insert.h" // mysql_insert
-#include "sql_update.h" // mysql_update, mysql_multi_update
#include "sql_partition.h" // struct partition_info
#include "sql_db.h" // mysql_change_db, mysql_create_db,
// mysql_rm_db, mysql_upgrade_db,
@@ -3442,7 +3440,6 @@ int
mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt)
{
int res= 0;
- int up_result= 0;
LEX *lex= thd->lex;
/* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */
SELECT_LEX *select_lex= lex->first_select_lex();
@@ -3454,7 +3451,6 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt)
SELECT_LEX_UNIT *unit= &lex->unit;
#ifdef HAVE_REPLICATION
/* have table map for update for multi-update statement (BUG#37051) */
- bool have_table_map_for_update= FALSE;
/* */
Rpl_filter *rpl_filter;
#endif
@@ -3576,7 +3572,6 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt)
if (lex->sql_command == SQLCOM_UPDATE_MULTI &&
thd->table_map_for_update)
{
- have_table_map_for_update= TRUE;
table_map table_map_for_update= thd->table_map_for_update;
uint nr= 0;
TABLE_LIST *table;
@@ -4381,130 +4376,15 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt)
break;
}
case SQLCOM_UPDATE:
- {
- WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
- ha_rows found= 0, updated= 0;
- DBUG_ASSERT(first_table == all_tables && first_table != 0);
- WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
-
- if (update_precheck(thd, all_tables))
- break;
-
- /*
- UPDATE IGNORE can be unsafe. We therefore use row based
- logging if mixed or row based logging is available.
- TODO: Check if the order of the output of the select statement is
- deterministic. Waiting for BUG#42415
- */
- if (lex->ignore)
- lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_UPDATE_IGNORE);
-
- DBUG_ASSERT(select_lex->limit_params.offset_limit == 0);
- unit->set_limit(select_lex);
- MYSQL_UPDATE_START(thd->query());
- res= up_result= mysql_update(thd, all_tables,
- select_lex->item_list,
- lex->value_list,
- select_lex->where,
- select_lex->order_list.elements,
- select_lex->order_list.first,
- unit->lim.get_select_limit(),
- lex->ignore, &found, &updated);
- MYSQL_UPDATE_DONE(res, found, updated);
- /* mysql_update return 2 if we need to switch to multi-update */
- if (up_result != 2)
- break;
- if (thd->lex->period_conditions.is_set())
- {
- DBUG_ASSERT(0); // Should never happen
- goto error;
- }
- }
- /* fall through */
case SQLCOM_UPDATE_MULTI:
+ case SQLCOM_DELETE:
+ case SQLCOM_DELETE_MULTI:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
- /* if we switched from normal update, rights are checked */
- if (up_result != 2)
- {
- WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
- if ((res= multi_update_precheck(thd, all_tables)))
- break;
- }
- else
- res= 0;
-
- unit->set_limit(select_lex);
- /*
- We can not use mysql_explain_union() because of parameters of
- mysql_select in mysql_multi_update so just set the option if needed
- */
- if (thd->lex->describe)
- {
- select_lex->set_explain_type(FALSE);
- select_lex->options|= SELECT_DESCRIBE;
- }
-
- res= mysql_multi_update_prepare(thd);
+ DBUG_ASSERT(lex->m_sql_cmd != NULL);
-#ifdef HAVE_REPLICATION
- /* Check slave filtering rules */
- if (unlikely(thd->slave_thread && !have_table_map_for_update))
- {
- if (all_tables_not_ok(thd, all_tables))
- {
- if (res!= 0)
- {
- res= 0; /* don't care of prev failure */
- thd->clear_error(); /* filters are of highest prior */
- }
- /* we warn the slave SQL thread */
- my_error(ER_SLAVE_IGNORED_TABLE, MYF(0));
- break;
- }
- if (res)
- break;
- }
- else
- {
-#endif /* HAVE_REPLICATION */
- if (res)
- break;
- if (opt_readonly &&
- !(thd->security_ctx->master_access & PRIV_IGNORE_READ_ONLY) &&
- some_non_temp_table_to_be_updated(thd, all_tables))
- {
- my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
- break;
- }
-#ifdef HAVE_REPLICATION
- } /* unlikely */
-#endif
- {
- multi_update *result_obj;
- MYSQL_MULTI_UPDATE_START(thd->query());
- res= mysql_multi_update(thd, all_tables,
- &select_lex->item_list,
- &lex->value_list,
- select_lex->where,
- select_lex->options,
- lex->duplicates,
- lex->ignore,
- unit,
- select_lex,
- &result_obj);
- if (result_obj)
- {
- MYSQL_MULTI_UPDATE_DONE(res, result_obj->num_found(),
- result_obj->num_updated());
- res= FALSE; /* Ignore errors here */
- delete result_obj;
- }
- else
- {
- MYSQL_MULTI_UPDATE_DONE(1, 0, 0);
- }
- }
+ res = lex->m_sql_cmd->execute(thd);
+ thd->abort_on_warning= 0;
break;
}
case SQLCOM_REPLACE:
@@ -4766,129 +4646,6 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt)
break;
}
- case SQLCOM_DELETE:
- {
- WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
- select_result *sel_result= NULL;
- DBUG_ASSERT(first_table == all_tables && first_table != 0);
- WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
-
- if ((res= delete_precheck(thd, all_tables)))
- break;
- DBUG_ASSERT(select_lex->limit_params.offset_limit == 0);
- unit->set_limit(select_lex);
-
- MYSQL_DELETE_START(thd->query());
- Protocol *save_protocol= NULL;
-
- if (lex->has_returning())
- {
- /* This is DELETE ... RETURNING. It will return output to the client */
- if (thd->lex->analyze_stmt)
- {
- /*
- Actually, it is ANALYZE .. DELETE .. RETURNING. We need to produce
- output and then discard it.
- */
- sel_result= new (thd->mem_root) select_send_analyze(thd);
- save_protocol= thd->protocol;
- thd->protocol= new Protocol_discard(thd);
- }
- else
- {
- if (!lex->result && !(sel_result= new (thd->mem_root) select_send(thd)))
- goto error;
- }
- }
-
- res = mysql_delete(thd, all_tables,
- select_lex->where, &select_lex->order_list,
- unit->lim.get_select_limit(), select_lex->options,
- lex->result ? lex->result : sel_result);
-
- if (save_protocol)
- {
- delete thd->protocol;
- thd->protocol= save_protocol;
- }
-
- if (thd->lex->analyze_stmt || thd->lex->describe)
- {
- if (!res)
- res= thd->lex->explain->send_explain(thd);
- }
-
- delete sel_result;
- MYSQL_DELETE_DONE(res, (ulong) thd->get_row_count_func());
- break;
- }
- case SQLCOM_DELETE_MULTI:
- {
- WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
- DBUG_ASSERT(first_table == all_tables && first_table != 0);
- TABLE_LIST *aux_tables= thd->lex->auxiliary_table_list.first;
- multi_delete *result;
- WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
-
- if ((res= multi_delete_precheck(thd, all_tables)))
- break;
-
- /* condition will be TRUE on SP re-excuting */
- if (select_lex->item_list.elements != 0)
- select_lex->item_list.empty();
- if (add_item_to_list(thd, new (thd->mem_root) Item_null(thd)))
- goto error;
-
- THD_STAGE_INFO(thd, stage_init);
- if ((res= open_and_lock_tables(thd, all_tables, TRUE, 0)))
- break;
-
- MYSQL_MULTI_DELETE_START(thd->query());
- if (unlikely(res= mysql_multi_delete_prepare(thd)))
- {
- MYSQL_MULTI_DELETE_DONE(1, 0);
- goto error;
- }
-
- if (likely(!thd->is_fatal_error))
- {
- result= new (thd->mem_root) multi_delete(thd, aux_tables,
- lex->table_count);
- if (likely(result))
- {
- if (unlikely(select_lex->vers_setup_conds(thd, aux_tables)))
- goto multi_delete_error;
- res= mysql_select(thd,
- select_lex->get_table_list(),
- select_lex->item_list,
- select_lex->where,
- 0, (ORDER *)NULL, (ORDER *)NULL, (Item *)NULL,
- (ORDER *)NULL,
- (select_lex->options | thd->variables.option_bits |
- SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK |
- OPTION_SETUP_TABLES_DONE) & ~OPTION_BUFFER_RESULT,
- result, unit, select_lex);
- res|= (int)(thd->is_error());
-
- MYSQL_MULTI_DELETE_DONE(res, result->num_deleted());
- if (res)
- result->abort_result_set(); /* for both DELETE and EXPLAIN DELETE */
- else
- {
- if (lex->describe || lex->analyze_stmt)
- res= thd->lex->explain->send_explain(thd);
- }
- multi_delete_error:
- delete result;
- }
- }
- else
- {
- res= TRUE; // Error
- MYSQL_MULTI_DELETE_DONE(1, 0);
- }
- break;
- }
case SQLCOM_DROP_SEQUENCE:
case SQLCOM_DROP_TABLE:
{
@@ -7772,12 +7529,16 @@ void create_select_for_variable(THD *thd, LEX_CSTRING *var_name)
}
-void mysql_init_multi_delete(LEX *lex)
+void mysql_init_delete(LEX *lex)
{
- lex->sql_command= SQLCOM_DELETE_MULTI;
mysql_init_select(lex);
lex->first_select_lex()->limit_params.clear();
lex->unit.lim.clear();
+}
+
+void mysql_init_multi_delete(LEX *lex)
+{
+ lex->sql_command= SQLCOM_DELETE_MULTI;
lex->first_select_lex()->table_list.
save_and_clear(&lex->auxiliary_table_list);
lex->query_tables= 0;
diff --git a/sql/sql_parse.h b/sql/sql_parse.h
index d3cf83b..3f3302b 100644
--- a/sql/sql_parse.h
+++ b/sql/sql_parse.h
@@ -93,6 +93,7 @@ void mysql_parse(THD *thd, char *rawbuf, uint length,
bool mysql_new_select(LEX *lex, bool move_down, SELECT_LEX *sel);
void create_select_for_variable(THD *thd, LEX_CSTRING *var_name);
void create_table_set_open_action_and_adjust_tables(LEX *lex);
+void mysql_init_delete(LEX *lex);
void mysql_init_multi_delete(LEX *lex);
bool multi_delete_set_locks_and_link_aux_tables(LEX *lex);
void create_table_set_open_action_and_adjust_tables(LEX *lex);
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index b10a81d..b9ae058 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -95,10 +95,8 @@ When one supplies long data for a placeholder:
#include "sql_base.h" // open_normal_and_derived_tables
#include "sql_cache.h" // query_cache_*
#include "sql_view.h" // create_view_precheck
-#include "sql_delete.h" // mysql_prepare_delete
#include "sql_select.h" // for JOIN
#include "sql_insert.h" // upgrade_lock_type_for_insert, mysql_prepare_insert
-#include "sql_update.h" // mysql_prepare_update
#include "sql_db.h" // mysql_opt_change_db, mysql_change_db
#include "sql_derived.h" // mysql_derived_prepare,
// mysql_handle_derived
@@ -1399,160 +1397,6 @@ static bool mysql_test_insert(Prepared_statement *stmt,
}
-/**
- Validate UPDATE statement.
-
- @param stmt prepared statement
- @param tables list of tables used in this query
-
- @todo
- - here we should send types of placeholders to the client.
-
- @retval
- 0 success
- @retval
- 1 error, error message is set in THD
- @retval
- 2 convert to multi_update
-*/
-
-static int mysql_test_update(Prepared_statement *stmt,
- TABLE_LIST *table_list)
-{
- int res;
- THD *thd= stmt->thd;
- uint table_count= 0;
- TABLE_LIST *update_source_table;
- SELECT_LEX *select= stmt->lex->first_select_lex();
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- privilege_t want_privilege(NO_ACL);
-#endif
- DBUG_ENTER("mysql_test_update");
-
- if (update_precheck(thd, table_list) ||
- open_tables(thd, &table_list, &table_count, MYSQL_OPEN_FORCE_SHARED_MDL))
- goto error;
-
- if (mysql_handle_derived(thd->lex, DT_INIT))
- goto error;
-
- if (((update_source_table= unique_table(thd, table_list,
- table_list->next_global, 0)) ||
- table_list->is_multitable()))
- {
- DBUG_ASSERT(update_source_table || table_list->view != 0);
- DBUG_PRINT("info", ("Switch to multi-update"));
- /* pass counter value */
- thd->lex->table_count= table_count;
- /* convert to multiupdate */
- DBUG_RETURN(2);
- }
-
- /*
- thd->fill_derived_tables() is false here for sure (because it is
- preparation of PS, so we even do not check it).
- */
- if (table_list->handle_derived(thd->lex, DT_MERGE_FOR_INSERT))
- goto error;
- if (table_list->handle_derived(thd->lex, DT_PREPARE))
- goto error;
-
- if (!table_list->single_table_updatable())
- {
- my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias.str, "UPDATE");
- goto error;
- }
-
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- /* Force privilege re-checking for views after they have been opened. */
- want_privilege= (table_list->view ? UPDATE_ACL :
- table_list->grant.want_privilege);
-#endif
-
- if (mysql_prepare_update(thd, table_list, &select->where,
- select->order_list.elements,
- select->order_list.first))
- goto error;
-
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- table_list->grant.want_privilege= want_privilege;
- table_list->table->grant.want_privilege= want_privilege;
- table_list->register_want_access(want_privilege);
-#endif
- thd->lex->first_select_lex()->no_wrap_view_item= TRUE;
- res= setup_fields(thd, Ref_ptr_array(),
- select->item_list, MARK_COLUMNS_READ, 0, NULL, 0);
- thd->lex->first_select_lex()->no_wrap_view_item= FALSE;
- if (res)
- goto error;
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- /* Check values */
- table_list->grant.want_privilege=
- table_list->table->grant.want_privilege=
- (SELECT_ACL & ~table_list->table->grant.privilege);
- table_list->register_want_access(SELECT_ACL);
-#endif
- if (setup_fields(thd, Ref_ptr_array(),
- stmt->lex->value_list, COLUMNS_READ, 0, NULL, 0) ||
- check_unique_table(thd, table_list))
- goto error;
- /* TODO: here we should send types of placeholders to the client. */
- DBUG_RETURN(0);
-error:
- DBUG_RETURN(1);
-}
-
-
-/**
- Validate DELETE statement.
-
- @param stmt prepared statement
- @param tables list of tables used in this query
-
- @retval
- FALSE success
- @retval
- TRUE error, error message is set in THD
-*/
-
-static bool mysql_test_delete(Prepared_statement *stmt,
- TABLE_LIST *table_list)
-{
- uint table_count= 0;
- THD *thd= stmt->thd;
- LEX *lex= stmt->lex;
- bool delete_while_scanning;
- DBUG_ENTER("mysql_test_delete");
-
- if (delete_precheck(thd, table_list) ||
- open_tables(thd, &table_list, &table_count, MYSQL_OPEN_FORCE_SHARED_MDL))
- goto error;
-
- if (mysql_handle_derived(thd->lex, DT_INIT))
- goto error;
- if (mysql_handle_derived(thd->lex, DT_MERGE_FOR_INSERT))
- goto error;
- if (mysql_handle_derived(thd->lex, DT_PREPARE))
- goto error;
-
- if (!table_list->single_table_updatable())
- {
- my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias.str, "DELETE");
- goto error;
- }
- if (!table_list->table || !table_list->table->is_created())
- {
- my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
- table_list->view_db.str, table_list->view_name.str);
- goto error;
- }
-
- DBUG_RETURN(mysql_prepare_delete(thd, table_list,
- &lex->first_select_lex()->where,
- &delete_while_scanning));
-error:
- DBUG_RETURN(TRUE);
-}
/**
@@ -2135,74 +1979,6 @@ static bool mysql_test_create_view(Prepared_statement *stmt)
}
-/*
- Validate and prepare for execution a multi update statement.
-
- @param stmt prepared statement
- @param tables list of tables used in this query
- @param converted converted to multi-update from usual update
-
- @retval
- FALSE success
- @retval
- TRUE error, error message is set in THD
-*/
-
-static bool mysql_test_multiupdate(Prepared_statement *stmt,
- TABLE_LIST *tables,
- bool converted)
-{
- /* if we switched from normal update, rights are checked */
- if (!converted && multi_update_precheck(stmt->thd, tables))
- return TRUE;
-
- return select_like_stmt_test(stmt, &mysql_multi_update_prepare,
- OPTION_SETUP_TABLES_DONE);
-}
-
-
-/**
- Validate and prepare for execution a multi delete statement.
-
- @param stmt prepared statement
- @param tables list of tables used in this query
-
- @retval
- FALSE success
- @retval
- TRUE error, error message in THD is set.
-*/
-
-static bool mysql_test_multidelete(Prepared_statement *stmt,
- TABLE_LIST *tables)
-{
- THD *thd= stmt->thd;
-
- thd->lex->current_select= thd->lex->first_select_lex();
- if (add_item_to_list(thd, new (thd->mem_root)
- Item_null(thd)))
- {
- my_error(ER_OUTOFMEMORY, MYF(ME_FATAL), 0);
- goto error;
- }
-
- if (multi_delete_precheck(thd, tables) ||
- select_like_stmt_test_with_open(stmt, tables,
- &mysql_multi_delete_prepare,
- OPTION_SETUP_TABLES_DONE))
- goto error;
- if (!tables->table)
- {
- my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
- tables->view_db.str, tables->view_name.str);
- goto error;
- }
- return FALSE;
-error:
- return TRUE;
-}
-
-
/**
Wrapper for mysql_insert_select_prepare, to make change of local tables
after open_normal_and_derived_tables() call.
@@ -2484,18 +2260,14 @@ static bool check_prepared_statement(Prepared_statement *stmt)
break;
case SQLCOM_UPDATE:
- res= mysql_test_update(stmt, tables);
- /* mysql_test_update returns 2 if we need to switch to multi-update */
- if (res != 2)
- break;
- /* fall through */
case SQLCOM_UPDATE_MULTI:
- res= mysql_test_multiupdate(stmt, tables, res == 2);
- break;
-
case SQLCOM_DELETE:
- res= mysql_test_delete(stmt, tables);
+ case SQLCOM_DELETE_MULTI:
+ res = lex->m_sql_cmd->prepare(thd);
+ if (!res)
+ lex->m_sql_cmd->unprepare(thd);
break;
+
/* The following allow WHERE clause, so they must be tested like SELECT */
case SQLCOM_SHOW_DATABASES:
case SQLCOM_SHOW_TABLES:
@@ -2632,10 +2404,6 @@ static bool check_prepared_statement(Prepared_statement *stmt)
res= mysql_test_set_fields(stmt, tables, &lex->var_list);
break;
- case SQLCOM_DELETE_MULTI:
- res= mysql_test_multidelete(stmt, tables);
- break;
-
case SQLCOM_INSERT_SELECT:
case SQLCOM_REPLACE_SELECT:
res= mysql_test_insert_select(stmt, tables);
@@ -4373,6 +4141,9 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
thd->is_error() ||
init_param_array(this));
+ if (lex->m_sql_cmd)
+ lex->m_sql_cmd->set_owner(this);
+
if (thd->security_ctx->password_expired &&
lex->sql_command != SQLCOM_SET_OPTION &&
lex->sql_command != SQLCOM_PREPARE &&
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 2a56292..bf49d69 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1430,7 +1430,7 @@ JOIN::prepare(TABLE_LIST *tables_init, COND *conds_init, uint og_num,
}
}
- if (setup_fields(thd, ref_ptrs, fields_list, MARK_COLUMNS_READ,
+ if (setup_fields(thd, ref_ptrs, fields_list, select_lex->item_list_usage,
&all_fields, &select_lex->pre_fix, 1))
DBUG_RETURN(-1);
thd->lex->current_select->context_analysis_place= save_place;
@@ -1720,6 +1720,8 @@ JOIN::prepare(TABLE_LIST *tables_init, COND *conds_init, uint og_num,
if (!procedure && result && result->prepare(fields_list, unit_arg))
goto err; /* purecov: inspected */
+ select_lex->where_cond_after_prepare= conds;
+
unit= unit_arg;
if (prepare_stage2())
goto err;
@@ -29028,7 +29030,8 @@ static bool get_range_limit_read_cost(const JOIN_TAB *tab,
@note
This function takes into account table->opt_range_condition_rows statistic
(that is calculated by the make_join_statistics function).
- However, single table procedures such as mysql_update() and mysql_delete()
+ However, single table procedures such as Sql_cmd_update:update_single_table()
+ and Sql_cmd_delete::delete_single_table()
never call make_join_statistics, so they have to update it manually
(@see get_index_for_order()).
*/
@@ -30463,6 +30466,266 @@ static bool process_direct_rownum_comparison(THD *thd, SELECT_LEX_UNIT *unit,
}
+static void MYSQL_DML_START(THD *thd)
+{
+ switch (thd->lex->sql_command) {
+
+ case SQLCOM_UPDATE:
+ MYSQL_UPDATE_START(thd->query());
+ break;
+ case SQLCOM_UPDATE_MULTI:
+ MYSQL_MULTI_UPDATE_START(thd->query());
+ break;
+ case SQLCOM_DELETE:
+ MYSQL_DELETE_START(thd->query());
+ break;
+ case SQLCOM_DELETE_MULTI:
+ MYSQL_MULTI_DELETE_START(thd->query());
+ break;
+ default:
+ DBUG_ASSERT(0);
+ }
+}
+
+
+static void MYSQL_DML_DONE(THD *thd, int rc)
+{
+ switch (thd->lex->sql_command) {
+
+ case SQLCOM_UPDATE:
+ MYSQL_UPDATE_DONE(
+ rc,
+ (rc ? 0 :
+ ((multi_update*)(((Sql_cmd_dml*)(thd->lex->m_sql_cmd))->get_result()))
+ ->num_found()),
+ (rc ? 0 :
+ ((multi_update*)(((Sql_cmd_dml*)(thd->lex->m_sql_cmd))->get_result()))
+ ->num_updated()));
+ break;
+ case SQLCOM_UPDATE_MULTI:
+ MYSQL_MULTI_UPDATE_DONE(
+ rc,
+ (rc ? 0 :
+ ((multi_update*)(((Sql_cmd_dml*)(thd->lex->m_sql_cmd))->get_result()))
+ ->num_found()),
+ (rc ? 0 :
+ ((multi_update*)(((Sql_cmd_dml*)(thd->lex->m_sql_cmd))->get_result()))
+ ->num_updated()));
+ break;
+ case SQLCOM_DELETE:
+ MYSQL_DELETE_DONE(rc, (rc ? 0 : (ulong) (thd->get_row_count_func())));
+ break;
+ case SQLCOM_DELETE_MULTI:
+ MYSQL_MULTI_DELETE_DONE(
+ rc,
+ (rc ? 0 :
+ ((multi_delete*)(((Sql_cmd_dml*)(thd->lex->m_sql_cmd))->get_result()))
+ ->num_deleted()));
+ break;
+ default:
+ DBUG_ASSERT(0);
+ }
+}
+
+/*
+ @brief Perform actions needed before locking tables for a DML statement
+
+ @param thd global context the processed statement
+ @returns false if success, true if error
+
+ @details
+ This function calls the precheck() procedure fo the processed statement,
+ then is opens tables used in the statement and finally it calls the function
+ prepare_inner() that is specific for the type of the statement.
+
+ @note
+ The function are used when processing:
+ - a DML statement
+ - PREPARE stmt FROM <DML "statement>"
+ - EXECUTE stmt when stmt is prepared from a DML statement.
+*/
+
+bool Sql_cmd_dml::prepare(THD *thd)
+{
+ lex= thd->lex;
+ SELECT_LEX_UNIT *unit= &lex->unit;
+
+ DBUG_ASSERT(!is_prepared());
+
+ // Perform a coarse statement-specific privilege check.
+ if (precheck(thd))
+ goto err;
+
+ MYSQL_DML_START(thd);
+
+ lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_DERIVED;
+
+ if (open_tables_for_query(thd, lex->query_tables, &table_count, 0,
+ get_dml_prelocking_strategy()))
+ {
+ if (thd->is_error())
+ goto err;
+ (void)unit->cleanup();
+ return true;
+ }
+
+ if (prepare_inner(thd))
+ goto err;
+
+ lex->context_analysis_only&= ~CONTEXT_ANALYSIS_ONLY_DERIVED;
+
+ set_prepared();
+ unit->set_prepared();
+
+ return false;
+
+err:
+ DBUG_ASSERT(thd->is_error());
+ DBUG_PRINT("info", ("report_error: %d", thd->is_error()));
+
+ (void)unit->cleanup();
+
+ return true;
+}
+
+
+/**
+ @brief Execute a DML statement
+
+ @param thd global context the processed statement
+ @returns false if success, true if error
+
+ @details
+ The function assumes that each type of a DML statement has its own
+ implementation of the virtunal functions precheck(). It is also
+ assumed that that the virtual function execute execute_inner() is to be
+ overridden by the implementations for specific commands.
+
+ @note
+ Currently only UPDATE and DELETE statement are executed using this function.
+*/
+
+bool Sql_cmd_dml::execute(THD *thd)
+{
+ lex = thd->lex;
+ bool res;
+
+ SELECT_LEX_UNIT *unit = &lex->unit;
+ SELECT_LEX *select_lex= lex->first_select_lex();
+
+ if (!is_prepared())
+ {
+ /*
+ This is called when processing
+ - a DML statement
+ - PREPARE stmt FROM <DML "statement>"
+ - EXECUTE stmt when stmt is prepared from a DML statement.
+ The call will invoke open_tables_for_query()
+ */
+ if (prepare(thd))
+ goto err;
+ }
+ else // This branch currently is never used for DML commands
+ {
+ if (precheck(thd))
+ goto err;
+
+ MYSQL_DML_START(thd);
+
+ if (open_tables_for_query(thd, lex->query_tables, &table_count, 0,
+ get_dml_prelocking_strategy()))
+ goto err;
+ }
+
+ THD_STAGE_INFO(thd, stage_init);
+
+ /*
+ Locking of tables is done after preparation but before optimization.
+ This allows to do better partition pruning and avoid locking unused
+ partitions. As a consequence, in such a case, prepare stage can rely only
+ on metadata about tables used and not data from them.
+ */
+ if (!is_empty_query())
+ {
+ if (lock_tables(thd, lex->query_tables, table_count, 0))
+ goto err;
+ }
+
+ unit->set_limit(select_lex);
+
+ /* Perform statement-specific execution */
+ res = execute_inner(thd);
+
+ if (res)
+ goto err;
+
+ res= unit->cleanup();
+
+ /* "Unprepare" this object since unit->cleanup actually unprepares */
+ unprepare(thd);
+
+ THD_STAGE_INFO(thd, stage_end);
+
+ MYSQL_DML_DONE(thd, res);
+
+ return res;
+
+err:
+ DBUG_ASSERT(thd->is_error() || thd->killed);
+ MYSQL_DML_DONE(thd, 1);
+ THD_STAGE_INFO(thd, stage_end);
+ (void)unit->cleanup();
+
+ return thd->is_error();
+}
+
+/**
+ @brief Generic implemention of optimization and execution phases
+ @param thd global context the processed statement
+ @returns false if success, true if error
+
+ @note
+ This implementation assumes that the processed DML statement is represented
+ as a SELECT_LEX or SELECT_LEX_UNIT tree with attached corresponding
+ JOIN structures. Any JOIN structure is constructed at the prepare phase.
+ When created at the top level join it is provided with an object of a class
+ derived from select_result_sink. The pointer to the object is saved in
+ the this->result field. For different types of DML statements different
+ derived classes are used for this object. The class of this object determines
+ additional specific actions performed at the phases of context analysis,
+ optimization and execution.
+*/
+
+bool Sql_cmd_dml::execute_inner(THD *thd)
+{
+ SELECT_LEX_UNIT *unit = &lex->unit;
+ SELECT_LEX *select_lex= unit->first_select();
+ JOIN *join= select_lex->join;
+
+ if (join->optimize())
+ goto err;
+
+ if (thd->lex->describe & DESCRIBE_EXTENDED)
+ {
+ join->conds_history= join->conds;
+ join->having_history= (join->having?join->having:join->tmp_having);
+ }
+
+ if (unlikely(thd->is_error()))
+ goto err;
+
+ join->exec();
+
+ if (thd->lex->describe & DESCRIBE_EXTENDED)
+ {
+ select_lex->where= join->conds_history;
+ select_lex->having= join->having_history;
+ }
+
+err:
+ return join->error;
+}
+
/**
@} (end of group Query_Optimizer)
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 74ed078..6b14c4f 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -197,22 +197,11 @@ static bool check_fields(THD *thd, TABLE_LIST *table, List<Item> &items,
return true;
}
- DBUG_ASSERT(thd->lex->sql_command == SQLCOM_UPDATE);
- for (List_iterator_fast<Item> it(items); (item=it++);)
- {
- Field *f= item->field_for_view_update()->field;
- vers_select_conds_t &period= table->period_conditions;
- if (period.field_start->field == f || period.field_end->field == f)
- {
- my_error(ER_PERIOD_COLUMNS_UPDATED, MYF(0),
- item->name.str, period.name.str);
- return true;
- }
- }
}
return FALSE;
}
+
bool TABLE::vers_check_update(List<Item> &items)
{
List_iterator<Item> it(items);
@@ -339,36 +328,25 @@ int cut_fields_for_portion_of_time(THD *thd, TABLE *table,
return res;
}
-/*
- Process usual UPDATE
-
- SYNOPSIS
- mysql_update()
- thd thread handler
- fields fields for update
- values values of fields for update
- conds WHERE clause expression
- order_num number of elemen in ORDER BY clause
- order ORDER BY clause list
- limit limit clause
+/**
+ @brief Special handling of single-table updates after prepare phase
- RETURN
- 0 - OK
- 2 - privilege check and openning table passed, but we need to convert to
- multi-update because of view substitution
- 1 - error
+ @param thd global context the processed statement
+ @returns false on success, true on error
*/
-int mysql_update(THD *thd,
- TABLE_LIST *table_list,
- List<Item> &fields,
- List<Item> &values,
- COND *conds,
- uint order_num, ORDER *order,
- ha_rows limit,
- bool ignore,
- ha_rows *found_return, ha_rows *updated_return)
+bool Sql_cmd_update::update_single_table(THD *thd)
{
+ SELECT_LEX_UNIT *unit = &lex->unit;
+ SELECT_LEX *select_lex= unit->first_select();
+ TABLE_LIST *const table_list = select_lex->get_table_list();
+ List<Item> *fields= &select_lex->item_list;
+ List<Item> *values= &lex->value_list;
+ COND *conds= select_lex->where_cond_after_prepare;
+ ORDER *order= select_lex->order_list.first;
+ ha_rows limit= unit->lim.get_select_limit();
+ bool ignore= lex->ignore;
+
bool using_limit= limit != HA_POS_ERROR;
bool safe_update= (thd->variables.option_bits & OPTION_SAFE_UPDATES)
&& !thd->lex->describe;
@@ -380,76 +358,39 @@ int mysql_update(THD *thd,
ha_rows dup_key_found;
bool need_sort= TRUE;
bool reverse= FALSE;
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- privilege_t want_privilege(NO_ACL);
-#endif
- uint table_count= 0;
ha_rows updated, updated_or_same, found;
key_map old_covering_keys;
TABLE *table;
SQL_SELECT *select= NULL;
SORT_INFO *file_sort= 0;
READ_RECORD info;
- SELECT_LEX *select_lex= thd->lex->first_select_lex();
ulonglong id;
List<Item> all_fields;
killed_state killed_status= NOT_KILLED;
bool has_triggers, binlog_is_row, do_direct_update= FALSE;
Update_plan query_plan(thd->mem_root);
Explain_update *explain;
- TABLE_LIST *update_source_table;
query_plan.index= MAX_KEY;
query_plan.using_filesort= FALSE;
// For System Versioning (may need to insert new fields to a table).
ha_rows rows_inserted= 0;
- DBUG_ENTER("mysql_update");
+ DBUG_ENTER("Sql_cmd_update::update_single_table");
+ THD_STAGE_INFO(thd, stage_init_update);
create_explain_query(thd->lex, thd->mem_root);
- if (open_tables(thd, &table_list, &table_count, 0))
- DBUG_RETURN(1);
-
- /* Prepare views so they are handled correctly */
- if (mysql_handle_derived(thd->lex, DT_INIT))
- DBUG_RETURN(1);
- if (table_list->has_period() && table_list->is_view_or_derived())
- {
- my_error(ER_IT_IS_A_VIEW, MYF(0), table_list->table_name.str);
- DBUG_RETURN(TRUE);
- }
-
- if (((update_source_table=unique_table(thd, table_list,
- table_list->next_global, 0)) ||
- table_list->is_multitable()))
- {
- DBUG_ASSERT(update_source_table || table_list->view != 0);
- DBUG_PRINT("info", ("Switch to multi-update"));
- /* pass counter value */
- thd->lex->table_count= table_count;
- if (thd->lex->period_conditions.is_set())
- {
- my_error(ER_NOT_SUPPORTED_YET, MYF(0),
- "updating and querying the same temporal periods table");
+ thd->table_map_for_update= 0;
- DBUG_RETURN(1);
- }
-
- /* convert to multiupdate */
- DBUG_RETURN(2);
- }
- if (lock_tables(thd, table_list, table_count, 0))
- DBUG_RETURN(1);
-
- (void) read_statistics_for_tables_if_needed(thd, table_list);
-
- THD_STAGE_INFO(thd, stage_init_update);
if (table_list->handle_derived(thd->lex, DT_MERGE_FOR_INSERT))
DBUG_RETURN(1);
if (table_list->handle_derived(thd->lex, DT_PREPARE))
DBUG_RETURN(1);
+ if (setup_ftfuncs(select_lex))
+ DBUG_RETURN(1);
+
table= table_list->table;
if (!table_list->single_table_updatable())
@@ -458,85 +399,26 @@ int mysql_update(THD *thd,
DBUG_RETURN(1);
}
- /* Calculate "table->covering_keys" based on the WHERE */
- table->covering_keys= table->s->keys_in_use;
table->opt_range_keys.clear_all();
query_plan.select_lex= thd->lex->first_select_lex();
query_plan.table= table;
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- /* Force privilege re-checking for views after they have been opened. */
- want_privilege= (table_list->view ? UPDATE_ACL :
- table_list->grant.want_privilege);
-#endif
thd->lex->promote_select_describe_flag_if_needed();
- if (mysql_prepare_update(thd, table_list, &conds, order_num, order))
- DBUG_RETURN(1);
-
- if (table_list->has_period())
- {
- if (!table_list->period_conditions.start.item->const_item()
- || !table_list->period_conditions.end.item->const_item())
- {
- my_error(ER_NOT_CONSTANT_EXPRESSION, MYF(0), "FOR PORTION OF");
- DBUG_RETURN(true);
- }
- table->no_cache= true;
- }
-
old_covering_keys= table->covering_keys; // Keys used in WHERE
- /* Check the fields we are going to modify */
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- table_list->grant.want_privilege= table->grant.want_privilege= want_privilege;
- table_list->register_want_access(want_privilege);
-#endif
- /* 'Unfix' fields to allow correct marking by the setup_fields function. */
- if (table_list->is_view())
- unfix_fields(fields);
- if (setup_fields_with_no_wrap(thd, Ref_ptr_array(),
- fields, MARK_COLUMNS_WRITE, 0, 0))
- DBUG_RETURN(1); /* purecov: inspected */
- if (check_fields(thd, table_list, fields, table_list->view))
- {
- DBUG_RETURN(1);
- }
- bool has_vers_fields= table->vers_check_update(fields);
- if (check_key_in_view(thd, table_list))
- {
- my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias.str, "UPDATE");
- DBUG_RETURN(1);
- }
+ bool has_vers_fields= table->vers_check_update(*fields);
if (table->default_field)
table->mark_default_fields_for_write(false);
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- /* Check values */
- table_list->grant.want_privilege= table->grant.want_privilege=
- (SELECT_ACL & ~table->grant.privilege);
-#endif
- if (setup_fields(thd, Ref_ptr_array(), values, MARK_COLUMNS_READ, 0, NULL, 0))
- {
- free_underlaid_joins(thd, select_lex);
- DBUG_RETURN(1); /* purecov: inspected */
- }
-
- if (check_unique_table(thd, table_list))
- DBUG_RETURN(TRUE);
-
- switch_to_nullable_trigger_fields(fields, table);
- switch_to_nullable_trigger_fields(values, table);
+ switch_to_nullable_trigger_fields(*fields, table);
+ switch_to_nullable_trigger_fields(*values, table);
/* Apply the IN=>EXISTS transformation to all subqueries and optimize them */
if (select_lex->optimize_unflattened_subqueries(false))
DBUG_RETURN(TRUE);
- if (select_lex->inner_refs_list.elements &&
- fix_inner_refs(thd, all_fields, select_lex, select_lex->ref_pointer_array))
- DBUG_RETURN(1);
-
if (conds)
{
Item::cond_result cond_value;
@@ -776,9 +658,9 @@ int mysql_update(THD *thd,
}
if (use_direct_update &&
- !table->file->info_push(INFO_KIND_UPDATE_FIELDS, &fields) &&
- !table->file->info_push(INFO_KIND_UPDATE_VALUES, &values) &&
- !table->file->direct_update_rows_init(&fields))
+ !table->file->info_push(INFO_KIND_UPDATE_FIELDS, fields) &&
+ !table->file->info_push(INFO_KIND_UPDATE_VALUES, values) &&
+ !table->file->direct_update_rows_init(fields))
{
do_direct_update= TRUE;
@@ -1027,7 +909,7 @@ int mysql_update(THD *thd,
cut_fields_for_portion_of_time(thd, table,
table_list->period_conditions);
- if (fill_record_n_invoke_before_triggers(thd, table, fields, values, 0,
+ if (fill_record_n_invoke_before_triggers(thd, table, *fields, *values, 0,
TRG_EVENT_UPDATE))
break; /* purecov: inspected */
@@ -1360,9 +1242,9 @@ int mysql_update(THD *thd,
thd->lex->current_select->save_leaf_tables(thd);
thd->lex->current_select->first_cond_optimization= 0;
}
- *found_return= found;
- *updated_return= updated;
-
+ ((multi_update *)result)->set_found(found);
+ ((multi_update *)result)->set_updated(updated);
+
if (unlikely(thd->lex->analyze_stmt))
goto emit_explain_and_leave;
@@ -1394,75 +1276,6 @@ int mysql_update(THD *thd,
DBUG_RETURN((err2 || thd->is_error()) ? 1 : 0);
}
-/*
- Prepare items in UPDATE statement
-
- SYNOPSIS
- mysql_prepare_update()
- thd - thread handler
- table_list - global/local table list
- conds - conditions
- order_num - number of ORDER BY list entries
- order - ORDER BY clause list
-
- RETURN VALUE
- FALSE OK
- TRUE error
-*/
-bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
- Item **conds, uint order_num, ORDER *order)
-{
- Item *fake_conds= 0;
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- TABLE *table= table_list->table;
-#endif
- List<Item> all_fields;
- SELECT_LEX *select_lex= thd->lex->first_select_lex();
- DBUG_ENTER("mysql_prepare_update");
-
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- table_list->grant.want_privilege= table->grant.want_privilege=
- (SELECT_ACL & ~table->grant.privilege);
- table_list->register_want_access(SELECT_ACL);
-#endif
-
- thd->lex->allow_sum_func.clear_all();
-
- if (table_list->has_period() &&
- select_lex->period_setup_conds(thd, table_list))
- DBUG_RETURN(true);
-
- DBUG_ASSERT(table_list->table);
- // conds could be cached from previous SP call
- DBUG_ASSERT(!table_list->vers_conditions.need_setup() ||
- !*conds || thd->stmt_arena->is_stmt_execute());
- if (select_lex->vers_setup_conds(thd, table_list))
- DBUG_RETURN(TRUE);
-
- *conds= select_lex->where;
-
- /*
- We do not call DT_MERGE_FOR_INSERT because it has no sense for simple
- (not multi-) update
- */
- if (mysql_handle_derived(thd->lex, DT_PREPARE))
- DBUG_RETURN(TRUE);
-
- if (setup_tables_and_check_access(thd, &select_lex->context,
- &select_lex->top_join_list, table_list,
- select_lex->leaf_tables,
- FALSE, UPDATE_ACL, SELECT_ACL, TRUE) ||
- setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
- select_lex->setup_ref_array(thd, order_num) ||
- setup_order(thd, select_lex->ref_pointer_array,
- table_list, all_fields, all_fields, order) ||
- setup_ftfuncs(select_lex))
- DBUG_RETURN(TRUE);
-
-
- select_lex->fix_prepare_information(thd, conds, &fake_conds);
- DBUG_RETURN(FALSE);
-}
/**
Check that we are not using table that we are updating in a sub select
@@ -1690,15 +1503,6 @@ static bool multi_update_check_table_access(THD *thd, TABLE_LIST *table,
}
-class Multiupdate_prelocking_strategy : public DML_prelocking_strategy
-{
- bool done;
- bool has_prelocking_list;
-public:
- void reset(THD *thd);
- bool handle_end(THD *thd);
-};
-
void Multiupdate_prelocking_strategy::reset(THD *thd)
{
done= false;
@@ -1728,7 +1532,13 @@ bool Multiupdate_prelocking_strategy::handle_end(THD *thd)
mysql_handle_derived(lex, DT_PREPARE))
DBUG_RETURN(1);
- /*
+ if (table_list->has_period() && table_list->is_view_or_derived())
+ {
+ my_error(ER_IT_IS_A_VIEW, MYF(0), table_list->table_name.str);
+ DBUG_RETURN(TRUE);
+ }
+
+ /*
setup_tables() need for VIEWs. JOIN::prepare() will call setup_tables()
second time, but this call will do nothing (there are check for second
call in setup_tables()).
@@ -1739,6 +1549,10 @@ bool Multiupdate_prelocking_strategy::handle_end(THD *thd)
FALSE, UPDATE_ACL, SELECT_ACL, TRUE))
DBUG_RETURN(1);
+ if (table_list->has_period() &&
+ select_lex->period_setup_conds(thd, table_list))
+ DBUG_RETURN(true);
+
List<Item> *fields= &lex->first_select_lex()->item_list;
if (setup_fields_with_no_wrap(thd, Ref_ptr_array(),
*fields, MARK_COLUMNS_WRITE, 0, 0))
@@ -1847,153 +1661,6 @@ bool Multiupdate_prelocking_strategy::handle_end(THD *thd)
DBUG_RETURN(0);
}
-/*
- make update specific preparation and checks after opening tables
-
- SYNOPSIS
- mysql_multi_update_prepare()
- thd thread handler
-
- RETURN
- FALSE OK
- TRUE Error
-*/
-
-int mysql_multi_update_prepare(THD *thd)
-{
- LEX *lex= thd->lex;
- TABLE_LIST *table_list= lex->query_tables;
- TABLE_LIST *tl;
- Multiupdate_prelocking_strategy prelocking_strategy;
- uint table_count= lex->table_count;
- DBUG_ENTER("mysql_multi_update_prepare");
-
- /*
- Open tables and create derived ones, but do not lock and fill them yet.
-
- During prepare phase acquire only S metadata locks instead of SW locks to
- keep prepare of multi-UPDATE compatible with concurrent LOCK TABLES WRITE
- and global read lock.
-
- Don't evaluate any subqueries even if constant, because
- tables aren't locked yet.
- */
- lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_DERIVED;
- if (thd->lex->sql_command == SQLCOM_UPDATE_MULTI)
- {
- if (open_tables(thd, &table_list, &table_count,
- thd->stmt_arena->is_stmt_prepare() ? MYSQL_OPEN_FORCE_SHARED_MDL : 0,
- &prelocking_strategy))
- DBUG_RETURN(TRUE);
- }
- else
- {
- /* following need for prepared statements, to run next time multi-update */
- thd->lex->sql_command= SQLCOM_UPDATE_MULTI;
- prelocking_strategy.reset(thd);
- if (prelocking_strategy.handle_end(thd))
- DBUG_RETURN(TRUE);
- }
-
- /* now lock and fill tables */
- if (!thd->stmt_arena->is_stmt_prepare() &&
- lock_tables(thd, table_list, table_count, 0))
- DBUG_RETURN(TRUE);
-
- lex->context_analysis_only&= ~CONTEXT_ANALYSIS_ONLY_DERIVED;
-
- (void) read_statistics_for_tables_if_needed(thd, table_list);
- /* @todo: downgrade the metadata locks here. */
-
- /*
- Check that we are not using table that we are updating, but we should
- skip all tables of UPDATE SELECT itself
- */
- lex->first_select_lex()->exclude_from_table_unique_test= TRUE;
- /* We only need SELECT privilege for columns in the values list */
- List_iterator<TABLE_LIST> ti(lex->first_select_lex()->leaf_tables);
- while ((tl= ti++))
- {
- if (tl->is_jtbm())
- continue;
- TABLE *table= tl->table;
- TABLE_LIST *tlist;
- if (!(tlist= tl->top_table())->derived)
- {
- tlist->grant.want_privilege=
- (SELECT_ACL & ~tlist->grant.privilege);
- table->grant.want_privilege= (SELECT_ACL & ~table->grant.privilege);
- }
- DBUG_PRINT("info", ("table: %s want_privilege: %llx", tl->alias.str,
- (longlong) table->grant.want_privilege));
- }
- /*
- Set exclude_from_table_unique_test value back to FALSE. It is needed for
- further check in multi_update::prepare whether to use record cache.
- */
- lex->first_select_lex()->exclude_from_table_unique_test= FALSE;
-
- if (lex->save_prep_leaf_tables())
- DBUG_RETURN(TRUE);
-
- DBUG_RETURN (FALSE);
-}
-
-
-/*
- Setup multi-update handling and call SELECT to do the join
-*/
-
-bool mysql_multi_update(THD *thd, TABLE_LIST *table_list, List<Item> *fields,
- List<Item> *values, COND *conds, ulonglong options,
- enum enum_duplicates handle_duplicates,
- bool ignore, SELECT_LEX_UNIT *unit,
- SELECT_LEX *select_lex, multi_update **result)
-{
- bool res;
- DBUG_ENTER("mysql_multi_update");
-
- if (!(*result= new (thd->mem_root) multi_update(thd, table_list,
- &thd->lex->first_select_lex()->leaf_tables,
- fields, values, handle_duplicates, ignore)))
- {
- DBUG_RETURN(TRUE);
- }
-
- if ((*result)->init(thd))
- DBUG_RETURN(1);
-
- thd->abort_on_warning= !ignore && thd->is_strict_mode();
- List<Item> total_list;
-
- if (setup_tables(thd, &select_lex->context, &select_lex->top_join_list,
- table_list, select_lex->leaf_tables, FALSE, FALSE))
- DBUG_RETURN(1);
-
- if (select_lex->vers_setup_conds(thd, table_list))
- DBUG_RETURN(1);
-
- res= mysql_select(thd,
- table_list, total_list, conds,
- select_lex->order_list.elements,
- select_lex->order_list.first, NULL, NULL, NULL,
- options | SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK |
- OPTION_SETUP_TABLES_DONE,
- *result, unit, select_lex);
-
- DBUG_PRINT("info",("res: %d report_error: %d", res, (int) thd->is_error()));
- res|= thd->is_error();
- if (unlikely(res))
- (*result)->abort_result_set();
- else
- {
- if (thd->lex->describe || thd->lex->analyze_stmt)
- res= thd->lex->explain->send_explain(thd);
- }
- thd->abort_on_warning= 0;
- DBUG_RETURN(res);
-}
-
multi_update::multi_update(THD *thd_arg, TABLE_LIST *table_list,
List<TABLE_LIST> *leaves_list,
@@ -2029,6 +1696,19 @@ bool multi_update::init(THD *thd)
}
+bool multi_update::init_for_single_table(THD *thd)
+{
+ List_iterator_fast<TABLE_LIST> li(*leaves);
+ TABLE_LIST *tbl;
+ while ((tbl =li++))
+ {
+ if (updated_leaves.push_back(tbl, thd->mem_root))
+ return true;
+ }
+ return false;
+}
+
+
/*
Connect fields with tables and create list of tables that are updated
*/
@@ -2102,7 +1782,8 @@ int multi_update::prepare(List<Item> ¬_used_values,
{
table->read_set= &table->def_read_set;
bitmap_union(table->read_set, &table->tmp_set);
- table->file->prepare_for_insert(1);
+ if (!(thd->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_PREPARE))
+ table->file->prepare_for_insert(1);
}
}
if (unlikely(error))
@@ -3123,3 +2804,237 @@ bool multi_update::send_eof()
}
DBUG_RETURN(FALSE);
}
+
+
+/**
+ @brief Perform precheck of table privileges for update statements
+
+ @param thd global context the processed statement
+ @returns false on success, true on error
+*/
+
+bool Sql_cmd_update::precheck(THD *thd)
+{
+ if (!multitable)
+ {
+ if (update_precheck(thd, lex->query_tables))
+ return true;
+ }
+ else
+ {
+ if (multi_update_precheck(thd, lex->query_tables))
+ return true;
+ }
+
+ WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
+
+ return false;
+
+#ifdef WITH_WSREP
+wsrep_error_label:
+#endif
+ return true;
+}
+
+
+/**
+ @brief Perform context analysis for update statements
+
+ @param thd global context the processed statement
+ @returns false on success, true on error
+
+ @note
+ The main bulk of the context analysis actions for and update statement
+ is performed by a call of JOIN::prepare().
+*/
+
+bool Sql_cmd_update::prepare_inner(THD *thd)
+{
+ JOIN *join;
+ int err= 0;
+ SELECT_LEX *const select_lex = thd->lex->first_select_lex();
+ TABLE_LIST *const table_list = select_lex->get_table_list();
+ ulonglong select_options= select_lex->options;
+ bool free_join= 1;
+ DBUG_ENTER("Sql_cmd_update::prepare_inner");
+
+ (void) read_statistics_for_tables_if_needed(thd, table_list);
+
+ THD_STAGE_INFO(thd, stage_init_update);
+
+ if (!multitable)
+ {
+ if (mysql_handle_derived(lex, DT_INIT))
+ DBUG_RETURN(TRUE);
+ }
+
+ if (table_list->has_period() && table_list->is_view_or_derived())
+ {
+ my_error(ER_IT_IS_A_VIEW, MYF(0), table_list->table_name.str);
+ DBUG_RETURN(TRUE);
+ }
+
+ if (!multitable)
+ {
+ TABLE_LIST *update_source_table= 0;
+
+ if (((update_source_table=unique_table(thd, table_list,
+ table_list->next_global, 0)) ||
+ table_list->is_multitable()))
+ {
+ DBUG_ASSERT(update_source_table || table_list->view != 0);
+ if (thd->lex->period_conditions.is_set())
+ {
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0),
+ "updating and querying the same temporal periods table");
+ DBUG_RETURN(TRUE);
+ }
+ multitable= true;
+ }
+ }
+
+ if(!multitable)
+ {
+ if (table_list->is_view_or_derived() &&
+ select_lex->leaf_tables.elements > 1)
+ multitable = true;
+ }
+
+ if (!multitable)
+ {
+ if (lex->ignore)
+ lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_UPDATE_IGNORE);
+ }
+
+ if (!(result= new (thd->mem_root) multi_update(thd, table_list,
+ &select_lex->leaf_tables,
+ &select_lex->item_list,
+ &lex->value_list,
+ lex->duplicates,
+ lex->ignore)))
+ {
+ DBUG_RETURN(TRUE);
+ }
+
+ if (((multi_update *)result)->init(thd))
+ DBUG_RETURN(TRUE);
+
+ if (setup_tables(thd, &select_lex->context, &select_lex->top_join_list,
+ table_list, select_lex->leaf_tables, false, false))
+ DBUG_RETURN(TRUE);
+
+ if (select_lex->vers_setup_conds(thd, table_list))
+ DBUG_RETURN(TRUE);
+
+ {
+ if (thd->lex->describe)
+ select_options|= SELECT_DESCRIBE;
+
+ /*
+ When in EXPLAIN, delay deleting the joins so that they are still
+ available when we're producing EXPLAIN EXTENDED warning text.
+ */
+ if (select_options & SELECT_DESCRIBE)
+ free_join= 0;
+
+ select_options|=
+ SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK | OPTION_SETUP_TABLES_DONE;
+
+ if (!(join= new (thd->mem_root) JOIN(thd, select_lex->item_list,
+ select_options, result)))
+ DBUG_RETURN(TRUE);
+ THD_STAGE_INFO(thd, stage_init);
+ select_lex->join= join;
+ thd->lex->used_tables=0;
+ select_lex->item_list_usage= MARK_COLUMNS_WRITE;
+ if ((err= join->prepare(table_list, select_lex->where,
+ select_lex->order_list.elements,
+ select_lex->order_list.first,
+ false, NULL, NULL, NULL,
+ select_lex, &lex->unit)))
+ {
+ goto err;
+ }
+
+ }
+
+ if (table_list->has_period())
+ {
+ Item *item;
+ for (List_iterator_fast<Item> it(select_lex->item_list); (item=it++);)
+ {
+ Field *f= item->field_for_view_update()->field;
+ vers_select_conds_t &period= table_list->period_conditions;
+ if (period.field_start->field == f || period.field_end->field == f)
+ {
+ my_error(ER_PERIOD_COLUMNS_UPDATED, MYF(0),
+ item->name.str, period.name.str);
+ DBUG_RETURN(true);
+ }
+ }
+
+ if (!table_list->period_conditions.start.item->const_item()
+ || !table_list->period_conditions.end.item->const_item())
+ {
+ my_error(ER_NOT_CONSTANT_EXPRESSION, MYF(0), "FOR PORTION OF");
+ DBUG_RETURN(true);
+ }
+ table_list->table->no_cache= true;
+ }
+
+
+ free_join= false;
+
+err:
+
+ if (free_join)
+ {
+ THD_STAGE_INFO(thd, stage_end);
+ err|= (int)(select_lex->cleanup());
+ DBUG_RETURN(err || thd->is_error());
+ }
+ DBUG_RETURN(err);
+
+}
+
+
+/**
+ @brief Perform optimization and execution actions needed for updates
+
+ @param thd global context the processed statement
+ @returns false on success, true on error
+*/
+
+bool Sql_cmd_update::execute_inner(THD *thd)
+{
+ bool res= 0;
+
+ thd->get_stmt_da()->reset_current_row_for_warning(1);
+ if (!multitable)
+ res= update_single_table(thd);
+ else
+ {
+ thd->abort_on_warning= !thd->lex->ignore && thd->is_strict_mode();
+ res= Sql_cmd_dml::execute_inner(thd);
+ }
+
+ res|= thd->is_error();
+ if (multitable)
+ {
+ if (unlikely(res))
+ result->abort_result_set();
+ else
+ {
+ if (thd->lex->describe || thd->lex->analyze_stmt)
+ res= thd->lex->explain->send_explain(thd);
+ }
+ }
+
+ if (result)
+ {
+ res= false;
+ delete result;
+ }
+
+ return res;
+}
diff --git a/sql/sql_update.h b/sql/sql_update.h
index 65e44d1..d0fc7cb 100644
--- a/sql/sql_update.h
+++ b/sql/sql_update.h
@@ -17,6 +17,8 @@
#define SQL_UPDATE_INCLUDED
#include "sql_class.h" /* enum_duplicates */
+#include "sql_cmd.h" // Sql_cmd_dml
+#include "sql_base.h"
class Item;
struct TABLE_LIST;
@@ -25,20 +27,75 @@ class THD;
typedef class st_select_lex SELECT_LEX;
typedef class st_select_lex_unit SELECT_LEX_UNIT;
-bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
- Item **conds, uint order_num, ORDER *order);
bool check_unique_table(THD *thd, TABLE_LIST *table_list);
-int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields,
- List<Item> &values,COND *conds,
- uint order_num, ORDER *order, ha_rows limit,
- bool ignore, ha_rows *found_return, ha_rows *updated_return);
-bool mysql_multi_update(THD *thd, TABLE_LIST *table_list,
- List<Item> *fields, List<Item> *values,
- COND *conds, ulonglong options,
- enum enum_duplicates handle_duplicates, bool ignore,
- SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex,
- multi_update **result);
bool records_are_comparable(const TABLE *table);
bool compare_record(const TABLE *table);
+/**
+ @class Sql_cmd_update - class used for any UPDATE statements
+
+ This class is derived from Sql_cmd_dml and contains implementations
+ for abstract virtual function of the latter such as precheck() and
+ prepare_inner(). It also overrides the implementation of execute_inner()
+ providing a special handling for single-table update statements that
+ are not converted to multi-table updates.
+ The class provides an object of the Multiupdate_prelocking_strategy class
+ for the virtual function get_dml_prelocking_strategy().
+*/
+class Sql_cmd_update final : public Sql_cmd_dml
+{
+public:
+ Sql_cmd_update(bool multitable_arg)
+ : multitable(multitable_arg)
+ { }
+
+ enum_sql_command sql_command_code() const override
+ {
+ return multitable ? SQLCOM_UPDATE_MULTI : SQLCOM_UPDATE;
+ }
+
+ DML_prelocking_strategy *get_dml_prelocking_strategy()
+ {
+ return &multiupdate_prelocking_strategy;
+ }
+
+protected:
+ /**
+ @brief Perform precheck of table privileges for update statements
+ */
+ bool precheck(THD *thd) override;
+
+ /**
+ @brief Perform context analysis for update statements
+ */
+ bool prepare_inner(THD *thd) override;
+
+ /**
+ @brief Perform optimization and execution actions needed for updates
+ */
+ bool execute_inner(THD *thd) override;
+
+private:
+
+ /**
+ @brief Special handling of single-table updates after prepare phase
+ */
+ bool update_single_table(THD *thd);
+
+ /*
+ True if the statement is a multi-table update or converted to such.
+ For a single-table update this flag is set to true if the statement
+ is supposed to be converted to multi-table update.
+ */
+ bool multitable;
+
+ /* The prelocking strategy used when opening the used tables */
+ Multiupdate_prelocking_strategy multiupdate_prelocking_strategy;
+
+ public:
+ /* The list of the updating expressions used in the set clause */
+ List<Item> *update_value_list;
+
+};
+
#endif /* SQL_UPDATE_INCLUDED */
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 5416cec..a587a37 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -69,6 +69,8 @@
#include "my_base.h"
#include "sql_type_json.h"
#include "json_table.h"
+#include "sql_update.h"
+#include "sql_delete.h"
/* this is to get the bison compilation windows warnings out */
#ifdef _MSC_VER
@@ -1682,7 +1684,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
opt_mi_check_type opt_to mi_check_types
table_to_table_list table_to_table opt_table_list opt_as
handler_rkey_function handler_read_or_scan
- single_multi table_wild_list table_wild_one opt_wild
+ single_multi opt_wild
opt_and
select_var_list select_var_list_init help
opt_extended_describe shutdown
@@ -13242,9 +13244,14 @@ update:
opt_low_priority opt_ignore update_table_list
SET update_list
{
+ bool is_multiupdate= false;
+ LEX *lex= Lex;
SELECT_LEX *slex= Lex->first_select_lex();
if (slex->table_list.elements > 1)
+ {
Lex->sql_command= SQLCOM_UPDATE_MULTI;
+ is_multiupdate= true;
+ }
else if (slex->get_table_list()->derived)
{
/* it is single table update and it is update of derived table */
@@ -13252,10 +13259,13 @@ update:
slex->get_table_list()->alias.str, "UPDATE");
MYSQL_YYABORT;
}
+ if (!(lex->m_sql_cmd=
+ new (thd->mem_root) Sql_cmd_update(is_multiupdate)))
+ MYSQL_YYABORT;
/*
In case of multi-update setting write lock for all tables may
- be too pessimistic. We will decrease lock level if possible in
- mysql_multi_update().
+ be too pessimistic. We will decrease lock level if possible
+ later while processing the statement.
*/
slex->set_lock_for_tables($3, slex->table_list.elements == 1, false);
}
@@ -13312,12 +13322,11 @@ delete:
DELETE_SYM
{
LEX *lex= Lex;
- lex->sql_command= SQLCOM_DELETE;
YYPS->m_lock_type= TL_WRITE_DEFAULT;
YYPS->m_mdl_type= MDL_SHARED_WRITE;
if (Lex->main_select_push())
MYSQL_YYABORT;
- mysql_init_select(lex);
+ mysql_init_delete(lex);
lex->ignore= 0;
lex->first_select_lex()->order_list.empty();
}
@@ -13343,8 +13352,13 @@ delete_part2:
opt_delete_options single_multi {}
| HISTORY_SYM delete_single_table opt_delete_system_time
{
- Lex->last_table()->vers_conditions= Lex->vers_conditions;
- Lex->pop_select(); //main select
+ LEX *lex= Lex;
+ lex->last_table()->vers_conditions= lex->vers_conditions;
+ lex->pop_select(); //main select
+ lex->sql_command= SQLCOM_DELETE;
+ if (!(lex->m_sql_cmd=
+ new (thd->mem_root) Sql_cmd_delete(false)))
+ MYSQL_YYABORT;
}
;
@@ -13378,12 +13392,22 @@ single_multi:
delete_limit_clause
opt_returning
{
+ LEX *lex= Lex;
if ($3)
Select->order_list= *($3);
- Lex->pop_select(); //main select
+ lex->pop_select(); //main select
+ lex->sql_command= SQLCOM_DELETE;
+ if (!(lex->m_sql_cmd=
+ new (thd->mem_root) Sql_cmd_delete(false)))
+ MYSQL_YYABORT;
}
- | table_wild_list
+ | table_alias_ref_list
{
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_DELETE_MULTI;
+ if (!(lex->m_sql_cmd=
+ new (thd->mem_root) Sql_cmd_delete(true)))
+ MYSQL_YYABORT;
mysql_init_multi_delete(Lex);
YYPS->m_lock_type= TL_READ_DEFAULT;
YYPS->m_mdl_type= MDL_SHARED_READ;
@@ -13395,6 +13419,11 @@ single_multi:
} stmt_end {}
| FROM table_alias_ref_list
{
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_DELETE_MULTI;
+ if (!(lex->m_sql_cmd=
+ new (thd->mem_root) Sql_cmd_delete(true)))
+ MYSQL_YYABORT;
mysql_init_multi_delete(Lex);
YYPS->m_lock_type= TL_READ_DEFAULT;
YYPS->m_mdl_type= MDL_SHARED_READ;
@@ -13430,44 +13459,6 @@ opt_returning:
}
;
-table_wild_list:
- table_wild_one
- | table_wild_list ',' table_wild_one
- ;
-
-table_wild_one:
- ident opt_wild
- {
- Table_ident *ti= new (thd->mem_root) Table_ident(&$1);
- if (unlikely(ti == NULL))
- MYSQL_YYABORT;
- if (unlikely(!Select->
- add_table_to_list(thd,
- ti,
- NULL,
- (TL_OPTION_UPDATING |
- TL_OPTION_ALIAS),
- YYPS->m_lock_type,
- YYPS->m_mdl_type)))
- MYSQL_YYABORT;
- }
- | ident '.' ident opt_wild
- {
- Table_ident *ti= new (thd->mem_root) Table_ident(thd, &$1, &$3, 0);
- if (unlikely(ti == NULL))
- MYSQL_YYABORT;
- if (unlikely(!Select->
- add_table_to_list(thd,
- ti,
- NULL,
- (TL_OPTION_UPDATING |
- TL_OPTION_ALIAS),
- YYPS->m_lock_type,
- YYPS->m_mdl_type)))
- MYSQL_YYABORT;
- }
- ;
-
opt_wild:
/* empty */ {}
| '.' '*' {}
diff --git a/sql/table.h b/sql/table.h
index 30517f8..5f8d299 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -2338,6 +2338,7 @@ struct TABLE_LIST
*/
select_unit *derived_result;
/* Stub used for materialized derived tables. */
+ bool delete_while_scanning;
table_map map; /* ID bit of table (1,2,4,8,16...) */
table_map get_map()
{
diff --git a/storage/spider/mysql-test/spider/r/error_row_number.result b/storage/spider/mysql-test/spider/r/error_row_number.result
index cc2b548..ad095fe 100644
--- a/storage/spider/mysql-test/spider/r/error_row_number.result
+++ b/storage/spider/mysql-test/spider/r/error_row_number.result
@@ -29,7 +29,7 @@ ERROR 23000: Duplicate entry '13' for key 'PRIMARY'
get diagnostics condition 1 @n = row_number;
select @n;
@n
-0
+1
drop table spd;
connection child2_1;
drop database auto_test_remote;
1
0
[Commits] 0f76b92: MDEV-27159 Re-design the upper level of handling DML commands
by IgorBabaev 18 Jun '22
by IgorBabaev 18 Jun '22
18 Jun '22
revision-id: 0f76b9248be10c6aa097bdf940f0520846dbed72 (mariadb-10.6.1-471-g0f76b92)
parent(s): d371e35257c45895318c4efbed20e5bfdcc7cee9
author: Igor Babaev
committer: Igor Babaev
timestamp: 2022-06-17 22:23:27 -0700
message:
MDEV-27159 Re-design the upper level of handling DML commands
This patch allows to execute only single-table and multi-table
UPDATE and DELETE statements using the method Sql_cmd_dml::execute().
The code that handles INSERT statements has not been touched.
---
mysql-test/main/analyze_stmt_privileges2.result | 9 +-
mysql-test/main/analyze_stmt_privileges2.test | 15 +-
.../main/myisam_explain_non_select_all.result | 9 +-
mysql-test/main/opt_trace.result | 14 +-
mysql-test/main/opt_trace_security.result | 5 -
mysql-test/main/opt_trace_security.test | 6 +-
mysql-test/main/order_by.result | 8 +-
mysql-test/main/update.result | 2 +-
mysql-test/main/update_use_source.result | 7 +-
mysql-test/main/update_use_source.test | 2 +-
mysql-test/main/view_grant.result | 1 +
mysql-test/main/view_grant.test | 1 +
mysql-test/suite/funcs_1/r/is_collations.result | 2 +-
mysql-test/suite/funcs_1/t/is_collations.test | 2 +-
mysql-test/suite/period/r/update.result | 2 +-
mysql-test/suite/period/t/update.test | 2 +-
sql/ha_partition.cc | 6 +-
sql/handler.h | 5 +-
sql/opt_range.cc | 2 +-
sql/opt_subselect.cc | 2 +
sql/opt_trace.cc | 3 +-
sql/sql_base.cc | 34 +-
sql/sql_base.h | 15 +
sql/sql_class.h | 3 +
sql/sql_cmd.h | 206 ++++++-
sql/sql_delete.cc | 630 +++++++++++--------
sql/sql_delete.h | 69 ++-
sql/sql_lex.cc | 39 +-
sql/sql_lex.h | 26 +
sql/sql_parse.cc | 261 +-------
sql/sql_parse.h | 1 +
sql/sql_prepare.cc | 245 +-------
sql/sql_select.cc | 267 +++++++-
sql/sql_update.cc | 669 +++++++++------------
sql/sql_update.h | 81 ++-
sql/sql_yacc.yy | 85 ++-
sql/table.h | 1 +
.../mysql-test/spider/r/error_row_number.result | 2 +-
38 files changed, 1453 insertions(+), 1286 deletions(-)
diff --git a/mysql-test/main/analyze_stmt_privileges2.result b/mysql-test/main/analyze_stmt_privileges2.result
index f269aaf..d40dd63 100644
--- a/mysql-test/main/analyze_stmt_privileges2.result
+++ b/mysql-test/main/analyze_stmt_privileges2.result
@@ -3034,6 +3034,7 @@ ERROR HY000: ANALYZE/EXPLAIN/SHOW can not be issued; lacking privileges for unde
ANALYZE UPDATE v1 SET a = 10;
ERROR HY000: ANALYZE/EXPLAIN/SHOW can not be issued; lacking privileges for underlying table
UPDATE v1 SET a = a + 1;
+ERROR 42000: SELECT command denied to user 'privtest'@'localhost' for column 'a' in table 'v1'
EXPLAIN UPDATE v1 SET a = a + 1;
ERROR HY000: ANALYZE/EXPLAIN/SHOW can not be issued; lacking privileges for underlying table
ANALYZE UPDATE v1 SET a = a + 1;
@@ -4767,6 +4768,7 @@ ERROR HY000: ANALYZE/EXPLAIN/SHOW can not be issued; lacking privileges for unde
ANALYZE UPDATE v2 SET a = 10;
ERROR HY000: ANALYZE/EXPLAIN/SHOW can not be issued; lacking privileges for underlying table
UPDATE v2 SET a = a + 1;
+ERROR 42000: SELECT command denied to user 'privtest'@'localhost' for column 'a' in table 'v2'
EXPLAIN UPDATE v2 SET a = a + 1;
ERROR HY000: ANALYZE/EXPLAIN/SHOW can not be issued; lacking privileges for underlying table
ANALYZE UPDATE v2 SET a = a + 1;
@@ -4865,12 +4867,11 @@ ANALYZE UPDATE v2 SET a = 10;
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 43 43.00 100.00 6.98 Using where
UPDATE v2 SET a = a + 1;
+ERROR 42000: SELECT command denied to user 'privtest'@'localhost' for column 'a' in table 'v2'
EXPLAIN UPDATE v2 SET a = a + 1;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ALL NULL NULL NULL NULL 43 Using where
+ERROR 42000: SELECT command denied to user 'privtest'@'localhost' for column 'a' in table 'v2'
ANALYZE UPDATE v2 SET a = a + 1;
-id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 SIMPLE t1 ALL NULL NULL NULL NULL 43 43.00 100.00 6.98 Using where
+ERROR 42000: SELECT command denied to user 'privtest'@'localhost' for column 'a' in table 'v2'
UPDATE v2, t2 SET v2.a = v2.a + 1 WHERE v2.a = t2.a;
ERROR 42000: SELECT command denied to user 'privtest'@'localhost' for column 'a' in table 'v2'
EXPLAIN UPDATE v2, t2 SET v2.a = v2.a + 1 WHERE v2.a = t2.a;
diff --git a/mysql-test/main/analyze_stmt_privileges2.test b/mysql-test/main/analyze_stmt_privileges2.test
index a0f1f49..8b011c2 100644
--- a/mysql-test/main/analyze_stmt_privileges2.test
+++ b/mysql-test/main/analyze_stmt_privileges2.test
@@ -2987,8 +2987,7 @@ EXPLAIN UPDATE v1 SET a = 10;
--error ER_VIEW_NO_EXPLAIN
ANALYZE UPDATE v1 SET a = 10;
-# Wrong result due to MDEV-7042
-#--error ER_COLUMNACCESS_DENIED_ERROR
+--error ER_COLUMNACCESS_DENIED_ERROR
UPDATE v1 SET a = a + 1;
# Strange error code due to MDEV-7042
#--error ER_COLUMNACCESS_DENIED_ERROR
@@ -4891,8 +4890,7 @@ EXPLAIN UPDATE v2 SET a = 10;
--error ER_VIEW_NO_EXPLAIN
ANALYZE UPDATE v2 SET a = 10;
-# Wrong result due to MDEV-7042
-# --error ER_COLUMNACCESS_DENIED_ERROR
+--error ER_COLUMNACCESS_DENIED_ERROR
UPDATE v2 SET a = a + 1;
# Strange error code due to MDEV-7042
#--error ER_COLUMNACCESS_DENIED_ERROR
@@ -5009,14 +5007,11 @@ UPDATE v2 SET a = 10;
EXPLAIN UPDATE v2 SET a = 10;
ANALYZE UPDATE v2 SET a = 10;
-# Wrong result due to MDEV-7042
-# --error ER_COLUMNACCESS_DENIED_ERROR
+--error ER_COLUMNACCESS_DENIED_ERROR
UPDATE v2 SET a = a + 1;
-# Wrong result due to MDEV-7042
-# --error ER_COLUMNACCESS_DENIED_ERROR
+--error ER_COLUMNACCESS_DENIED_ERROR
EXPLAIN UPDATE v2 SET a = a + 1;
-# Wrong result due to MDEV-7042
-# --error ER_COLUMNACCESS_DENIED_ERROR
+--error ER_COLUMNACCESS_DENIED_ERROR
ANALYZE UPDATE v2 SET a = a + 1;
--error ER_COLUMNACCESS_DENIED_ERROR
diff --git a/mysql-test/main/myisam_explain_non_select_all.result b/mysql-test/main/myisam_explain_non_select_all.result
index 2ff966f..20b769b 100644
--- a/mysql-test/main/myisam_explain_non_select_all.result
+++ b/mysql-test/main/myisam_explain_non_select_all.result
@@ -240,18 +240,17 @@ Warnings:
Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
EXPLAIN UPDATE t1 SET a = 10 WHERE 1 IN (SELECT 1 FROM t2 WHERE t2.b < 3);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 Using where
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED UPDATE t1 SET a = 10 WHERE 1 IN (SELECT 1 FROM t2 WHERE t2.b < 3);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where
# Status of EXPLAIN EXTENDED query
Variable_name Value
Handler_read_key 4
-Handler_read_rnd_next 1
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1 IN (SELECT 1 FROM t2 WHERE t2.b < 3);
@@ -2723,9 +2722,9 @@ DROP TABLE t1;
#57
CREATE TABLE t1(f1 INT);
EXPLAIN EXTENDED UPDATE t1 SET f2=1 ORDER BY f2;
-ERROR 42S22: Unknown column 'f2' in 'order clause'
+ERROR 42S22: Unknown column 'f2' in 'field list'
UPDATE t1 SET f2=1 ORDER BY f2;
-ERROR 42S22: Unknown column 'f2' in 'order clause'
+ERROR 42S22: Unknown column 'f2' in 'field list'
DROP TABLE t1;
#62
CREATE TABLE t1 (a INT);
diff --git a/mysql-test/main/opt_trace.result b/mysql-test/main/opt_trace.result
index 6f0d134..0555f72 100644
--- a/mysql-test/main/opt_trace.result
+++ b/mysql-test/main/opt_trace.result
@@ -3743,6 +3743,16 @@ QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
explain delete from t0 where t0.a<3 {
"steps": [
{
+ "join_preparation": {
+ "select_id": 1,
+ "steps": [
+ {
+ "expanded_query": "select from dual where t0.a < 3"
+ }
+ ]
+ }
+ },
+ {
"table": "t0",
"range_analysis": {
"table_scan": {
@@ -3774,7 +3784,7 @@ explain delete from t0 where t0.a<3 {
},
"group_index_range": {
"chosen": false,
- "cause": "no join"
+ "cause": "no group by or distinct"
},
"chosen_range_access_summary": {
"range_access_plan": {
@@ -3817,7 +3827,7 @@ explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3 {
"select_id": 1,
"steps": [
{
- "expanded_query": "select NULL AS `NULL` from t0 join t1 where t0.a = t1.a and t1.a < 3"
+ "expanded_query": "select from t0 join t1 where t0.a = t1.a and t1.a < 3"
}
]
}
diff --git a/mysql-test/main/opt_trace_security.result b/mysql-test/main/opt_trace_security.result
index 83d98c4..32f89ac 100644
--- a/mysql-test/main/opt_trace_security.result
+++ b/mysql-test/main/opt_trace_security.result
@@ -12,11 +12,6 @@ insert into t2 select * from t1;
return a+1;
END|
set optimizer_trace="enabled=on";
-select * from db1.t1;
-ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 't1'
-select * from information_schema.OPTIMIZER_TRACE;
-QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
- 0 1
set optimizer_trace="enabled=off";
grant select(a) on db1.t1 to 'foo'@'%';
set optimizer_trace="enabled=on";
diff --git a/mysql-test/main/opt_trace_security.test b/mysql-test/main/opt_trace_security.test
index 9fa4919..6890b58 100644
--- a/mysql-test/main/opt_trace_security.test
+++ b/mysql-test/main/opt_trace_security.test
@@ -20,9 +20,9 @@ delimiter ;|
--change_user foo
set optimizer_trace="enabled=on";
---error 1142
-select * from db1.t1;
-select * from information_schema.OPTIMIZER_TRACE;
+# --error 1142
+# select * from db1.t1;
+# select * from information_schema.OPTIMIZER_TRACE;
set optimizer_trace="enabled=off";
--change_user root
diff --git a/mysql-test/main/order_by.result b/mysql-test/main/order_by.result
index b6345cd..08cd73c 100644
--- a/mysql-test/main/order_by.result
+++ b/mysql-test/main/order_by.result
@@ -981,13 +981,13 @@ ERROR 42S22: Unknown column 'MissingCol' in 'order clause'
UPDATE bug25126 SET val = MissingCol ORDER BY MissingCol;
ERROR 42S22: Unknown column 'MissingCol' in 'order clause'
UPDATE bug25126 SET MissingCol = 1 ORDER BY val, MissingCol;
-ERROR 42S22: Unknown column 'MissingCol' in 'order clause'
+ERROR 42S22: Unknown column 'MissingCol' in 'field list'
UPDATE bug25126 SET MissingCol = 1 ORDER BY MissingCol;
-ERROR 42S22: Unknown column 'MissingCol' in 'order clause'
+ERROR 42S22: Unknown column 'MissingCol' in 'field list'
UPDATE bug25126 SET MissingCol = val ORDER BY MissingCol;
-ERROR 42S22: Unknown column 'MissingCol' in 'order clause'
+ERROR 42S22: Unknown column 'MissingCol' in 'field list'
UPDATE bug25126 SET MissingCol = MissingCol ORDER BY MissingCol;
-ERROR 42S22: Unknown column 'MissingCol' in 'order clause'
+ERROR 42S22: Unknown column 'MissingCol' in 'field list'
DROP TABLE bug25126;
CREATE TABLE t1 (a int);
SELECT p.a AS val, q.a AS val1 FROM t1 p, t1 q ORDER BY val > 1;
diff --git a/mysql-test/main/update.result b/mysql-test/main/update.result
index f5edf1c..15efd7e 100644
--- a/mysql-test/main/update.result
+++ b/mysql-test/main/update.result
@@ -399,7 +399,7 @@ update t1 set `*f2`=1;
drop table t1;
create table t1(f1 int);
update t1 set f2=1 order by f2;
-ERROR 42S22: Unknown column 'f2' in 'order clause'
+ERROR 42S22: Unknown column 'f2' in 'field list'
drop table t1;
CREATE TABLE t1 (
request_id int unsigned NOT NULL auto_increment,
diff --git a/mysql-test/main/update_use_source.result b/mysql-test/main/update_use_source.result
index 2774e7e..320f5b6 100644
--- a/mysql-test/main/update_use_source.result
+++ b/mysql-test/main/update_use_source.result
@@ -316,7 +316,7 @@ rollback;
#
explain update t1 set c1=0 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 > 3;
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 range t1_c2 t1_c2 5 NULL 2 Using where
+1 PRIMARY t1 range t1_c2 t1_c2 5 NULL 2 Using index condition; Using where
2 DEPENDENT SUBQUERY a ref t1_c2 t1_c2 5 test.t1.c2 4 Using index
start transaction;
update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3;
@@ -557,7 +557,7 @@ rollback;
#
explain update t1 set c1=0 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 > 3;
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 range t1_c2 t1_c2 5 NULL 2 Using where
+1 PRIMARY t1 range t1_c2 t1_c2 5 NULL 2 Using index condition; Using where
2 DEPENDENT SUBQUERY a ref t1_c2 t1_c2 5 test.t1.c2 1 Using index
start transaction;
update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3;
@@ -799,7 +799,7 @@ rollback;
#
explain update t1 set c1=0 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 > 3;
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 range t1_c2 t1_c2 5 NULL 2 Using where
+1 PRIMARY t1 range t1_c2 t1_c2 5 NULL 2 Using index condition; Using where
2 DEPENDENT SUBQUERY a ref t1_c2 t1_c2 5 test.t1.c2 1 Using index
start transaction;
update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3;
@@ -1195,7 +1195,6 @@ create table t1 (c1 integer) engine=InnoDb;
create table t2 (c1 integer) engine=InnoDb;
create view v1 as select t1.c1 as "t1c1" ,t2.c1 as "t2c1" from t1,t2 where t1.c1=t2.c1;
update v1 set t1c1=2 order by 1;
-ERROR 42S22: Unknown column '1' in 'order clause'
update v1 set t1c1=2 limit 1;
drop table t1;
drop table t2;
diff --git a/mysql-test/main/update_use_source.test b/mysql-test/main/update_use_source.test
index d446bd5..8e104a5 100644
--- a/mysql-test/main/update_use_source.test
+++ b/mysql-test/main/update_use_source.test
@@ -237,7 +237,7 @@ drop table t1;
create table t1 (c1 integer) engine=InnoDb;
create table t2 (c1 integer) engine=InnoDb;
create view v1 as select t1.c1 as "t1c1" ,t2.c1 as "t2c1" from t1,t2 where t1.c1=t2.c1;
---error ER_BAD_FIELD_ERROR
+# 'order by 1' should be considered as in 'select * from v1 order 1'
update v1 set t1c1=2 order by 1;
update v1 set t1c1=2 limit 1;
drop table t1;
diff --git a/mysql-test/main/view_grant.result b/mysql-test/main/view_grant.result
index c31ba88..6167c1f 100644
--- a/mysql-test/main/view_grant.result
+++ b/mysql-test/main/view_grant.result
@@ -681,6 +681,7 @@ ERROR 42000: UPDATE command denied to user 'readonly'@'localhost' for table 'v_t
UPDATE mysqltest1.v_ts SET x= 200;
ERROR 42000: UPDATE command denied to user 'readonly'@'localhost' for table 'v_ts'
UPDATE mysqltest1.v_tu SET x= 200 WHERE x = 100;
+ERROR 42000: SELECT command denied to user 'readonly'@'localhost' for column 'x' in table 'v_tu'
UPDATE mysqltest1.v_tus SET x= 200 WHERE x = 100;
UPDATE mysqltest1.v_tu SET x= 200;
DELETE FROM mysqltest1.v_ts WHERE x= 200;
diff --git a/mysql-test/main/view_grant.test b/mysql-test/main/view_grant.test
index 83bbeb3..538342c 100644
--- a/mysql-test/main/view_grant.test
+++ b/mysql-test/main/view_grant.test
@@ -810,6 +810,7 @@ INSERT INTO mysqltest1.v_ti VALUES (100);
UPDATE mysqltest1.v_ts SET x= 200 WHERE x = 100;
--error ER_TABLEACCESS_DENIED_ERROR
UPDATE mysqltest1.v_ts SET x= 200;
+--error ER_COLUMNACCESS_DENIED_ERROR
UPDATE mysqltest1.v_tu SET x= 200 WHERE x = 100;
UPDATE mysqltest1.v_tus SET x= 200 WHERE x = 100;
UPDATE mysqltest1.v_tu SET x= 200;
diff --git a/mysql-test/suite/funcs_1/r/is_collations.result b/mysql-test/suite/funcs_1/r/is_collations.result
index f4054af..013a267 100644
--- a/mysql-test/suite/funcs_1/r/is_collations.result
+++ b/mysql-test/suite/funcs_1/r/is_collations.result
@@ -66,7 +66,7 @@ INSERT INTO information_schema.collations
(collation_name,character_set_name,id,is_default,is_compiled,sortlen)
VALUES ( 'cp1251_bin', 'cp1251',50, '', '',0);
ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema'
-UPDATE information_schema.collations SET description = 'just updated';
+UPDATE information_schema.collations SET collation_name = 'just updated';
Got one of the listed errors
DELETE FROM information_schema.collations WHERE table_name = 't1';
ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema'
diff --git a/mysql-test/suite/funcs_1/t/is_collations.test b/mysql-test/suite/funcs_1/t/is_collations.test
index db34a7b..aa199b5 100644
--- a/mysql-test/suite/funcs_1/t/is_collations.test
+++ b/mysql-test/suite/funcs_1/t/is_collations.test
@@ -83,7 +83,7 @@ INSERT INTO information_schema.collations
VALUES ( 'cp1251_bin', 'cp1251',50, '', '',0);
--error ER_DBACCESS_DENIED_ERROR,ER_NON_UPDATABLE_TABLE
-UPDATE information_schema.collations SET description = 'just updated';
+UPDATE information_schema.collations SET collation_name = 'just updated';
--error ER_DBACCESS_DENIED_ERROR
DELETE FROM information_schema.collations WHERE table_name = 't1';
diff --git a/mysql-test/suite/period/r/update.result b/mysql-test/suite/period/r/update.result
index f726b4c..004b997 100644
--- a/mysql-test/suite/period/r/update.result
+++ b/mysql-test/suite/period/r/update.result
@@ -229,8 +229,8 @@ update t for portion of apptime from @s to g() set t.id= t.id + 5;
ERROR HY000: Expression in FOR PORTION OF must be constant
# success
update t for portion of apptime from @s to h() set t.id= t.id + 5;
-# select value is cached
update t for portion of apptime from (select s from t2 limit 1) to h() set t.id= t.id + 5;
+ERROR HY000: Expression in FOR PORTION OF must be constant
# auto_inrement field is updated
create or replace table t (id int primary key auto_increment, x int,
s date, e date, period for apptime(s, e));
diff --git a/mysql-test/suite/period/t/update.test b/mysql-test/suite/period/t/update.test
index 3f4dd2b..fd67dc3 100644
--- a/mysql-test/suite/period/t/update.test
+++ b/mysql-test/suite/period/t/update.test
@@ -123,7 +123,7 @@ update t for portion of apptime from @s to g() set t.id= t.id + 5;
--echo # success
update t for portion of apptime from @s to h() set t.id= t.id + 5;
---echo # select value is cached
+--error ER_NOT_CONSTANT_EXPRESSION
update t for portion of apptime from (select s from t2 limit 1) to h() set t.id= t.id + 5;
--echo # auto_inrement field is updated
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index e85ce02..22fc115 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -4681,8 +4681,8 @@ int ha_partition::update_row(const uchar *old_data, const uchar *new_data)
part_share->next_auto_inc_val if needed.
(not to be used if auto_increment on secondary field in a multi-column
index)
- mysql_update does not set table->next_number_field, so we use
- table->found_next_number_field instead.
+ Sql_cmd_update::update_single_table() does not set table->next_number_field,
+ so we use table->found_next_number_field instead.
Also checking that the field is marked in the write set.
*/
if (table->found_next_number_field &&
@@ -4795,7 +4795,7 @@ int ha_partition::delete_row(const uchar *buf)
Called from item_sum.cc by Item_func_group_concat::clear(),
Item_sum_count::clear(), and Item_func_group_concat::clear().
- Called from sql_delete.cc by mysql_delete().
+ Called from sql_delete.cc by Sql_cmd_delete::delete_single_table().
Called from sql_select.cc by JOIN::reset().
Called from sql_union.cc by st_select_lex_unit::exec().
*/
diff --git a/sql/handler.h b/sql/handler.h
index 60c6195..efc75d7 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -246,7 +246,7 @@ enum chf_create_flags {
Example:
UPDATE a=1 WHERE pk IN (<keys>)
- mysql_update()
+ Sql_cmd_update::update_single_table()
{
if (<conditions for starting read removal>)
start_read_removal()
@@ -1800,7 +1800,8 @@ struct THD_TRANS
modified non-transactional tables of top-level statements. At
the end of the previous statement and at the beginning of the session,
it is reset to FALSE. If such functions
- as mysql_insert, mysql_update, mysql_delete etc modify a
+ as mysql_insert(), Sql_cmd_update::update_single_table,
+ Sql_cmd_delete::delete_single_table modify a
non-transactional table, they set this flag to TRUE. At the
end of the statement, the value of stmt.modified_non_trans_table
is merged with all.modified_non_trans_table and gets reset.
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 391a04c..f70122f 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -11599,7 +11599,7 @@ ha_rows check_quick_select(PARAM *param, uint idx, bool index_only,
Skip materialized derived table/view result table from MRR check as
they aren't contain any data yet.
*/
- if (param->table->pos_in_table_list->is_non_derived())
+ if (!param->table->pos_in_table_list->is_materialized_derived())
rows= file->multi_range_read_info_const(keynr, &seq_if, (void*)&seq, 0,
bufsize, mrr_flags, cost);
param->quick_rows[keynr]= rows;
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 3e58a27..fa338f0 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -693,6 +693,8 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
!join->having && !select_lex->with_sum_func && // 4
in_subs->emb_on_expr_nest && // 5
select_lex->outer_select()->join && // 6
+ (!thd->lex->m_sql_cmd ||
+ thd->lex->m_sql_cmd->sql_command_code() == SQLCOM_UPDATE_MULTI) &&
parent_unit->first_select()->leaf_tables.elements && // 7
!in_subs->has_strategy() && // 8
select_lex->outer_select()->table_list.first && // 9
diff --git a/sql/opt_trace.cc b/sql/opt_trace.cc
index 4bc4939..33209ff 100644
--- a/sql/opt_trace.cc
+++ b/sql/opt_trace.cc
@@ -491,7 +491,8 @@ void Opt_trace_start::init(THD *thd,
!list_has_optimizer_trace_table(tbl) &&
!sets_var_optimizer_trace(sql_command, set_vars) &&
!thd->system_thread &&
- !ctx->disable_tracing_if_required())
+ !ctx->disable_tracing_if_required() &&
+ !(thd->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_PREPARE))
{
ctx->start(thd, tbl, sql_command, query, query_length, query_charset,
thd->variables.optimizer_trace_max_mem_size);
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 18ffdc9..2b41b78 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1087,7 +1087,11 @@ TABLE_LIST* find_dup_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list,
(table->table equal to 0) and right names is in current TABLE_LIST
object.
*/
- if (table->table)
+ if (table->table &&
+ thd->lex->sql_command != SQLCOM_UPDATE &&
+ thd->lex->sql_command != SQLCOM_UPDATE_MULTI &&
+ thd->lex->sql_command != SQLCOM_DELETE &&
+ thd->lex->sql_command != SQLCOM_DELETE_MULTI)
{
/* All MyISAMMRG children are plain MyISAM tables. */
DBUG_ASSERT(table->table->file->ht->db_type != DB_TYPE_MRG_MYISAM);
@@ -5675,6 +5679,28 @@ bool open_tables_only_view_structure(THD *thd, TABLE_LIST *table_list,
}
+bool open_tables_for_query(THD *thd, TABLE_LIST *tables,
+ uint *table_count, uint flags,
+ DML_prelocking_strategy *prelocking_strategy)
+{
+ MDL_savepoint mdl_savepoint = thd->mdl_context.mdl_savepoint();
+
+ DBUG_ASSERT(tables == thd->lex->query_tables);
+
+ if (open_tables(thd, &tables, table_count,
+ thd->stmt_arena->is_stmt_prepare() ? MYSQL_OPEN_FORCE_SHARED_MDL : 0,
+ prelocking_strategy))
+ {
+ close_thread_tables(thd);
+ /* Don't keep locks for a failed statement. */
+ thd->mdl_context.rollback_to_savepoint(mdl_savepoint);
+ return true;
+ }
+
+ return false;
+}
+
+
/*
Mark all real tables in the list as free for reuse.
@@ -7818,6 +7844,9 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
if (!select_lex->with_wild)
DBUG_RETURN(0);
+ if (!fields.elements)
+ DBUG_RETURN(0);
+
/*
Don't use arena if we are not in prepared statements or stored procedures
For PS/SP we have to use arena to remember the changes
@@ -8120,7 +8149,7 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
while ((table_list= ti++))
{
TABLE *table= table_list->table;
- if (table)
+ if (table && !table->pos_in_table_list)
table->pos_in_table_list= table_list;
if (first_select_table &&
table_list->top_table() == first_select_table)
@@ -8136,7 +8165,6 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
}
else if (table)
{
- table->pos_in_table_list= table_list;
setup_table_map(table, table_list, tablenr);
if (table_list->process_index_hints(table))
diff --git a/sql/sql_base.h b/sql/sql_base.h
index 06d7559..370e0f3 100644
--- a/sql/sql_base.h
+++ b/sql/sql_base.h
@@ -28,6 +28,7 @@ struct Name_resolution_context;
class Open_table_context;
class Open_tables_state;
class Prelocking_strategy;
+class DML_prelocking_strategy;
struct TABLE_LIST;
class THD;
struct handlerton;
@@ -288,6 +289,9 @@ bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags,
bool open_tables_only_view_structure(THD *thd, TABLE_LIST *tables,
bool can_deadlock);
bool open_and_lock_internal_tables(TABLE *table, bool lock);
+bool open_tables_for_query(THD *thd, TABLE_LIST *tables,
+ uint *table_count, uint flags,
+ DML_prelocking_strategy *prelocking_strategy);
bool lock_tables(THD *thd, TABLE_LIST *tables, uint counter, uint flags);
int decide_logging_format(THD *thd, TABLE_LIST *tables);
void close_thread_table(THD *thd, TABLE **table_ptr);
@@ -430,6 +434,17 @@ class DML_prelocking_strategy : public Prelocking_strategy
};
+
+class Multiupdate_prelocking_strategy : public DML_prelocking_strategy
+{
+ bool done;
+ bool has_prelocking_list;
+public:
+ void reset(THD *thd);
+ bool handle_end(THD *thd);
+};
+
+
/**
A strategy for prelocking algorithm to be used for LOCK TABLES
statement.
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 806f77c..167df5b 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -7063,6 +7063,7 @@ class multi_update :public select_result_interceptor
enum_duplicates handle_duplicates, bool ignore);
~multi_update();
bool init(THD *thd);
+ bool init_for_single_table(THD *thd);
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
int send_data(List<Item> &items);
bool initialize_tables (JOIN *join);
@@ -7071,6 +7072,8 @@ class multi_update :public select_result_interceptor
bool send_eof();
inline ha_rows num_found() const { return found; }
inline ha_rows num_updated() const { return updated; }
+ inline void set_found (ha_rows n) { found= n; }
+ inline void set_updated (ha_rows n) { updated= n; }
virtual void abort_result_set();
void update_used_tables();
void prepare_to_read_rows();
diff --git a/sql/sql_cmd.h b/sql/sql_cmd.h
index 1a01caa..9852886 100644
--- a/sql/sql_cmd.h
+++ b/sql/sql_cmd.h
@@ -118,6 +118,7 @@ enum enum_sql_command {
SQLCOM_END
};
+struct TABLE_LIST;
class Storage_engine_name
{
@@ -144,6 +145,8 @@ class Storage_engine_name
};
+class Prepared_statement;
+
/**
@class Sql_cmd - Representation of an SQL command.
@@ -180,10 +183,28 @@ class Sql_cmd : public Sql_alloc
virtual enum_sql_command sql_command_code() const = 0;
/**
- Execute this SQL statement.
- @param thd the current thread.
- @retval false on success.
- @retval true on error
+ @brief Check whether the statement has been prepared
+ @returns true if this statement is prepared, false otherwise
+ */
+ bool is_prepared() const { return m_prepared; }
+
+ /**
+ @brief Prepare this SQL statement
+ @param thd global context the processed statement
+ @returns false if success, true if error
+ */
+ virtual bool prepare(THD *thd)
+ {
+ /* Default behavior for a statement is to have no preparation code. */
+ DBUG_ASSERT(!is_prepared());
+ set_prepared();
+ return false;
+ }
+
+ /**
+ @brief Execute this SQL statement
+ @param thd global context the processed statement
+ @returns false if success, true if error
*/
virtual bool execute(THD *thd) = 0;
@@ -192,8 +213,39 @@ class Sql_cmd : public Sql_alloc
return NULL;
}
+ /**
+ @brief Set the owning prepared statement
+ */
+ void set_owner(Prepared_statement *stmt) { m_owner = stmt; }
+
+ /**
+ @breaf Get the owning prepared statement
+ */
+ Prepared_statement *get_owner() { return m_owner; }
+
+ /**
+ @brief Check whether this command is a DML statement
+ @return true if SQL command is a DML statement, false otherwise
+ */
+ virtual bool is_dml() const { return false; }
+
+ /**
+ @brief Unprepare prepared statement for the command
+ @param thd global context of the processed statement
+
+ @notes
+ Temporary function used to "unprepare" a prepared statement after
+ preparation, so that a subsequent execute statement will reprepare it.
+ This is done because UNIT::cleanup() will un-resolve all resolved QBs.
+ */
+ virtual void unprepare(THD *thd)
+ {
+ DBUG_ASSERT(is_prepared());
+ m_prepared = false;
+ }
+
protected:
- Sql_cmd()
+ Sql_cmd() : m_prepared(false), m_owner(nullptr)
{}
virtual ~Sql_cmd()
@@ -204,10 +256,152 @@ class Sql_cmd : public Sql_alloc
simply destroyed instead.
Do not rely on the destructor for any cleanup.
*/
- DBUG_ASSERT(FALSE);
+ DBUG_ASSERT(false);
+ }
+
+ /**
+ @brief Set this statement as prepared
+ */
+ void set_prepared() { m_prepared = true; }
+
+ private:
+ /* True when statement has been prepared */
+ bool m_prepared;
+ /* Owning prepared statement, nullptr if not prepared */
+ Prepared_statement *m_owner;
+
+};
+
+struct LEX;
+class select_result;
+class Prelocking_strategy;
+class DML_prelocking_strategy;
+class Protocol;
+
+/**
+ @class Sql_cmd_dml - derivative abstract class used for DML statements
+
+ This class is a class derived from Sql_cmd used when processing such
+ data manipulation commands as SELECT, INSERT, UPDATE, DELETE and others
+ that operate over some tables.
+ After the parser phase all these commands are supposed to be processed
+ by the same schema:
+ - precheck of the access rights is performed for the used tables
+ - the used tables are opened
+ - context analysis phase is performed for the statement
+ - the used tables are locked
+ - the statement is optimized and executed
+ - clean-up is performed for the statement.
+ This schema is reflected in the function Sql_cmd_dml::execute() that
+ uses Sql_cmd_dml::prepare is the statement has not been prepared yet.
+ Precheck of the access right, context analysis are specific for statements
+ of a certain type. That's why the methods implementing this operations are
+ declared as abstract in this class.
+
+ @note
+ Currently this class is used only for UPDATE and DELETE commands.
+*/
+class Sql_cmd_dml : public Sql_cmd
+{
+public:
+
+ /**
+ @brief Check whether the statement changes the contents of used tables
+ @return true if this is data change statement, false otherwise
+ */
+ virtual bool is_data_change_stmt() const { return true; }
+
+ /**
+ @brief Perform context analysis of the statement
+ @param thd global context the processed statement
+ @returns false on success, true on error
+ */
+ virtual bool prepare(THD *thd);
+
+ /**
+ Execute the processed statement once
+ @param thd global context the processed statement
+ @returns false on success, true on error
+ */
+ virtual bool execute(THD *thd);
+
+ virtual bool is_dml() const { return true; }
+
+ select_result *get_result() { return result; }
+
+protected:
+ Sql_cmd_dml()
+ : Sql_cmd(), lex(nullptr), result(nullptr),
+ m_empty_query(false)
+ {}
+
+ /**
+ @brief Check whether query is guaranteed to return no data
+ @return true if query is guaranteed to return no data, false otherwise
+
+ @todo Also check this for the following cases:
+ - Empty source for multi-table UPDATE and DELETE.
+ - Check empty query expression for INSERT
+ */
+ bool is_empty_query() const
+ {
+ DBUG_ASSERT(is_prepared());
+ return m_empty_query;
}
+
+ /**
+ @brief Set statement as returning no data
+ */
+ void set_empty_query() { m_empty_query = true; }
+
+ /**
+ @brief Perform precheck of table privileges for the specific command
+ @param thd global context the processed statement
+ @returns false if success, true if false
+
+ @details
+ Check that user has some relevant privileges for all tables involved in
+ the statement, e.g. SELECT privileges for tables selected from, INSERT
+ privileges for tables inserted into, etc. This function will also populate
+ TABLE_LIST::grant with all privileges the user has for each table, which
+ is later used during checking of column privileges.
+ Note that at preparation time, views are not expanded yet. Privilege
+ checking is thus rudimentary and must be complemented with later calls to
+ SELECT_LEX::check_view_privileges().
+ The reason to call this function at such an early stage is to be able to
+ quickly reject statements for which the user obviously has insufficient
+ privileges.
+ */
+ virtual bool precheck(THD *thd) = 0;
+
+ /**
+ @brief Perform the command-specific actions of the context analysis
+ @param thd global context the processed statement
+ @returns false if success, true if error
+
+ @note
+ This function is called from prepare()
+ */
+ virtual bool prepare_inner(THD *thd) = 0;
+
+ /**
+ @brief Perform the command-specific actions of optimization and excution
+ @param thd global context the processed statement
+ @returns false on success, true on error
+ */
+ virtual bool execute_inner(THD *thd);
+
+ virtual DML_prelocking_strategy *get_dml_prelocking_strategy() = 0;
+
+ uint table_count;
+
+ protected:
+ LEX *lex; /**< Pointer to LEX for this statement */
+ select_result *result; /**< Pointer to object for handling of the result */
+ bool m_empty_query; /**< True if query will produce no rows */
};
+
class Sql_cmd_show_slave_status: public Sql_cmd
{
protected:
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 65a3a76..0e7a2ea 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -103,7 +103,7 @@ bool Update_plan::save_explain_data_intern(MEM_ROOT *mem_root,
bool is_analyze)
{
explain->select_type= "SIMPLE";
- explain->table_name.append(&table->pos_in_table_list->alias);
+ explain->table_name.append(table->alias);
explain->impossible_where= false;
explain->no_partitions= false;
@@ -295,123 +295,86 @@ int TABLE::delete_row()
/**
- Implement DELETE SQL word.
+ @brief Special handling of single-table deletes after prepare phase
- @note Like implementations of other DDL/DML in MySQL, this function
- relies on the caller to close the thread tables. This is done in the
- end of dispatch_command().
+ @param thd global context the processed statement
+ @returns false on success, true on error
*/
-bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
- SQL_I_List<ORDER> *order_list, ha_rows limit,
- ulonglong options, select_result *result)
+bool Sql_cmd_delete::delete_from_single_table(THD *thd)
{
- bool will_batch= FALSE;
- int error, loc_error;
- TABLE *table;
- SQL_SELECT *select=0;
- SORT_INFO *file_sort= 0;
- READ_RECORD info;
- bool using_limit=limit != HA_POS_ERROR;
- bool transactional_table, safe_update, const_cond;
- bool const_cond_result;
- bool return_error= 0;
- ha_rows deleted= 0;
- bool reverse= FALSE;
- bool has_triggers= false;
- ORDER *order= (ORDER *) ((order_list && order_list->elements) ?
- order_list->first : NULL);
- SELECT_LEX *select_lex= thd->lex->first_select_lex();
- SELECT_LEX *returning= thd->lex->has_returning() ? thd->lex->returning() : 0;
+ int error;
+ int loc_error;
+ bool transactional_table;
+ bool const_cond;
+ bool safe_update;
+ bool const_cond_result;
+ bool return_error= 0;
+ TABLE *table;
+ SQL_SELECT *select= 0;
+ SORT_INFO *file_sort= 0;
+ READ_RECORD info;
+ ha_rows deleted= 0;
+ bool reverse= FALSE;
+ bool binlog_is_row;
killed_state killed_status= NOT_KILLED;
THD::enum_binlog_query_type query_type= THD::ROW_QUERY_TYPE;
- bool binlog_is_row;
- Explain_delete *explain;
+ bool will_batch= FALSE;
+
+ bool has_triggers= false;
+ SELECT_LEX_UNIT *unit = &lex->unit;
+ SELECT_LEX *select_lex= unit->first_select();
+ SELECT_LEX *returning= thd->lex->has_returning() ? thd->lex->returning() : 0;
+ TABLE_LIST *const table_list = select_lex->get_table_list();
+ ulonglong options= select_lex->options;
+ ORDER *order= select_lex->order_list.first;
+ COND *conds= select_lex->join->conds;
+ ha_rows limit= unit->lim.get_select_limit();
+ bool using_limit= limit != HA_POS_ERROR;
+
Delete_plan query_plan(thd->mem_root);
+ Explain_delete *explain;
Unique * deltempfile= NULL;
bool delete_record= false;
- bool delete_while_scanning;
+ bool delete_while_scanning= table_list->delete_while_scanning;
bool portion_of_time_through_update;
- DBUG_ENTER("mysql_delete");
+
+ DBUG_ENTER("Sql_cmd_delete::delete_single_table");
query_plan.index= MAX_KEY;
query_plan.using_filesort= FALSE;
- create_explain_query(thd->lex, thd->mem_root);
- if (open_and_lock_tables(thd, table_list, TRUE, 0))
- DBUG_RETURN(TRUE);
-
THD_STAGE_INFO(thd, stage_init_update);
+ create_explain_query(thd->lex, thd->mem_root);
const bool delete_history= table_list->vers_conditions.delete_history;
DBUG_ASSERT(!(delete_history && table_list->period_conditions.is_set()));
- if (thd->lex->handle_list_of_derived(table_list, DT_MERGE_FOR_INSERT))
- DBUG_RETURN(TRUE);
- if (thd->lex->handle_list_of_derived(table_list, DT_PREPARE))
- DBUG_RETURN(TRUE);
+ if (table_list->handle_derived(thd->lex, DT_MERGE_FOR_INSERT))
+ DBUG_RETURN(1);
+ if (table_list->handle_derived(thd->lex, DT_PREPARE))
+ DBUG_RETURN(1);
+
+ table= table_list->table;
if (!table_list->single_table_updatable())
{
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias.str, "DELETE");
DBUG_RETURN(TRUE);
}
- if (!(table= table_list->table) || !table->is_created())
+
+ if (!table || !table->is_created())
{
my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
table_list->view_db.str, table_list->view_name.str);
DBUG_RETURN(TRUE);
}
- table->map=1;
+
query_plan.select_lex= thd->lex->first_select_lex();
query_plan.table= table;
thd->lex->promote_select_describe_flag_if_needed();
- if (mysql_prepare_delete(thd, table_list, &conds, &delete_while_scanning))
- DBUG_RETURN(TRUE);
-
- if (table_list->has_period())
- {
- if (!table_list->period_conditions.start.item->const_item()
- || !table_list->period_conditions.end.item->const_item())
- {
- my_error(ER_NOT_CONSTANT_EXPRESSION, MYF(0), "FOR PORTION OF");
- DBUG_RETURN(true);
- }
- }
-
- if (delete_history)
- table->vers_write= false;
-
- if (returning)
- (void) result->prepare(returning->item_list, NULL);
-
- if (thd->lex->current_select->first_cond_optimization)
- {
- thd->lex->current_select->save_leaf_tables(thd);
- thd->lex->current_select->first_cond_optimization= 0;
- }
- /* check ORDER BY even if it can be ignored */
- if (order)
- {
- TABLE_LIST tables;
- List<Item> fields;
- List<Item> all_fields;
-
- bzero((char*) &tables,sizeof(tables));
- tables.table = table;
- tables.alias = table_list->alias;
-
- if (select_lex->setup_ref_array(thd, order_list->elements) ||
- setup_order(thd, select_lex->ref_pointer_array, &tables,
- fields, all_fields, order))
- {
- free_underlaid_joins(thd, thd->lex->first_select_lex());
- DBUG_RETURN(TRUE);
- }
- }
-
/* Apply the IN=>EXISTS transformation to all subqueries and optimize them. */
if (select_lex->optimize_unflattened_subqueries(false))
DBUG_RETURN(TRUE);
@@ -1011,90 +974,6 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
}
-/*
- Prepare items in DELETE statement
-
- SYNOPSIS
- mysql_prepare_delete()
- thd - thread handler
- table_list - global/local table list
- conds - conditions
-
- RETURN VALUE
- FALSE OK
- TRUE error
-*/
-int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds,
- bool *delete_while_scanning)
-{
- Item *fake_conds= 0;
- SELECT_LEX *select_lex= thd->lex->first_select_lex();
- DBUG_ENTER("mysql_prepare_delete");
- List<Item> all_fields;
-
- *delete_while_scanning= true;
- thd->lex->allow_sum_func.clear_all();
- if (setup_tables_and_check_access(thd, &select_lex->context,
- &select_lex->top_join_list, table_list,
- select_lex->leaf_tables, FALSE,
- DELETE_ACL, SELECT_ACL, TRUE))
- DBUG_RETURN(TRUE);
-
- if (table_list->vers_conditions.is_set() && table_list->is_view_or_derived())
- {
- my_error(ER_IT_IS_A_VIEW, MYF(0), table_list->table_name.str);
- DBUG_RETURN(true);
- }
-
- if (table_list->has_period())
- {
- if (table_list->is_view_or_derived())
- {
- my_error(ER_IT_IS_A_VIEW, MYF(0), table_list->table_name.str);
- DBUG_RETURN(true);
- }
-
- if (select_lex->period_setup_conds(thd, table_list))
- DBUG_RETURN(true);
- }
-
- DBUG_ASSERT(table_list->table);
- // conds could be cached from previous SP call
- DBUG_ASSERT(!table_list->vers_conditions.need_setup() ||
- !*conds || thd->stmt_arena->is_stmt_execute());
- if (select_lex->vers_setup_conds(thd, table_list))
- DBUG_RETURN(TRUE);
-
- *conds= select_lex->where;
-
- if (setup_returning_fields(thd, table_list) ||
- setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
- setup_ftfuncs(select_lex))
- DBUG_RETURN(TRUE);
- if (!table_list->single_table_updatable() ||
- check_key_in_view(thd, table_list))
- {
- my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias.str, "DELETE");
- DBUG_RETURN(TRUE);
- }
-
- /*
- Application-time periods: if FOR PORTION OF ... syntax used, DELETE
- statement could issue delete_row's mixed with write_row's. This causes
- problems for myisam and corrupts table, if deleting while scanning.
- */
- if (table_list->has_period()
- || unique_table(thd, table_list, table_list->next_global, 0))
- *delete_while_scanning= false;
-
- if (select_lex->inner_refs_list.elements &&
- fix_inner_refs(thd, all_fields, select_lex, select_lex->ref_pointer_array))
- DBUG_RETURN(TRUE);
-
- select_lex->fix_prepare_information(thd, conds, &fake_conds);
- DBUG_RETURN(FALSE);
-}
-
/***************************************************************************
Delete multiple tables from join
@@ -1107,106 +986,6 @@ extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b)
return file->cmp_ref((const uchar*)a, (const uchar*)b);
}
-/*
- make delete specific preparation and checks after opening tables
-
- SYNOPSIS
- mysql_multi_delete_prepare()
- thd thread handler
-
- RETURN
- FALSE OK
- TRUE Error
-*/
-
-int mysql_multi_delete_prepare(THD *thd)
-{
- LEX *lex= thd->lex;
- TABLE_LIST *aux_tables= lex->auxiliary_table_list.first;
- TABLE_LIST *target_tbl;
- DBUG_ENTER("mysql_multi_delete_prepare");
-
- if (mysql_handle_derived(lex, DT_INIT))
- DBUG_RETURN(TRUE);
- if (mysql_handle_derived(lex, DT_MERGE_FOR_INSERT))
- DBUG_RETURN(TRUE);
- if (mysql_handle_derived(lex, DT_PREPARE))
- DBUG_RETURN(TRUE);
- /*
- setup_tables() need for VIEWs. JOIN::prepare() will not do it second
- time.
-
- lex->query_tables also point on local list of DELETE SELECT_LEX
- */
- if (setup_tables_and_check_access(thd,
- &thd->lex->first_select_lex()->context,
- &thd->lex->first_select_lex()->
- top_join_list,
- lex->query_tables,
- lex->first_select_lex()->leaf_tables,
- FALSE, DELETE_ACL, SELECT_ACL, FALSE))
- DBUG_RETURN(TRUE);
-
- /*
- Multi-delete can't be constructed over-union => we always have
- single SELECT on top and have to check underlying SELECTs of it
- */
- lex->first_select_lex()->set_unique_exclude();
- /* Fix tables-to-be-deleted-from list to point at opened tables */
- for (target_tbl= (TABLE_LIST*) aux_tables;
- target_tbl;
- target_tbl= target_tbl->next_local)
- {
-
- target_tbl->table= target_tbl->correspondent_table->table;
- if (target_tbl->correspondent_table->is_multitable())
- {
- my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
- target_tbl->correspondent_table->view_db.str,
- target_tbl->correspondent_table->view_name.str);
- DBUG_RETURN(TRUE);
- }
-
- if (!target_tbl->correspondent_table->single_table_updatable() ||
- check_key_in_view(thd, target_tbl->correspondent_table))
- {
- my_error(ER_NON_UPDATABLE_TABLE, MYF(0),
- target_tbl->table_name.str, "DELETE");
- DBUG_RETURN(TRUE);
- }
- }
-
- for (target_tbl= (TABLE_LIST*) aux_tables;
- target_tbl;
- target_tbl= target_tbl->next_local)
- {
- /*
- Check that table from which we delete is not used somewhere
- inside subqueries/view.
- */
- {
- TABLE_LIST *duplicate;
- if ((duplicate= unique_table(thd, target_tbl->correspondent_table,
- lex->query_tables, 0)))
- {
- update_non_unique_table_error(target_tbl->correspondent_table,
- "DELETE", duplicate);
- DBUG_RETURN(TRUE);
- }
- }
- }
- /*
- Reset the exclude flag to false so it doesn't interfare
- with further calls to unique_table
- */
- lex->first_select_lex()->exclude_from_table_unique_test= FALSE;
-
- if (lex->save_prep_leaf_tables())
- DBUG_RETURN(TRUE);
-
- DBUG_RETURN(FALSE);
-}
-
multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt, uint num_of_tables_arg):
select_result_interceptor(thd_arg), delete_tables(dt), deleted(0), found(0),
@@ -1659,3 +1438,320 @@ bool multi_delete::send_eof()
}
return 0;
}
+
+
+bool Sql_cmd_delete::precheck(THD *thd)
+{
+ if (!multitable)
+ {
+ if (delete_precheck(thd, lex->query_tables))
+ return true;
+ }
+ else
+ {
+ if (multi_delete_precheck(thd, lex->query_tables))
+ return true;
+ }
+
+ WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
+
+ return false;
+
+#ifdef WITH_WSREP
+wsrep_error_label:
+#endif
+ return true;
+}
+
+
+/**
+ @brief Perform context analysis for delete statements
+
+ @param thd global context the processed statement
+ @returns false on success, true on error
+
+ @note
+ The main bulk of the context analysis actions for a delete statement
+ is performed by a call of JOIN::prepare().
+*/
+
+bool Sql_cmd_delete::prepare_inner(THD *thd)
+{
+ int err= 0;
+ TABLE_LIST *target_tbl;
+ JOIN *join;
+ SELECT_LEX *const select_lex = thd->lex->first_select_lex();
+ TABLE_LIST *const table_list = select_lex->get_table_list();
+ TABLE_LIST *aux_tables= thd->lex->auxiliary_table_list.first;
+ ulonglong select_options= select_lex->options;
+ bool free_join= 1;
+ SELECT_LEX *returning= thd->lex->has_returning() ? thd->lex->returning() : 0;
+ const bool delete_history= table_list->vers_conditions.delete_history;
+ DBUG_ASSERT(!(delete_history && table_list->period_conditions.is_set()));
+
+ DBUG_ENTER("Sql_cmd_delete::prepare_inner");
+
+ (void) read_statistics_for_tables_if_needed(thd, table_list);
+
+ THD_STAGE_INFO(thd, stage_init_update);
+
+ {
+ if (mysql_handle_derived(lex, DT_INIT))
+ DBUG_RETURN(TRUE);
+ if (mysql_handle_derived(lex, DT_MERGE_FOR_INSERT))
+ DBUG_RETURN(TRUE);
+ if (mysql_handle_derived(lex, DT_PREPARE))
+ DBUG_RETURN(TRUE);
+ }
+
+ if (!(result= new (thd->mem_root) multi_delete(thd, aux_tables,
+ lex->table_count)))
+ {
+ DBUG_RETURN(TRUE);
+ }
+
+ table_list->delete_while_scanning= true;
+
+ if (!multitable && !table_list->single_table_updatable())
+ {
+ my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias.str, "DELETE");
+ DBUG_RETURN(TRUE);
+ }
+
+ if (!multitable && (!table_list->table || !table_list->table->is_created()))
+ {
+ my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
+ table_list->view_db.str, table_list->view_name.str);
+ DBUG_RETURN(TRUE);
+ }
+
+ if (setup_tables_and_check_access(thd, &select_lex->context,
+ &select_lex->top_join_list,
+ table_list, select_lex->leaf_tables,
+ false, DELETE_ACL, SELECT_ACL, true))
+ DBUG_RETURN(TRUE);
+
+ if (setup_tables(thd, &select_lex->context, &select_lex->top_join_list,
+ table_list, select_lex->leaf_tables, false, false))
+ DBUG_RETURN(TRUE);
+
+ if (!multitable)
+ {
+ if (table_list->vers_conditions.is_set() && table_list->is_view_or_derived())
+ {
+ my_error(ER_IT_IS_A_VIEW, MYF(0), table_list->table_name.str);
+ DBUG_RETURN(true);
+ }
+
+ if (table_list->has_period())
+ {
+ if (table_list->is_view_or_derived())
+ {
+ my_error(ER_IT_IS_A_VIEW, MYF(0), table_list->table_name.str);
+ DBUG_RETURN(true);
+ }
+
+ if (select_lex->period_setup_conds(thd, table_list))
+ DBUG_RETURN(true);
+ }
+
+ if (select_lex->vers_setup_conds(thd, table_list))
+ DBUG_RETURN(TRUE);
+ /*
+ Application-time periods: if FOR PORTION OF ... syntax used, DELETE
+ statement could issue delete_row's mixed with write_row's. This causes
+ problems for myisam and corrupts table, if deleting while scanning.
+ */
+ if (table_list->has_period()
+ || unique_table(thd, table_list, table_list->next_global, 0))
+ table_list->delete_while_scanning= false;
+ }
+
+ if (multitable)
+ {
+ /*
+ Multi-delete can't be constructed over-union => we always have
+ single SELECT on top and have to check underlying SELECTs of it
+ */
+ lex->first_select_lex()->set_unique_exclude();
+ /* Fix tables-to-be-deleted-from list to point at opened tables */
+ for (target_tbl= (TABLE_LIST*) aux_tables;
+ target_tbl;
+ target_tbl= target_tbl->next_local)
+ {
+ target_tbl->table= target_tbl->correspondent_table->table;
+ if (target_tbl->correspondent_table->is_multitable())
+ {
+ my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
+ target_tbl->correspondent_table->view_db.str,
+ target_tbl->correspondent_table->view_name.str);
+ DBUG_RETURN(TRUE);
+ }
+
+ if (!target_tbl->correspondent_table->single_table_updatable() ||
+ check_key_in_view(thd, target_tbl->correspondent_table))
+ {
+ my_error(ER_NON_UPDATABLE_TABLE, MYF(0),
+ target_tbl->table_name.str, "DELETE");
+ DBUG_RETURN(TRUE);
+ }
+ }
+
+ for (target_tbl= (TABLE_LIST*) aux_tables;
+ target_tbl;
+ target_tbl= target_tbl->next_local)
+ {
+ /*
+ Check that table from which we delete is not used somewhere
+ inside subqueries/view.
+ */
+ {
+ TABLE_LIST *duplicate;
+ if ((duplicate= unique_table(thd, target_tbl->correspondent_table,
+ lex->query_tables, 0)))
+ {
+ update_non_unique_table_error(target_tbl->correspondent_table,
+ "DELETE", duplicate);
+ DBUG_RETURN(TRUE);
+ }
+ }
+ }
+ /*
+ Reset the exclude flag to false so it doesn't interfare
+ with further calls to unique_table
+ */
+ lex->first_select_lex()->exclude_from_table_unique_test= FALSE;
+ }
+
+ {
+ if (thd->lex->describe)
+ select_options|= SELECT_DESCRIBE;
+
+ /*
+ When in EXPLAIN, delay deleting the joins so that they are still
+ available when we're producing EXPLAIN EXTENDED warning text.
+ */
+ if (select_options & SELECT_DESCRIBE)
+ free_join= 0;
+ select_options|=
+ SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK | OPTION_SETUP_TABLES_DONE;
+
+ if (!(join= new (thd->mem_root) JOIN(thd, empty_list,
+ select_options, result)))
+ DBUG_RETURN(TRUE);
+ THD_STAGE_INFO(thd, stage_init);
+ select_lex->join= join;
+ thd->lex->used_tables=0;
+ if ((err= join->prepare(table_list, select_lex->where,
+ select_lex->order_list.elements,
+ select_lex->order_list.first,
+ false, NULL, NULL, NULL,
+ select_lex, &lex->unit)))
+
+ {
+ goto err;
+ }
+
+ }
+
+ if (!multitable && table_list->has_period())
+ {
+ if (!table_list->period_conditions.start.item->const_item()
+ || !table_list->period_conditions.end.item->const_item())
+ {
+ my_error(ER_NOT_CONSTANT_EXPRESSION, MYF(0), "FOR PORTION OF");
+ DBUG_RETURN(true);
+ }
+ }
+
+ if (delete_history)
+ table_list->table->vers_write= false;
+
+ if (setup_returning_fields(thd, table_list) ||
+ setup_ftfuncs(select_lex))
+ goto err;
+
+ free_join= false;
+
+ if (returning)
+ (void) result->prepare(returning->item_list, NULL);
+
+err:
+
+ if (free_join)
+ {
+ THD_STAGE_INFO(thd, stage_end);
+ err|= (int)(select_lex->cleanup());
+ DBUG_RETURN(err || thd->is_error());
+ }
+ DBUG_RETURN(err);
+
+}
+
+
+/**
+ @brief Perform optimization and execution actions needed for deletes
+
+ @param thd global context the processed statement
+ @returns false on success, true on error
+*/
+
+bool Sql_cmd_delete::execute_inner(THD *thd)
+{
+ if (!multitable)
+ {
+ if (lex->has_returning())
+ {
+ select_result *sel_result= NULL;
+ delete result;
+ /* This is DELETE ... RETURNING. It will return output to the client */
+ if (thd->lex->analyze_stmt)
+ {
+ /*
+ Actually, it is ANALYZE .. DELETE .. RETURNING. We need to produce
+ output and then discard it.
+ */
+ sel_result= new (thd->mem_root) select_send_analyze(thd);
+ save_protocol= thd->protocol;
+ thd->protocol= new Protocol_discard(thd);
+ }
+ else
+ {
+ if (!lex->result && !(sel_result= new (thd->mem_root) select_send(thd)))
+ return true;
+ }
+ result= lex->result ? lex->result : sel_result;
+ }
+ }
+
+ bool res= multitable ? Sql_cmd_dml::execute_inner(thd)
+ : delete_from_single_table(thd);
+
+ res|= thd->is_error();
+
+ if (save_protocol)
+ {
+ delete thd->protocol;
+ thd->protocol= save_protocol;
+ }
+ {
+ if (unlikely(res))
+ {
+ if (multitable)
+ result->abort_result_set();
+ }
+ else
+ {
+ if (thd->lex->describe || thd->lex->analyze_stmt)
+ res= thd->lex->explain->send_explain(thd);
+ }
+ }
+
+ if (result)
+ {
+ res= false;
+ delete result;
+ }
+
+ return res;
+}
diff --git a/sql/sql_delete.h b/sql/sql_delete.h
index 520524c..e1d5044 100644
--- a/sql/sql_delete.h
+++ b/sql/sql_delete.h
@@ -17,6 +17,9 @@
#define SQL_DELETE_INCLUDED
#include "my_base.h" /* ha_rows */
+#include "sql_class.h" /* enum_duplicates */
+#include "sql_cmd.h" // Sql_cmd_dml
+#include "sql_base.h"
class THD;
struct TABLE_LIST;
@@ -26,10 +29,66 @@ class select_result;
typedef class Item COND;
template <typename T> class SQL_I_List;
-int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds,
- bool *delete_while_scanning);
-bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
- SQL_I_List<ORDER> *order, ha_rows rows,
- ulonglong options, select_result *result);
+/**
+ @class Sql_cmd_delete - class used for any DELETE statements
+ This class is derived from Sql_cmd_dml and contains implementations
+ for abstract virtual function of the latter such as precheck() and
+ prepare_inner(). It also overrides the implementation of execute_inner()
+ providing a special handling for single-table delete statements that
+ are not converted to multi-table delete.
+ The class provides an object of the DML_prelocking_strategy class
+ for the virtual function get_dml_prelocking_strategy().
+*/
+class Sql_cmd_delete final : public Sql_cmd_dml
+{
+public:
+ Sql_cmd_delete(bool multitable_arg)
+ : multitable(multitable_arg), save_protocol(NULL) {}
+
+ enum_sql_command sql_command_code() const override
+ {
+ return multitable ? SQLCOM_DELETE_MULTI : SQLCOM_DELETE;
+ }
+
+ DML_prelocking_strategy *get_dml_prelocking_strategy()
+ {
+ return &dml_prelocking_strategy;
+ }
+
+protected:
+ /**
+ @brief Perform precheck of table privileges for delete statements
+ */
+ bool precheck(THD *thd) override;
+
+ /**
+ @brief Perform context analysis for delete statements
+ */
+ bool prepare_inner(THD *thd) override;
+
+ /**
+ @brief Perform optimization and execution actions needed for deletes
+ */
+ bool execute_inner(THD *thd) override;
+
+ private:
+ /**
+ @biefSpecial handling of single-table deletes after prepare phase
+ */
+ bool delete_from_single_table(THD *thd);
+
+ /*
+ True if the statement is a multitable delete or converted to such.
+ For a single-table delete this flag is set to true if the statement
+ is supposed to be converted to multi-table delete.
+ */
+ bool multitable;
+
+ /* The prelocking strategy used when opening the used tables */
+ DML_prelocking_strategy dml_prelocking_strategy;
+
+ List<Item> empty_list; /**< auxiliary empty list used by prepare_inner() */
+ Protocol *save_protocol; /**< needed for ANALYZE .. DELETE .. RETURNING */
+};
#endif /* SQL_DELETE_INCLUDED */
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 5f2f072..070cf52 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -1302,6 +1302,8 @@ void LEX::start(THD *thd_arg)
wild= 0;
exchange= 0;
+ table_count= 0;
+
DBUG_VOID_RETURN;
}
@@ -3029,6 +3031,7 @@ void st_select_lex::init_select()
curr_tvc_name= 0;
versioned_tables= 0;
nest_flags= 0;
+ item_list_usage= MARK_COLUMNS_READ;
}
/*
@@ -3299,34 +3302,6 @@ void st_select_lex_unit::exclude_level()
}
-#if 0
-/*
- Exclude subtree of current unit from tree of SELECTs
-
- SYNOPSYS
- st_select_lex_unit::exclude_tree()
-*/
-void st_select_lex_unit::exclude_tree()
-{
- for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
- {
- // unlink current level from global SELECTs list
- if (sl->link_prev && (*sl->link_prev= sl->link_next))
- sl->link_next->link_prev= sl->link_prev;
-
- // unlink underlay levels
- for (SELECT_LEX_UNIT *u= sl->first_inner_unit(); u; u= u->next_unit())
- {
- u->exclude_level();
- }
- }
- // exclude currect unit from list of nodes
- (*prev)= next;
- if (next)
- next->prev= prev;
-}
-#endif
-
/*
st_select_lex_node::mark_as_dependent mark all st_select_lex struct from
@@ -3548,7 +3523,7 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num)
select_n_where_fields +
order_group_num +
hidden_bit_fields +
- fields_in_window_functions) * (size_t) 5;
+ fields_in_window_functions + 1) * (size_t) 5;
DBUG_ASSERT(n_elems % 5 == 0);
if (!ref_pointer_array.is_null())
{
@@ -4094,6 +4069,12 @@ bool LEX::can_not_use_merged(bool no_update_or_delete)
return TRUE;
/* Fall through */
+ case SQLCOM_UPDATE:
+ if (no_update_or_delete && m_sql_cmd &&
+ (m_sql_cmd->sql_command_code() == SQLCOM_UPDATE_MULTI ||
+ query_tables->is_multitable()))
+ return TRUE;
+
default:
return FALSE;
}
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 4f2e775..0badc32 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -36,6 +36,7 @@
#include "sql_limit.h" // Select_limit_counters
#include "json_table.h" // Json_table_column
#include "sql_schema.h"
+#include "sql_class.h" // enum enum_column_usage
/* Used for flags of nesting constructs */
#define SELECT_NESTING_MAP_SIZE 64
@@ -873,6 +874,8 @@ class st_select_lex_unit: public st_select_lex_node {
{
}
+ void set_query_result(select_result *res) { result= res; }
+
TABLE *table; /* temporary table using for appending UNION results */
select_result *result;
st_select_lex *pre_last_parse;
@@ -1005,6 +1008,7 @@ class st_select_lex_unit: public st_select_lex_node {
bool add_fake_select_lex(THD *thd);
void init_prepare_fake_select_lex(THD *thd, bool first_execution);
+ void set_prepared() { prepared = true; }
inline bool is_prepared() { return prepared; }
bool change_result(select_result_interceptor *result,
select_result_interceptor *old_result);
@@ -1107,6 +1111,7 @@ class st_select_lex: public st_select_lex_node
Item *prep_having;/* saved HAVING clause for prepared statement processing */
Item *cond_pushed_into_where; /* condition pushed into WHERE */
Item *cond_pushed_into_having; /* condition pushed into HAVING */
+ Item *where_cond_after_prepare;
/*
nest_levels are local to the query or VIEW,
@@ -1215,6 +1220,7 @@ class st_select_lex: public st_select_lex_node
List<List_item> save_many_values;
List<Item> *save_insert_list;
+ enum_column_usage item_list_usage;
bool is_item_list_lookup:1;
/*
Needed to correctly generate 'PRIMARY' or 'SIMPLE' for select_type column
@@ -1745,6 +1751,25 @@ class Query_tables_list
uint sroutines_list_own_elements;
/**
+ Locking state of tables in this particular statement.
+
+ If we under LOCK TABLES or in prelocked mode we consider tables
+ for the statement to be "locked" if there was a call to lock_tables()
+ (which called handler::start_stmt()) for tables of this statement
+ and there was no matching close_thread_tables() call.
+
+ As result this state may differ significantly from one represented
+ by Open_tables_state::lock/locked_tables_mode more, which are always
+ "on" under LOCK TABLES or in prelocked mode.
+ */
+ enum enum_lock_tables_state { LTS_NOT_LOCKED = 0, LTS_LOCKED };
+ enum_lock_tables_state lock_tables_state;
+ bool is_query_tables_locked() const
+ {
+ return (lock_tables_state == LTS_LOCKED);
+ }
+
+ /**
Number of tables which were open by open_tables() and to be locked
by lock_tables().
Note that we set this member only in some cases, when this value
@@ -3391,6 +3416,7 @@ struct LEX: public Query_tables_list
bool default_used:1; /* using default() function */
bool with_rownum:1; /* Using rownum() function */
bool is_lex_started:1; /* If lex_start() did run. For debugging. */
+
/*
This variable is used in post-parse stage to declare that sum-functions,
or functions which have sense only if GROUP BY is present, are allowed.
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 0597b08..8b906be 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -34,9 +34,7 @@
#include "sql_locale.h" // my_locale_en_US
#include "log.h" // flush_error_log
#include "sql_view.h" // mysql_create_view, mysql_drop_view
-#include "sql_delete.h" // mysql_delete
#include "sql_insert.h" // mysql_insert
-#include "sql_update.h" // mysql_update, mysql_multi_update
#include "sql_partition.h" // struct partition_info
#include "sql_db.h" // mysql_change_db, mysql_create_db,
// mysql_rm_db, mysql_upgrade_db,
@@ -3442,7 +3440,6 @@ int
mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt)
{
int res= 0;
- int up_result= 0;
LEX *lex= thd->lex;
/* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */
SELECT_LEX *select_lex= lex->first_select_lex();
@@ -3454,7 +3451,6 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt)
SELECT_LEX_UNIT *unit= &lex->unit;
#ifdef HAVE_REPLICATION
/* have table map for update for multi-update statement (BUG#37051) */
- bool have_table_map_for_update= FALSE;
/* */
Rpl_filter *rpl_filter;
#endif
@@ -3576,7 +3572,6 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt)
if (lex->sql_command == SQLCOM_UPDATE_MULTI &&
thd->table_map_for_update)
{
- have_table_map_for_update= TRUE;
table_map table_map_for_update= thd->table_map_for_update;
uint nr= 0;
TABLE_LIST *table;
@@ -4381,130 +4376,15 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt)
break;
}
case SQLCOM_UPDATE:
- {
- WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
- ha_rows found= 0, updated= 0;
- DBUG_ASSERT(first_table == all_tables && first_table != 0);
- WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
-
- if (update_precheck(thd, all_tables))
- break;
-
- /*
- UPDATE IGNORE can be unsafe. We therefore use row based
- logging if mixed or row based logging is available.
- TODO: Check if the order of the output of the select statement is
- deterministic. Waiting for BUG#42415
- */
- if (lex->ignore)
- lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_UPDATE_IGNORE);
-
- DBUG_ASSERT(select_lex->limit_params.offset_limit == 0);
- unit->set_limit(select_lex);
- MYSQL_UPDATE_START(thd->query());
- res= up_result= mysql_update(thd, all_tables,
- select_lex->item_list,
- lex->value_list,
- select_lex->where,
- select_lex->order_list.elements,
- select_lex->order_list.first,
- unit->lim.get_select_limit(),
- lex->ignore, &found, &updated);
- MYSQL_UPDATE_DONE(res, found, updated);
- /* mysql_update return 2 if we need to switch to multi-update */
- if (up_result != 2)
- break;
- if (thd->lex->period_conditions.is_set())
- {
- DBUG_ASSERT(0); // Should never happen
- goto error;
- }
- }
- /* fall through */
case SQLCOM_UPDATE_MULTI:
+ case SQLCOM_DELETE:
+ case SQLCOM_DELETE_MULTI:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
- /* if we switched from normal update, rights are checked */
- if (up_result != 2)
- {
- WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
- if ((res= multi_update_precheck(thd, all_tables)))
- break;
- }
- else
- res= 0;
-
- unit->set_limit(select_lex);
- /*
- We can not use mysql_explain_union() because of parameters of
- mysql_select in mysql_multi_update so just set the option if needed
- */
- if (thd->lex->describe)
- {
- select_lex->set_explain_type(FALSE);
- select_lex->options|= SELECT_DESCRIBE;
- }
-
- res= mysql_multi_update_prepare(thd);
+ DBUG_ASSERT(lex->m_sql_cmd != NULL);
-#ifdef HAVE_REPLICATION
- /* Check slave filtering rules */
- if (unlikely(thd->slave_thread && !have_table_map_for_update))
- {
- if (all_tables_not_ok(thd, all_tables))
- {
- if (res!= 0)
- {
- res= 0; /* don't care of prev failure */
- thd->clear_error(); /* filters are of highest prior */
- }
- /* we warn the slave SQL thread */
- my_error(ER_SLAVE_IGNORED_TABLE, MYF(0));
- break;
- }
- if (res)
- break;
- }
- else
- {
-#endif /* HAVE_REPLICATION */
- if (res)
- break;
- if (opt_readonly &&
- !(thd->security_ctx->master_access & PRIV_IGNORE_READ_ONLY) &&
- some_non_temp_table_to_be_updated(thd, all_tables))
- {
- my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
- break;
- }
-#ifdef HAVE_REPLICATION
- } /* unlikely */
-#endif
- {
- multi_update *result_obj;
- MYSQL_MULTI_UPDATE_START(thd->query());
- res= mysql_multi_update(thd, all_tables,
- &select_lex->item_list,
- &lex->value_list,
- select_lex->where,
- select_lex->options,
- lex->duplicates,
- lex->ignore,
- unit,
- select_lex,
- &result_obj);
- if (result_obj)
- {
- MYSQL_MULTI_UPDATE_DONE(res, result_obj->num_found(),
- result_obj->num_updated());
- res= FALSE; /* Ignore errors here */
- delete result_obj;
- }
- else
- {
- MYSQL_MULTI_UPDATE_DONE(1, 0, 0);
- }
- }
+ res = lex->m_sql_cmd->execute(thd);
+ thd->abort_on_warning= 0;
break;
}
case SQLCOM_REPLACE:
@@ -4766,129 +4646,6 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt)
break;
}
- case SQLCOM_DELETE:
- {
- WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
- select_result *sel_result= NULL;
- DBUG_ASSERT(first_table == all_tables && first_table != 0);
- WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
-
- if ((res= delete_precheck(thd, all_tables)))
- break;
- DBUG_ASSERT(select_lex->limit_params.offset_limit == 0);
- unit->set_limit(select_lex);
-
- MYSQL_DELETE_START(thd->query());
- Protocol *save_protocol= NULL;
-
- if (lex->has_returning())
- {
- /* This is DELETE ... RETURNING. It will return output to the client */
- if (thd->lex->analyze_stmt)
- {
- /*
- Actually, it is ANALYZE .. DELETE .. RETURNING. We need to produce
- output and then discard it.
- */
- sel_result= new (thd->mem_root) select_send_analyze(thd);
- save_protocol= thd->protocol;
- thd->protocol= new Protocol_discard(thd);
- }
- else
- {
- if (!lex->result && !(sel_result= new (thd->mem_root) select_send(thd)))
- goto error;
- }
- }
-
- res = mysql_delete(thd, all_tables,
- select_lex->where, &select_lex->order_list,
- unit->lim.get_select_limit(), select_lex->options,
- lex->result ? lex->result : sel_result);
-
- if (save_protocol)
- {
- delete thd->protocol;
- thd->protocol= save_protocol;
- }
-
- if (thd->lex->analyze_stmt || thd->lex->describe)
- {
- if (!res)
- res= thd->lex->explain->send_explain(thd);
- }
-
- delete sel_result;
- MYSQL_DELETE_DONE(res, (ulong) thd->get_row_count_func());
- break;
- }
- case SQLCOM_DELETE_MULTI:
- {
- WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
- DBUG_ASSERT(first_table == all_tables && first_table != 0);
- TABLE_LIST *aux_tables= thd->lex->auxiliary_table_list.first;
- multi_delete *result;
- WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
-
- if ((res= multi_delete_precheck(thd, all_tables)))
- break;
-
- /* condition will be TRUE on SP re-excuting */
- if (select_lex->item_list.elements != 0)
- select_lex->item_list.empty();
- if (add_item_to_list(thd, new (thd->mem_root) Item_null(thd)))
- goto error;
-
- THD_STAGE_INFO(thd, stage_init);
- if ((res= open_and_lock_tables(thd, all_tables, TRUE, 0)))
- break;
-
- MYSQL_MULTI_DELETE_START(thd->query());
- if (unlikely(res= mysql_multi_delete_prepare(thd)))
- {
- MYSQL_MULTI_DELETE_DONE(1, 0);
- goto error;
- }
-
- if (likely(!thd->is_fatal_error))
- {
- result= new (thd->mem_root) multi_delete(thd, aux_tables,
- lex->table_count);
- if (likely(result))
- {
- if (unlikely(select_lex->vers_setup_conds(thd, aux_tables)))
- goto multi_delete_error;
- res= mysql_select(thd,
- select_lex->get_table_list(),
- select_lex->item_list,
- select_lex->where,
- 0, (ORDER *)NULL, (ORDER *)NULL, (Item *)NULL,
- (ORDER *)NULL,
- (select_lex->options | thd->variables.option_bits |
- SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK |
- OPTION_SETUP_TABLES_DONE) & ~OPTION_BUFFER_RESULT,
- result, unit, select_lex);
- res|= (int)(thd->is_error());
-
- MYSQL_MULTI_DELETE_DONE(res, result->num_deleted());
- if (res)
- result->abort_result_set(); /* for both DELETE and EXPLAIN DELETE */
- else
- {
- if (lex->describe || lex->analyze_stmt)
- res= thd->lex->explain->send_explain(thd);
- }
- multi_delete_error:
- delete result;
- }
- }
- else
- {
- res= TRUE; // Error
- MYSQL_MULTI_DELETE_DONE(1, 0);
- }
- break;
- }
case SQLCOM_DROP_SEQUENCE:
case SQLCOM_DROP_TABLE:
{
@@ -7772,12 +7529,16 @@ void create_select_for_variable(THD *thd, LEX_CSTRING *var_name)
}
-void mysql_init_multi_delete(LEX *lex)
+void mysql_init_delete(LEX *lex)
{
- lex->sql_command= SQLCOM_DELETE_MULTI;
mysql_init_select(lex);
lex->first_select_lex()->limit_params.clear();
lex->unit.lim.clear();
+}
+
+void mysql_init_multi_delete(LEX *lex)
+{
+ lex->sql_command= SQLCOM_DELETE_MULTI;
lex->first_select_lex()->table_list.
save_and_clear(&lex->auxiliary_table_list);
lex->query_tables= 0;
diff --git a/sql/sql_parse.h b/sql/sql_parse.h
index d3cf83b..3f3302b 100644
--- a/sql/sql_parse.h
+++ b/sql/sql_parse.h
@@ -93,6 +93,7 @@ void mysql_parse(THD *thd, char *rawbuf, uint length,
bool mysql_new_select(LEX *lex, bool move_down, SELECT_LEX *sel);
void create_select_for_variable(THD *thd, LEX_CSTRING *var_name);
void create_table_set_open_action_and_adjust_tables(LEX *lex);
+void mysql_init_delete(LEX *lex);
void mysql_init_multi_delete(LEX *lex);
bool multi_delete_set_locks_and_link_aux_tables(LEX *lex);
void create_table_set_open_action_and_adjust_tables(LEX *lex);
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index b10a81d..b9ae058 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -95,10 +95,8 @@ When one supplies long data for a placeholder:
#include "sql_base.h" // open_normal_and_derived_tables
#include "sql_cache.h" // query_cache_*
#include "sql_view.h" // create_view_precheck
-#include "sql_delete.h" // mysql_prepare_delete
#include "sql_select.h" // for JOIN
#include "sql_insert.h" // upgrade_lock_type_for_insert, mysql_prepare_insert
-#include "sql_update.h" // mysql_prepare_update
#include "sql_db.h" // mysql_opt_change_db, mysql_change_db
#include "sql_derived.h" // mysql_derived_prepare,
// mysql_handle_derived
@@ -1399,160 +1397,6 @@ static bool mysql_test_insert(Prepared_statement *stmt,
}
-/**
- Validate UPDATE statement.
-
- @param stmt prepared statement
- @param tables list of tables used in this query
-
- @todo
- - here we should send types of placeholders to the client.
-
- @retval
- 0 success
- @retval
- 1 error, error message is set in THD
- @retval
- 2 convert to multi_update
-*/
-
-static int mysql_test_update(Prepared_statement *stmt,
- TABLE_LIST *table_list)
-{
- int res;
- THD *thd= stmt->thd;
- uint table_count= 0;
- TABLE_LIST *update_source_table;
- SELECT_LEX *select= stmt->lex->first_select_lex();
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- privilege_t want_privilege(NO_ACL);
-#endif
- DBUG_ENTER("mysql_test_update");
-
- if (update_precheck(thd, table_list) ||
- open_tables(thd, &table_list, &table_count, MYSQL_OPEN_FORCE_SHARED_MDL))
- goto error;
-
- if (mysql_handle_derived(thd->lex, DT_INIT))
- goto error;
-
- if (((update_source_table= unique_table(thd, table_list,
- table_list->next_global, 0)) ||
- table_list->is_multitable()))
- {
- DBUG_ASSERT(update_source_table || table_list->view != 0);
- DBUG_PRINT("info", ("Switch to multi-update"));
- /* pass counter value */
- thd->lex->table_count= table_count;
- /* convert to multiupdate */
- DBUG_RETURN(2);
- }
-
- /*
- thd->fill_derived_tables() is false here for sure (because it is
- preparation of PS, so we even do not check it).
- */
- if (table_list->handle_derived(thd->lex, DT_MERGE_FOR_INSERT))
- goto error;
- if (table_list->handle_derived(thd->lex, DT_PREPARE))
- goto error;
-
- if (!table_list->single_table_updatable())
- {
- my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias.str, "UPDATE");
- goto error;
- }
-
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- /* Force privilege re-checking for views after they have been opened. */
- want_privilege= (table_list->view ? UPDATE_ACL :
- table_list->grant.want_privilege);
-#endif
-
- if (mysql_prepare_update(thd, table_list, &select->where,
- select->order_list.elements,
- select->order_list.first))
- goto error;
-
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- table_list->grant.want_privilege= want_privilege;
- table_list->table->grant.want_privilege= want_privilege;
- table_list->register_want_access(want_privilege);
-#endif
- thd->lex->first_select_lex()->no_wrap_view_item= TRUE;
- res= setup_fields(thd, Ref_ptr_array(),
- select->item_list, MARK_COLUMNS_READ, 0, NULL, 0);
- thd->lex->first_select_lex()->no_wrap_view_item= FALSE;
- if (res)
- goto error;
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- /* Check values */
- table_list->grant.want_privilege=
- table_list->table->grant.want_privilege=
- (SELECT_ACL & ~table_list->table->grant.privilege);
- table_list->register_want_access(SELECT_ACL);
-#endif
- if (setup_fields(thd, Ref_ptr_array(),
- stmt->lex->value_list, COLUMNS_READ, 0, NULL, 0) ||
- check_unique_table(thd, table_list))
- goto error;
- /* TODO: here we should send types of placeholders to the client. */
- DBUG_RETURN(0);
-error:
- DBUG_RETURN(1);
-}
-
-
-/**
- Validate DELETE statement.
-
- @param stmt prepared statement
- @param tables list of tables used in this query
-
- @retval
- FALSE success
- @retval
- TRUE error, error message is set in THD
-*/
-
-static bool mysql_test_delete(Prepared_statement *stmt,
- TABLE_LIST *table_list)
-{
- uint table_count= 0;
- THD *thd= stmt->thd;
- LEX *lex= stmt->lex;
- bool delete_while_scanning;
- DBUG_ENTER("mysql_test_delete");
-
- if (delete_precheck(thd, table_list) ||
- open_tables(thd, &table_list, &table_count, MYSQL_OPEN_FORCE_SHARED_MDL))
- goto error;
-
- if (mysql_handle_derived(thd->lex, DT_INIT))
- goto error;
- if (mysql_handle_derived(thd->lex, DT_MERGE_FOR_INSERT))
- goto error;
- if (mysql_handle_derived(thd->lex, DT_PREPARE))
- goto error;
-
- if (!table_list->single_table_updatable())
- {
- my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias.str, "DELETE");
- goto error;
- }
- if (!table_list->table || !table_list->table->is_created())
- {
- my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
- table_list->view_db.str, table_list->view_name.str);
- goto error;
- }
-
- DBUG_RETURN(mysql_prepare_delete(thd, table_list,
- &lex->first_select_lex()->where,
- &delete_while_scanning));
-error:
- DBUG_RETURN(TRUE);
-}
/**
@@ -2135,74 +1979,6 @@ static bool mysql_test_create_view(Prepared_statement *stmt)
}
-/*
- Validate and prepare for execution a multi update statement.
-
- @param stmt prepared statement
- @param tables list of tables used in this query
- @param converted converted to multi-update from usual update
-
- @retval
- FALSE success
- @retval
- TRUE error, error message is set in THD
-*/
-
-static bool mysql_test_multiupdate(Prepared_statement *stmt,
- TABLE_LIST *tables,
- bool converted)
-{
- /* if we switched from normal update, rights are checked */
- if (!converted && multi_update_precheck(stmt->thd, tables))
- return TRUE;
-
- return select_like_stmt_test(stmt, &mysql_multi_update_prepare,
- OPTION_SETUP_TABLES_DONE);
-}
-
-
-/**
- Validate and prepare for execution a multi delete statement.
-
- @param stmt prepared statement
- @param tables list of tables used in this query
-
- @retval
- FALSE success
- @retval
- TRUE error, error message in THD is set.
-*/
-
-static bool mysql_test_multidelete(Prepared_statement *stmt,
- TABLE_LIST *tables)
-{
- THD *thd= stmt->thd;
-
- thd->lex->current_select= thd->lex->first_select_lex();
- if (add_item_to_list(thd, new (thd->mem_root)
- Item_null(thd)))
- {
- my_error(ER_OUTOFMEMORY, MYF(ME_FATAL), 0);
- goto error;
- }
-
- if (multi_delete_precheck(thd, tables) ||
- select_like_stmt_test_with_open(stmt, tables,
- &mysql_multi_delete_prepare,
- OPTION_SETUP_TABLES_DONE))
- goto error;
- if (!tables->table)
- {
- my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
- tables->view_db.str, tables->view_name.str);
- goto error;
- }
- return FALSE;
-error:
- return TRUE;
-}
-
-
/**
Wrapper for mysql_insert_select_prepare, to make change of local tables
after open_normal_and_derived_tables() call.
@@ -2484,18 +2260,14 @@ static bool check_prepared_statement(Prepared_statement *stmt)
break;
case SQLCOM_UPDATE:
- res= mysql_test_update(stmt, tables);
- /* mysql_test_update returns 2 if we need to switch to multi-update */
- if (res != 2)
- break;
- /* fall through */
case SQLCOM_UPDATE_MULTI:
- res= mysql_test_multiupdate(stmt, tables, res == 2);
- break;
-
case SQLCOM_DELETE:
- res= mysql_test_delete(stmt, tables);
+ case SQLCOM_DELETE_MULTI:
+ res = lex->m_sql_cmd->prepare(thd);
+ if (!res)
+ lex->m_sql_cmd->unprepare(thd);
break;
+
/* The following allow WHERE clause, so they must be tested like SELECT */
case SQLCOM_SHOW_DATABASES:
case SQLCOM_SHOW_TABLES:
@@ -2632,10 +2404,6 @@ static bool check_prepared_statement(Prepared_statement *stmt)
res= mysql_test_set_fields(stmt, tables, &lex->var_list);
break;
- case SQLCOM_DELETE_MULTI:
- res= mysql_test_multidelete(stmt, tables);
- break;
-
case SQLCOM_INSERT_SELECT:
case SQLCOM_REPLACE_SELECT:
res= mysql_test_insert_select(stmt, tables);
@@ -4373,6 +4141,9 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
thd->is_error() ||
init_param_array(this));
+ if (lex->m_sql_cmd)
+ lex->m_sql_cmd->set_owner(this);
+
if (thd->security_ctx->password_expired &&
lex->sql_command != SQLCOM_SET_OPTION &&
lex->sql_command != SQLCOM_PREPARE &&
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 2a56292..bf49d69 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1430,7 +1430,7 @@ JOIN::prepare(TABLE_LIST *tables_init, COND *conds_init, uint og_num,
}
}
- if (setup_fields(thd, ref_ptrs, fields_list, MARK_COLUMNS_READ,
+ if (setup_fields(thd, ref_ptrs, fields_list, select_lex->item_list_usage,
&all_fields, &select_lex->pre_fix, 1))
DBUG_RETURN(-1);
thd->lex->current_select->context_analysis_place= save_place;
@@ -1720,6 +1720,8 @@ JOIN::prepare(TABLE_LIST *tables_init, COND *conds_init, uint og_num,
if (!procedure && result && result->prepare(fields_list, unit_arg))
goto err; /* purecov: inspected */
+ select_lex->where_cond_after_prepare= conds;
+
unit= unit_arg;
if (prepare_stage2())
goto err;
@@ -29028,7 +29030,8 @@ static bool get_range_limit_read_cost(const JOIN_TAB *tab,
@note
This function takes into account table->opt_range_condition_rows statistic
(that is calculated by the make_join_statistics function).
- However, single table procedures such as mysql_update() and mysql_delete()
+ However, single table procedures such as Sql_cmd_update:update_single_table()
+ and Sql_cmd_delete::delete_single_table()
never call make_join_statistics, so they have to update it manually
(@see get_index_for_order()).
*/
@@ -30463,6 +30466,266 @@ static bool process_direct_rownum_comparison(THD *thd, SELECT_LEX_UNIT *unit,
}
+static void MYSQL_DML_START(THD *thd)
+{
+ switch (thd->lex->sql_command) {
+
+ case SQLCOM_UPDATE:
+ MYSQL_UPDATE_START(thd->query());
+ break;
+ case SQLCOM_UPDATE_MULTI:
+ MYSQL_MULTI_UPDATE_START(thd->query());
+ break;
+ case SQLCOM_DELETE:
+ MYSQL_DELETE_START(thd->query());
+ break;
+ case SQLCOM_DELETE_MULTI:
+ MYSQL_MULTI_DELETE_START(thd->query());
+ break;
+ default:
+ DBUG_ASSERT(0);
+ }
+}
+
+
+static void MYSQL_DML_DONE(THD *thd, int rc)
+{
+ switch (thd->lex->sql_command) {
+
+ case SQLCOM_UPDATE:
+ MYSQL_UPDATE_DONE(
+ rc,
+ (rc ? 0 :
+ ((multi_update*)(((Sql_cmd_dml*)(thd->lex->m_sql_cmd))->get_result()))
+ ->num_found()),
+ (rc ? 0 :
+ ((multi_update*)(((Sql_cmd_dml*)(thd->lex->m_sql_cmd))->get_result()))
+ ->num_updated()));
+ break;
+ case SQLCOM_UPDATE_MULTI:
+ MYSQL_MULTI_UPDATE_DONE(
+ rc,
+ (rc ? 0 :
+ ((multi_update*)(((Sql_cmd_dml*)(thd->lex->m_sql_cmd))->get_result()))
+ ->num_found()),
+ (rc ? 0 :
+ ((multi_update*)(((Sql_cmd_dml*)(thd->lex->m_sql_cmd))->get_result()))
+ ->num_updated()));
+ break;
+ case SQLCOM_DELETE:
+ MYSQL_DELETE_DONE(rc, (rc ? 0 : (ulong) (thd->get_row_count_func())));
+ break;
+ case SQLCOM_DELETE_MULTI:
+ MYSQL_MULTI_DELETE_DONE(
+ rc,
+ (rc ? 0 :
+ ((multi_delete*)(((Sql_cmd_dml*)(thd->lex->m_sql_cmd))->get_result()))
+ ->num_deleted()));
+ break;
+ default:
+ DBUG_ASSERT(0);
+ }
+}
+
+/*
+ @brief Perform actions needed before locking tables for a DML statement
+
+ @param thd global context the processed statement
+ @returns false if success, true if error
+
+ @details
+ This function calls the precheck() procedure fo the processed statement,
+ then is opens tables used in the statement and finally it calls the function
+ prepare_inner() that is specific for the type of the statement.
+
+ @note
+ The function are used when processing:
+ - a DML statement
+ - PREPARE stmt FROM <DML "statement>"
+ - EXECUTE stmt when stmt is prepared from a DML statement.
+*/
+
+bool Sql_cmd_dml::prepare(THD *thd)
+{
+ lex= thd->lex;
+ SELECT_LEX_UNIT *unit= &lex->unit;
+
+ DBUG_ASSERT(!is_prepared());
+
+ // Perform a coarse statement-specific privilege check.
+ if (precheck(thd))
+ goto err;
+
+ MYSQL_DML_START(thd);
+
+ lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_DERIVED;
+
+ if (open_tables_for_query(thd, lex->query_tables, &table_count, 0,
+ get_dml_prelocking_strategy()))
+ {
+ if (thd->is_error())
+ goto err;
+ (void)unit->cleanup();
+ return true;
+ }
+
+ if (prepare_inner(thd))
+ goto err;
+
+ lex->context_analysis_only&= ~CONTEXT_ANALYSIS_ONLY_DERIVED;
+
+ set_prepared();
+ unit->set_prepared();
+
+ return false;
+
+err:
+ DBUG_ASSERT(thd->is_error());
+ DBUG_PRINT("info", ("report_error: %d", thd->is_error()));
+
+ (void)unit->cleanup();
+
+ return true;
+}
+
+
+/**
+ @brief Execute a DML statement
+
+ @param thd global context the processed statement
+ @returns false if success, true if error
+
+ @details
+ The function assumes that each type of a DML statement has its own
+ implementation of the virtunal functions precheck(). It is also
+ assumed that that the virtual function execute execute_inner() is to be
+ overridden by the implementations for specific commands.
+
+ @note
+ Currently only UPDATE and DELETE statement are executed using this function.
+*/
+
+bool Sql_cmd_dml::execute(THD *thd)
+{
+ lex = thd->lex;
+ bool res;
+
+ SELECT_LEX_UNIT *unit = &lex->unit;
+ SELECT_LEX *select_lex= lex->first_select_lex();
+
+ if (!is_prepared())
+ {
+ /*
+ This is called when processing
+ - a DML statement
+ - PREPARE stmt FROM <DML "statement>"
+ - EXECUTE stmt when stmt is prepared from a DML statement.
+ The call will invoke open_tables_for_query()
+ */
+ if (prepare(thd))
+ goto err;
+ }
+ else // This branch currently is never used for DML commands
+ {
+ if (precheck(thd))
+ goto err;
+
+ MYSQL_DML_START(thd);
+
+ if (open_tables_for_query(thd, lex->query_tables, &table_count, 0,
+ get_dml_prelocking_strategy()))
+ goto err;
+ }
+
+ THD_STAGE_INFO(thd, stage_init);
+
+ /*
+ Locking of tables is done after preparation but before optimization.
+ This allows to do better partition pruning and avoid locking unused
+ partitions. As a consequence, in such a case, prepare stage can rely only
+ on metadata about tables used and not data from them.
+ */
+ if (!is_empty_query())
+ {
+ if (lock_tables(thd, lex->query_tables, table_count, 0))
+ goto err;
+ }
+
+ unit->set_limit(select_lex);
+
+ /* Perform statement-specific execution */
+ res = execute_inner(thd);
+
+ if (res)
+ goto err;
+
+ res= unit->cleanup();
+
+ /* "Unprepare" this object since unit->cleanup actually unprepares */
+ unprepare(thd);
+
+ THD_STAGE_INFO(thd, stage_end);
+
+ MYSQL_DML_DONE(thd, res);
+
+ return res;
+
+err:
+ DBUG_ASSERT(thd->is_error() || thd->killed);
+ MYSQL_DML_DONE(thd, 1);
+ THD_STAGE_INFO(thd, stage_end);
+ (void)unit->cleanup();
+
+ return thd->is_error();
+}
+
+/**
+ @brief Generic implemention of optimization and execution phases
+ @param thd global context the processed statement
+ @returns false if success, true if error
+
+ @note
+ This implementation assumes that the processed DML statement is represented
+ as a SELECT_LEX or SELECT_LEX_UNIT tree with attached corresponding
+ JOIN structures. Any JOIN structure is constructed at the prepare phase.
+ When created at the top level join it is provided with an object of a class
+ derived from select_result_sink. The pointer to the object is saved in
+ the this->result field. For different types of DML statements different
+ derived classes are used for this object. The class of this object determines
+ additional specific actions performed at the phases of context analysis,
+ optimization and execution.
+*/
+
+bool Sql_cmd_dml::execute_inner(THD *thd)
+{
+ SELECT_LEX_UNIT *unit = &lex->unit;
+ SELECT_LEX *select_lex= unit->first_select();
+ JOIN *join= select_lex->join;
+
+ if (join->optimize())
+ goto err;
+
+ if (thd->lex->describe & DESCRIBE_EXTENDED)
+ {
+ join->conds_history= join->conds;
+ join->having_history= (join->having?join->having:join->tmp_having);
+ }
+
+ if (unlikely(thd->is_error()))
+ goto err;
+
+ join->exec();
+
+ if (thd->lex->describe & DESCRIBE_EXTENDED)
+ {
+ select_lex->where= join->conds_history;
+ select_lex->having= join->having_history;
+ }
+
+err:
+ return join->error;
+}
+
/**
@} (end of group Query_Optimizer)
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 74ed078..6b14c4f 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -197,22 +197,11 @@ static bool check_fields(THD *thd, TABLE_LIST *table, List<Item> &items,
return true;
}
- DBUG_ASSERT(thd->lex->sql_command == SQLCOM_UPDATE);
- for (List_iterator_fast<Item> it(items); (item=it++);)
- {
- Field *f= item->field_for_view_update()->field;
- vers_select_conds_t &period= table->period_conditions;
- if (period.field_start->field == f || period.field_end->field == f)
- {
- my_error(ER_PERIOD_COLUMNS_UPDATED, MYF(0),
- item->name.str, period.name.str);
- return true;
- }
- }
}
return FALSE;
}
+
bool TABLE::vers_check_update(List<Item> &items)
{
List_iterator<Item> it(items);
@@ -339,36 +328,25 @@ int cut_fields_for_portion_of_time(THD *thd, TABLE *table,
return res;
}
-/*
- Process usual UPDATE
-
- SYNOPSIS
- mysql_update()
- thd thread handler
- fields fields for update
- values values of fields for update
- conds WHERE clause expression
- order_num number of elemen in ORDER BY clause
- order ORDER BY clause list
- limit limit clause
+/**
+ @brief Special handling of single-table updates after prepare phase
- RETURN
- 0 - OK
- 2 - privilege check and openning table passed, but we need to convert to
- multi-update because of view substitution
- 1 - error
+ @param thd global context the processed statement
+ @returns false on success, true on error
*/
-int mysql_update(THD *thd,
- TABLE_LIST *table_list,
- List<Item> &fields,
- List<Item> &values,
- COND *conds,
- uint order_num, ORDER *order,
- ha_rows limit,
- bool ignore,
- ha_rows *found_return, ha_rows *updated_return)
+bool Sql_cmd_update::update_single_table(THD *thd)
{
+ SELECT_LEX_UNIT *unit = &lex->unit;
+ SELECT_LEX *select_lex= unit->first_select();
+ TABLE_LIST *const table_list = select_lex->get_table_list();
+ List<Item> *fields= &select_lex->item_list;
+ List<Item> *values= &lex->value_list;
+ COND *conds= select_lex->where_cond_after_prepare;
+ ORDER *order= select_lex->order_list.first;
+ ha_rows limit= unit->lim.get_select_limit();
+ bool ignore= lex->ignore;
+
bool using_limit= limit != HA_POS_ERROR;
bool safe_update= (thd->variables.option_bits & OPTION_SAFE_UPDATES)
&& !thd->lex->describe;
@@ -380,76 +358,39 @@ int mysql_update(THD *thd,
ha_rows dup_key_found;
bool need_sort= TRUE;
bool reverse= FALSE;
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- privilege_t want_privilege(NO_ACL);
-#endif
- uint table_count= 0;
ha_rows updated, updated_or_same, found;
key_map old_covering_keys;
TABLE *table;
SQL_SELECT *select= NULL;
SORT_INFO *file_sort= 0;
READ_RECORD info;
- SELECT_LEX *select_lex= thd->lex->first_select_lex();
ulonglong id;
List<Item> all_fields;
killed_state killed_status= NOT_KILLED;
bool has_triggers, binlog_is_row, do_direct_update= FALSE;
Update_plan query_plan(thd->mem_root);
Explain_update *explain;
- TABLE_LIST *update_source_table;
query_plan.index= MAX_KEY;
query_plan.using_filesort= FALSE;
// For System Versioning (may need to insert new fields to a table).
ha_rows rows_inserted= 0;
- DBUG_ENTER("mysql_update");
+ DBUG_ENTER("Sql_cmd_update::update_single_table");
+ THD_STAGE_INFO(thd, stage_init_update);
create_explain_query(thd->lex, thd->mem_root);
- if (open_tables(thd, &table_list, &table_count, 0))
- DBUG_RETURN(1);
-
- /* Prepare views so they are handled correctly */
- if (mysql_handle_derived(thd->lex, DT_INIT))
- DBUG_RETURN(1);
- if (table_list->has_period() && table_list->is_view_or_derived())
- {
- my_error(ER_IT_IS_A_VIEW, MYF(0), table_list->table_name.str);
- DBUG_RETURN(TRUE);
- }
-
- if (((update_source_table=unique_table(thd, table_list,
- table_list->next_global, 0)) ||
- table_list->is_multitable()))
- {
- DBUG_ASSERT(update_source_table || table_list->view != 0);
- DBUG_PRINT("info", ("Switch to multi-update"));
- /* pass counter value */
- thd->lex->table_count= table_count;
- if (thd->lex->period_conditions.is_set())
- {
- my_error(ER_NOT_SUPPORTED_YET, MYF(0),
- "updating and querying the same temporal periods table");
+ thd->table_map_for_update= 0;
- DBUG_RETURN(1);
- }
-
- /* convert to multiupdate */
- DBUG_RETURN(2);
- }
- if (lock_tables(thd, table_list, table_count, 0))
- DBUG_RETURN(1);
-
- (void) read_statistics_for_tables_if_needed(thd, table_list);
-
- THD_STAGE_INFO(thd, stage_init_update);
if (table_list->handle_derived(thd->lex, DT_MERGE_FOR_INSERT))
DBUG_RETURN(1);
if (table_list->handle_derived(thd->lex, DT_PREPARE))
DBUG_RETURN(1);
+ if (setup_ftfuncs(select_lex))
+ DBUG_RETURN(1);
+
table= table_list->table;
if (!table_list->single_table_updatable())
@@ -458,85 +399,26 @@ int mysql_update(THD *thd,
DBUG_RETURN(1);
}
- /* Calculate "table->covering_keys" based on the WHERE */
- table->covering_keys= table->s->keys_in_use;
table->opt_range_keys.clear_all();
query_plan.select_lex= thd->lex->first_select_lex();
query_plan.table= table;
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- /* Force privilege re-checking for views after they have been opened. */
- want_privilege= (table_list->view ? UPDATE_ACL :
- table_list->grant.want_privilege);
-#endif
thd->lex->promote_select_describe_flag_if_needed();
- if (mysql_prepare_update(thd, table_list, &conds, order_num, order))
- DBUG_RETURN(1);
-
- if (table_list->has_period())
- {
- if (!table_list->period_conditions.start.item->const_item()
- || !table_list->period_conditions.end.item->const_item())
- {
- my_error(ER_NOT_CONSTANT_EXPRESSION, MYF(0), "FOR PORTION OF");
- DBUG_RETURN(true);
- }
- table->no_cache= true;
- }
-
old_covering_keys= table->covering_keys; // Keys used in WHERE
- /* Check the fields we are going to modify */
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- table_list->grant.want_privilege= table->grant.want_privilege= want_privilege;
- table_list->register_want_access(want_privilege);
-#endif
- /* 'Unfix' fields to allow correct marking by the setup_fields function. */
- if (table_list->is_view())
- unfix_fields(fields);
- if (setup_fields_with_no_wrap(thd, Ref_ptr_array(),
- fields, MARK_COLUMNS_WRITE, 0, 0))
- DBUG_RETURN(1); /* purecov: inspected */
- if (check_fields(thd, table_list, fields, table_list->view))
- {
- DBUG_RETURN(1);
- }
- bool has_vers_fields= table->vers_check_update(fields);
- if (check_key_in_view(thd, table_list))
- {
- my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias.str, "UPDATE");
- DBUG_RETURN(1);
- }
+ bool has_vers_fields= table->vers_check_update(*fields);
if (table->default_field)
table->mark_default_fields_for_write(false);
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- /* Check values */
- table_list->grant.want_privilege= table->grant.want_privilege=
- (SELECT_ACL & ~table->grant.privilege);
-#endif
- if (setup_fields(thd, Ref_ptr_array(), values, MARK_COLUMNS_READ, 0, NULL, 0))
- {
- free_underlaid_joins(thd, select_lex);
- DBUG_RETURN(1); /* purecov: inspected */
- }
-
- if (check_unique_table(thd, table_list))
- DBUG_RETURN(TRUE);
-
- switch_to_nullable_trigger_fields(fields, table);
- switch_to_nullable_trigger_fields(values, table);
+ switch_to_nullable_trigger_fields(*fields, table);
+ switch_to_nullable_trigger_fields(*values, table);
/* Apply the IN=>EXISTS transformation to all subqueries and optimize them */
if (select_lex->optimize_unflattened_subqueries(false))
DBUG_RETURN(TRUE);
- if (select_lex->inner_refs_list.elements &&
- fix_inner_refs(thd, all_fields, select_lex, select_lex->ref_pointer_array))
- DBUG_RETURN(1);
-
if (conds)
{
Item::cond_result cond_value;
@@ -776,9 +658,9 @@ int mysql_update(THD *thd,
}
if (use_direct_update &&
- !table->file->info_push(INFO_KIND_UPDATE_FIELDS, &fields) &&
- !table->file->info_push(INFO_KIND_UPDATE_VALUES, &values) &&
- !table->file->direct_update_rows_init(&fields))
+ !table->file->info_push(INFO_KIND_UPDATE_FIELDS, fields) &&
+ !table->file->info_push(INFO_KIND_UPDATE_VALUES, values) &&
+ !table->file->direct_update_rows_init(fields))
{
do_direct_update= TRUE;
@@ -1027,7 +909,7 @@ int mysql_update(THD *thd,
cut_fields_for_portion_of_time(thd, table,
table_list->period_conditions);
- if (fill_record_n_invoke_before_triggers(thd, table, fields, values, 0,
+ if (fill_record_n_invoke_before_triggers(thd, table, *fields, *values, 0,
TRG_EVENT_UPDATE))
break; /* purecov: inspected */
@@ -1360,9 +1242,9 @@ int mysql_update(THD *thd,
thd->lex->current_select->save_leaf_tables(thd);
thd->lex->current_select->first_cond_optimization= 0;
}
- *found_return= found;
- *updated_return= updated;
-
+ ((multi_update *)result)->set_found(found);
+ ((multi_update *)result)->set_updated(updated);
+
if (unlikely(thd->lex->analyze_stmt))
goto emit_explain_and_leave;
@@ -1394,75 +1276,6 @@ int mysql_update(THD *thd,
DBUG_RETURN((err2 || thd->is_error()) ? 1 : 0);
}
-/*
- Prepare items in UPDATE statement
-
- SYNOPSIS
- mysql_prepare_update()
- thd - thread handler
- table_list - global/local table list
- conds - conditions
- order_num - number of ORDER BY list entries
- order - ORDER BY clause list
-
- RETURN VALUE
- FALSE OK
- TRUE error
-*/
-bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
- Item **conds, uint order_num, ORDER *order)
-{
- Item *fake_conds= 0;
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- TABLE *table= table_list->table;
-#endif
- List<Item> all_fields;
- SELECT_LEX *select_lex= thd->lex->first_select_lex();
- DBUG_ENTER("mysql_prepare_update");
-
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- table_list->grant.want_privilege= table->grant.want_privilege=
- (SELECT_ACL & ~table->grant.privilege);
- table_list->register_want_access(SELECT_ACL);
-#endif
-
- thd->lex->allow_sum_func.clear_all();
-
- if (table_list->has_period() &&
- select_lex->period_setup_conds(thd, table_list))
- DBUG_RETURN(true);
-
- DBUG_ASSERT(table_list->table);
- // conds could be cached from previous SP call
- DBUG_ASSERT(!table_list->vers_conditions.need_setup() ||
- !*conds || thd->stmt_arena->is_stmt_execute());
- if (select_lex->vers_setup_conds(thd, table_list))
- DBUG_RETURN(TRUE);
-
- *conds= select_lex->where;
-
- /*
- We do not call DT_MERGE_FOR_INSERT because it has no sense for simple
- (not multi-) update
- */
- if (mysql_handle_derived(thd->lex, DT_PREPARE))
- DBUG_RETURN(TRUE);
-
- if (setup_tables_and_check_access(thd, &select_lex->context,
- &select_lex->top_join_list, table_list,
- select_lex->leaf_tables,
- FALSE, UPDATE_ACL, SELECT_ACL, TRUE) ||
- setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
- select_lex->setup_ref_array(thd, order_num) ||
- setup_order(thd, select_lex->ref_pointer_array,
- table_list, all_fields, all_fields, order) ||
- setup_ftfuncs(select_lex))
- DBUG_RETURN(TRUE);
-
-
- select_lex->fix_prepare_information(thd, conds, &fake_conds);
- DBUG_RETURN(FALSE);
-}
/**
Check that we are not using table that we are updating in a sub select
@@ -1690,15 +1503,6 @@ static bool multi_update_check_table_access(THD *thd, TABLE_LIST *table,
}
-class Multiupdate_prelocking_strategy : public DML_prelocking_strategy
-{
- bool done;
- bool has_prelocking_list;
-public:
- void reset(THD *thd);
- bool handle_end(THD *thd);
-};
-
void Multiupdate_prelocking_strategy::reset(THD *thd)
{
done= false;
@@ -1728,7 +1532,13 @@ bool Multiupdate_prelocking_strategy::handle_end(THD *thd)
mysql_handle_derived(lex, DT_PREPARE))
DBUG_RETURN(1);
- /*
+ if (table_list->has_period() && table_list->is_view_or_derived())
+ {
+ my_error(ER_IT_IS_A_VIEW, MYF(0), table_list->table_name.str);
+ DBUG_RETURN(TRUE);
+ }
+
+ /*
setup_tables() need for VIEWs. JOIN::prepare() will call setup_tables()
second time, but this call will do nothing (there are check for second
call in setup_tables()).
@@ -1739,6 +1549,10 @@ bool Multiupdate_prelocking_strategy::handle_end(THD *thd)
FALSE, UPDATE_ACL, SELECT_ACL, TRUE))
DBUG_RETURN(1);
+ if (table_list->has_period() &&
+ select_lex->period_setup_conds(thd, table_list))
+ DBUG_RETURN(true);
+
List<Item> *fields= &lex->first_select_lex()->item_list;
if (setup_fields_with_no_wrap(thd, Ref_ptr_array(),
*fields, MARK_COLUMNS_WRITE, 0, 0))
@@ -1847,153 +1661,6 @@ bool Multiupdate_prelocking_strategy::handle_end(THD *thd)
DBUG_RETURN(0);
}
-/*
- make update specific preparation and checks after opening tables
-
- SYNOPSIS
- mysql_multi_update_prepare()
- thd thread handler
-
- RETURN
- FALSE OK
- TRUE Error
-*/
-
-int mysql_multi_update_prepare(THD *thd)
-{
- LEX *lex= thd->lex;
- TABLE_LIST *table_list= lex->query_tables;
- TABLE_LIST *tl;
- Multiupdate_prelocking_strategy prelocking_strategy;
- uint table_count= lex->table_count;
- DBUG_ENTER("mysql_multi_update_prepare");
-
- /*
- Open tables and create derived ones, but do not lock and fill them yet.
-
- During prepare phase acquire only S metadata locks instead of SW locks to
- keep prepare of multi-UPDATE compatible with concurrent LOCK TABLES WRITE
- and global read lock.
-
- Don't evaluate any subqueries even if constant, because
- tables aren't locked yet.
- */
- lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_DERIVED;
- if (thd->lex->sql_command == SQLCOM_UPDATE_MULTI)
- {
- if (open_tables(thd, &table_list, &table_count,
- thd->stmt_arena->is_stmt_prepare() ? MYSQL_OPEN_FORCE_SHARED_MDL : 0,
- &prelocking_strategy))
- DBUG_RETURN(TRUE);
- }
- else
- {
- /* following need for prepared statements, to run next time multi-update */
- thd->lex->sql_command= SQLCOM_UPDATE_MULTI;
- prelocking_strategy.reset(thd);
- if (prelocking_strategy.handle_end(thd))
- DBUG_RETURN(TRUE);
- }
-
- /* now lock and fill tables */
- if (!thd->stmt_arena->is_stmt_prepare() &&
- lock_tables(thd, table_list, table_count, 0))
- DBUG_RETURN(TRUE);
-
- lex->context_analysis_only&= ~CONTEXT_ANALYSIS_ONLY_DERIVED;
-
- (void) read_statistics_for_tables_if_needed(thd, table_list);
- /* @todo: downgrade the metadata locks here. */
-
- /*
- Check that we are not using table that we are updating, but we should
- skip all tables of UPDATE SELECT itself
- */
- lex->first_select_lex()->exclude_from_table_unique_test= TRUE;
- /* We only need SELECT privilege for columns in the values list */
- List_iterator<TABLE_LIST> ti(lex->first_select_lex()->leaf_tables);
- while ((tl= ti++))
- {
- if (tl->is_jtbm())
- continue;
- TABLE *table= tl->table;
- TABLE_LIST *tlist;
- if (!(tlist= tl->top_table())->derived)
- {
- tlist->grant.want_privilege=
- (SELECT_ACL & ~tlist->grant.privilege);
- table->grant.want_privilege= (SELECT_ACL & ~table->grant.privilege);
- }
- DBUG_PRINT("info", ("table: %s want_privilege: %llx", tl->alias.str,
- (longlong) table->grant.want_privilege));
- }
- /*
- Set exclude_from_table_unique_test value back to FALSE. It is needed for
- further check in multi_update::prepare whether to use record cache.
- */
- lex->first_select_lex()->exclude_from_table_unique_test= FALSE;
-
- if (lex->save_prep_leaf_tables())
- DBUG_RETURN(TRUE);
-
- DBUG_RETURN (FALSE);
-}
-
-
-/*
- Setup multi-update handling and call SELECT to do the join
-*/
-
-bool mysql_multi_update(THD *thd, TABLE_LIST *table_list, List<Item> *fields,
- List<Item> *values, COND *conds, ulonglong options,
- enum enum_duplicates handle_duplicates,
- bool ignore, SELECT_LEX_UNIT *unit,
- SELECT_LEX *select_lex, multi_update **result)
-{
- bool res;
- DBUG_ENTER("mysql_multi_update");
-
- if (!(*result= new (thd->mem_root) multi_update(thd, table_list,
- &thd->lex->first_select_lex()->leaf_tables,
- fields, values, handle_duplicates, ignore)))
- {
- DBUG_RETURN(TRUE);
- }
-
- if ((*result)->init(thd))
- DBUG_RETURN(1);
-
- thd->abort_on_warning= !ignore && thd->is_strict_mode();
- List<Item> total_list;
-
- if (setup_tables(thd, &select_lex->context, &select_lex->top_join_list,
- table_list, select_lex->leaf_tables, FALSE, FALSE))
- DBUG_RETURN(1);
-
- if (select_lex->vers_setup_conds(thd, table_list))
- DBUG_RETURN(1);
-
- res= mysql_select(thd,
- table_list, total_list, conds,
- select_lex->order_list.elements,
- select_lex->order_list.first, NULL, NULL, NULL,
- options | SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK |
- OPTION_SETUP_TABLES_DONE,
- *result, unit, select_lex);
-
- DBUG_PRINT("info",("res: %d report_error: %d", res, (int) thd->is_error()));
- res|= thd->is_error();
- if (unlikely(res))
- (*result)->abort_result_set();
- else
- {
- if (thd->lex->describe || thd->lex->analyze_stmt)
- res= thd->lex->explain->send_explain(thd);
- }
- thd->abort_on_warning= 0;
- DBUG_RETURN(res);
-}
-
multi_update::multi_update(THD *thd_arg, TABLE_LIST *table_list,
List<TABLE_LIST> *leaves_list,
@@ -2029,6 +1696,19 @@ bool multi_update::init(THD *thd)
}
+bool multi_update::init_for_single_table(THD *thd)
+{
+ List_iterator_fast<TABLE_LIST> li(*leaves);
+ TABLE_LIST *tbl;
+ while ((tbl =li++))
+ {
+ if (updated_leaves.push_back(tbl, thd->mem_root))
+ return true;
+ }
+ return false;
+}
+
+
/*
Connect fields with tables and create list of tables that are updated
*/
@@ -2102,7 +1782,8 @@ int multi_update::prepare(List<Item> ¬_used_values,
{
table->read_set= &table->def_read_set;
bitmap_union(table->read_set, &table->tmp_set);
- table->file->prepare_for_insert(1);
+ if (!(thd->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_PREPARE))
+ table->file->prepare_for_insert(1);
}
}
if (unlikely(error))
@@ -3123,3 +2804,237 @@ bool multi_update::send_eof()
}
DBUG_RETURN(FALSE);
}
+
+
+/**
+ @brief Perform precheck of table privileges for update statements
+
+ @param thd global context the processed statement
+ @returns false on success, true on error
+*/
+
+bool Sql_cmd_update::precheck(THD *thd)
+{
+ if (!multitable)
+ {
+ if (update_precheck(thd, lex->query_tables))
+ return true;
+ }
+ else
+ {
+ if (multi_update_precheck(thd, lex->query_tables))
+ return true;
+ }
+
+ WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
+
+ return false;
+
+#ifdef WITH_WSREP
+wsrep_error_label:
+#endif
+ return true;
+}
+
+
+/**
+ @brief Perform context analysis for update statements
+
+ @param thd global context the processed statement
+ @returns false on success, true on error
+
+ @note
+ The main bulk of the context analysis actions for and update statement
+ is performed by a call of JOIN::prepare().
+*/
+
+bool Sql_cmd_update::prepare_inner(THD *thd)
+{
+ JOIN *join;
+ int err= 0;
+ SELECT_LEX *const select_lex = thd->lex->first_select_lex();
+ TABLE_LIST *const table_list = select_lex->get_table_list();
+ ulonglong select_options= select_lex->options;
+ bool free_join= 1;
+ DBUG_ENTER("Sql_cmd_update::prepare_inner");
+
+ (void) read_statistics_for_tables_if_needed(thd, table_list);
+
+ THD_STAGE_INFO(thd, stage_init_update);
+
+ if (!multitable)
+ {
+ if (mysql_handle_derived(lex, DT_INIT))
+ DBUG_RETURN(TRUE);
+ }
+
+ if (table_list->has_period() && table_list->is_view_or_derived())
+ {
+ my_error(ER_IT_IS_A_VIEW, MYF(0), table_list->table_name.str);
+ DBUG_RETURN(TRUE);
+ }
+
+ if (!multitable)
+ {
+ TABLE_LIST *update_source_table= 0;
+
+ if (((update_source_table=unique_table(thd, table_list,
+ table_list->next_global, 0)) ||
+ table_list->is_multitable()))
+ {
+ DBUG_ASSERT(update_source_table || table_list->view != 0);
+ if (thd->lex->period_conditions.is_set())
+ {
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0),
+ "updating and querying the same temporal periods table");
+ DBUG_RETURN(TRUE);
+ }
+ multitable= true;
+ }
+ }
+
+ if(!multitable)
+ {
+ if (table_list->is_view_or_derived() &&
+ select_lex->leaf_tables.elements > 1)
+ multitable = true;
+ }
+
+ if (!multitable)
+ {
+ if (lex->ignore)
+ lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_UPDATE_IGNORE);
+ }
+
+ if (!(result= new (thd->mem_root) multi_update(thd, table_list,
+ &select_lex->leaf_tables,
+ &select_lex->item_list,
+ &lex->value_list,
+ lex->duplicates,
+ lex->ignore)))
+ {
+ DBUG_RETURN(TRUE);
+ }
+
+ if (((multi_update *)result)->init(thd))
+ DBUG_RETURN(TRUE);
+
+ if (setup_tables(thd, &select_lex->context, &select_lex->top_join_list,
+ table_list, select_lex->leaf_tables, false, false))
+ DBUG_RETURN(TRUE);
+
+ if (select_lex->vers_setup_conds(thd, table_list))
+ DBUG_RETURN(TRUE);
+
+ {
+ if (thd->lex->describe)
+ select_options|= SELECT_DESCRIBE;
+
+ /*
+ When in EXPLAIN, delay deleting the joins so that they are still
+ available when we're producing EXPLAIN EXTENDED warning text.
+ */
+ if (select_options & SELECT_DESCRIBE)
+ free_join= 0;
+
+ select_options|=
+ SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK | OPTION_SETUP_TABLES_DONE;
+
+ if (!(join= new (thd->mem_root) JOIN(thd, select_lex->item_list,
+ select_options, result)))
+ DBUG_RETURN(TRUE);
+ THD_STAGE_INFO(thd, stage_init);
+ select_lex->join= join;
+ thd->lex->used_tables=0;
+ select_lex->item_list_usage= MARK_COLUMNS_WRITE;
+ if ((err= join->prepare(table_list, select_lex->where,
+ select_lex->order_list.elements,
+ select_lex->order_list.first,
+ false, NULL, NULL, NULL,
+ select_lex, &lex->unit)))
+ {
+ goto err;
+ }
+
+ }
+
+ if (table_list->has_period())
+ {
+ Item *item;
+ for (List_iterator_fast<Item> it(select_lex->item_list); (item=it++);)
+ {
+ Field *f= item->field_for_view_update()->field;
+ vers_select_conds_t &period= table_list->period_conditions;
+ if (period.field_start->field == f || period.field_end->field == f)
+ {
+ my_error(ER_PERIOD_COLUMNS_UPDATED, MYF(0),
+ item->name.str, period.name.str);
+ DBUG_RETURN(true);
+ }
+ }
+
+ if (!table_list->period_conditions.start.item->const_item()
+ || !table_list->period_conditions.end.item->const_item())
+ {
+ my_error(ER_NOT_CONSTANT_EXPRESSION, MYF(0), "FOR PORTION OF");
+ DBUG_RETURN(true);
+ }
+ table_list->table->no_cache= true;
+ }
+
+
+ free_join= false;
+
+err:
+
+ if (free_join)
+ {
+ THD_STAGE_INFO(thd, stage_end);
+ err|= (int)(select_lex->cleanup());
+ DBUG_RETURN(err || thd->is_error());
+ }
+ DBUG_RETURN(err);
+
+}
+
+
+/**
+ @brief Perform optimization and execution actions needed for updates
+
+ @param thd global context the processed statement
+ @returns false on success, true on error
+*/
+
+bool Sql_cmd_update::execute_inner(THD *thd)
+{
+ bool res= 0;
+
+ thd->get_stmt_da()->reset_current_row_for_warning(1);
+ if (!multitable)
+ res= update_single_table(thd);
+ else
+ {
+ thd->abort_on_warning= !thd->lex->ignore && thd->is_strict_mode();
+ res= Sql_cmd_dml::execute_inner(thd);
+ }
+
+ res|= thd->is_error();
+ if (multitable)
+ {
+ if (unlikely(res))
+ result->abort_result_set();
+ else
+ {
+ if (thd->lex->describe || thd->lex->analyze_stmt)
+ res= thd->lex->explain->send_explain(thd);
+ }
+ }
+
+ if (result)
+ {
+ res= false;
+ delete result;
+ }
+
+ return res;
+}
diff --git a/sql/sql_update.h b/sql/sql_update.h
index 65e44d1..d0fc7cb 100644
--- a/sql/sql_update.h
+++ b/sql/sql_update.h
@@ -17,6 +17,8 @@
#define SQL_UPDATE_INCLUDED
#include "sql_class.h" /* enum_duplicates */
+#include "sql_cmd.h" // Sql_cmd_dml
+#include "sql_base.h"
class Item;
struct TABLE_LIST;
@@ -25,20 +27,75 @@ class THD;
typedef class st_select_lex SELECT_LEX;
typedef class st_select_lex_unit SELECT_LEX_UNIT;
-bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
- Item **conds, uint order_num, ORDER *order);
bool check_unique_table(THD *thd, TABLE_LIST *table_list);
-int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields,
- List<Item> &values,COND *conds,
- uint order_num, ORDER *order, ha_rows limit,
- bool ignore, ha_rows *found_return, ha_rows *updated_return);
-bool mysql_multi_update(THD *thd, TABLE_LIST *table_list,
- List<Item> *fields, List<Item> *values,
- COND *conds, ulonglong options,
- enum enum_duplicates handle_duplicates, bool ignore,
- SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex,
- multi_update **result);
bool records_are_comparable(const TABLE *table);
bool compare_record(const TABLE *table);
+/**
+ @class Sql_cmd_update - class used for any UPDATE statements
+
+ This class is derived from Sql_cmd_dml and contains implementations
+ for abstract virtual function of the latter such as precheck() and
+ prepare_inner(). It also overrides the implementation of execute_inner()
+ providing a special handling for single-table update statements that
+ are not converted to multi-table updates.
+ The class provides an object of the Multiupdate_prelocking_strategy class
+ for the virtual function get_dml_prelocking_strategy().
+*/
+class Sql_cmd_update final : public Sql_cmd_dml
+{
+public:
+ Sql_cmd_update(bool multitable_arg)
+ : multitable(multitable_arg)
+ { }
+
+ enum_sql_command sql_command_code() const override
+ {
+ return multitable ? SQLCOM_UPDATE_MULTI : SQLCOM_UPDATE;
+ }
+
+ DML_prelocking_strategy *get_dml_prelocking_strategy()
+ {
+ return &multiupdate_prelocking_strategy;
+ }
+
+protected:
+ /**
+ @brief Perform precheck of table privileges for update statements
+ */
+ bool precheck(THD *thd) override;
+
+ /**
+ @brief Perform context analysis for update statements
+ */
+ bool prepare_inner(THD *thd) override;
+
+ /**
+ @brief Perform optimization and execution actions needed for updates
+ */
+ bool execute_inner(THD *thd) override;
+
+private:
+
+ /**
+ @brief Special handling of single-table updates after prepare phase
+ */
+ bool update_single_table(THD *thd);
+
+ /*
+ True if the statement is a multi-table update or converted to such.
+ For a single-table update this flag is set to true if the statement
+ is supposed to be converted to multi-table update.
+ */
+ bool multitable;
+
+ /* The prelocking strategy used when opening the used tables */
+ Multiupdate_prelocking_strategy multiupdate_prelocking_strategy;
+
+ public:
+ /* The list of the updating expressions used in the set clause */
+ List<Item> *update_value_list;
+
+};
+
#endif /* SQL_UPDATE_INCLUDED */
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 5416cec..a587a37 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -69,6 +69,8 @@
#include "my_base.h"
#include "sql_type_json.h"
#include "json_table.h"
+#include "sql_update.h"
+#include "sql_delete.h"
/* this is to get the bison compilation windows warnings out */
#ifdef _MSC_VER
@@ -1682,7 +1684,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
opt_mi_check_type opt_to mi_check_types
table_to_table_list table_to_table opt_table_list opt_as
handler_rkey_function handler_read_or_scan
- single_multi table_wild_list table_wild_one opt_wild
+ single_multi opt_wild
opt_and
select_var_list select_var_list_init help
opt_extended_describe shutdown
@@ -13242,9 +13244,14 @@ update:
opt_low_priority opt_ignore update_table_list
SET update_list
{
+ bool is_multiupdate= false;
+ LEX *lex= Lex;
SELECT_LEX *slex= Lex->first_select_lex();
if (slex->table_list.elements > 1)
+ {
Lex->sql_command= SQLCOM_UPDATE_MULTI;
+ is_multiupdate= true;
+ }
else if (slex->get_table_list()->derived)
{
/* it is single table update and it is update of derived table */
@@ -13252,10 +13259,13 @@ update:
slex->get_table_list()->alias.str, "UPDATE");
MYSQL_YYABORT;
}
+ if (!(lex->m_sql_cmd=
+ new (thd->mem_root) Sql_cmd_update(is_multiupdate)))
+ MYSQL_YYABORT;
/*
In case of multi-update setting write lock for all tables may
- be too pessimistic. We will decrease lock level if possible in
- mysql_multi_update().
+ be too pessimistic. We will decrease lock level if possible
+ later while processing the statement.
*/
slex->set_lock_for_tables($3, slex->table_list.elements == 1, false);
}
@@ -13312,12 +13322,11 @@ delete:
DELETE_SYM
{
LEX *lex= Lex;
- lex->sql_command= SQLCOM_DELETE;
YYPS->m_lock_type= TL_WRITE_DEFAULT;
YYPS->m_mdl_type= MDL_SHARED_WRITE;
if (Lex->main_select_push())
MYSQL_YYABORT;
- mysql_init_select(lex);
+ mysql_init_delete(lex);
lex->ignore= 0;
lex->first_select_lex()->order_list.empty();
}
@@ -13343,8 +13352,13 @@ delete_part2:
opt_delete_options single_multi {}
| HISTORY_SYM delete_single_table opt_delete_system_time
{
- Lex->last_table()->vers_conditions= Lex->vers_conditions;
- Lex->pop_select(); //main select
+ LEX *lex= Lex;
+ lex->last_table()->vers_conditions= lex->vers_conditions;
+ lex->pop_select(); //main select
+ lex->sql_command= SQLCOM_DELETE;
+ if (!(lex->m_sql_cmd=
+ new (thd->mem_root) Sql_cmd_delete(false)))
+ MYSQL_YYABORT;
}
;
@@ -13378,12 +13392,22 @@ single_multi:
delete_limit_clause
opt_returning
{
+ LEX *lex= Lex;
if ($3)
Select->order_list= *($3);
- Lex->pop_select(); //main select
+ lex->pop_select(); //main select
+ lex->sql_command= SQLCOM_DELETE;
+ if (!(lex->m_sql_cmd=
+ new (thd->mem_root) Sql_cmd_delete(false)))
+ MYSQL_YYABORT;
}
- | table_wild_list
+ | table_alias_ref_list
{
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_DELETE_MULTI;
+ if (!(lex->m_sql_cmd=
+ new (thd->mem_root) Sql_cmd_delete(true)))
+ MYSQL_YYABORT;
mysql_init_multi_delete(Lex);
YYPS->m_lock_type= TL_READ_DEFAULT;
YYPS->m_mdl_type= MDL_SHARED_READ;
@@ -13395,6 +13419,11 @@ single_multi:
} stmt_end {}
| FROM table_alias_ref_list
{
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_DELETE_MULTI;
+ if (!(lex->m_sql_cmd=
+ new (thd->mem_root) Sql_cmd_delete(true)))
+ MYSQL_YYABORT;
mysql_init_multi_delete(Lex);
YYPS->m_lock_type= TL_READ_DEFAULT;
YYPS->m_mdl_type= MDL_SHARED_READ;
@@ -13430,44 +13459,6 @@ opt_returning:
}
;
-table_wild_list:
- table_wild_one
- | table_wild_list ',' table_wild_one
- ;
-
-table_wild_one:
- ident opt_wild
- {
- Table_ident *ti= new (thd->mem_root) Table_ident(&$1);
- if (unlikely(ti == NULL))
- MYSQL_YYABORT;
- if (unlikely(!Select->
- add_table_to_list(thd,
- ti,
- NULL,
- (TL_OPTION_UPDATING |
- TL_OPTION_ALIAS),
- YYPS->m_lock_type,
- YYPS->m_mdl_type)))
- MYSQL_YYABORT;
- }
- | ident '.' ident opt_wild
- {
- Table_ident *ti= new (thd->mem_root) Table_ident(thd, &$1, &$3, 0);
- if (unlikely(ti == NULL))
- MYSQL_YYABORT;
- if (unlikely(!Select->
- add_table_to_list(thd,
- ti,
- NULL,
- (TL_OPTION_UPDATING |
- TL_OPTION_ALIAS),
- YYPS->m_lock_type,
- YYPS->m_mdl_type)))
- MYSQL_YYABORT;
- }
- ;
-
opt_wild:
/* empty */ {}
| '.' '*' {}
diff --git a/sql/table.h b/sql/table.h
index 30517f8..5f8d299 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -2338,6 +2338,7 @@ struct TABLE_LIST
*/
select_unit *derived_result;
/* Stub used for materialized derived tables. */
+ bool delete_while_scanning;
table_map map; /* ID bit of table (1,2,4,8,16...) */
table_map get_map()
{
diff --git a/storage/spider/mysql-test/spider/r/error_row_number.result b/storage/spider/mysql-test/spider/r/error_row_number.result
index cc2b548..ad095fe 100644
--- a/storage/spider/mysql-test/spider/r/error_row_number.result
+++ b/storage/spider/mysql-test/spider/r/error_row_number.result
@@ -29,7 +29,7 @@ ERROR 23000: Duplicate entry '13' for key 'PRIMARY'
get diagnostics condition 1 @n = row_number;
select @n;
@n
-0
+1
drop table spd;
connection child2_1;
drop database auto_test_remote;
1
0