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)
|
if (node->withCheckOptionLists != NIL && mtstate->mt_num_partitions > 0)
|
||||||
{
|
{
|
||||||
List *wcoList;
|
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);
|
wcoList = linitial(node->withCheckOptionLists);
|
||||||
|
plan = mtstate->mt_plans[0];
|
||||||
|
resultRelInfo = mtstate->mt_partitions;
|
||||||
for (i = 0; i < mtstate->mt_num_partitions; i++)
|
for (i = 0; i < mtstate->mt_num_partitions; i++)
|
||||||
{
|
{
|
||||||
Relation partrel = resultRelInfo->ri_RelationDesc;
|
Relation partrel = resultRelInfo->ri_RelationDesc;
|
||||||
@ -1858,9 +1869,9 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
|
|||||||
partrel, rel);
|
partrel, rel);
|
||||||
foreach(ll, mapped_wcoList)
|
foreach(ll, mapped_wcoList)
|
||||||
{
|
{
|
||||||
WithCheckOption *wco = (WithCheckOption *) lfirst(ll);
|
WithCheckOption *wco = castNode(WithCheckOption, lfirst(ll));
|
||||||
ExprState *wcoExpr = ExecInitQual((List *) wco->qual,
|
ExprState *wcoExpr = ExecInitQual(castNode(List, wco->qual),
|
||||||
mtstate->mt_plans[i]);
|
plan);
|
||||||
|
|
||||||
wcoExprs = lappend(wcoExprs, wcoExpr);
|
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"
|
ERROR: query would be affected by row-level security policy for table "part_document"
|
||||||
SELECT * FROM part_document_satire ORDER by did;
|
SELECT * FROM part_document_satire ORDER by did;
|
||||||
ERROR: query would be affected by row-level security policy for table "part_document_satire"
|
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 -----
|
----- Dependencies -----
|
||||||
SET SESSION AUTHORIZATION regress_rls_alice;
|
SET SESSION AUTHORIZATION regress_rls_alice;
|
||||||
SET row_security TO ON;
|
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 ORDER by did;
|
||||||
SELECT * FROM part_document_satire 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 -----
|
----- Dependencies -----
|
||||||
SET SESSION AUTHORIZATION regress_rls_alice;
|
SET SESSION AUTHORIZATION regress_rls_alice;
|
||||||
SET row_security TO ON;
|
SET row_security TO ON;
|
||||||
|
Reference in New Issue
Block a user