mirror of
https://github.com/postgres/postgres.git
synced 2025-06-16 06:01:02 +03:00
Fix confusion about number of subplans in partitioned INSERT setup.
ExecInitModifyTable() thought there was a plan per partition, but no,
there's only one. The problem had escaped detection so far because there
would only be visible misbehavior if there were a SubPlan (not an InitPlan)
in the quals being duplicated for each partition. However, valgrind
detected a bogus memory access in test cases added by commit 4f7a95be2
,
and investigation of that led to discovery of the bug. The additional
test case added here crashes without the patch.
Patch by Amit Langote, test case by me.
Discussion: https://postgr.es/m/10974.1497227727@sss.pgh.pa.us
This commit is contained in:
@ -1841,10 +1841,21 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
|
||||
if (node->withCheckOptionLists != NIL && mtstate->mt_num_partitions > 0)
|
||||
{
|
||||
List *wcoList;
|
||||
PlanState *plan;
|
||||
|
||||
Assert(operation == CMD_INSERT);
|
||||
resultRelInfo = mtstate->mt_partitions;
|
||||
/*
|
||||
* In case of INSERT on partitioned tables, there is only one plan.
|
||||
* Likewise, there is only one WITH CHECK OPTIONS list, not one per
|
||||
* partition. We make a copy of the WCO qual for each partition; note
|
||||
* that, if there are SubPlans in there, they all end up attached to
|
||||
* the one parent Plan node.
|
||||
*/
|
||||
Assert(operation == CMD_INSERT &&
|
||||
list_length(node->withCheckOptionLists) == 1 &&
|
||||
mtstate->mt_nplans == 1);
|
||||
wcoList = linitial(node->withCheckOptionLists);
|
||||
plan = mtstate->mt_plans[0];
|
||||
resultRelInfo = mtstate->mt_partitions;
|
||||
for (i = 0; i < mtstate->mt_num_partitions; i++)
|
||||
{
|
||||
Relation partrel = resultRelInfo->ri_RelationDesc;
|
||||
@ -1858,9 +1869,9 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
|
||||
partrel, rel);
|
||||
foreach(ll, mapped_wcoList)
|
||||
{
|
||||
WithCheckOption *wco = (WithCheckOption *) lfirst(ll);
|
||||
ExprState *wcoExpr = ExecInitQual((List *) wco->qual,
|
||||
mtstate->mt_plans[i]);
|
||||
WithCheckOption *wco = castNode(WithCheckOption, lfirst(ll));
|
||||
ExprState *wcoExpr = ExecInitQual(castNode(List, wco->qual),
|
||||
plan);
|
||||
|
||||
wcoExprs = lappend(wcoExprs, wcoExpr);
|
||||
}
|
||||
|
@ -1327,6 +1327,14 @@ SELECT * FROM part_document ORDER by did;
|
||||
ERROR: query would be affected by row-level security policy for table "part_document"
|
||||
SELECT * FROM part_document_satire ORDER by did;
|
||||
ERROR: query would be affected by row-level security policy for table "part_document_satire"
|
||||
-- Check behavior with a policy that uses a SubPlan not an InitPlan.
|
||||
SET SESSION AUTHORIZATION regress_rls_alice;
|
||||
SET row_security TO ON;
|
||||
CREATE POLICY pp3 ON part_document AS RESTRICTIVE
|
||||
USING ((SELECT dlevel <= seclv FROM uaccount WHERE pguser = current_user));
|
||||
SET SESSION AUTHORIZATION regress_rls_carol;
|
||||
INSERT INTO part_document VALUES (100, 11, 5, 'regress_rls_carol', 'testing pp3'); -- fail
|
||||
ERROR: new row violates row-level security policy "pp3" for table "part_document"
|
||||
----- Dependencies -----
|
||||
SET SESSION AUTHORIZATION regress_rls_alice;
|
||||
SET row_security TO ON;
|
||||
|
@ -450,6 +450,15 @@ SET row_security TO OFF;
|
||||
SELECT * FROM part_document ORDER by did;
|
||||
SELECT * FROM part_document_satire ORDER by did;
|
||||
|
||||
-- Check behavior with a policy that uses a SubPlan not an InitPlan.
|
||||
SET SESSION AUTHORIZATION regress_rls_alice;
|
||||
SET row_security TO ON;
|
||||
CREATE POLICY pp3 ON part_document AS RESTRICTIVE
|
||||
USING ((SELECT dlevel <= seclv FROM uaccount WHERE pguser = current_user));
|
||||
|
||||
SET SESSION AUTHORIZATION regress_rls_carol;
|
||||
INSERT INTO part_document VALUES (100, 11, 5, 'regress_rls_carol', 'testing pp3'); -- fail
|
||||
|
||||
----- Dependencies -----
|
||||
SET SESSION AUTHORIZATION regress_rls_alice;
|
||||
SET row_security TO ON;
|
||||
|
Reference in New Issue
Block a user