LCOV - code coverage report
Current view: top level - src/backend/executor - nodeForeignscan.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 76.8 % 142 109
Test Date: 2026-07-12 21:15:34 Functions: 71.4 % 14 10
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 66.7 % 66 44

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * nodeForeignscan.c
       4                 :             :  *    Routines to support scans of foreign tables
       5                 :             :  *
       6                 :             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
       7                 :             :  * Portions Copyright (c) 1994, Regents of the University of California
       8                 :             :  *
       9                 :             :  *
      10                 :             :  * IDENTIFICATION
      11                 :             :  *    src/backend/executor/nodeForeignscan.c
      12                 :             :  *
      13                 :             :  *-------------------------------------------------------------------------
      14                 :             :  */
      15                 :             : /*
      16                 :             :  * INTERFACE ROUTINES
      17                 :             :  *
      18                 :             :  *      ExecForeignScan         scans a foreign table.
      19                 :             :  *      ExecInitForeignScan     creates and initializes state info.
      20                 :             :  *      ExecReScanForeignScan   rescans the foreign relation.
      21                 :             :  *      ExecEndForeignScan      releases any resources allocated.
      22                 :             :  */
      23                 :             : #include "postgres.h"
      24                 :             : 
      25                 :             : #include "executor/executor.h"
      26                 :             : #include "executor/nodeForeignscan.h"
      27                 :             : #include "foreign/fdwapi.h"
      28                 :             : #include "utils/rel.h"
      29                 :             : 
      30                 :             : static TupleTableSlot *ForeignNext(ForeignScanState *node);
      31                 :             : static bool ForeignRecheck(ForeignScanState *node, TupleTableSlot *slot);
      32                 :             : 
      33                 :             : 
      34                 :             : /* ----------------------------------------------------------------
      35                 :             :  *      ForeignNext
      36                 :             :  *
      37                 :             :  *      This is a workhorse for ExecForeignScan
      38                 :             :  * ----------------------------------------------------------------
      39                 :             :  */
      40                 :             : static TupleTableSlot *
      41                 :       71484 : ForeignNext(ForeignScanState *node)
      42                 :             : {
      43                 :             :     TupleTableSlot *slot;
      44                 :       71484 :     ForeignScan *plan = (ForeignScan *) node->ss.ps.plan;
      45                 :       71484 :     ExprContext *econtext = node->ss.ps.ps_ExprContext;
      46                 :             :     MemoryContext oldcontext;
      47                 :             : 
      48                 :             :     /* Call the Iterate function in short-lived context */
      49                 :       71484 :     oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
      50         [ +  + ]:       71484 :     if (plan->operation != CMD_SELECT)
      51                 :             :     {
      52                 :             :         /*
      53                 :             :          * direct modifications cannot be re-evaluated, so shouldn't get here
      54                 :             :          * during EvalPlanQual processing
      55                 :             :          */
      56                 :             :         Assert(node->ss.ps.state->es_epq_active == NULL);
      57                 :             : 
      58                 :         420 :         slot = node->fdwroutine->IterateDirectModify(node);
      59                 :             :     }
      60                 :             :     else
      61                 :       71064 :         slot = node->fdwroutine->IterateForeignScan(node);
      62                 :       71460 :     MemoryContextSwitchTo(oldcontext);
      63                 :             : 
      64                 :             :     /*
      65                 :             :      * Insert valid value into tableoid, the only actually-useful system
      66                 :             :      * column.
      67                 :             :      */
      68   [ +  +  +  -  :       71460 :     if (plan->fsSystemCol && !TupIsNull(slot))
                   +  + ]
      69                 :        4537 :         slot->tts_tableOid = RelationGetRelid(node->ss.ss_currentRelation);
      70                 :             : 
      71                 :       71460 :     return slot;
      72                 :             : }
      73                 :             : 
      74                 :             : /*
      75                 :             :  * ForeignRecheck -- access method routine to recheck a tuple in EvalPlanQual
      76                 :             :  */
      77                 :             : static bool
      78                 :           5 : ForeignRecheck(ForeignScanState *node, TupleTableSlot *slot)
      79                 :             : {
      80                 :           5 :     FdwRoutine *fdwroutine = node->fdwroutine;
      81                 :             :     ExprContext *econtext;
      82                 :             : 
      83                 :             :     /*
      84                 :             :      * extract necessary information from foreign scan node
      85                 :             :      */
      86                 :           5 :     econtext = node->ss.ps.ps_ExprContext;
      87                 :             : 
      88                 :             :     /* Does the tuple meet the remote qual condition? */
      89                 :           5 :     econtext->ecxt_scantuple = slot;
      90                 :             : 
      91                 :           5 :     ResetExprContext(econtext);
      92                 :             : 
      93                 :             :     /*
      94                 :             :      * If an outer join is pushed down, RecheckForeignScan may need to store a
      95                 :             :      * different tuple in the slot, because a different set of columns may go
      96                 :             :      * to NULL upon recheck.  Otherwise, it shouldn't need to change the slot
      97                 :             :      * contents, just return true or false to indicate whether the quals still
      98                 :             :      * pass.  For simple cases, setting fdw_recheck_quals may be easier than
      99                 :             :      * providing this callback.
     100                 :             :      */
     101         [ +  - ]:           5 :     if (fdwroutine->RecheckForeignScan &&
     102         [ +  + ]:           5 :         !fdwroutine->RecheckForeignScan(node, slot))
     103                 :           1 :         return false;
     104                 :             : 
     105                 :           4 :     return ExecQual(node->fdw_recheck_quals, econtext);
     106                 :             : }
     107                 :             : 
     108                 :             : /* ----------------------------------------------------------------
     109                 :             :  *      ExecForeignScan(node)
     110                 :             :  *
     111                 :             :  *      Fetches the next tuple from the FDW, checks local quals, and
     112                 :             :  *      returns it.
     113                 :             :  *      We call the ExecScan() routine and pass it the appropriate
     114                 :             :  *      access method functions.
     115                 :             :  * ----------------------------------------------------------------
     116                 :             :  */
     117                 :             : static TupleTableSlot *
     118                 :       62405 : ExecForeignScan(PlanState *pstate)
     119                 :             : {
     120                 :       62405 :     ForeignScanState *node = castNode(ForeignScanState, pstate);
     121                 :       62405 :     ForeignScan *plan = (ForeignScan *) node->ss.ps.plan;
     122                 :       62405 :     EState     *estate = node->ss.ps.state;
     123                 :             : 
     124                 :             :     /*
     125                 :             :      * Ignore direct modifications when EvalPlanQual is active --- they are
     126                 :             :      * irrelevant for EvalPlanQual rechecking
     127                 :             :      */
     128   [ +  +  -  + ]:       62405 :     if (estate->es_epq_active != NULL && plan->operation != CMD_SELECT)
     129                 :           0 :         return NULL;
     130                 :             : 
     131                 :       62405 :     return ExecScan(&node->ss,
     132                 :             :                     (ExecScanAccessMtd) ForeignNext,
     133                 :             :                     (ExecScanRecheckMtd) ForeignRecheck);
     134                 :             : }
     135                 :             : 
     136                 :             : 
     137                 :             : /* ----------------------------------------------------------------
     138                 :             :  *      ExecInitForeignScan
     139                 :             :  * ----------------------------------------------------------------
     140                 :             :  */
     141                 :             : ForeignScanState *
     142                 :        1071 : ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags)
     143                 :             : {
     144                 :             :     ForeignScanState *scanstate;
     145                 :        1071 :     Relation    currentRelation = NULL;
     146                 :        1071 :     Index       scanrelid = node->scan.scanrelid;
     147                 :             :     int         tlistvarno;
     148                 :             :     FdwRoutine *fdwroutine;
     149                 :             : 
     150                 :             :     /* check for unsupported flags */
     151                 :             :     Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
     152                 :             : 
     153                 :             :     /*
     154                 :             :      * create state structure
     155                 :             :      */
     156                 :        1071 :     scanstate = makeNode(ForeignScanState);
     157                 :        1071 :     scanstate->ss.ps.plan = (Plan *) node;
     158                 :        1071 :     scanstate->ss.ps.state = estate;
     159                 :        1071 :     scanstate->ss.ps.ExecProcNode = ExecForeignScan;
     160                 :             : 
     161                 :             :     /*
     162                 :             :      * Miscellaneous initialization
     163                 :             :      *
     164                 :             :      * create expression context for node
     165                 :             :      */
     166                 :        1071 :     ExecAssignExprContext(estate, &scanstate->ss.ps);
     167                 :             : 
     168                 :             :     /*
     169                 :             :      * open the scan relation, if any; also acquire function pointers from the
     170                 :             :      * FDW's handler
     171                 :             :      */
     172         [ +  + ]:        1071 :     if (scanrelid > 0)
     173                 :             :     {
     174                 :         772 :         currentRelation = ExecOpenScanRelation(estate, scanrelid, eflags);
     175                 :         772 :         scanstate->ss.ss_currentRelation = currentRelation;
     176                 :         772 :         fdwroutine = GetFdwRoutineForRelation(currentRelation, true);
     177                 :             :     }
     178                 :             :     else
     179                 :             :     {
     180                 :             :         /* We can't use the relcache, so get fdwroutine the hard way */
     181                 :         299 :         fdwroutine = GetFdwRoutineByServerId(node->fs_server);
     182                 :             :     }
     183                 :             : 
     184                 :             :     /*
     185                 :             :      * Determine the scan tuple type.  If the FDW provided a targetlist
     186                 :             :      * describing the scan tuples, use that; else use base relation's rowtype.
     187                 :             :      */
     188   [ +  +  +  + ]:        1071 :     if (node->fdw_scan_tlist != NIL || currentRelation == NULL)
     189                 :         299 :     {
     190                 :             :         TupleDesc   scan_tupdesc;
     191                 :             : 
     192                 :         299 :         scan_tupdesc = ExecTypeFromTL(node->fdw_scan_tlist);
     193                 :         299 :         ExecInitScanTupleSlot(estate, &scanstate->ss, scan_tupdesc,
     194                 :             :                               &TTSOpsHeapTuple, 0);
     195                 :             :         /* Node's targetlist will contain Vars with varno = INDEX_VAR */
     196                 :         299 :         tlistvarno = INDEX_VAR;
     197                 :             :     }
     198                 :             :     else
     199                 :             :     {
     200                 :             :         TupleDesc   scan_tupdesc;
     201                 :             : 
     202                 :             :         /* don't trust FDWs to return tuples fulfilling NOT NULL constraints */
     203                 :         772 :         scan_tupdesc = CreateTupleDescCopy(RelationGetDescr(currentRelation));
     204                 :         772 :         ExecInitScanTupleSlot(estate, &scanstate->ss, scan_tupdesc,
     205                 :             :                               &TTSOpsHeapTuple, 0);
     206                 :             :         /* Node's targetlist will contain Vars with varno = scanrelid */
     207                 :         772 :         tlistvarno = scanrelid;
     208                 :             :     }
     209                 :             : 
     210                 :             :     /* Don't know what an FDW might return */
     211                 :        1071 :     scanstate->ss.ps.scanopsfixed = false;
     212                 :        1071 :     scanstate->ss.ps.scanopsset = true;
     213                 :             : 
     214                 :             :     /*
     215                 :             :      * Initialize result slot, type and projection.
     216                 :             :      */
     217                 :        1071 :     ExecInitResultTypeTL(&scanstate->ss.ps);
     218                 :        1071 :     ExecAssignScanProjectionInfoWithVarno(&scanstate->ss, tlistvarno);
     219                 :             : 
     220                 :             :     /*
     221                 :             :      * initialize child expressions
     222                 :             :      */
     223                 :        1071 :     scanstate->ss.ps.qual =
     224                 :        1071 :         ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
     225                 :        1071 :     scanstate->fdw_recheck_quals =
     226                 :        1071 :         ExecInitQual(node->fdw_recheck_quals, (PlanState *) scanstate);
     227                 :             : 
     228                 :             :     /*
     229                 :             :      * Determine whether to scan the foreign relation asynchronously or not;
     230                 :             :      * this has to be kept in sync with the code in ExecInitAppend().
     231                 :             :      */
     232         [ +  + ]:        1164 :     scanstate->ss.ps.async_capable = (((Plan *) node)->async_capable &&
     233         [ +  - ]:          93 :                                       estate->es_epq_active == NULL);
     234                 :             : 
     235                 :             :     /*
     236                 :             :      * Initialize FDW-related state.
     237                 :             :      */
     238                 :        1071 :     scanstate->fdwroutine = fdwroutine;
     239                 :        1071 :     scanstate->fdw_state = NULL;
     240                 :             : 
     241                 :             :     /*
     242                 :             :      * For the FDW's convenience, look up the modification target relation's
     243                 :             :      * ResultRelInfo.  The ModifyTable node should have initialized it for us,
     244                 :             :      * see ExecInitModifyTable.
     245                 :             :      *
     246                 :             :      * Don't try to look up the ResultRelInfo when EvalPlanQual is active,
     247                 :             :      * though.  Direct modifications cannot be re-evaluated as part of
     248                 :             :      * EvalPlanQual.  The lookup wouldn't work anyway because during
     249                 :             :      * EvalPlanQual processing, EvalPlanQual only initializes the subtree
     250                 :             :      * under the ModifyTable, and doesn't run ExecInitModifyTable.
     251                 :             :      */
     252   [ +  +  +  - ]:        1071 :     if (node->resultRelation > 0 && estate->es_epq_active == NULL)
     253                 :             :     {
     254         [ +  - ]:         106 :         if (estate->es_result_relations == NULL ||
     255         [ -  + ]:         106 :             estate->es_result_relations[node->resultRelation - 1] == NULL)
     256                 :             :         {
     257         [ #  # ]:           0 :             elog(ERROR, "result relation not initialized");
     258                 :             :         }
     259                 :         106 :         scanstate->resultRelInfo = estate->es_result_relations[node->resultRelation - 1];
     260                 :             :     }
     261                 :             : 
     262                 :             :     /* Initialize any outer plan. */
     263         [ +  + ]:        1071 :     if (outerPlan(node))
     264                 :          19 :         outerPlanState(scanstate) =
     265                 :          19 :             ExecInitNode(outerPlan(node), estate, eflags);
     266                 :             : 
     267                 :             :     /*
     268                 :             :      * Tell the FDW to initialize the scan.
     269                 :             :      */
     270         [ +  + ]:        1071 :     if (node->operation != CMD_SELECT)
     271                 :             :     {
     272                 :             :         /*
     273                 :             :          * Direct modifications cannot be re-evaluated by EvalPlanQual, so
     274                 :             :          * don't bother preparing the FDW.
     275                 :             :          *
     276                 :             :          * In case of an inherited UPDATE/DELETE with foreign targets there
     277                 :             :          * can be direct-modify ForeignScan nodes in the EvalPlanQual subtree,
     278                 :             :          * so we need to ignore such ForeignScan nodes during EvalPlanQual
     279                 :             :          * processing.  See also ExecForeignScan/ExecReScanForeignScan.
     280                 :             :          */
     281         [ +  - ]:         106 :         if (estate->es_epq_active == NULL)
     282                 :         106 :             fdwroutine->BeginDirectModify(scanstate, eflags);
     283                 :             :     }
     284                 :             :     else
     285                 :         965 :         fdwroutine->BeginForeignScan(scanstate, eflags);
     286                 :             : 
     287                 :        1058 :     return scanstate;
     288                 :             : }
     289                 :             : 
     290                 :             : /* ----------------------------------------------------------------
     291                 :             :  *      ExecEndForeignScan
     292                 :             :  *
     293                 :             :  *      frees any storage allocated through C routines.
     294                 :             :  * ----------------------------------------------------------------
     295                 :             :  */
     296                 :             : void
     297                 :        1017 : ExecEndForeignScan(ForeignScanState *node)
     298                 :             : {
     299                 :        1017 :     ForeignScan *plan = (ForeignScan *) node->ss.ps.plan;
     300                 :        1017 :     EState     *estate = node->ss.ps.state;
     301                 :             : 
     302                 :             :     /* Let the FDW shut down */
     303         [ +  + ]:        1017 :     if (plan->operation != CMD_SELECT)
     304                 :             :     {
     305         [ +  - ]:          98 :         if (estate->es_epq_active == NULL)
     306                 :          98 :             node->fdwroutine->EndDirectModify(node);
     307                 :             :     }
     308                 :             :     else
     309                 :         919 :         node->fdwroutine->EndForeignScan(node);
     310                 :             : 
     311                 :             :     /* Shut down any outer plan. */
     312         [ +  + ]:        1016 :     if (outerPlanState(node))
     313                 :          19 :         ExecEndNode(outerPlanState(node));
     314                 :        1016 : }
     315                 :             : 
     316                 :             : /* ----------------------------------------------------------------
     317                 :             :  *      ExecReScanForeignScan
     318                 :             :  *
     319                 :             :  *      Rescans the relation.
     320                 :             :  * ----------------------------------------------------------------
     321                 :             :  */
     322                 :             : void
     323                 :         410 : ExecReScanForeignScan(ForeignScanState *node)
     324                 :             : {
     325                 :         410 :     ForeignScan *plan = (ForeignScan *) node->ss.ps.plan;
     326                 :         410 :     EState     *estate = node->ss.ps.state;
     327                 :         410 :     PlanState  *outerPlan = outerPlanState(node);
     328                 :             : 
     329                 :             :     /*
     330                 :             :      * Ignore direct modifications when EvalPlanQual is active --- they are
     331                 :             :      * irrelevant for EvalPlanQual rechecking
     332                 :             :      */
     333   [ +  +  -  + ]:         410 :     if (estate->es_epq_active != NULL && plan->operation != CMD_SELECT)
     334                 :           0 :         return;
     335                 :             : 
     336                 :         410 :     node->fdwroutine->ReScanForeignScan(node);
     337                 :             : 
     338                 :             :     /*
     339                 :             :      * If chgParam of subnode is not null then plan will be re-scanned by
     340                 :             :      * first ExecProcNode.  outerPlan may also be NULL, in which case there is
     341                 :             :      * nothing to rescan at all.
     342                 :             :      */
     343   [ +  +  +  - ]:         410 :     if (outerPlan != NULL && outerPlan->chgParam == NULL)
     344                 :          10 :         ExecReScan(outerPlan);
     345                 :             : 
     346                 :         410 :     ExecScanReScan(&node->ss);
     347                 :             : }
     348                 :             : 
     349                 :             : /* ----------------------------------------------------------------
     350                 :             :  *      ExecForeignScanEstimate
     351                 :             :  *
     352                 :             :  *      Informs size of the parallel coordination information, if any
     353                 :             :  * ----------------------------------------------------------------
     354                 :             :  */
     355                 :             : void
     356                 :           0 : ExecForeignScanEstimate(ForeignScanState *node, ParallelContext *pcxt)
     357                 :             : {
     358                 :           0 :     FdwRoutine *fdwroutine = node->fdwroutine;
     359                 :             : 
     360         [ #  # ]:           0 :     if (fdwroutine->EstimateDSMForeignScan)
     361                 :             :     {
     362                 :           0 :         node->pscan_len = fdwroutine->EstimateDSMForeignScan(node, pcxt);
     363                 :           0 :         shm_toc_estimate_chunk(&pcxt->estimator, node->pscan_len);
     364                 :           0 :         shm_toc_estimate_keys(&pcxt->estimator, 1);
     365                 :             :     }
     366                 :           0 : }
     367                 :             : 
     368                 :             : /* ----------------------------------------------------------------
     369                 :             :  *      ExecForeignScanInitializeDSM
     370                 :             :  *
     371                 :             :  *      Initialize the parallel coordination information
     372                 :             :  * ----------------------------------------------------------------
     373                 :             :  */
     374                 :             : void
     375                 :           0 : ExecForeignScanInitializeDSM(ForeignScanState *node, ParallelContext *pcxt)
     376                 :             : {
     377                 :           0 :     FdwRoutine *fdwroutine = node->fdwroutine;
     378                 :             : 
     379         [ #  # ]:           0 :     if (fdwroutine->InitializeDSMForeignScan)
     380                 :             :     {
     381                 :           0 :         int         plan_node_id = node->ss.ps.plan->plan_node_id;
     382                 :             :         void       *coordinate;
     383                 :             : 
     384                 :           0 :         coordinate = shm_toc_allocate(pcxt->toc, node->pscan_len);
     385                 :           0 :         fdwroutine->InitializeDSMForeignScan(node, pcxt, coordinate);
     386                 :           0 :         shm_toc_insert(pcxt->toc, plan_node_id, coordinate);
     387                 :             :     }
     388                 :           0 : }
     389                 :             : 
     390                 :             : /* ----------------------------------------------------------------
     391                 :             :  *      ExecForeignScanReInitializeDSM
     392                 :             :  *
     393                 :             :  *      Reset shared state before beginning a fresh scan.
     394                 :             :  * ----------------------------------------------------------------
     395                 :             :  */
     396                 :             : void
     397                 :           0 : ExecForeignScanReInitializeDSM(ForeignScanState *node, ParallelContext *pcxt)
     398                 :             : {
     399                 :           0 :     FdwRoutine *fdwroutine = node->fdwroutine;
     400                 :             : 
     401         [ #  # ]:           0 :     if (fdwroutine->ReInitializeDSMForeignScan)
     402                 :             :     {
     403                 :           0 :         int         plan_node_id = node->ss.ps.plan->plan_node_id;
     404                 :             :         void       *coordinate;
     405                 :             : 
     406                 :           0 :         coordinate = shm_toc_lookup(pcxt->toc, plan_node_id, false);
     407                 :           0 :         fdwroutine->ReInitializeDSMForeignScan(node, pcxt, coordinate);
     408                 :             :     }
     409                 :           0 : }
     410                 :             : 
     411                 :             : /* ----------------------------------------------------------------
     412                 :             :  *      ExecForeignScanInitializeWorker
     413                 :             :  *
     414                 :             :  *      Initialization according to the parallel coordination information
     415                 :             :  * ----------------------------------------------------------------
     416                 :             :  */
     417                 :             : void
     418                 :           0 : ExecForeignScanInitializeWorker(ForeignScanState *node,
     419                 :             :                                 ParallelWorkerContext *pwcxt)
     420                 :             : {
     421                 :           0 :     FdwRoutine *fdwroutine = node->fdwroutine;
     422                 :             : 
     423         [ #  # ]:           0 :     if (fdwroutine->InitializeWorkerForeignScan)
     424                 :             :     {
     425                 :           0 :         int         plan_node_id = node->ss.ps.plan->plan_node_id;
     426                 :             :         void       *coordinate;
     427                 :             : 
     428                 :           0 :         coordinate = shm_toc_lookup(pwcxt->toc, plan_node_id, false);
     429                 :           0 :         fdwroutine->InitializeWorkerForeignScan(node, pwcxt->toc, coordinate);
     430                 :             :     }
     431                 :           0 : }
     432                 :             : 
     433                 :             : /* ----------------------------------------------------------------
     434                 :             :  *      ExecShutdownForeignScan
     435                 :             :  *
     436                 :             :  *      Gives FDW chance to stop asynchronous resource consumption
     437                 :             :  *      and release any resources still held.
     438                 :             :  * ----------------------------------------------------------------
     439                 :             :  */
     440                 :             : void
     441                 :         589 : ExecShutdownForeignScan(ForeignScanState *node)
     442                 :             : {
     443                 :         589 :     FdwRoutine *fdwroutine = node->fdwroutine;
     444                 :             : 
     445         [ -  + ]:         589 :     if (fdwroutine->ShutdownForeignScan)
     446                 :           0 :         fdwroutine->ShutdownForeignScan(node);
     447                 :         589 : }
     448                 :             : 
     449                 :             : /* ----------------------------------------------------------------
     450                 :             :  *      ExecAsyncForeignScanRequest
     451                 :             :  *
     452                 :             :  *      Asynchronously request a tuple from a designed async-capable node
     453                 :             :  * ----------------------------------------------------------------
     454                 :             :  */
     455                 :             : void
     456                 :        6175 : ExecAsyncForeignScanRequest(AsyncRequest *areq)
     457                 :             : {
     458                 :        6175 :     ForeignScanState *node = (ForeignScanState *) areq->requestee;
     459                 :        6175 :     FdwRoutine *fdwroutine = node->fdwroutine;
     460                 :             : 
     461                 :             :     Assert(fdwroutine->ForeignAsyncRequest != NULL);
     462                 :        6175 :     fdwroutine->ForeignAsyncRequest(areq);
     463                 :        6175 : }
     464                 :             : 
     465                 :             : /* ----------------------------------------------------------------
     466                 :             :  *      ExecAsyncForeignScanConfigureWait
     467                 :             :  *
     468                 :             :  *      In async mode, configure for a wait
     469                 :             :  * ----------------------------------------------------------------
     470                 :             :  */
     471                 :             : void
     472                 :         248 : ExecAsyncForeignScanConfigureWait(AsyncRequest *areq)
     473                 :             : {
     474                 :         248 :     ForeignScanState *node = (ForeignScanState *) areq->requestee;
     475                 :         248 :     FdwRoutine *fdwroutine = node->fdwroutine;
     476                 :             : 
     477                 :             :     Assert(fdwroutine->ForeignAsyncConfigureWait != NULL);
     478                 :         248 :     fdwroutine->ForeignAsyncConfigureWait(areq);
     479                 :         247 : }
     480                 :             : 
     481                 :             : /* ----------------------------------------------------------------
     482                 :             :  *      ExecAsyncForeignScanNotify
     483                 :             :  *
     484                 :             :  *      Callback invoked when a relevant event has occurred
     485                 :             :  * ----------------------------------------------------------------
     486                 :             :  */
     487                 :             : void
     488                 :         149 : ExecAsyncForeignScanNotify(AsyncRequest *areq)
     489                 :             : {
     490                 :         149 :     ForeignScanState *node = (ForeignScanState *) areq->requestee;
     491                 :         149 :     FdwRoutine *fdwroutine = node->fdwroutine;
     492                 :             : 
     493                 :             :     Assert(fdwroutine->ForeignAsyncNotify != NULL);
     494                 :         149 :     fdwroutine->ForeignAsyncNotify(areq);
     495                 :         149 : }
        

Generated by: LCOV version 2.0-1