mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-08-20 06:03:22 +02:00
Fix Assert failure for MERGE into a partitioned table with RLS.
In ExecInitPartitionInfo(), the Assert when building the WITH CHECK OPTION list for the new partition assumed that the command would be an INSERT or UPDATE, but it can also be a MERGE. This can be triggered by a MERGE into a partitioned table with RLS checks to enforce. Fix, and back-patch to v15, where MERGE was introduced. Discussion: https://postgr.es/m/CAEZATCWWFtQmW67F3XTyMU5Am10Oxa_b8oe0x%2BNu5Mo%2BCdRErg%40mail.gmail.com
This commit is contained in:
parent
018af1cc1c
commit
d8c3b65db5
@ -545,8 +545,8 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate,
|
|||||||
* Build WITH CHECK OPTION constraints for the partition. Note that we
|
* Build WITH CHECK OPTION constraints for the partition. Note that we
|
||||||
* didn't build the withCheckOptionList for partitions within the planner,
|
* didn't build the withCheckOptionList for partitions within the planner,
|
||||||
* but simple translation of varattnos will suffice. This only occurs for
|
* but simple translation of varattnos will suffice. This only occurs for
|
||||||
* the INSERT case or in the case of UPDATE tuple routing where we didn't
|
* the INSERT case or in the case of UPDATE/MERGE tuple routing where we
|
||||||
* find a result rel to reuse.
|
* didn't find a result rel to reuse.
|
||||||
*/
|
*/
|
||||||
if (node && node->withCheckOptionLists != NIL)
|
if (node && node->withCheckOptionLists != NIL)
|
||||||
{
|
{
|
||||||
@ -557,12 +557,15 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate,
|
|||||||
/*
|
/*
|
||||||
* In the case of INSERT on a partitioned table, there is only one
|
* In the case of INSERT on a partitioned table, there is only one
|
||||||
* plan. Likewise, there is only one WCO list, not one per partition.
|
* plan. Likewise, there is only one WCO list, not one per partition.
|
||||||
* For UPDATE, there are as many WCO lists as there are plans.
|
* For UPDATE/MERGE, there are as many WCO lists as there are plans.
|
||||||
*/
|
*/
|
||||||
Assert((node->operation == CMD_INSERT &&
|
Assert((node->operation == CMD_INSERT &&
|
||||||
list_length(node->withCheckOptionLists) == 1 &&
|
list_length(node->withCheckOptionLists) == 1 &&
|
||||||
list_length(node->resultRelations) == 1) ||
|
list_length(node->resultRelations) == 1) ||
|
||||||
(node->operation == CMD_UPDATE &&
|
(node->operation == CMD_UPDATE &&
|
||||||
|
list_length(node->withCheckOptionLists) ==
|
||||||
|
list_length(node->resultRelations)) ||
|
||||||
|
(node->operation == CMD_MERGE &&
|
||||||
list_length(node->withCheckOptionLists) ==
|
list_length(node->withCheckOptionLists) ==
|
||||||
list_length(node->resultRelations)));
|
list_length(node->resultRelations)));
|
||||||
|
|
||||||
@ -618,6 +621,7 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate,
|
|||||||
List *returningList;
|
List *returningList;
|
||||||
|
|
||||||
/* See the comment above for WCO lists. */
|
/* See the comment above for WCO lists. */
|
||||||
|
/* (except no RETURNING support for MERGE yet) */
|
||||||
Assert((node->operation == CMD_INSERT &&
|
Assert((node->operation == CMD_INSERT &&
|
||||||
list_length(node->returningLists) == 1 &&
|
list_length(node->returningLists) == 1 &&
|
||||||
list_length(node->resultRelations) == 1) ||
|
list_length(node->resultRelations) == 1) ||
|
||||||
|
@ -1736,6 +1736,18 @@ SELECT * FROM pa_target ORDER BY tid;
|
|||||||
14 | 140 | inserted by merge
|
14 | 140 | inserted by merge
|
||||||
(14 rows)
|
(14 rows)
|
||||||
|
|
||||||
|
ROLLBACK;
|
||||||
|
-- test RLS enforcement
|
||||||
|
BEGIN;
|
||||||
|
ALTER TABLE pa_target ENABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE pa_target FORCE ROW LEVEL SECURITY;
|
||||||
|
CREATE POLICY pa_target_pol ON pa_target USING (tid != 0);
|
||||||
|
MERGE INTO pa_target t
|
||||||
|
USING pa_source s
|
||||||
|
ON t.tid = s.sid AND t.tid IN (1,2,3,4)
|
||||||
|
WHEN MATCHED THEN
|
||||||
|
UPDATE SET tid = tid - 1;
|
||||||
|
ERROR: new row violates row-level security policy for table "pa_target"
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
DROP TABLE pa_source;
|
DROP TABLE pa_source;
|
||||||
DROP TABLE pa_target CASCADE;
|
DROP TABLE pa_target CASCADE;
|
||||||
|
@ -1082,6 +1082,18 @@ MERGE INTO pa_target t
|
|||||||
SELECT * FROM pa_target ORDER BY tid;
|
SELECT * FROM pa_target ORDER BY tid;
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
|
|
||||||
|
-- test RLS enforcement
|
||||||
|
BEGIN;
|
||||||
|
ALTER TABLE pa_target ENABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE pa_target FORCE ROW LEVEL SECURITY;
|
||||||
|
CREATE POLICY pa_target_pol ON pa_target USING (tid != 0);
|
||||||
|
MERGE INTO pa_target t
|
||||||
|
USING pa_source s
|
||||||
|
ON t.tid = s.sid AND t.tid IN (1,2,3,4)
|
||||||
|
WHEN MATCHED THEN
|
||||||
|
UPDATE SET tid = tid - 1;
|
||||||
|
ROLLBACK;
|
||||||
|
|
||||||
DROP TABLE pa_source;
|
DROP TABLE pa_source;
|
||||||
DROP TABLE pa_target CASCADE;
|
DROP TABLE pa_target CASCADE;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user