Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Postgres/src/interfaces/ecpg/test/expected/   (Postgres Database Version 18.4©)  Datei vom 11.4.2026 mit Größe 37 B image not shown  

Quellcode-Bibliothek nodeValuesscan.c  Sprache: unbekannt

 
/*-------------------------------------------------------------------------
 *
 * nodeValuesscan.c
 *   Support routines for scanning Values lists
 *   ("VALUES (...), (...), ..." in rangetable).
 *
 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *   src/backend/executor/nodeValuesscan.c
 *
 *-------------------------------------------------------------------------
 */

/*
 * INTERFACE ROUTINES
 *  ExecValuesScan   scans a values list.
 *  ExecValuesNext   retrieve next tuple in sequential order.
 *  ExecInitValuesScan  creates and initializes a valuesscan node.
 *  ExecReScanValuesScan rescans the values list
 */

#include "postgres.h"

#include "executor/executor.h"
#include "executor/nodeValuesscan.h"
#include "jit/jit.h"
#include "optimizer/clauses.h"
#include "utils/expandeddatum.h"


static TupleTableSlot *ValuesNext(ValuesScanState *node);


/* ----------------------------------------------------------------
 *      Scan Support
 * ----------------------------------------------------------------
 */


/* ----------------------------------------------------------------
 *  ValuesNext
 *
 *  This is a workhorse for ExecValuesScan
 * ----------------------------------------------------------------
 */

static TupleTableSlot *
ValuesNext(ValuesScanState *node)
{
 TupleTableSlot *slot;
 EState    *estate;
 ExprContext *econtext;
 ScanDirection direction;
 int   curr_idx;

 /*
  * get information from the estate and scan state
 */

 estate = node->ss.ps.state;
 direction = estate->es_direction;
 slot = node->ss.ss_ScanTupleSlot;
 econtext = node->rowcontext;

 /*
  * Get the next tuple. Return NULL if no more tuples.
 */

 if (ScanDirectionIsForward(direction))
 {
  if (node->curr_idx < node->array_len)
   node->curr_idx++;
 }
 else
 {
  if (node->curr_idx >= 0)
   node->curr_idx--;
 }

 /*
  * Always clear the result slot; this is appropriate if we are at the end
  * of the data, and if we're not, we still need it as the first step of
  * the store-virtual-tuple protocol.  It seems wise to clear the slot
  * before we reset the context it might have pointers into.
 */

 ExecClearTuple(slot);

 curr_idx = node->curr_idx;
 if (curr_idx >= 0 && curr_idx < node->array_len)
 {
  List    *exprlist = node->exprlists[curr_idx];
  List    *exprstatelist = node->exprstatelists[curr_idx];
  MemoryContext oldContext;
  Datum    *values;
  bool    *isnull;
  ListCell   *lc;
  int   resind;

  /*
   * Get rid of any prior cycle's leftovers.  We use ReScanExprContext
   * not just ResetExprContext because we want any registered shutdown
   * callbacks to be called.
 */

  ReScanExprContext(econtext);

  /*
   * Do per-VALUES-row work in the per-tuple context.
 */

  oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);

  /*
   * Unless we already made the expression eval state for this row,
   * build it in the econtext's per-tuple memory.  This is a tad
   * unusual, but we want to delete the eval state again when we move to
   * the next row, to avoid growth of memory requirements over a long
   * values list.  For rows in which that won't work, we already built
   * the eval state at plan startup.
 */

  if (exprstatelist == NIL)
  {
   /*
    * Pass parent as NULL, not my plan node, because we don't want
    * anything in this transient state linking into permanent state.
    * The only expression type that might wish to do so is a SubPlan,
    * and we already checked that there aren't any.
    *
    * Note that passing parent = NULL also disables JIT compilation
    * of the expressions, which is a win, because they're only going
    * to be used once under normal circumstances.
 */

   exprstatelist = ExecInitExprList(exprlist, NULL);
  }

  /* parser should have checked all sublists are the same length */
  Assert(list_length(exprstatelist) == slot->tts_tupleDescriptor->natts);

  /*
   * Compute the expressions and build a virtual result tuple. We
   * already did ExecClearTuple(slot).
 */

  values = slot->tts_values;
  isnull = slot->tts_isnull;

  resind = 0;
  foreach(lc, exprstatelist)
  {
   ExprState  *estate = (ExprState *) lfirst(lc);
   CompactAttribute *attr = TupleDescCompactAttr(slot->tts_tupleDescriptor,
                resind);

   values[resind] = ExecEvalExpr(estate,
            econtext,
            &isnull[resind]);

   /*
    * We must force any R/W expanded datums to read-only state, in
    * case they are multiply referenced in the plan node's output
    * expressions, or in case we skip the output projection and the
    * output column is multiply referenced in higher plan nodes.
 */

   values[resind] = MakeExpandedObjectReadOnly(values[resind],
              isnull[resind],
              attr->attlen);

   resind++;
  }

  MemoryContextSwitchTo(oldContext);

  /*
   * And return the virtual tuple.
 */

  ExecStoreVirtualTuple(slot);
 }

 return slot;
}

/*
 * ValuesRecheck -- access method routine to recheck a tuple in EvalPlanQual
 */

static bool
ValuesRecheck(ValuesScanState *node, TupleTableSlot *slot)
{
 /* nothing to check */
 return true;
}

/* ----------------------------------------------------------------
 *  ExecValuesScan(node)
 *
 *  Scans the values lists sequentially and returns the next qualifying
 *  tuple.
 *  We call the ExecScan() routine and pass it the appropriate
 *  access method functions.
 * ----------------------------------------------------------------
 */

static TupleTableSlot *
ExecValuesScan(PlanState *pstate)
{
 ValuesScanState *node = castNode(ValuesScanState, pstate);

 return ExecScan(&node->ss,
     (ExecScanAccessMtd) ValuesNext,
     (ExecScanRecheckMtd) ValuesRecheck);
}

/* ----------------------------------------------------------------
 *  ExecInitValuesScan
 * ----------------------------------------------------------------
 */

ValuesScanState *
ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
{
 ValuesScanState *scanstate;
 TupleDesc tupdesc;
 ListCell   *vtl;
 int   i;
 PlanState  *planstate;

 /*
  * ValuesScan should not have any children.
 */

 Assert(outerPlan(node) == NULL);
 Assert(innerPlan(node) == NULL);

 /*
  * create new ScanState for node
 */

 scanstate = makeNode(ValuesScanState);
 scanstate->ss.ps.plan = (Plan *) node;
 scanstate->ss.ps.state = estate;
 scanstate->ss.ps.ExecProcNode = ExecValuesScan;

 /*
  * Miscellaneous initialization
 */

 planstate = &scanstate->ss.ps;

 /*
  * Create expression contexts.  We need two, one for per-sublist
  * processing and one for execScan.c to use for quals and projections. We
  * cheat a little by using ExecAssignExprContext() to build both.
 */

 ExecAssignExprContext(estate, planstate);
 scanstate->rowcontext = planstate->ps_ExprContext;
 ExecAssignExprContext(estate, planstate);

 /*
  * Get info about values list, initialize scan slot with it.
 */

 tupdesc = ExecTypeFromExprList((List *) linitial(node->values_lists));
 ExecInitScanTupleSlot(estate, &scanstate->ss, tupdesc, &TTSOpsVirtual);

 /*
  * Initialize result type and projection.
 */

 ExecInitResultTypeTL(&scanstate->ss.ps);
 ExecAssignScanProjectionInfo(&scanstate->ss);

 /*
  * initialize child expressions
 */

 scanstate->ss.ps.qual =
  ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);

 /*
  * Other node-specific setup
 */

 scanstate->curr_idx = -1;
 scanstate->array_len = list_length(node->values_lists);

 /*
  * Convert the list of expression sublists into an array for easier
  * addressing at runtime.  Also, detect whether any sublists contain
  * SubPlans; for just those sublists, go ahead and do expression
  * initialization.  (This avoids problems with SubPlans wanting to connect
  * themselves up to the outer plan tree.  Notably, EXPLAIN won't see the
  * subplans otherwise; also we will have troubles with dangling pointers
  * and/or leaked resources if we try to handle SubPlans the same as
  * simpler expressions.)
 */

 scanstate->exprlists = (List **)
  palloc(scanstate->array_len * sizeof(List *));
 scanstate->exprstatelists = (List **)
  palloc0(scanstate->array_len * sizeof(List *));
 i = 0;
 foreach(vtl, node->values_lists)
 {
  List    *exprs = lfirst_node(List, vtl);

  scanstate->exprlists[i] = exprs;

  /*
   * We can avoid the cost of a contain_subplans() scan in the simple
   * case where there are no SubPlans anywhere.
 */

  if (estate->es_subplanstates &&
   contain_subplans((Node *) exprs))
  {
   int   saved_jit_flags;

   /*
    * As these expressions are only used once, disable JIT for them.
    * This is worthwhile because it's common to insert significant
    * amounts of data via VALUES().  Note that this doesn't prevent
    * use of JIT *within* a subplan, since that's initialized
    * separately; this just affects the upper-level subexpressions.
 */

   saved_jit_flags = estate->es_jit_flags;
   estate->es_jit_flags = PGJIT_NONE;

   scanstate->exprstatelists[i] = ExecInitExprList(exprs,
               &scanstate->ss.ps);

   estate->es_jit_flags = saved_jit_flags;
  }
  i++;
 }

 return scanstate;
}

/* ----------------------------------------------------------------
 *  ExecReScanValuesScan
 *
 *  Rescans the relation.
 * ----------------------------------------------------------------
 */

void
ExecReScanValuesScan(ValuesScanState *node)
{
 if (node->ss.ps.ps_ResultTupleSlot)
  ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);

 ExecScanReScan(&node->ss);

 node->curr_idx = -1;
}

Messung V0.5 in Prozent
C=93 H=94 G=93

[0.15QuellennavigatorsProjekt 2026-09-28]