Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Avoid crash with WHERE CURRENT OF and a custom scan plan.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 18 Jan 2021 23:32:30 +0000 (18:32 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 18 Jan 2021 23:33:07 +0000 (18:33 -0500)
execCurrent.c's search_plan_tree() assumed that ForeignScanStates
and CustomScanStates necessarily have a valid ss_currentRelation.
This is demonstrably untrue for postgres_fdw's remote join and
remote aggregation plans, and non-leaf custom scans might not have
an identifiable scan relation either.  Avoid crashing by ignoring
such nodes when the field is null.

This solution will lead to errors like 'cursor "foo" is not a
simply updatable scan of table "bar"' in cases where maybe we
could have allowed WHERE CURRENT OF to work.  That's not an issue
for postgres_fdw's usages, since joins or aggregations would render
WHERE CURRENT OF invalid anyway.  But an otherwise-transparent
upper level custom scan node might find this annoying.  When and if
someone cares to expend work on such a scenario, we could invent a
custom-scan-provider callback to determine what's safe.

Report and patch by David Geier, commentary by me.  It's been like
this for awhile, so back-patch to all supported branches.

Discussion: https://postgr.es/m/0253344d-9bdd-11c4-7f0d-d88c02cd7991@swarm64.com

src/backend/executor/execCurrent.c

index d50968920d61b52c64c62c6e3fc474a05b35889d..3f0e608f0d454fc4c5daae21d8302c8beb560a1f 100644 (file)
@@ -314,7 +314,12 @@ search_plan_tree(PlanState *node, Oid table_oid,
    switch (nodeTag(node))
    {
            /*
-            * Relation scan nodes can all be treated alike
+            * Relation scan nodes can all be treated alike.  Note that
+            * ForeignScan and CustomScan might not have a currentRelation, in
+            * which case we just ignore them.  (We dare not descend to any
+            * child plan nodes they might have, since we do not know the
+            * relationship of such a node's current output tuple to the
+            * children's current outputs.)
             */
        case T_SeqScanState:
        case T_SampleScanState:
@@ -327,7 +332,8 @@ search_plan_tree(PlanState *node, Oid table_oid,
            {
                ScanState  *sstate = (ScanState *) node;
 
-               if (RelationGetRelid(sstate->ss_currentRelation) == table_oid)
+               if (sstate->ss_currentRelation &&
+                   RelationGetRelid(sstate->ss_currentRelation) == table_oid)
                    result = sstate;
                break;
            }