Route UPDATE through HypertableModify

Route UPDATE on Hypertables through our custom HypertableModify
node. This patch by itself does not make any other changes to
UPDATE but is the foundation for other features regarding UPDATE
on hypertables.
This commit is contained in:
Sven Klemm 2022-03-18 05:33:35 +01:00 committed by Sven Klemm
parent 846878c6bb
commit 566a4ff104
5 changed files with 72 additions and 66 deletions

View File

@ -480,12 +480,12 @@ hypertable_modify_plan_create(PlannerInfo *root, RelOptInfo *rel, CustomPath *be
cscan->scan.plan.targetlist = copyObject(root->processed_tlist);
/*
* For DELETE processed_tlist will have ROWID_VAR. We need to remove
* For UPDATE/DELETE processed_tlist will have ROWID_VAR. We need to remove
* those because set_customscan_references will bail if it sees
* ROWID_VAR entries in the targetlist.
*/
#if PG14_GE
if (mt->operation == CMD_DELETE)
if (mt->operation == CMD_UPDATE || mt->operation == CMD_DELETE)
{
ListCell *lc;
foreach (lc, cscan->scan.plan.targetlist)
@ -500,8 +500,9 @@ hypertable_modify_plan_create(PlannerInfo *root, RelOptInfo *rel, CustomPath *be
}
}
#else
/* We only route DELETEs through our CustomNode for PG 14+ because
* the codepath for earlier versions is different. */
/*
* For postgres versions < PG14 we only route INSERT through our custom node.
*/
Assert(mt->operation == CMD_INSERT);
#endif
cscan->custom_scan_tlist = cscan->scan.plan.targetlist;

View File

@ -1137,9 +1137,10 @@ replace_hypertable_modify_paths(PlannerInfo *root, List *pathlist)
ModifyTablePath *mt = castNode(ModifyTablePath, path);
#if PG14_GE
/* We only route DELETEs through our CustomNode for PG 14+ because
/* We only route UPDATE/DELETE through our CustomNode for PG 14+ because
* the codepath for earlier versions is different. */
if (mt->operation == CMD_INSERT || mt->operation == CMD_DELETE)
if (mt->operation == CMD_INSERT || mt->operation == CMD_UPDATE ||
mt->operation == CMD_DELETE)
#else
if (mt->operation == CMD_INSERT)
#endif

View File

@ -2265,19 +2265,20 @@ INSERT INTO bv1 VALUES (11, 'xxx'); -- should fail RLS check
ERROR: new row violates row-level security policy for table "b1"
INSERT INTO bv1 VALUES (12, 'xxx'); -- ok
EXPLAIN (COSTS OFF) UPDATE bv1 SET b = 'yyy' WHERE a = 4 AND f_leak(b);
QUERY PLAN
-----------------------------------------------------------------------------------------
Update on b1
Update on b1 b1_1
Update on _hyper_8_41_chunk b1_2
-> Result
-> Append
-> Seq Scan on b1 b1_1
Filter: ((a > 0) AND (a = 4) AND ((a % 2) = 0) AND f_leak(b))
-> Index Scan using _hyper_8_41_chunk_b1_a_idx on _hyper_8_41_chunk b1_2
Index Cond: ((a > 0) AND (a = 4))
Filter: (((a % 2) = 0) AND f_leak(b))
(10 rows)
QUERY PLAN
-----------------------------------------------------------------------------------------------
Custom Scan (HypertableModify)
-> Update on b1
Update on b1 b1_1
Update on _hyper_8_41_chunk b1_2
-> Result
-> Append
-> Seq Scan on b1 b1_1
Filter: ((a > 0) AND (a = 4) AND ((a % 2) = 0) AND f_leak(b))
-> Index Scan using _hyper_8_41_chunk_b1_a_idx on _hyper_8_41_chunk b1_2
Index Cond: ((a > 0) AND (a = 4))
Filter: (((a % 2) = 0) AND f_leak(b))
(11 rows)
UPDATE bv1 SET b = 'yyy' WHERE a = 4 AND f_leak(b);
NOTICE: f_leak => a87ff679a2f3e71d9181a67b7542122c
@ -4354,19 +4355,20 @@ SELECT * FROM current_check;
-- Plan should be a subquery TID scan
EXPLAIN (COSTS OFF) UPDATE current_check SET payload = payload WHERE CURRENT OF current_check_cursor;
QUERY PLAN
-------------------------------------------------------------------
Update on current_check
Update on current_check current_check_1
Update on _hyper_21_104_chunk current_check_2
-> Append
-> Tid Scan on current_check current_check_1
TID Cond: CURRENT OF current_check_cursor
Filter: ((currentid = 4) AND ((currentid % 2) = 0))
-> Tid Scan on _hyper_21_104_chunk current_check_2
TID Cond: CURRENT OF current_check_cursor
Filter: ((currentid = 4) AND ((currentid % 2) = 0))
(10 rows)
QUERY PLAN
-------------------------------------------------------------------------
Custom Scan (HypertableModify)
-> Update on current_check
Update on current_check current_check_1
Update on _hyper_21_104_chunk current_check_2
-> Append
-> Tid Scan on current_check current_check_1
TID Cond: CURRENT OF current_check_cursor
Filter: ((currentid = 4) AND ((currentid % 2) = 0))
-> Tid Scan on _hyper_21_104_chunk current_check_2
TID Cond: CURRENT OF current_check_cursor
Filter: ((currentid = 4) AND ((currentid % 2) = 0))
(11 rows)
-- Similarly can only delete row 4
FETCH ABSOLUTE 1 FROM current_check_cursor;

View File

@ -81,33 +81,34 @@ EXPLAIN (costs off)
UPDATE "one_Partition"
SET series_1 = 8
WHERE series_1 IN (SELECT series_1 FROM "one_Partition" WHERE series_1 > series_val());
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------
Update on "one_Partition"
Update on "one_Partition" "one_Partition_2"
Update on _hyper_1_1_chunk "one_Partition_3"
Update on _hyper_1_2_chunk "one_Partition_4"
Update on _hyper_1_3_chunk "one_Partition_5"
-> Hash Join
Hash Cond: ("one_Partition".series_1 = "one_Partition_1".series_1)
-> Append
-> Seq Scan on "one_Partition" "one_Partition_2"
-> Seq Scan on _hyper_1_1_chunk "one_Partition_3"
-> Seq Scan on _hyper_1_2_chunk "one_Partition_4"
-> Seq Scan on _hyper_1_3_chunk "one_Partition_5"
-> Hash
-> HashAggregate
Group Key: "one_Partition_1".series_1
-> Append
-> Seq Scan on "one_Partition" "one_Partition_6"
Filter: (series_1 > (series_val())::double precision)
-> Index Scan using "_hyper_1_1_chunk_one_Partition_timeCustom_series_1_idx" on _hyper_1_1_chunk "one_Partition_7"
Index Cond: (series_1 > (series_val())::double precision)
-> Index Scan using "_hyper_1_2_chunk_one_Partition_timeCustom_series_1_idx" on _hyper_1_2_chunk "one_Partition_8"
Index Cond: (series_1 > (series_val())::double precision)
-> Index Scan using "_hyper_1_3_chunk_one_Partition_timeCustom_series_1_idx" on _hyper_1_3_chunk "one_Partition_9"
Index Cond: (series_1 > (series_val())::double precision)
(24 rows)
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------
Custom Scan (HypertableModify)
-> Update on "one_Partition"
Update on "one_Partition" "one_Partition_2"
Update on _hyper_1_1_chunk "one_Partition_3"
Update on _hyper_1_2_chunk "one_Partition_4"
Update on _hyper_1_3_chunk "one_Partition_5"
-> Hash Join
Hash Cond: ("one_Partition".series_1 = "one_Partition_1".series_1)
-> Append
-> Seq Scan on "one_Partition" "one_Partition_2"
-> Seq Scan on _hyper_1_1_chunk "one_Partition_3"
-> Seq Scan on _hyper_1_2_chunk "one_Partition_4"
-> Seq Scan on _hyper_1_3_chunk "one_Partition_5"
-> Hash
-> HashAggregate
Group Key: "one_Partition_1".series_1
-> Append
-> Seq Scan on "one_Partition" "one_Partition_6"
Filter: (series_1 > (series_val())::double precision)
-> Index Scan using "_hyper_1_1_chunk_one_Partition_timeCustom_series_1_idx" on _hyper_1_1_chunk "one_Partition_7"
Index Cond: (series_1 > (series_val())::double precision)
-> Index Scan using "_hyper_1_2_chunk_one_Partition_timeCustom_series_1_idx" on _hyper_1_2_chunk "one_Partition_8"
Index Cond: (series_1 > (series_val())::double precision)
-> Index Scan using "_hyper_1_3_chunk_one_Partition_timeCustom_series_1_idx" on _hyper_1_3_chunk "one_Partition_9"
Index Cond: (series_1 > (series_val())::double precision)
(25 rows)
SELECT * FROM "one_Partition" ORDER BY "timeCustom", device_id, series_0, series_1, series_2;
timeCustom | device_id | series_0 | series_1 | series_2 | series_bool

View File

@ -141,13 +141,14 @@ SELECT * FROM jit_test_interval WHERE id >= 23 and id < 73 ORDER BY id;
:PREFIX
UPDATE jit_test_interval SET temp = temp * 2.3 WHERE id >= 23 and id < 73;
QUERY PLAN
------------------------------------------------------------------------------------
Update on public.jit_test_interval
-> Index Scan using jit_test_interval_id_idx on public.jit_test_interval
Output: (temp * '2.3'::double precision), ctid
Index Cond: ((jit_test_interval.id >= 23) AND (jit_test_interval.id < 73))
(4 rows)
QUERY PLAN
------------------------------------------------------------------------------------------
Custom Scan (HypertableModify)
-> Update on public.jit_test_interval
-> Index Scan using jit_test_interval_id_idx on public.jit_test_interval
Output: (temp * '2.3'::double precision), ctid
Index Cond: ((jit_test_interval.id >= 23) AND (jit_test_interval.id < 73))
(5 rows)
:PREFIX
SELECT * FROM jit_test_interval ORDER BY id;