LCOV - code coverage report
Current view: top level - src/backend/executor - nodeNamedtuplestorescan.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 71.8 % 39 28
Test Date: 2026-03-03 01:14:37 Functions: 60.0 % 5 3
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*-------------------------------------------------------------------------
       2              :  *
       3              :  * nodeNamedtuplestorescan.c
       4              :  *    routines to handle NamedTuplestoreScan nodes.
       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/nodeNamedtuplestorescan.c
      12              :  *
      13              :  *-------------------------------------------------------------------------
      14              :  */
      15              : 
      16              : #include "postgres.h"
      17              : 
      18              : #include "executor/executor.h"
      19              : #include "executor/nodeNamedtuplestorescan.h"
      20              : #include "utils/queryenvironment.h"
      21              : 
      22              : static TupleTableSlot *NamedTuplestoreScanNext(NamedTuplestoreScanState *node);
      23              : 
      24              : /* ----------------------------------------------------------------
      25              :  *      NamedTuplestoreScanNext
      26              :  *
      27              :  *      This is a workhorse for ExecNamedTuplestoreScan
      28              :  * ----------------------------------------------------------------
      29              :  */
      30              : static TupleTableSlot *
      31        33345 : NamedTuplestoreScanNext(NamedTuplestoreScanState *node)
      32              : {
      33              :     TupleTableSlot *slot;
      34              : 
      35              :     /* We intentionally do not support backward scan. */
      36              :     Assert(ScanDirectionIsForward(node->ss.ps.state->es_direction));
      37              : 
      38              :     /*
      39              :      * Get the next tuple from tuplestore. Return NULL if no more tuples.
      40              :      */
      41        33345 :     slot = node->ss.ss_ScanTupleSlot;
      42        33345 :     tuplestore_select_read_pointer(node->relation, node->readptr);
      43        33345 :     (void) tuplestore_gettupleslot(node->relation, true, false, slot);
      44        33345 :     return slot;
      45              : }
      46              : 
      47              : /*
      48              :  * NamedTuplestoreScanRecheck -- access method routine to recheck a tuple in
      49              :  * EvalPlanQual
      50              :  */
      51              : static bool
      52            0 : NamedTuplestoreScanRecheck(NamedTuplestoreScanState *node, TupleTableSlot *slot)
      53              : {
      54              :     /* nothing to check */
      55            0 :     return true;
      56              : }
      57              : 
      58              : /* ----------------------------------------------------------------
      59              :  *      ExecNamedTuplestoreScan(node)
      60              :  *
      61              :  *      Scans the CTE sequentially and returns the next qualifying tuple.
      62              :  *      We call the ExecScan() routine and pass it the appropriate
      63              :  *      access method functions.
      64              :  * ----------------------------------------------------------------
      65              :  */
      66              : static TupleTableSlot *
      67        33345 : ExecNamedTuplestoreScan(PlanState *pstate)
      68              : {
      69        33345 :     NamedTuplestoreScanState *node = castNode(NamedTuplestoreScanState, pstate);
      70              : 
      71        33345 :     return ExecScan(&node->ss,
      72              :                     (ExecScanAccessMtd) NamedTuplestoreScanNext,
      73              :                     (ExecScanRecheckMtd) NamedTuplestoreScanRecheck);
      74              : }
      75              : 
      76              : 
      77              : /* ----------------------------------------------------------------
      78              :  *      ExecInitNamedTuplestoreScan
      79              :  * ----------------------------------------------------------------
      80              :  */
      81              : NamedTuplestoreScanState *
      82          345 : ExecInitNamedTuplestoreScan(NamedTuplestoreScan *node, EState *estate, int eflags)
      83              : {
      84              :     NamedTuplestoreScanState *scanstate;
      85              :     EphemeralNamedRelation enr;
      86              : 
      87              :     /* check for unsupported flags */
      88              :     Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
      89              : 
      90              :     /*
      91              :      * NamedTuplestoreScan should not have any children.
      92              :      */
      93              :     Assert(outerPlan(node) == NULL);
      94              :     Assert(innerPlan(node) == NULL);
      95              : 
      96              :     /*
      97              :      * create new NamedTuplestoreScanState for node
      98              :      */
      99          345 :     scanstate = makeNode(NamedTuplestoreScanState);
     100          345 :     scanstate->ss.ps.plan = (Plan *) node;
     101          345 :     scanstate->ss.ps.state = estate;
     102          345 :     scanstate->ss.ps.ExecProcNode = ExecNamedTuplestoreScan;
     103              : 
     104          345 :     enr = get_ENR(estate->es_queryEnv, node->enrname);
     105          345 :     if (!enr)
     106            0 :         elog(ERROR, "executor could not find named tuplestore \"%s\"",
     107              :              node->enrname);
     108              : 
     109              :     Assert(enr->reldata);
     110          345 :     scanstate->relation = (Tuplestorestate *) enr->reldata;
     111          345 :     scanstate->tupdesc = ENRMetadataGetTupDesc(&(enr->md));
     112          345 :     scanstate->readptr =
     113          345 :         tuplestore_alloc_read_pointer(scanstate->relation, EXEC_FLAG_REWIND);
     114              : 
     115              :     /*
     116              :      * The new read pointer copies its position from read pointer 0, which
     117              :      * could be anywhere, so explicitly rewind it.
     118              :      */
     119          345 :     tuplestore_select_read_pointer(scanstate->relation, scanstate->readptr);
     120          345 :     tuplestore_rescan(scanstate->relation);
     121              : 
     122              :     /*
     123              :      * XXX: Should we add a function to free that read pointer when done?
     124              :      *
     125              :      * This was attempted, but it did not improve performance or memory usage
     126              :      * in any tested cases.
     127              :      */
     128              : 
     129              :     /*
     130              :      * Miscellaneous initialization
     131              :      *
     132              :      * create expression context for node
     133              :      */
     134          345 :     ExecAssignExprContext(estate, &scanstate->ss.ps);
     135              : 
     136              :     /*
     137              :      * The scan tuple type is specified for the tuplestore.
     138              :      */
     139          345 :     ExecInitScanTupleSlot(estate, &scanstate->ss, scanstate->tupdesc,
     140              :                           &TTSOpsMinimalTuple);
     141              : 
     142              :     /*
     143              :      * Initialize result type and projection.
     144              :      */
     145          345 :     ExecInitResultTypeTL(&scanstate->ss.ps);
     146          345 :     ExecAssignScanProjectionInfo(&scanstate->ss);
     147              : 
     148              :     /*
     149              :      * initialize child expressions
     150              :      */
     151          345 :     scanstate->ss.ps.qual =
     152          345 :         ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
     153              : 
     154          345 :     return scanstate;
     155              : }
     156              : 
     157              : /* ----------------------------------------------------------------
     158              :  *      ExecReScanNamedTuplestoreScan
     159              :  *
     160              :  *      Rescans the relation.
     161              :  * ----------------------------------------------------------------
     162              :  */
     163              : void
     164            0 : ExecReScanNamedTuplestoreScan(NamedTuplestoreScanState *node)
     165              : {
     166            0 :     Tuplestorestate *tuplestorestate = node->relation;
     167              : 
     168            0 :     if (node->ss.ps.ps_ResultTupleSlot)
     169            0 :         ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
     170              : 
     171            0 :     ExecScanReScan(&node->ss);
     172              : 
     173              :     /*
     174              :      * Rewind my own pointer.
     175              :      */
     176            0 :     tuplestore_select_read_pointer(tuplestorestate, node->readptr);
     177            0 :     tuplestore_rescan(tuplestorestate);
     178            0 : }
        

Generated by: LCOV version 2.0-1