mirror of
https://github.com/timescale/timescaledb.git
synced 2025-05-16 18:43:18 +08:00
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:
parent
3fa3822d08
commit
ddb8f46b5f
@ -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,
|
||||
|
@ -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 *
|
||||
|
@ -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 *
|
||||
|
@ -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 *
|
||||
|
@ -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 *
|
||||
|
Loading…
x
Reference in New Issue
Block a user