Skip to content

Commit d11be23

Browse files
committed
MDEV-17096 Pushdown of simple derived tables to storage engines
Resolved the problem of forming a proper query string for FEDERATEDX. Added test cases. Cleanup of extra spaces.
1 parent 3f90400 commit d11be23

14 files changed

+233
-67
lines changed

mysql-test/suite/federated/federatedx_create_handlers.result

Lines changed: 113 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Warnings:
1010
Note 1051 Unknown table 'federated.t1'
1111
CREATE TABLE federated.t1 (
1212
id int(20) NOT NULL,
13-
name varchar(16) NOT NULL default ''
13+
name varchar(16) NOT NULL default ''
1414
)
1515
DEFAULT CHARSET=latin1;
1616
INSERT INTO federated.t1 VALUES
@@ -19,7 +19,7 @@ DROP TABLE IF EXISTS federated.t2;
1919
Warnings:
2020
Note 1051 Unknown table 'federated.t2'
2121
CREATE TABLE federated.t2 (
22-
name varchar(16) NOT NULL default ''
22+
name varchar(16) NOT NULL default ''
2323
)
2424
DEFAULT CHARSET=latin1;
2525
INSERT INTO federated.t2 VALUES
@@ -30,15 +30,15 @@ Warnings:
3030
Note 1051 Unknown table 'federated.t1'
3131
CREATE TABLE federated.t1 (
3232
id int(20) NOT NULL,
33-
name varchar(16) NOT NULL default ''
33+
name varchar(16) NOT NULL default ''
3434
)
3535
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
3636
CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1';
3737
DROP TABLE IF EXISTS federated.t2;
3838
Warnings:
3939
Note 1051 Unknown table 'federated.t2'
4040
CREATE TABLE federated.t2 (
41-
name varchar(16) NOT NULL default ''
41+
name varchar(16) NOT NULL default ''
4242
)
4343
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
4444
CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t2';
@@ -123,7 +123,7 @@ ANALYZE
123123
}
124124
}
125125
CREATE TABLE federated.t3 (
126-
name varchar(16) NOT NULL default ''
126+
name varchar(16) NOT NULL default ''
127127
)
128128
DEFAULT CHARSET=latin1;
129129
INSERT INTO federated.t3 VALUES
@@ -190,7 +190,114 @@ id select_type table type possible_keys key key_len ref rows r_rows filtered r_f
190190
1 PRIMARY t3 ALL NULL NULL NULL NULL 7 7.00 100.00 100.00
191191
1 PRIMARY <derived2> ref key0 key0 18 federated.t3.name 2 0.00 100.00 100.00
192192
2 PUSHED DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
193-
DROP TABLE federated.t1, federated.t2;
193+
SELECT *
194+
FROM federated.t3, (SELECT t1.name FROM federated.t1
195+
WHERE id IN (SELECT count(*)
196+
FROM federated.t2 GROUP BY name)) t
197+
WHERE federated.t3.name=t.name;
198+
name name
199+
xxx xxx
200+
EXPLAIN
201+
SELECT *
202+
FROM federated.t3, (SELECT t1.name FROM federated.t1
203+
WHERE id IN (SELECT count(*)
204+
FROM federated.t2 GROUP BY name)) t
205+
WHERE federated.t3.name=t.name;
206+
id select_type table type possible_keys key key_len ref rows Extra
207+
1 PRIMARY t3 ALL NULL NULL NULL NULL 7
208+
1 PRIMARY <derived2> ref key0 key0 18 federated.t3.name 2
209+
2 PUSHED DERIVED NULL NULL NULL NULL NULL NULL NULL NULL
210+
3 MATERIALIZED t2 ALL NULL NULL NULL NULL 7 Using temporary
211+
ANALYZE FORMAT=JSON
212+
SELECT *
213+
FROM federated.t3, (SELECT t1.name FROM federated.t1
214+
WHERE id IN (SELECT count(*)
215+
FROM federated.t2 GROUP BY name)) t
216+
WHERE federated.t3.name=t.name;
217+
ANALYZE
218+
{
219+
"query_block": {
220+
"select_id": 1,
221+
"r_loops": 1,
222+
"r_total_time_ms": "REPLACED",
223+
"table": {
224+
"table_name": "t3",
225+
"access_type": "ALL",
226+
"r_loops": 1,
227+
"rows": 7,
228+
"r_rows": 7,
229+
"r_total_time_ms": "REPLACED",
230+
"filtered": 100,
231+
"r_filtered": 100
232+
},
233+
"table": {
234+
"table_name": "<derived2>",
235+
"access_type": "ref",
236+
"possible_keys": ["key0"],
237+
"key": "key0",
238+
"key_length": "18",
239+
"used_key_parts": ["name"],
240+
"ref": ["federated.t3.name"],
241+
"r_loops": 7,
242+
"rows": 2,
243+
"r_rows": 0,
244+
"r_total_time_ms": "REPLACED",
245+
"filtered": 100,
246+
"r_filtered": 100,
247+
"materialized": {
248+
"query_block": {
249+
"select_id": 2,
250+
"table": {
251+
"message": "Pushed derived"
252+
},
253+
"subqueries": [
254+
{
255+
"query_block": {
256+
"select_id": 3,
257+
"temporary_table": {
258+
"table": {
259+
"table_name": "t2",
260+
"access_type": "ALL",
261+
"r_loops": 0,
262+
"rows": 7,
263+
"r_rows": null,
264+
"filtered": 100,
265+
"r_filtered": null
266+
}
267+
}
268+
}
269+
}
270+
]
271+
}
272+
}
273+
}
274+
}
275+
}
276+
SELECT t.id, federated.t3.name
277+
FROM federated.t3,
278+
( SELECT * FROM federated.t1 WHERE id < 3
279+
UNION
280+
SELECT * FROM federated.t1 WHERE id >= 5) t
281+
WHERE federated.t3.name=t.name;
282+
id name
283+
5 yyy
284+
7 yyy
285+
5 yyy
286+
7 yyy
287+
5 yyy
288+
7 yyy
289+
EXPLAIN
290+
SELECT t.id, federated.t3.name
291+
FROM federated.t3,
292+
( SELECT * FROM federated.t1 WHERE id < 3
293+
UNION
294+
SELECT * FROM federated.t1 WHERE id >= 5) t
295+
WHERE federated.t3.name=t.name;
296+
id select_type table type possible_keys key key_len ref rows Extra
297+
1 PRIMARY t3 ALL NULL NULL NULL NULL 7
298+
1 PRIMARY <derived2> ref key0 key0 18 federated.t3.name 2
299+
2 PUSHED DERIVED NULL NULL NULL NULL NULL NULL NULL NULL
300+
DROP TABLE federated.t1, federated.t2, federated.t3;
194301
connection slave;
195302
DROP TABLE federated.t1, federated.t2;
196303
connection default;

mysql-test/suite/federated/federatedx_create_handlers.test

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ DROP TABLE IF EXISTS federated.t1;
77

88
CREATE TABLE federated.t1 (
99
id int(20) NOT NULL,
10-
name varchar(16) NOT NULL default ''
10+
name varchar(16) NOT NULL default ''
1111
)
1212
DEFAULT CHARSET=latin1;
1313

@@ -17,7 +17,7 @@ INSERT INTO federated.t1 VALUES
1717
DROP TABLE IF EXISTS federated.t2;
1818

1919
CREATE TABLE federated.t2 (
20-
name varchar(16) NOT NULL default ''
20+
name varchar(16) NOT NULL default ''
2121
)
2222
DEFAULT CHARSET=latin1;
2323

@@ -33,7 +33,7 @@ DROP TABLE IF EXISTS federated.t1;
3333
eval
3434
CREATE TABLE federated.t1 (
3535
id int(20) NOT NULL,
36-
name varchar(16) NOT NULL default ''
36+
name varchar(16) NOT NULL default ''
3737
)
3838
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
3939
CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1';
@@ -43,7 +43,7 @@ DROP TABLE IF EXISTS federated.t2;
4343
--replace_result $SLAVE_MYPORT SLAVE_PORT
4444
eval
4545
CREATE TABLE federated.t2 (
46-
name varchar(16) NOT NULL default ''
46+
name varchar(16) NOT NULL default ''
4747
)
4848
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
4949
CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t2';
@@ -76,11 +76,12 @@ SELECT id FROM federated.t1 WHERE id < 5;
7676
ANALYZE
7777
SELECT id FROM federated.t1 WHERE id < 5;
7878

79+
--source include/analyze-format.inc
7980
ANALYZE FORMAT=JSON
8081
SELECT id FROM federated.t1 WHERE id < 5;
8182

8283
CREATE TABLE federated.t3 (
83-
name varchar(16) NOT NULL default ''
84+
name varchar(16) NOT NULL default ''
8485
)
8586
DEFAULT CHARSET=latin1;
8687

@@ -89,26 +90,63 @@ INSERT INTO federated.t3 VALUES
8990

9091
SELECT *
9192
FROM federated.t3, (SELECT * FROM federated.t1 WHERE id > 3) t
92-
WHERE federated.t3.name=t.name;
93+
WHERE federated.t3.name=t.name;
9394

9495
EXPLAIN
9596
SELECT *
9697
FROM federated.t3, (SELECT * FROM federated.t1 WHERE id > 3) t
97-
WHERE federated.t3.name=t.name;
98+
WHERE federated.t3.name=t.name;
9899

99100
EXPLAIN FORMAT=JSON
100101
SELECT *
101102
FROM federated.t3, (SELECT * FROM federated.t1 WHERE id > 3) t
102-
WHERE federated.t3.name=t.name;
103+
WHERE federated.t3.name=t.name;
103104

104105
ANALYZE
105106
SELECT *
106107
FROM federated.t3, (SELECT * FROM federated.t1 WHERE id > 3) t
107-
WHERE federated.t3.name=t.name;
108+
WHERE federated.t3.name=t.name;
108109

109-
DROP TABLE federated.t1, federated.t2;
110+
SELECT *
111+
FROM federated.t3, (SELECT t1.name FROM federated.t1
112+
WHERE id IN (SELECT count(*)
113+
FROM federated.t2 GROUP BY name)) t
114+
WHERE federated.t3.name=t.name;
110115

111-
connection slave;
116+
EXPLAIN
117+
SELECT *
118+
FROM federated.t3, (SELECT t1.name FROM federated.t1
119+
WHERE id IN (SELECT count(*)
120+
FROM federated.t2 GROUP BY name)) t
121+
WHERE federated.t3.name=t.name;
122+
123+
--source include/analyze-format.inc
124+
ANALYZE FORMAT=JSON
125+
SELECT *
126+
FROM federated.t3, (SELECT t1.name FROM federated.t1
127+
WHERE id IN (SELECT count(*)
128+
FROM federated.t2 GROUP BY name)) t
129+
WHERE federated.t3.name=t.name;
130+
131+
SELECT t.id, federated.t3.name
132+
FROM federated.t3,
133+
( SELECT * FROM federated.t1 WHERE id < 3
134+
UNION
135+
SELECT * FROM federated.t1 WHERE id >= 5) t
136+
WHERE federated.t3.name=t.name;
137+
138+
EXPLAIN
139+
SELECT t.id, federated.t3.name
140+
FROM federated.t3,
141+
( SELECT * FROM federated.t1 WHERE id < 3
142+
UNION
143+
SELECT * FROM federated.t1 WHERE id >= 5) t
144+
WHERE federated.t3.name=t.name;
145+
146+
147+
DROP TABLE federated.t1, federated.t2, federated.t3;
148+
149+
connection slave;
112150
DROP TABLE federated.t1, federated.t2;
113151

114152
connection default;

sql/derived_handler.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ void derived_handler::set_derived(TABLE_LIST *tbl)
1616

1717
Pushdown_derived::Pushdown_derived(TABLE_LIST *tbl, derived_handler *h)
1818
: derived(tbl), handler(h)
19-
{
19+
{
2020
is_analyze= handler->thd->lex->analyze_stmt;
2121
}
2222

@@ -42,15 +42,15 @@ int Pushdown_derived::execute()
4242
handler->end_scan();
4343
DBUG_RETURN(0);
4444
}
45-
45+
4646
while (!(err= handler->next_row()))
4747
{
4848
if (unlikely(thd->check_killed()))
4949
{
5050
handler->end_scan();
5151
DBUG_RETURN(-1);
5252
}
53-
53+
5454
if ((err= table->file->ha_write_tmp_row(table->record[0])))
5555
{
5656
bool is_duplicate;
@@ -81,4 +81,4 @@ int Pushdown_derived::execute()
8181
handler->print_error(err, MYF(0));
8282
DBUG_RETURN(-1); // Error not sent to client
8383
}
84-
84+

sql/item_cmpfunc.cc

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1215,8 +1215,13 @@ bool Item_in_optimizer::eval_not_null_tables(void *opt_arg)
12151215

12161216
void Item_in_optimizer::print(String *str, enum_query_type query_type)
12171217
{
1218-
restore_first_argument();
1219-
Item_func::print(str, query_type);
1218+
if (query_type & QT_PARSABLE)
1219+
args[1]->print(str, query_type);
1220+
else
1221+
{
1222+
restore_first_argument();
1223+
Item_func::print(str, query_type);
1224+
}
12201225
}
12211226

12221227

sql/item_subselect.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3272,7 +3272,8 @@ Item_in_subselect::select_in_like_transformer(JOIN *join)
32723272

32733273
void Item_in_subselect::print(String *str, enum_query_type query_type)
32743274
{
3275-
if (test_strategy(SUBS_IN_TO_EXISTS))
3275+
if (test_strategy(SUBS_IN_TO_EXISTS) &&
3276+
!(query_type & QT_PARSABLE))
32763277
str->append(STRING_WITH_LEN("<exists>"));
32773278
else
32783279
{
@@ -3499,7 +3500,8 @@ Item_allany_subselect::select_transformer(JOIN *join)
34993500

35003501
void Item_allany_subselect::print(String *str, enum_query_type query_type)
35013502
{
3502-
if (test_strategy(SUBS_IN_TO_EXISTS))
3503+
if (test_strategy(SUBS_IN_TO_EXISTS) &&
3504+
!(query_type & QT_PARSABLE))
35033505
str->append(STRING_WITH_LEN("<exists>"));
35043506
else
35053507
{

sql/mysqld.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -745,6 +745,8 @@ enum enum_query_type
745745
/// SHOW CREATE {VIEW|PROCEDURE|FUNCTION} and other cases where the
746746
/// original representation is required, should set this flag.
747747
QT_ITEM_ORIGINAL_FUNC_NULLIF= (1 << 7),
748+
/// good for parsing
749+
QT_PARSABLE= (1 << 8),
748750

749751
/// This value means focus on readability, not on ability to parse back, etc.
750752
QT_EXPLAIN= QT_TO_SYSTEM_CHARSET |

0 commit comments

Comments
 (0)