/* * GetFdwRoutineForRelation - look up the handler of the foreign-data wrapper * for the given foreign table, and retrieve its FdwRoutine struct. * * This function is preferred over GetFdwRoutineByRelId because it caches * the data in the relcache entry, saving a number of catalog lookups. * * If makecopy is true then the returned data is freshly palloc'd in the * caller's memory context. Otherwise, it's a pointer to the relcache data, * which will be lost in any relcache reset --- so don't rely on it long. */ FdwRoutine * GetFdwRoutineForRelation(Relation relation, bool makecopy) { FdwRoutine *fdwroutine; FdwRoutine *cfdwroutine; if (relation->rd_fdwroutine == NULL) { /* Get the info by consulting the catalogs and the FDW code */ fdwroutine = GetFdwRoutineByRelId(RelationGetRelid(relation)); /* Save the data for later reuse in CacheMemoryContext */ cfdwroutine = (FdwRoutine *) MemoryContextAlloc(CacheMemoryContext, sizeof(FdwRoutine)); memcpy(cfdwroutine, fdwroutine, sizeof(FdwRoutine)); relation->rd_fdwroutine = cfdwroutine; /* Give back the locally palloc'd copy regardless of makecopy */ return fdwroutine; } /* We have valid cached data --- does the caller want a copy? */ if (makecopy) { fdwroutine = (FdwRoutine *) palloc(sizeof(FdwRoutine)); memcpy(fdwroutine, relation->rd_fdwroutine, sizeof(FdwRoutine)); return fdwroutine; } /* Only a short-lived reference is needed, so just hand back cached copy */ return relation->rd_fdwroutine; }
/* ---------------------------------------------------------------- * ExecInitForeignScan * ---------------------------------------------------------------- */ ForeignScanState * ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags) { ForeignScanState *scanstate; Relation currentRelation; FdwRoutine *fdwroutine; /* check for unsupported flags */ Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK))); /* * create state structure */ scanstate = makeNode(ForeignScanState); scanstate->ss.ps.plan = (Plan *) node; scanstate->ss.ps.state = estate; /* * Miscellaneous initialization * * create expression context for node */ ExecAssignExprContext(estate, &scanstate->ss.ps); scanstate->ss.ps.ps_TupFromTlist = false; /* * initialize child expressions */ scanstate->ss.ps.targetlist = (List *) ExecInitExpr((Expr *) node->scan.plan.targetlist, (PlanState *) scanstate); scanstate->ss.ps.qual = (List *) ExecInitExpr((Expr *) node->scan.plan.qual, (PlanState *) scanstate); /* * tuple table initialization */ ExecInitResultTupleSlot(estate, &scanstate->ss.ps); ExecInitScanTupleSlot(estate, &scanstate->ss); /* * open the base relation and acquire appropriate lock on it. */ currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid); scanstate->ss.ss_currentRelation = currentRelation; /* * get the scan type from the relation descriptor. */ ExecAssignScanType(&scanstate->ss, RelationGetDescr(currentRelation)); /* * Initialize result tuple type and projection info. */ ExecAssignResultTypeFromTL(&scanstate->ss.ps); ExecAssignScanProjectionInfo(&scanstate->ss); /* * Acquire function pointers from the FDW's handler, and init fdw_state. */ fdwroutine = GetFdwRoutineByRelId(RelationGetRelid(currentRelation)); scanstate->fdwroutine = fdwroutine; scanstate->fdw_state = NULL; /* * Tell the FDW to initiate the scan. */ fdwroutine->BeginForeignScan(scanstate, eflags); return scanstate; }
/* ---------------------------------------------------------------- * ExecInitForeignScan * ---------------------------------------------------------------- */ foreign_ss * ExecInitForeignScan(foreign_scan_sc *node, exec_state_n *estate, int eflags) { foreign_ss* scanstate; struct relation* currentRelation; FdwRoutine *fdwroutine; /* check for unsupported flags */ ASSERT(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK))); /* * create state structure */ scanstate = MK_N(ForeignScanState,foreign_ss); scanstate->ss.ps.plan = (plan_n *) node; scanstate->ss.ps.state = estate; /* * Miscellaneous initialization * * create expression context for node */ ExecAssignExprContext(estate, &scanstate->ss.ps); scanstate->ss.ps.ps_TupFromTlist = false; /* * initialize child expressions */ scanstate->ss.ps.targetlist = (struct list *) exec_init_expr( (expr_n *) node->scan.plan.targetlist, (plan_state_n *) scanstate); scanstate->ss.ps.qual = (struct list *) exec_init_expr( (expr_n *) node->scan.plan.qual, (plan_state_n *) scanstate); /* * tuple table initialization */ exec_init_result_tupslot(estate, &scanstate->ss.ps); exec_init_scan_tupslot(estate, &scanstate->ss); /* * open the base relation and acquire appropriate lock on it. */ currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid); scanstate->ss.ss_currentRelation = currentRelation; /* * get the scan type from the relation descriptor. */ ExecAssignScanType(&scanstate->ss, REL_DESC(currentRelation)); /* * Initialize result tuple type and projection info. */ ExecAssignResultTypeFromTL(&scanstate->ss.ps); ExecAssignScanProjectionInfo(&scanstate->ss); /* * Acquire function pointers from the FDW's handler, and init fdw_state. */ fdwroutine = GetFdwRoutineByRelId(REL_ID(currentRelation)); scanstate->fdwroutine = fdwroutine; scanstate->fdw_state = NULL; /* * Tell the FDW to initiate the scan. */ fdwroutine->BeginForeignScan(scanstate, eflags); return scanstate; }