Skip to content

Commit 989092c

Browse files
committed
improve assign_rel_parenthood_status() and some other functions, implement Query tracking via hashtable, HACK for pg_stat_statements
1 parent d0fb919 commit 989092c

File tree

5 files changed

+387
-177
lines changed

5 files changed

+387
-177
lines changed

expected/pathman_basic.out

Lines changed: 198 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -191,27 +191,206 @@ SELECT COUNT(*) FROM ONLY test.num_range_rel;
191191
(1 row)
192192

193193
/* test special case: ONLY statement with not-ONLY for partitioned table */
194-
SELECT * FROM ONLY test.range_rel UNION SELECT * FROM test.range_rel;
195-
ERROR: It is prohibited to apply ONLY modifier to partitioned tables which have already been mentioned without ONLY
196-
SELECT * FROM test.range_rel UNION SELECT * FROM ONLY test.range_rel;
197-
ERROR: It is prohibited to apply ONLY modifier to partitioned tables which have already been mentioned without ONLY
198-
SELECT * FROM test.range_rel UNION SELECT * FROM test.range_rel UNION SELECT * FROM ONLY test.range_rel;
199-
ERROR: It is prohibited to apply ONLY modifier to partitioned tables which have already been mentioned without ONLY
200-
SELECT * FROM ONLY test.range_rel UNION SELECT * FROM test.range_rel UNION SELECT * FROM test.range_rel;
201-
ERROR: It is prohibited to apply ONLY modifier to partitioned tables which have already been mentioned without ONLY
202-
/* FIXME: result of next command execution is not right just yet */
203-
WITH q1 AS (SELECT * FROM test.range_rel), q2 AS (SELECT * FROM ONLY test.range_rel) SELECT * FROM q1 JOIN q2 USING(id);
194+
CREATE TABLE test.from_only_test(val INT NOT NULL);
195+
INSERT INTO test.from_only_test SELECT generate_series(1, 20);
196+
SELECT pathman.create_range_partitions('test.from_only_test', 'val', 1, 2);
197+
NOTICE: sequence "from_only_test_seq" does not exist, skipping
198+
create_range_partitions
199+
-------------------------
200+
10
201+
(1 row)
202+
203+
/* should be OK */
204+
EXPLAIN (COSTS OFF)
205+
SELECT * FROM ONLY test.from_only_test
206+
UNION SELECT * FROM test.from_only_test;
207+
QUERY PLAN
208+
-------------------------------------------------
209+
HashAggregate
210+
Group Key: from_only_test.val
211+
-> Append
212+
-> Seq Scan on from_only_test
213+
-> Append
214+
-> Seq Scan on from_only_test_1
215+
-> Seq Scan on from_only_test_2
216+
-> Seq Scan on from_only_test_3
217+
-> Seq Scan on from_only_test_4
218+
-> Seq Scan on from_only_test_5
219+
-> Seq Scan on from_only_test_6
220+
-> Seq Scan on from_only_test_7
221+
-> Seq Scan on from_only_test_8
222+
-> Seq Scan on from_only_test_9
223+
-> Seq Scan on from_only_test_10
224+
(15 rows)
225+
226+
/* should be OK */
227+
EXPLAIN (COSTS OFF)
228+
SELECT * FROM test.from_only_test
229+
UNION SELECT * FROM ONLY test.from_only_test;
230+
QUERY PLAN
231+
-------------------------------------------------
232+
HashAggregate
233+
Group Key: from_only_test_1.val
234+
-> Append
235+
-> Append
236+
-> Seq Scan on from_only_test_1
237+
-> Seq Scan on from_only_test_2
238+
-> Seq Scan on from_only_test_3
239+
-> Seq Scan on from_only_test_4
240+
-> Seq Scan on from_only_test_5
241+
-> Seq Scan on from_only_test_6
242+
-> Seq Scan on from_only_test_7
243+
-> Seq Scan on from_only_test_8
244+
-> Seq Scan on from_only_test_9
245+
-> Seq Scan on from_only_test_10
246+
-> Seq Scan on from_only_test
247+
(15 rows)
248+
249+
/* should be OK */
250+
EXPLAIN (COSTS OFF)
251+
SELECT * FROM test.from_only_test
252+
UNION SELECT * FROM test.from_only_test
253+
UNION SELECT * FROM ONLY test.from_only_test;
254+
QUERY PLAN
255+
---------------------------------------------------------------------
256+
HashAggregate
257+
Group Key: from_only_test_1.val
258+
-> Append
259+
-> Append
260+
-> Seq Scan on from_only_test_1
261+
-> Seq Scan on from_only_test_2
262+
-> Seq Scan on from_only_test_3
263+
-> Seq Scan on from_only_test_4
264+
-> Seq Scan on from_only_test_5
265+
-> Seq Scan on from_only_test_6
266+
-> Seq Scan on from_only_test_7
267+
-> Seq Scan on from_only_test_8
268+
-> Seq Scan on from_only_test_9
269+
-> Seq Scan on from_only_test_10
270+
-> Append
271+
-> Seq Scan on from_only_test_1 from_only_test_1_1
272+
-> Seq Scan on from_only_test_2 from_only_test_2_1
273+
-> Seq Scan on from_only_test_3 from_only_test_3_1
274+
-> Seq Scan on from_only_test_4 from_only_test_4_1
275+
-> Seq Scan on from_only_test_5 from_only_test_5_1
276+
-> Seq Scan on from_only_test_6 from_only_test_6_1
277+
-> Seq Scan on from_only_test_7 from_only_test_7_1
278+
-> Seq Scan on from_only_test_8 from_only_test_8_1
279+
-> Seq Scan on from_only_test_9 from_only_test_9_1
280+
-> Seq Scan on from_only_test_10 from_only_test_10_1
281+
-> Seq Scan on from_only_test
282+
(26 rows)
283+
284+
/* should be OK */
285+
EXPLAIN (COSTS OFF)
286+
SELECT * FROM ONLY test.from_only_test
287+
UNION SELECT * FROM test.from_only_test
288+
UNION SELECT * FROM test.from_only_test;
289+
QUERY PLAN
290+
---------------------------------------------------------------------
291+
HashAggregate
292+
Group Key: from_only_test.val
293+
-> Append
294+
-> Seq Scan on from_only_test
295+
-> Append
296+
-> Seq Scan on from_only_test_1
297+
-> Seq Scan on from_only_test_2
298+
-> Seq Scan on from_only_test_3
299+
-> Seq Scan on from_only_test_4
300+
-> Seq Scan on from_only_test_5
301+
-> Seq Scan on from_only_test_6
302+
-> Seq Scan on from_only_test_7
303+
-> Seq Scan on from_only_test_8
304+
-> Seq Scan on from_only_test_9
305+
-> Seq Scan on from_only_test_10
306+
-> Append
307+
-> Seq Scan on from_only_test_1 from_only_test_1_1
308+
-> Seq Scan on from_only_test_2 from_only_test_2_1
309+
-> Seq Scan on from_only_test_3 from_only_test_3_1
310+
-> Seq Scan on from_only_test_4 from_only_test_4_1
311+
-> Seq Scan on from_only_test_5 from_only_test_5_1
312+
-> Seq Scan on from_only_test_6 from_only_test_6_1
313+
-> Seq Scan on from_only_test_7 from_only_test_7_1
314+
-> Seq Scan on from_only_test_8 from_only_test_8_1
315+
-> Seq Scan on from_only_test_9 from_only_test_9_1
316+
-> Seq Scan on from_only_test_10 from_only_test_10_1
317+
(26 rows)
318+
319+
/* not ok, ONLY|non-ONLY in one query */
320+
EXPLAIN (COSTS OFF)
321+
SELECT * FROM test.from_only_test a JOIN ONLY test.from_only_test b USING(val);
204322
ERROR: It is prohibited to apply ONLY modifier to partitioned tables which have already been mentioned without ONLY
205-
WITH q1 AS (SELECT * FROM ONLY test.range_rel) SELECT * FROM test.range_rel JOIN q1 USING(id);
206-
id | dt | txt | dt | txt
207-
----+----+-----+----+-----
208-
(0 rows)
323+
EXPLAIN (COSTS OFF)
324+
WITH q1 AS (SELECT * FROM test.from_only_test),
325+
q2 AS (SELECT * FROM ONLY test.from_only_test)
326+
SELECT * FROM q1 JOIN q2 USING(val);
327+
QUERY PLAN
328+
---------------------------------------------
329+
Hash Join
330+
Hash Cond: (q1.val = q2.val)
331+
CTE q1
332+
-> Append
333+
-> Seq Scan on from_only_test_1
334+
-> Seq Scan on from_only_test_2
335+
-> Seq Scan on from_only_test_3
336+
-> Seq Scan on from_only_test_4
337+
-> Seq Scan on from_only_test_5
338+
-> Seq Scan on from_only_test_6
339+
-> Seq Scan on from_only_test_7
340+
-> Seq Scan on from_only_test_8
341+
-> Seq Scan on from_only_test_9
342+
-> Seq Scan on from_only_test_10
343+
CTE q2
344+
-> Seq Scan on from_only_test
345+
-> CTE Scan on q1
346+
-> Hash
347+
-> CTE Scan on q2
348+
(19 rows)
209349

210-
SELECT * FROM test.range_rel WHERE id = (SELECT id FROM ONLY test.range_rel LIMIT 1);
211-
id | dt | txt
212-
----+----+-----
213-
(0 rows)
350+
EXPLAIN (COSTS OFF)
351+
WITH q1 AS (SELECT * FROM ONLY test.from_only_test)
352+
SELECT * FROM test.from_only_test JOIN q1 USING(val);
353+
QUERY PLAN
354+
----------------------------------------------
355+
Hash Join
356+
Hash Cond: (from_only_test_1.val = q1.val)
357+
CTE q1
358+
-> Seq Scan on from_only_test
359+
-> Append
360+
-> Seq Scan on from_only_test_1
361+
-> Seq Scan on from_only_test_2
362+
-> Seq Scan on from_only_test_3
363+
-> Seq Scan on from_only_test_4
364+
-> Seq Scan on from_only_test_5
365+
-> Seq Scan on from_only_test_6
366+
-> Seq Scan on from_only_test_7
367+
-> Seq Scan on from_only_test_8
368+
-> Seq Scan on from_only_test_9
369+
-> Seq Scan on from_only_test_10
370+
-> Hash
371+
-> CTE Scan on q1
372+
(17 rows)
214373

374+
EXPLAIN (COSTS OFF)
375+
SELECT * FROM test.range_rel WHERE id = (SELECT id FROM ONLY test.range_rel LIMIT 1);
376+
QUERY PLAN
377+
--------------------------------------------------------
378+
Append
379+
InitPlan 1 (returns $0)
380+
-> Limit
381+
-> Seq Scan on range_rel
382+
-> Index Scan using range_rel_1_pkey on range_rel_1
383+
Index Cond: (id = $0)
384+
-> Index Scan using range_rel_2_pkey on range_rel_2
385+
Index Cond: (id = $0)
386+
-> Index Scan using range_rel_3_pkey on range_rel_3
387+
Index Cond: (id = $0)
388+
-> Index Scan using range_rel_4_pkey on range_rel_4
389+
Index Cond: (id = $0)
390+
(12 rows)
391+
392+
DROP TABLE test.from_only_test CASCADE;
393+
NOTICE: drop cascades to 10 other objects
215394
SET pg_pathman.enable_runtimeappend = OFF;
216395
SET pg_pathman.enable_runtimemergeappend = OFF;
217396
VACUUM;
@@ -1449,7 +1628,7 @@ EXPLAIN (COSTS OFF) SELECT * FROM messages;
14491628
(3 rows)
14501629

14511630
DROP SCHEMA test CASCADE;
1452-
NOTICE: drop cascades to 13 other objects
1631+
NOTICE: drop cascades to 14 other objects
14531632
DROP EXTENSION pg_pathman CASCADE;
14541633
NOTICE: drop cascades to 3 other objects
14551634
DROP SCHEMA pathman CASCADE;

sql/pathman_basic.sql

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,15 +58,51 @@ SELECT COUNT(*) FROM test.num_range_rel;
5858
SELECT COUNT(*) FROM ONLY test.num_range_rel;
5959

6060
/* test special case: ONLY statement with not-ONLY for partitioned table */
61-
SELECT * FROM ONLY test.range_rel UNION SELECT * FROM test.range_rel;
62-
SELECT * FROM test.range_rel UNION SELECT * FROM ONLY test.range_rel;
63-
SELECT * FROM test.range_rel UNION SELECT * FROM test.range_rel UNION SELECT * FROM ONLY test.range_rel;
64-
SELECT * FROM ONLY test.range_rel UNION SELECT * FROM test.range_rel UNION SELECT * FROM test.range_rel;
65-
/* FIXME: result of next command execution is not right just yet */
66-
WITH q1 AS (SELECT * FROM test.range_rel), q2 AS (SELECT * FROM ONLY test.range_rel) SELECT * FROM q1 JOIN q2 USING(id);
67-
WITH q1 AS (SELECT * FROM ONLY test.range_rel) SELECT * FROM test.range_rel JOIN q1 USING(id);
61+
CREATE TABLE test.from_only_test(val INT NOT NULL);
62+
INSERT INTO test.from_only_test SELECT generate_series(1, 20);
63+
SELECT pathman.create_range_partitions('test.from_only_test', 'val', 1, 2);
64+
65+
/* should be OK */
66+
EXPLAIN (COSTS OFF)
67+
SELECT * FROM ONLY test.from_only_test
68+
UNION SELECT * FROM test.from_only_test;
69+
70+
/* should be OK */
71+
EXPLAIN (COSTS OFF)
72+
SELECT * FROM test.from_only_test
73+
UNION SELECT * FROM ONLY test.from_only_test;
74+
75+
/* should be OK */
76+
EXPLAIN (COSTS OFF)
77+
SELECT * FROM test.from_only_test
78+
UNION SELECT * FROM test.from_only_test
79+
UNION SELECT * FROM ONLY test.from_only_test;
80+
81+
/* should be OK */
82+
EXPLAIN (COSTS OFF)
83+
SELECT * FROM ONLY test.from_only_test
84+
UNION SELECT * FROM test.from_only_test
85+
UNION SELECT * FROM test.from_only_test;
86+
87+
/* not ok, ONLY|non-ONLY in one query */
88+
EXPLAIN (COSTS OFF)
89+
SELECT * FROM test.from_only_test a JOIN ONLY test.from_only_test b USING(val);
90+
91+
EXPLAIN (COSTS OFF)
92+
WITH q1 AS (SELECT * FROM test.from_only_test),
93+
q2 AS (SELECT * FROM ONLY test.from_only_test)
94+
SELECT * FROM q1 JOIN q2 USING(val);
95+
96+
EXPLAIN (COSTS OFF)
97+
WITH q1 AS (SELECT * FROM ONLY test.from_only_test)
98+
SELECT * FROM test.from_only_test JOIN q1 USING(val);
99+
100+
EXPLAIN (COSTS OFF)
68101
SELECT * FROM test.range_rel WHERE id = (SELECT id FROM ONLY test.range_rel LIMIT 1);
69102

103+
DROP TABLE test.from_only_test CASCADE;
104+
105+
70106
SET pg_pathman.enable_runtimeappend = OFF;
71107
SET pg_pathman.enable_runtimemergeappend = OFF;
72108

src/hooks.c

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -199,16 +199,19 @@ pathman_rel_pathlist_hook(PlannerInfo *root,
199199
if (set_rel_pathlist_hook_next != NULL)
200200
set_rel_pathlist_hook_next(root, rel, rti, rte);
201201

202+
/* Make sure that pg_pathman is ready */
202203
if (!IsPathmanReady())
203-
return; /* pg_pathman is not ready */
204+
return;
204205

205-
/* This works only for SELECT queries (at least for now) */
206-
if (root->parse->commandType != CMD_SELECT)
206+
/* This works only for SELECTs on simple relations */
207+
if (root->parse->commandType != CMD_SELECT ||
208+
rte->rtekind != RTE_RELATION ||
209+
rte->relkind != RELKIND_RELATION)
207210
return;
208211

209212
/* Skip if this table is not allowed to act as parent (see FROM ONLY) */
210-
if (PARENTHOOD_DISALLOWED == get_parenthood_status(root->query_level,
211-
rte->relid))
213+
if (PARENTHOOD_DISALLOWED == get_rel_parenthood_status(root->parse->queryId,
214+
rte->relid))
212215
return;
213216

214217
/* Proceed iff relation 'rel' is partitioned */
@@ -443,10 +446,16 @@ pathman_planner_hook(Query *parse, int cursorOptions, ParamListInfo boundParams)
443446
} while (0)
444447

445448
PlannedStmt *result;
449+
uint32 query_id = parse->queryId;
446450

447-
/* Modify query tree if needed */
448451
if (IsPathmanReady())
452+
{
453+
/* Increment parenthood_statuses refcount */
454+
incr_refcount_parenthood_statuses();
455+
456+
/* Modify query tree if needed */
449457
pathman_transform_query(parse);
458+
}
450459

451460
/* Invoke original hook if needed */
452461
if (planner_hook_next)
@@ -462,8 +471,11 @@ pathman_planner_hook(Query *parse, int cursorOptions, ParamListInfo boundParams)
462471
/* Add PartitionFilter node for INSERT queries */
463472
ExecuteForPlanTree(result, add_partition_filters);
464473

465-
/* Free all parenthood lists (see pathman_transform_query()) */
466-
reset_parenthood_statuses();
474+
/* Decrement parenthood_statuses refcount */
475+
decr_refcount_parenthood_statuses();
476+
477+
/* HACK: restore queryId set by pg_stat_statements */
478+
result->queryId = query_id;
467479
}
468480

469481
return result;

0 commit comments

Comments
 (0)