diff options
Diffstat (limited to 'src/backend/executor')
-rw-r--r-- | src/backend/executor/execScan.c | 23 | ||||
-rw-r--r-- | src/backend/executor/nodeCustom.c | 55 | ||||
-rw-r--r-- | src/backend/executor/nodeForeignscan.c | 41 | ||||
-rw-r--r-- | src/backend/executor/nodeIndexonlyscan.c | 6 |
4 files changed, 82 insertions, 43 deletions
diff --git a/src/backend/executor/execScan.c b/src/backend/executor/execScan.c index fa475014f13..a96e826ba42 100644 --- a/src/backend/executor/execScan.c +++ b/src/backend/executor/execScan.c @@ -246,19 +246,18 @@ void ExecAssignScanProjectionInfo(ScanState *node) { Scan *scan = (Scan *) node->ps.plan; - Index varno; - /* Vars in an index-only scan's tlist should be INDEX_VAR */ - if (IsA(scan, IndexOnlyScan)) - varno = INDEX_VAR; - /* Also foreign or custom scan on pseudo relation should be INDEX_VAR */ - else if (scan->scanrelid == 0) - { - Assert(IsA(scan, ForeignScan) || IsA(scan, CustomScan)); - varno = INDEX_VAR; - } - else - varno = scan->scanrelid; + ExecAssignScanProjectionInfoWithVarno(node, scan->scanrelid); +} + +/* + * ExecAssignScanProjectionInfoWithVarno + * As above, but caller can specify varno expected in Vars in the tlist. + */ +void +ExecAssignScanProjectionInfoWithVarno(ScanState *node, Index varno) +{ + Scan *scan = (Scan *) node->ps.plan; if (tlist_matches_tupdesc(&node->ps, scan->plan.targetlist, diff --git a/src/backend/executor/nodeCustom.c b/src/backend/executor/nodeCustom.c index db1b4f2ffa4..0a022dff940 100644 --- a/src/backend/executor/nodeCustom.c +++ b/src/backend/executor/nodeCustom.c @@ -22,13 +22,24 @@ CustomScanState * ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags) { - CustomScanState *css; - Index scan_relid = cscan->scan.scanrelid; + CustomScanState *css; + Relation scan_rel = NULL; + Index scanrelid = cscan->scan.scanrelid; + Index tlistvarno; - /* populate a CustomScanState according to the CustomScan */ + /* + * Allocate the CustomScanState object. We let the custom scan provider + * do the palloc, in case it wants to make a larger object that embeds + * CustomScanState as the first field. It must set the node tag and the + * methods field correctly at this time. Other standard fields should be + * set to zero. + */ css = (CustomScanState *) cscan->methods->CreateCustomScanState(cscan); Assert(IsA(css, CustomScanState)); + /* ensure flags is filled correctly */ + css->flags = cscan->flags; + /* fill up fields of ScanState */ css->ss.ps.plan = &cscan->scan.plan; css->ss.ps.state = estate; @@ -36,6 +47,8 @@ ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags) /* create expression context for node */ ExecAssignExprContext(estate, &css->ss.ps); + css->ss.ps.ps_TupFromTlist = false; + /* initialize child expressions */ css->ss.ps.targetlist = (List *) ExecInitExpr((Expr *) cscan->scan.plan.targetlist, @@ -49,32 +62,40 @@ ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags) ExecInitResultTupleSlot(estate, &css->ss.ps); /* - * open the base relation and acquire an appropriate lock on it; - * also, get and assign the scan type + * open the base relation, if any, and acquire an appropriate lock on it */ - if (scan_relid > 0) + if (scanrelid > 0) { - Relation scan_rel; - - scan_rel = ExecOpenScanRelation(estate, scan_relid, eflags); + scan_rel = ExecOpenScanRelation(estate, scanrelid, eflags); css->ss.ss_currentRelation = scan_rel; - css->ss.ss_currentScanDesc = NULL; /* set by provider */ - ExecAssignScanType(&css->ss, RelationGetDescr(scan_rel)); } - else + + /* + * Determine the scan tuple type. If the custom scan provider provided a + * targetlist describing the scan tuples, use that; else use base + * relation's rowtype. + */ + if (cscan->custom_scan_tlist != NIL || scan_rel == NULL) { - TupleDesc ps_tupdesc; + TupleDesc scan_tupdesc; - ps_tupdesc = ExecCleanTypeFromTL(cscan->custom_ps_tlist, false); - ExecAssignScanType(&css->ss, ps_tupdesc); + scan_tupdesc = ExecTypeFromTL(cscan->custom_scan_tlist, false); + ExecAssignScanType(&css->ss, scan_tupdesc); + /* Node's targetlist will contain Vars with varno = INDEX_VAR */ + tlistvarno = INDEX_VAR; + } + else + { + ExecAssignScanType(&css->ss, RelationGetDescr(scan_rel)); + /* Node's targetlist will contain Vars with varno = scanrelid */ + tlistvarno = scanrelid; } - css->ss.ps.ps_TupFromTlist = false; /* * Initialize result tuple type and projection info. */ ExecAssignResultTypeFromTL(&css->ss.ps); - ExecAssignScanProjectionInfo(&css->ss); + ExecAssignScanProjectionInfoWithVarno(&css->ss, tlistvarno); /* * The callback of custom-scan provider applies the final initialization diff --git a/src/backend/executor/nodeForeignscan.c b/src/backend/executor/nodeForeignscan.c index fa553ace5d6..bb28a7372d1 100644 --- a/src/backend/executor/nodeForeignscan.c +++ b/src/backend/executor/nodeForeignscan.c @@ -102,7 +102,9 @@ ForeignScanState * ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags) { ForeignScanState *scanstate; + Relation currentRelation = NULL; Index scanrelid = node->scan.scanrelid; + Index tlistvarno; FdwRoutine *fdwroutine; /* check for unsupported flags */ @@ -141,40 +143,55 @@ ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags) ExecInitScanTupleSlot(estate, &scanstate->ss); /* - * open the base relation and acquire an appropriate lock on it; - * also, get and assign the scan type + * open the base relation, if any, and acquire an appropriate lock on it; + * also acquire function pointers from the FDW's handler */ if (scanrelid > 0) { - Relation currentRelation; - currentRelation = ExecOpenScanRelation(estate, scanrelid, eflags); scanstate->ss.ss_currentRelation = currentRelation; - ExecAssignScanType(&scanstate->ss, RelationGetDescr(currentRelation)); + fdwroutine = GetFdwRoutineForRelation(currentRelation, true); } else { - TupleDesc ps_tupdesc; + /* We can't use the relcache, so get fdwroutine the hard way */ + fdwroutine = GetFdwRoutineByServerId(node->fs_server); + } - ps_tupdesc = ExecCleanTypeFromTL(node->fdw_ps_tlist, false); - ExecAssignScanType(&scanstate->ss, ps_tupdesc); + /* + * Determine the scan tuple type. If the FDW provided a targetlist + * describing the scan tuples, use that; else use base relation's rowtype. + */ + if (node->fdw_scan_tlist != NIL || currentRelation == NULL) + { + TupleDesc scan_tupdesc; + + scan_tupdesc = ExecTypeFromTL(node->fdw_scan_tlist, false); + ExecAssignScanType(&scanstate->ss, scan_tupdesc); + /* Node's targetlist will contain Vars with varno = INDEX_VAR */ + tlistvarno = INDEX_VAR; + } + else + { + ExecAssignScanType(&scanstate->ss, RelationGetDescr(currentRelation)); + /* Node's targetlist will contain Vars with varno = scanrelid */ + tlistvarno = scanrelid; } /* * Initialize result tuple type and projection info. */ ExecAssignResultTypeFromTL(&scanstate->ss.ps); - ExecAssignScanProjectionInfo(&scanstate->ss); + ExecAssignScanProjectionInfoWithVarno(&scanstate->ss, tlistvarno); /* - * Acquire function pointers from the FDW's handler, and init fdw_state. + * Initialize FDW-related state. */ - fdwroutine = GetFdwRoutine(node->fdw_handler); scanstate->fdwroutine = fdwroutine; scanstate->fdw_state = NULL; /* - * Tell the FDW to initiate the scan. + * Tell the FDW to initialize the scan. */ fdwroutine->BeginForeignScan(scanstate, eflags); diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c index 06b7c3c457a..61bd644ab71 100644 --- a/src/backend/executor/nodeIndexonlyscan.c +++ b/src/backend/executor/nodeIndexonlyscan.c @@ -442,10 +442,12 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags) ExecAssignScanType(&indexstate->ss, tupDesc); /* - * Initialize result tuple type and projection info. + * Initialize result tuple type and projection info. The node's + * targetlist will contain Vars with varno = INDEX_VAR, referencing the + * scan tuple. */ ExecAssignResultTypeFromTL(&indexstate->ss.ps); - ExecAssignScanProjectionInfo(&indexstate->ss); + ExecAssignScanProjectionInfoWithVarno(&indexstate->ss, INDEX_VAR); /* * If we are just doing EXPLAIN (ie, aren't going to run the plan), stop |