/* * ForeignRecheck -- access method routine to recheck a tuple in EvalPlanQual */ static bool ForeignRecheck(ForeignScanState *node, TupleTableSlot *slot) { FdwRoutine *fdwroutine = node->fdwroutine; ExprContext *econtext; /* * extract necessary information from foreign scan node */ econtext = node->ss.ps.ps_ExprContext; /* Does the tuple meet the remote qual condition? */ econtext->ecxt_scantuple = slot; ResetExprContext(econtext); /* * If an outer join is pushed down, RecheckForeignScan may need to store a * different tuple in the slot, because a different set of columns may go * to NULL upon recheck. Otherwise, it shouldn't need to change the slot * contents, just return true or false to indicate whether the quals still * pass. For simple cases, setting fdw_recheck_quals may be easier than * providing this callback. */ if (fdwroutine->RecheckForeignScan && !fdwroutine->RecheckForeignScan(node, slot)) return false; return ExecQual(node->fdw_recheck_quals, econtext, false); }
/* ---------------------------------------------------------------- * ExecForeignScanEstimate * * Informs size of the parallel coordination information, if any * ---------------------------------------------------------------- */ void ExecForeignScanEstimate(ForeignScanState *node, ParallelContext *pcxt) { FdwRoutine *fdwroutine = node->fdwroutine; if (fdwroutine->EstimateDSMForeignScan) { node->pscan_len = fdwroutine->EstimateDSMForeignScan(node, pcxt); shm_toc_estimate_chunk(&pcxt->estimator, node->pscan_len); shm_toc_estimate_keys(&pcxt->estimator, 1); } }
/* ---------------------------------------------------------------- * ExecForeignScanInitializeDSM * * Initialization according to the parallel coordination information * ---------------------------------------------------------------- */ void ExecForeignScanInitializeWorker(ForeignScanState *node, shm_toc *toc) { FdwRoutine *fdwroutine = node->fdwroutine; if (fdwroutine->InitializeWorkerForeignScan) { int plan_node_id = node->ss.ps.plan->plan_node_id; void *coordinate; coordinate = shm_toc_lookup(toc, plan_node_id); fdwroutine->InitializeWorkerForeignScan(node, toc, coordinate); } }
/* ---------------------------------------------------------------- * ExecForeignScanInitializeDSM * * Initialize the parallel coordination information * ---------------------------------------------------------------- */ void ExecForeignScanInitializeDSM(ForeignScanState *node, ParallelContext *pcxt) { FdwRoutine *fdwroutine = node->fdwroutine; if (fdwroutine->InitializeDSMForeignScan) { int plan_node_id = node->ss.ps.plan->plan_node_id; void *coordinate; coordinate = shm_toc_allocate(pcxt->toc, node->pscan_len); fdwroutine->InitializeDSMForeignScan(node, pcxt, coordinate); shm_toc_insert(pcxt->toc, plan_node_id, coordinate); } }
/* ---------------------------------------------------------------- * 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; }
/* ---------------------------------------------------------------- * ExecInitForeignScan * ---------------------------------------------------------------- */ 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 */ 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); scanstate->fdw_recheck_quals = (List *) ExecInitExpr((Expr *) node->fdw_recheck_quals, (PlanState *) scanstate); /* * tuple table initialization */ ExecInitResultTupleSlot(estate, &scanstate->ss.ps); ExecInitScanTupleSlot(estate, &scanstate->ss); /* * 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) { currentRelation = ExecOpenScanRelation(estate, scanrelid, eflags); scanstate->ss.ss_currentRelation = currentRelation; fdwroutine = GetFdwRoutineForRelation(currentRelation, true); } else { /* We can't use the relcache, so get fdwroutine the hard way */ fdwroutine = GetFdwRoutineByServerId(node->fs_server); } /* * 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); ExecAssignScanProjectionInfoWithVarno(&scanstate->ss, tlistvarno); /* * Initialize FDW-related state. */ scanstate->fdwroutine = fdwroutine; scanstate->fdw_state = NULL; /* Initialize any outer plan. */ if (outerPlan(node)) outerPlanState(scanstate) = ExecInitNode(outerPlan(node), estate, eflags); /* * Tell the FDW to initialize the scan. */ fdwroutine->BeginForeignScan(scanstate, eflags); return scanstate; }