Impressum nodeValuesscan.c
Sprache: C
/*-------------------------------------------------------------------------
*
* 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=92 H=95 G=93
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.19Bemerkung:
(vorverarbeitet am 2026-08-08)
¤
*Bot Zugriff
2026-08-25
Neuigkeiten
Aktuelles
Motto des Tages
Open Source Software
Jenseits des Üblichen ....
Besucherstatistik
Statistik
#Sources=141584
#Domains=738142