Fix ordered append with space partitioning

Ordered append for space partitioned hypertable would lead to an
error when the ORDER BY clause was not a column reference on PG 9.6
and PG 10. This patch fixes ordered append for space partitioned
hypertable and allows arbitary expressions to be used in the
ORDER BY clause.
This commit is contained in:
Sven Klemm 2019-10-04 15:19:27 +02:00 committed by Sven Klemm
parent 3fa3822d08
commit ddb8f46b5f
5 changed files with 198 additions and 13 deletions

View File

@ -53,6 +53,7 @@ adjust_childscan(PlannerInfo *root, Plan *plan, Path *path, List *pathkeys, List
Oid *sortOperators;
Oid *collations;
bool *nullsFirst;
AttrNumber *childColIdx;
/* push down targetlist to children */
plan->targetlist = (List *) adjust_appendrel_attrs_compat(root, (Node *) tlist, appinfo);
@ -64,7 +65,7 @@ adjust_childscan(PlannerInfo *root, Plan *plan, Path *path, List *pathkeys, List
sortColIdx,
true,
&childSortCols,
&sortColIdx,
&childColIdx,
&sortOperators,
&collations,
&nullsFirst);
@ -73,7 +74,7 @@ adjust_childscan(PlannerInfo *root, Plan *plan, Path *path, List *pathkeys, List
if (!pathkeys_contained_in(pathkeys, path->pathkeys))
{
plan = (Plan *)
make_sort(plan, childSortCols, sortColIdx, sortOperators, collations, nullsFirst);
make_sort(plan, childSortCols, childColIdx, sortOperators, collations, nullsFirst);
}
return plan;
}
@ -186,17 +187,17 @@ chunk_append_plan_create(PlannerInfo *root, RelOptInfo *rel, CustomPath *path, L
MergeAppend *merge_plan = castNode(MergeAppend, lfirst(lc_plan));
MergeAppendPath *merge_path = castNode(MergeAppendPath, lfirst(lc_path));
/* Compute sort column info, and adjust MergeAppend's tlist as needed */
ts_prepare_sort_from_pathkeys((Plan *) merge_plan,
pathkeys,
merge_path->path.parent->relids,
NULL,
true,
&numCols,
&sortColIdx,
&sortOperators,
&collations,
&nullsFirst);
/*
* Since for space partitioning the MergeAppend below ChunkAppend
* still has the hypertable as rel we can copy sort properties and
* target list from toplevel ChunkAppend.
*/
merge_plan->plan.targetlist = cscan->scan.plan.targetlist;
merge_plan->sortColIdx = sortColIdx;
merge_plan->sortOperators = sortOperators;
merge_plan->collations = collations;
merge_plan->nullsFirst = nullsFirst;
forboth (lc_childpath, merge_path->subpaths, lc_childplan, merge_plan->mergeplans)
{
lfirst(lc_childplan) = adjust_childscan(root,

View File

@ -1281,6 +1281,69 @@ ORDER BY time DESC;
Heap Fetches: 6720
(38 rows)
-- expressions in ORDER BY clause
:PREFIX SELECT
time_bucket('1h',time)
FROM space
ORDER BY 1 LIMIT 10;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------
Limit (actual rows=10 loops=1)
-> Custom Scan (ChunkAppend) on space (actual rows=10 loops=1)
Order: time_bucket('@ 1 hour'::interval, space."time")
-> Merge Append (actual rows=10 loops=1)
Sort Key: (time_bucket('@ 1 hour'::interval, _hyper_7_24_chunk."time"))
-> Index Only Scan Backward using _hyper_7_24_chunk_space_time_idx on _hyper_7_24_chunk (actual rows=10 loops=1)
Heap Fetches: 10
-> Index Only Scan Backward using _hyper_7_26_chunk_space_time_idx on _hyper_7_26_chunk (actual rows=1 loops=1)
Heap Fetches: 1
-> Index Only Scan Backward using _hyper_7_28_chunk_space_time_idx on _hyper_7_28_chunk (actual rows=1 loops=1)
Heap Fetches: 1
-> Index Only Scan Backward using _hyper_7_30_chunk_space_time_idx on _hyper_7_30_chunk (actual rows=1 loops=1)
Heap Fetches: 1
-> Merge Append (never executed)
Sort Key: (time_bucket('@ 1 hour'::interval, _hyper_7_23_chunk."time"))
-> Index Only Scan Backward using _hyper_7_23_chunk_space_time_idx on _hyper_7_23_chunk (never executed)
Heap Fetches: 0
-> Index Only Scan Backward using _hyper_7_25_chunk_space_time_idx on _hyper_7_25_chunk (never executed)
Heap Fetches: 0
-> Index Only Scan Backward using _hyper_7_27_chunk_space_time_idx on _hyper_7_27_chunk (never executed)
Heap Fetches: 0
-> Index Only Scan Backward using _hyper_7_29_chunk_space_time_idx on _hyper_7_29_chunk (never executed)
Heap Fetches: 0
(23 rows)
:PREFIX SELECT
time_bucket('1h',time)
FROM space
ORDER BY 1 DESC LIMIT 10;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------
Limit (actual rows=10 loops=1)
-> Custom Scan (ChunkAppend) on space (actual rows=10 loops=1)
Order: time_bucket('@ 1 hour'::interval, space."time") DESC
-> Merge Append (actual rows=10 loops=1)
Sort Key: (time_bucket('@ 1 hour'::interval, _hyper_7_29_chunk."time")) DESC
-> Index Only Scan using _hyper_7_29_chunk_space_time_idx on _hyper_7_29_chunk (actual rows=3 loops=1)
Heap Fetches: 3
-> Index Only Scan using _hyper_7_27_chunk_space_time_idx on _hyper_7_27_chunk (actual rows=2 loops=1)
Heap Fetches: 2
-> Index Only Scan using _hyper_7_25_chunk_space_time_idx on _hyper_7_25_chunk (actual rows=6 loops=1)
Heap Fetches: 6
-> Index Only Scan using _hyper_7_23_chunk_space_time_idx on _hyper_7_23_chunk (actual rows=2 loops=1)
Heap Fetches: 2
-> Merge Append (never executed)
Sort Key: (time_bucket('@ 1 hour'::interval, _hyper_7_30_chunk."time")) DESC
-> Index Only Scan using _hyper_7_30_chunk_space_time_idx on _hyper_7_30_chunk (never executed)
Heap Fetches: 0
-> Index Only Scan using _hyper_7_28_chunk_space_time_idx on _hyper_7_28_chunk (never executed)
Heap Fetches: 0
-> Index Only Scan using _hyper_7_26_chunk_space_time_idx on _hyper_7_26_chunk (never executed)
Heap Fetches: 0
-> Index Only Scan using _hyper_7_24_chunk_space_time_idx on _hyper_7_24_chunk (never executed)
Heap Fetches: 0
(23 rows)
-- test LATERAL with correlated query
-- only last chunk should be executed
:PREFIX SELECT *

View File

@ -1281,6 +1281,69 @@ ORDER BY time DESC;
Heap Fetches: 6720
(38 rows)
-- expressions in ORDER BY clause
:PREFIX SELECT
time_bucket('1h',time)
FROM space
ORDER BY 1 LIMIT 10;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------
Limit (actual rows=10 loops=1)
-> Custom Scan (ChunkAppend) on space (actual rows=10 loops=1)
Order: time_bucket('@ 1 hour'::interval, space."time")
-> Merge Append (actual rows=10 loops=1)
Sort Key: (time_bucket('@ 1 hour'::interval, _hyper_7_24_chunk."time"))
-> Index Only Scan Backward using _hyper_7_24_chunk_space_time_idx on _hyper_7_24_chunk (actual rows=10 loops=1)
Heap Fetches: 10
-> Index Only Scan Backward using _hyper_7_26_chunk_space_time_idx on _hyper_7_26_chunk (actual rows=1 loops=1)
Heap Fetches: 1
-> Index Only Scan Backward using _hyper_7_28_chunk_space_time_idx on _hyper_7_28_chunk (actual rows=1 loops=1)
Heap Fetches: 1
-> Index Only Scan Backward using _hyper_7_30_chunk_space_time_idx on _hyper_7_30_chunk (actual rows=1 loops=1)
Heap Fetches: 1
-> Merge Append (never executed)
Sort Key: (time_bucket('@ 1 hour'::interval, _hyper_7_23_chunk."time"))
-> Index Only Scan Backward using _hyper_7_23_chunk_space_time_idx on _hyper_7_23_chunk (never executed)
Heap Fetches: 0
-> Index Only Scan Backward using _hyper_7_25_chunk_space_time_idx on _hyper_7_25_chunk (never executed)
Heap Fetches: 0
-> Index Only Scan Backward using _hyper_7_27_chunk_space_time_idx on _hyper_7_27_chunk (never executed)
Heap Fetches: 0
-> Index Only Scan Backward using _hyper_7_29_chunk_space_time_idx on _hyper_7_29_chunk (never executed)
Heap Fetches: 0
(23 rows)
:PREFIX SELECT
time_bucket('1h',time)
FROM space
ORDER BY 1 DESC LIMIT 10;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------
Limit (actual rows=10 loops=1)
-> Custom Scan (ChunkAppend) on space (actual rows=10 loops=1)
Order: time_bucket('@ 1 hour'::interval, space."time") DESC
-> Merge Append (actual rows=10 loops=1)
Sort Key: (time_bucket('@ 1 hour'::interval, _hyper_7_29_chunk."time")) DESC
-> Index Only Scan using _hyper_7_29_chunk_space_time_idx on _hyper_7_29_chunk (actual rows=3 loops=1)
Heap Fetches: 3
-> Index Only Scan using _hyper_7_27_chunk_space_time_idx on _hyper_7_27_chunk (actual rows=2 loops=1)
Heap Fetches: 2
-> Index Only Scan using _hyper_7_25_chunk_space_time_idx on _hyper_7_25_chunk (actual rows=6 loops=1)
Heap Fetches: 6
-> Index Only Scan using _hyper_7_23_chunk_space_time_idx on _hyper_7_23_chunk (actual rows=2 loops=1)
Heap Fetches: 2
-> Merge Append (never executed)
Sort Key: (time_bucket('@ 1 hour'::interval, _hyper_7_30_chunk."time")) DESC
-> Index Only Scan using _hyper_7_30_chunk_space_time_idx on _hyper_7_30_chunk (never executed)
Heap Fetches: 0
-> Index Only Scan using _hyper_7_28_chunk_space_time_idx on _hyper_7_28_chunk (never executed)
Heap Fetches: 0
-> Index Only Scan using _hyper_7_26_chunk_space_time_idx on _hyper_7_26_chunk (never executed)
Heap Fetches: 0
-> Index Only Scan using _hyper_7_24_chunk_space_time_idx on _hyper_7_24_chunk (never executed)
Heap Fetches: 0
(23 rows)
-- test LATERAL with correlated query
-- only last chunk should be executed
:PREFIX SELECT *

View File

@ -1236,6 +1236,53 @@ ORDER BY time DESC;
-> Index Only Scan using _hyper_9_50_chunk_space3_time_idx on _hyper_9_50_chunk
(22 rows)
-- expressions in ORDER BY clause
:PREFIX SELECT
time_bucket('1h',time)
FROM space
ORDER BY 1 LIMIT 10;
QUERY PLAN
--------------------------------------------------------------------------------------------------------
Limit
-> Custom Scan (ChunkAppend) on space
Order: time_bucket('@ 1 hour'::interval, space."time")
-> Merge Append
Sort Key: (time_bucket('@ 1 hour'::interval, _hyper_7_24_chunk."time"))
-> Index Only Scan Backward using _hyper_7_24_chunk_space_time_idx on _hyper_7_24_chunk
-> Index Only Scan Backward using _hyper_7_26_chunk_space_time_idx on _hyper_7_26_chunk
-> Index Only Scan Backward using _hyper_7_28_chunk_space_time_idx on _hyper_7_28_chunk
-> Index Only Scan Backward using _hyper_7_30_chunk_space_time_idx on _hyper_7_30_chunk
-> Merge Append
Sort Key: (time_bucket('@ 1 hour'::interval, _hyper_7_23_chunk."time"))
-> Index Only Scan Backward using _hyper_7_23_chunk_space_time_idx on _hyper_7_23_chunk
-> Index Only Scan Backward using _hyper_7_25_chunk_space_time_idx on _hyper_7_25_chunk
-> Index Only Scan Backward using _hyper_7_27_chunk_space_time_idx on _hyper_7_27_chunk
-> Index Only Scan Backward using _hyper_7_29_chunk_space_time_idx on _hyper_7_29_chunk
(15 rows)
:PREFIX SELECT
time_bucket('1h',time)
FROM space
ORDER BY 1 DESC LIMIT 10;
QUERY PLAN
-----------------------------------------------------------------------------------------------
Limit
-> Custom Scan (ChunkAppend) on space
Order: time_bucket('@ 1 hour'::interval, space."time") DESC
-> Merge Append
Sort Key: (time_bucket('@ 1 hour'::interval, _hyper_7_29_chunk."time")) DESC
-> Index Only Scan using _hyper_7_29_chunk_space_time_idx on _hyper_7_29_chunk
-> Index Only Scan using _hyper_7_27_chunk_space_time_idx on _hyper_7_27_chunk
-> Index Only Scan using _hyper_7_25_chunk_space_time_idx on _hyper_7_25_chunk
-> Index Only Scan using _hyper_7_23_chunk_space_time_idx on _hyper_7_23_chunk
-> Merge Append
Sort Key: (time_bucket('@ 1 hour'::interval, _hyper_7_30_chunk."time")) DESC
-> Index Only Scan using _hyper_7_30_chunk_space_time_idx on _hyper_7_30_chunk
-> Index Only Scan using _hyper_7_28_chunk_space_time_idx on _hyper_7_28_chunk
-> Index Only Scan using _hyper_7_26_chunk_space_time_idx on _hyper_7_26_chunk
-> Index Only Scan using _hyper_7_24_chunk_space_time_idx on _hyper_7_24_chunk
(15 rows)
-- test LATERAL with correlated query
-- only last chunk should be executed
:PREFIX SELECT *

View File

@ -315,6 +315,17 @@ ORDER BY time DESC;
FROM space3
ORDER BY time DESC;
-- expressions in ORDER BY clause
:PREFIX SELECT
time_bucket('1h',time)
FROM space
ORDER BY 1 LIMIT 10;
:PREFIX SELECT
time_bucket('1h',time)
FROM space
ORDER BY 1 DESC LIMIT 10;
-- test LATERAL with correlated query
-- only last chunk should be executed
:PREFIX SELECT *