Header And Logo

PostgreSQL
| The world's most advanced open source database.

Data Structures | Defines | Typedefs | Functions | Variables

executor.h File Reference

#include "executor/execdesc.h"
#include "nodes/parsenodes.h"
Include dependency graph for executor.h:

Go to the source code of this file.

Data Structures

struct  TupOutputState

Defines

#define EXEC_FLAG_EXPLAIN_ONLY   0x0001
#define EXEC_FLAG_REWIND   0x0002
#define EXEC_FLAG_BACKWARD   0x0004
#define EXEC_FLAG_MARK   0x0008
#define EXEC_FLAG_SKIP_TRIGGERS   0x0010
#define EXEC_FLAG_WITH_OIDS   0x0020
#define EXEC_FLAG_WITHOUT_OIDS   0x0040
#define EXEC_FLAG_WITH_NO_DATA   0x0080
#define ExecEvalExpr(expr, econtext, isNull, isDone)   ((*(expr)->evalfunc) (expr, econtext, isNull, isDone))
#define EvalPlanQualSetSlot(epqstate, slot)   ((epqstate)->origslot = (slot))
#define do_text_output_oneline(tstate, str_to_emit)
#define ResetExprContext(econtext)   MemoryContextReset((econtext)->ecxt_per_tuple_memory)
#define GetPerTupleExprContext(estate)
#define GetPerTupleMemoryContext(estate)   (GetPerTupleExprContext(estate)->ecxt_per_tuple_memory)
#define ResetPerTupleExprContext(estate)

Typedefs

typedef void(* ExecutorStart_hook_type )(QueryDesc *queryDesc, int eflags)
typedef void(* ExecutorRun_hook_type )(QueryDesc *queryDesc, ScanDirection direction, long count)
typedef void(* ExecutorFinish_hook_type )(QueryDesc *queryDesc)
typedef void(* ExecutorEnd_hook_type )(QueryDesc *queryDesc)
typedef bool(* ExecutorCheckPerms_hook_type )(List *, bool)
typedef TupleTableSlot *(* ExecScanAccessMtd )(ScanState *node)
typedef bool(* ExecScanRecheckMtd )(ScanState *node, TupleTableSlot *slot)
typedef struct TupOutputState TupOutputState

Functions

void ExecReScan (PlanState *node)
void ExecMarkPos (PlanState *node)
void ExecRestrPos (PlanState *node)
bool ExecSupportsMarkRestore (NodeTag plantype)
bool ExecSupportsBackwardScan (Plan *node)
bool ExecMaterializesOutput (NodeTag plantype)
bool execCurrentOf (CurrentOfExpr *cexpr, ExprContext *econtext, Oid table_oid, ItemPointer current_tid)
bool execTuplesMatch (TupleTableSlot *slot1, TupleTableSlot *slot2, int numCols, AttrNumber *matchColIdx, FmgrInfo *eqfunctions, MemoryContext evalContext)
bool execTuplesUnequal (TupleTableSlot *slot1, TupleTableSlot *slot2, int numCols, AttrNumber *matchColIdx, FmgrInfo *eqfunctions, MemoryContext evalContext)
FmgrInfoexecTuplesMatchPrepare (int numCols, Oid *eqOperators)
void execTuplesHashPrepare (int numCols, Oid *eqOperators, FmgrInfo **eqFunctions, FmgrInfo **hashFunctions)
TupleHashTable BuildTupleHashTable (int numCols, AttrNumber *keyColIdx, FmgrInfo *eqfunctions, FmgrInfo *hashfunctions, long nbuckets, Size entrysize, MemoryContext tablecxt, MemoryContext tempcxt)
TupleHashEntry LookupTupleHashEntry (TupleHashTable hashtable, TupleTableSlot *slot, bool *isnew)
TupleHashEntry FindTupleHashEntry (TupleHashTable hashtable, TupleTableSlot *slot, FmgrInfo *eqfunctions, FmgrInfo *hashfunctions)
JunkFilterExecInitJunkFilter (List *targetList, bool hasoid, TupleTableSlot *slot)
JunkFilterExecInitJunkFilterConversion (List *targetList, TupleDesc cleanTupType, TupleTableSlot *slot)
AttrNumber ExecFindJunkAttribute (JunkFilter *junkfilter, const char *attrName)
AttrNumber ExecFindJunkAttributeInTlist (List *targetlist, const char *attrName)
Datum ExecGetJunkAttribute (TupleTableSlot *slot, AttrNumber attno, bool *isNull)
TupleTableSlotExecFilterJunk (JunkFilter *junkfilter, TupleTableSlot *slot)
void ExecutorStart (QueryDesc *queryDesc, int eflags)
void standard_ExecutorStart (QueryDesc *queryDesc, int eflags)
void ExecutorRun (QueryDesc *queryDesc, ScanDirection direction, long count)
void standard_ExecutorRun (QueryDesc *queryDesc, ScanDirection direction, long count)
void ExecutorFinish (QueryDesc *queryDesc)
void standard_ExecutorFinish (QueryDesc *queryDesc)
void ExecutorEnd (QueryDesc *queryDesc)
void standard_ExecutorEnd (QueryDesc *queryDesc)
void ExecutorRewind (QueryDesc *queryDesc)
bool ExecCheckRTPerms (List *rangeTable, bool ereport_on_violation)
void CheckValidResultRel (Relation resultRel, CmdType operation)
void InitResultRelInfo (ResultRelInfo *resultRelInfo, Relation resultRelationDesc, Index resultRelationIndex, int instrument_options)
ResultRelInfoExecGetTriggerResultRel (EState *estate, Oid relid)
bool ExecContextForcesOids (PlanState *planstate, bool *hasoids)
void ExecConstraints (ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate)
ExecRowMarkExecFindRowMark (EState *estate, Index rti)
ExecAuxRowMarkExecBuildAuxRowMark (ExecRowMark *erm, List *targetlist)
TupleTableSlotEvalPlanQual (EState *estate, EPQState *epqstate, Relation relation, Index rti, int lockmode, ItemPointer tid, TransactionId priorXmax)
HeapTuple EvalPlanQualFetch (EState *estate, Relation relation, int lockmode, ItemPointer tid, TransactionId priorXmax)
void EvalPlanQualInit (EPQState *epqstate, EState *estate, Plan *subplan, List *auxrowmarks, int epqParam)
void EvalPlanQualSetPlan (EPQState *epqstate, Plan *subplan, List *auxrowmarks)
void EvalPlanQualSetTuple (EPQState *epqstate, Index rti, HeapTuple tuple)
HeapTuple EvalPlanQualGetTuple (EPQState *epqstate, Index rti)
void EvalPlanQualFetchRowMarks (EPQState *epqstate)
TupleTableSlotEvalPlanQualNext (EPQState *epqstate)
void EvalPlanQualBegin (EPQState *epqstate, EState *parentestate)
void EvalPlanQualEnd (EPQState *epqstate)
PlanStateExecInitNode (Plan *node, EState *estate, int eflags)
TupleTableSlotExecProcNode (PlanState *node)
NodeMultiExecProcNode (PlanState *node)
void ExecEndNode (PlanState *node)
Datum GetAttributeByNum (HeapTupleHeader tuple, AttrNumber attrno, bool *isNull)
Datum GetAttributeByName (HeapTupleHeader tuple, const char *attname, bool *isNull)
TuplestorestateExecMakeTableFunctionResult (ExprState *funcexpr, ExprContext *econtext, TupleDesc expectedDesc, bool randomAccess)
Datum ExecEvalExprSwitchContext (ExprState *expression, ExprContext *econtext, bool *isNull, ExprDoneCond *isDone)
ExprStateExecInitExpr (Expr *node, PlanState *parent)
ExprStateExecPrepareExpr (Expr *node, EState *estate)
bool ExecQual (List *qual, ExprContext *econtext, bool resultForNull)
int ExecTargetListLength (List *targetlist)
int ExecCleanTargetListLength (List *targetlist)
TupleTableSlotExecProject (ProjectionInfo *projInfo, ExprDoneCond *isDone)
TupleTableSlotExecScan (ScanState *node, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd)
void ExecAssignScanProjectionInfo (ScanState *node)
void ExecScanReScan (ScanState *node)
void ExecInitResultTupleSlot (EState *estate, PlanState *planstate)
void ExecInitScanTupleSlot (EState *estate, ScanState *scanstate)
TupleTableSlotExecInitExtraTupleSlot (EState *estate)
TupleTableSlotExecInitNullTupleSlot (EState *estate, TupleDesc tupType)
TupleDesc ExecTypeFromTL (List *targetList, bool hasoid)
TupleDesc ExecCleanTypeFromTL (List *targetList, bool hasoid)
TupleDesc ExecTypeFromExprList (List *exprList, List *namesList)
void UpdateChangedParamSet (PlanState *node, Bitmapset *newchg)
TupOutputStatebegin_tup_output_tupdesc (DestReceiver *dest, TupleDesc tupdesc)
void do_tup_output (TupOutputState *tstate, Datum *values, bool *isnull)
void do_text_output_multiline (TupOutputState *tstate, char *text)
void end_tup_output (TupOutputState *tstate)
EStateCreateExecutorState (void)
void FreeExecutorState (EState *estate)
ExprContextCreateExprContext (EState *estate)
ExprContextCreateStandaloneExprContext (void)
void FreeExprContext (ExprContext *econtext, bool isCommit)
void ReScanExprContext (ExprContext *econtext)
ExprContextMakePerTupleExprContext (EState *estate)
void ExecAssignExprContext (EState *estate, PlanState *planstate)
void ExecAssignResultType (PlanState *planstate, TupleDesc tupDesc)
void ExecAssignResultTypeFromTL (PlanState *planstate)
TupleDesc ExecGetResultType (PlanState *planstate)
ProjectionInfoExecBuildProjectionInfo (List *targetList, ExprContext *econtext, TupleTableSlot *slot, TupleDesc inputDesc)
void ExecAssignProjectionInfo (PlanState *planstate, TupleDesc inputDesc)
void ExecFreeExprContext (PlanState *planstate)
TupleDesc ExecGetScanType (ScanState *scanstate)
void ExecAssignScanType (ScanState *scanstate, TupleDesc tupDesc)
void ExecAssignScanTypeFromOuterPlan (ScanState *scanstate)
bool ExecRelationIsTargetRelation (EState *estate, Index scanrelid)
Relation ExecOpenScanRelation (EState *estate, Index scanrelid, int eflags)
void ExecCloseScanRelation (Relation scanrel)
void ExecOpenIndices (ResultRelInfo *resultRelInfo)
void ExecCloseIndices (ResultRelInfo *resultRelInfo)
ListExecInsertIndexTuples (TupleTableSlot *slot, ItemPointer tupleid, EState *estate)
bool check_exclusion_constraint (Relation heap, Relation index, IndexInfo *indexInfo, ItemPointer tupleid, Datum *values, bool *isnull, EState *estate, bool newIndex, bool errorOK)
void RegisterExprContextCallback (ExprContext *econtext, ExprContextCallbackFunction function, Datum arg)
void UnregisterExprContextCallback (ExprContext *econtext, ExprContextCallbackFunction function, Datum arg)

Variables

PGDLLIMPORT ExecutorStart_hook_type ExecutorStart_hook
PGDLLIMPORT ExecutorRun_hook_type ExecutorRun_hook
PGDLLIMPORT
ExecutorFinish_hook_type 
ExecutorFinish_hook
PGDLLIMPORT ExecutorEnd_hook_type ExecutorEnd_hook
PGDLLIMPORT
ExecutorCheckPerms_hook_type 
ExecutorCheckPerms_hook

Define Documentation

#define do_text_output_oneline (   tstate,
  str_to_emit 
)
Value:
do { \
        Datum   values_[1]; \
        bool    isnull_[1]; \
        values_[0] = PointerGetDatum(cstring_to_text(str_to_emit)); \
        isnull_[0] = false; \
        do_tup_output(tstate, values_, isnull_); \
        pfree(DatumGetPointer(values_[0])); \
    } while (0)

Definition at line 285 of file executor.h.

Referenced by ExplainQuery(), and ShowGUCConfigOption().

#define EvalPlanQualSetSlot (   epqstate,
  slot 
)    ((epqstate)->origslot = (slot))

Definition at line 209 of file executor.h.

Referenced by ExecLockRows(), and ExecModifyTable().

#define EXEC_FLAG_BACKWARD   0x0004
#define EXEC_FLAG_EXPLAIN_ONLY   0x0001
#define EXEC_FLAG_MARK   0x0008
#define EXEC_FLAG_REWIND   0x0002
#define EXEC_FLAG_SKIP_TRIGGERS   0x0010

Definition at line 61 of file executor.h.

Referenced by standard_ExecutorFinish(), and standard_ExecutorStart().

#define EXEC_FLAG_WITH_NO_DATA   0x0080

Definition at line 64 of file executor.h.

Referenced by ExecOpenScanRelation().

#define EXEC_FLAG_WITH_OIDS   0x0020

Definition at line 62 of file executor.h.

Referenced by ExecContextForcesOids().

#define EXEC_FLAG_WITHOUT_OIDS   0x0040

Definition at line 63 of file executor.h.

Referenced by ExecContextForcesOids(), and refresh_matview_datafill().

#define ExecEvalExpr (   expr,
  econtext,
  isNull,
  isDone 
)    ((*(expr)->evalfunc) (expr, econtext, isNull, isDone))
#define GetPerTupleExprContext (   estate  ) 
#define GetPerTupleMemoryContext (   estate  )     (GetPerTupleExprContext(estate)->ecxt_per_tuple_memory)
#define ResetExprContext (   econtext  )     MemoryContextReset((econtext)->ecxt_per_tuple_memory)
#define ResetPerTupleExprContext (   estate  ) 
Value:
do { \
        if ((estate)->es_per_tuple_exprcontext) \
            ResetExprContext((estate)->es_per_tuple_exprcontext); \
    } while (0)

Definition at line 321 of file executor.h.

Referenced by comparetup_cluster(), CopyFrom(), ExecModifyTable(), ExecPostprocessPlan(), and ExecutePlan().


Typedef Documentation

Definition at line 247 of file executor.h.

typedef bool(* ExecScanRecheckMtd)(ScanState *node, TupleTableSlot *slot)

Definition at line 248 of file executor.h.

Definition at line 95 of file executor.h.

typedef void(* ExecutorEnd_hook_type)(QueryDesc *queryDesc)

Definition at line 91 of file executor.h.

typedef void(* ExecutorFinish_hook_type)(QueryDesc *queryDesc)

Definition at line 87 of file executor.h.

typedef void(* ExecutorRun_hook_type)(QueryDesc *queryDesc, ScanDirection direction, long count)

Definition at line 81 of file executor.h.

typedef void(* ExecutorStart_hook_type)(QueryDesc *queryDesc, int eflags)

Definition at line 77 of file executor.h.


Function Documentation

TupOutputState* begin_tup_output_tupdesc ( DestReceiver dest,
TupleDesc  tupdesc 
)

Definition at line 1142 of file execTuples.c.

References TupOutputState::dest, MakeSingleTupleTableSlot(), palloc(), _DestReceiver::rStartup, and TupOutputState::slot.

Referenced by ExplainQuery(), ShowAllGUCConfig(), and ShowGUCConfigOption().

{
    TupOutputState *tstate;

    tstate = (TupOutputState *) palloc(sizeof(TupOutputState));

    tstate->slot = MakeSingleTupleTableSlot(tupdesc);
    tstate->dest = dest;

    (*tstate->dest->rStartup) (tstate->dest, (int) CMD_SELECT, tupdesc);

    return tstate;
}

TupleHashTable BuildTupleHashTable ( int  numCols,
AttrNumber keyColIdx,
FmgrInfo eqfunctions,
FmgrInfo hashfunctions,
long  nbuckets,
Size  entrysize,
MemoryContext  tablecxt,
MemoryContext  tempcxt 
)

Definition at line 275 of file execGrouping.c.

References Assert, TupleHashTableData::cur_eq_funcs, HASHCTL::entrysize, TupleHashTableData::entrysize, HASHCTL::hash, HASH_COMPARE, HASH_CONTEXT, hash_create(), HASH_ELEM, HASH_FUNCTION, TupleHashTableData::hashtab, HASHCTL::hcxt, TupleHashTableData::in_hash_funcs, TupleHashTableData::inputslot, TupleHashTableData::keyColIdx, HASHCTL::keysize, HASHCTL::match, MemoryContextAlloc(), MemSet, Min, TupleHashTableData::numCols, TupleHashTableData::tab_eq_funcs, TupleHashTableData::tab_hash_funcs, TupleHashTableData::tablecxt, TupleHashTableData::tableslot, TupleHashTableData::tempcxt, and work_mem.

Referenced by build_hash_table(), and buildSubPlanHash().

{
    TupleHashTable hashtable;
    HASHCTL     hash_ctl;

    Assert(nbuckets > 0);
    Assert(entrysize >= sizeof(TupleHashEntryData));

    /* Limit initial table size request to not more than work_mem */
    nbuckets = Min(nbuckets, (long) ((work_mem * 1024L) / entrysize));

    hashtable = (TupleHashTable) MemoryContextAlloc(tablecxt,
                                                 sizeof(TupleHashTableData));

    hashtable->numCols = numCols;
    hashtable->keyColIdx = keyColIdx;
    hashtable->tab_hash_funcs = hashfunctions;
    hashtable->tab_eq_funcs = eqfunctions;
    hashtable->tablecxt = tablecxt;
    hashtable->tempcxt = tempcxt;
    hashtable->entrysize = entrysize;
    hashtable->tableslot = NULL;    /* will be made on first lookup */
    hashtable->inputslot = NULL;
    hashtable->in_hash_funcs = NULL;
    hashtable->cur_eq_funcs = NULL;

    MemSet(&hash_ctl, 0, sizeof(hash_ctl));
    hash_ctl.keysize = sizeof(TupleHashEntryData);
    hash_ctl.entrysize = entrysize;
    hash_ctl.hash = TupleHashTableHash;
    hash_ctl.match = TupleHashTableMatch;
    hash_ctl.hcxt = tablecxt;
    hashtable->hashtab = hash_create("TupleHashTable", nbuckets,
                                     &hash_ctl,
                    HASH_ELEM | HASH_FUNCTION | HASH_COMPARE | HASH_CONTEXT);

    return hashtable;
}

bool check_exclusion_constraint ( Relation  heap,
Relation  index,
IndexInfo indexInfo,
ItemPointer  tupleid,
Datum values,
bool isnull,
EState estate,
bool  newIndex,
bool  errorOK 
)

Definition at line 1174 of file execUtils.c.

References BuildIndexValueDescription(), ExprContext::ecxt_scantuple, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, errtableconstraint(), ExecDropSingleTupleTableSlot(), ExecStoreTuple(), FormIndexDatum(), ForwardScanDirection, GetPerTupleExprContext, i, IndexInfo::ii_ExclusionProcs, IndexInfo::ii_ExclusionStrats, index_beginscan(), index_endscan(), index_getnext(), index_recheck_constraint(), index_rescan(), InitDirtySnapshot, InvalidBuffer, InvalidOid, ItemPointerEquals(), MakeSingleTupleTableSlot(), NULL, RelationData::rd_indcollation, RelationData::rd_index, RelationGetDescr, RelationGetRelationName, ScanKeyEntryInitialize(), HeapTupleData::t_self, TransactionIdIsValid, XactLockTableWait(), SnapshotData::xmax, SnapshotData::xmin, and IndexScanDescData::xs_recheck.

Referenced by ExecInsertIndexTuples(), and IndexCheckExclusion().

{
    Oid        *constr_procs = indexInfo->ii_ExclusionProcs;
    uint16     *constr_strats = indexInfo->ii_ExclusionStrats;
    Oid        *index_collations = index->rd_indcollation;
    int         index_natts = index->rd_index->indnatts;
    IndexScanDesc index_scan;
    HeapTuple   tup;
    ScanKeyData scankeys[INDEX_MAX_KEYS];
    SnapshotData DirtySnapshot;
    int         i;
    bool        conflict;
    bool        found_self;
    ExprContext *econtext;
    TupleTableSlot *existing_slot;
    TupleTableSlot *save_scantuple;

    /*
     * If any of the input values are NULL, the constraint check is assumed to
     * pass (i.e., we assume the operators are strict).
     */
    for (i = 0; i < index_natts; i++)
    {
        if (isnull[i])
            return true;
    }

    /*
     * Search the tuples that are in the index for any violations, including
     * tuples that aren't visible yet.
     */
    InitDirtySnapshot(DirtySnapshot);

    for (i = 0; i < index_natts; i++)
    {
        ScanKeyEntryInitialize(&scankeys[i],
                               0,
                               i + 1,
                               constr_strats[i],
                               InvalidOid,
                               index_collations[i],
                               constr_procs[i],
                               values[i]);
    }

    /*
     * Need a TupleTableSlot to put existing tuples in.
     *
     * To use FormIndexDatum, we have to make the econtext's scantuple point
     * to this slot.  Be sure to save and restore caller's value for
     * scantuple.
     */
    existing_slot = MakeSingleTupleTableSlot(RelationGetDescr(heap));

    econtext = GetPerTupleExprContext(estate);
    save_scantuple = econtext->ecxt_scantuple;
    econtext->ecxt_scantuple = existing_slot;

    /*
     * May have to restart scan from this point if a potential conflict is
     * found.
     */
retry:
    conflict = false;
    found_self = false;
    index_scan = index_beginscan(heap, index, &DirtySnapshot, index_natts, 0);
    index_rescan(index_scan, scankeys, index_natts, NULL, 0);

    while ((tup = index_getnext(index_scan,
                                ForwardScanDirection)) != NULL)
    {
        TransactionId xwait;
        Datum       existing_values[INDEX_MAX_KEYS];
        bool        existing_isnull[INDEX_MAX_KEYS];
        char       *error_new;
        char       *error_existing;

        /*
         * Ignore the entry for the tuple we're trying to check.
         */
        if (ItemPointerEquals(tupleid, &tup->t_self))
        {
            if (found_self)     /* should not happen */
                elog(ERROR, "found self tuple multiple times in index \"%s\"",
                     RelationGetRelationName(index));
            found_self = true;
            continue;
        }

        /*
         * Extract the index column values and isnull flags from the existing
         * tuple.
         */
        ExecStoreTuple(tup, existing_slot, InvalidBuffer, false);
        FormIndexDatum(indexInfo, existing_slot, estate,
                       existing_values, existing_isnull);

        /* If lossy indexscan, must recheck the condition */
        if (index_scan->xs_recheck)
        {
            if (!index_recheck_constraint(index,
                                          constr_procs,
                                          existing_values,
                                          existing_isnull,
                                          values))
                continue;       /* tuple doesn't actually match, so no
                                 * conflict */
        }

        /*
         * At this point we have either a conflict or a potential conflict. If
         * we're not supposed to raise error, just return the fact of the
         * potential conflict without waiting to see if it's real.
         */
        if (errorOK)
        {
            conflict = true;
            break;
        }

        /*
         * If an in-progress transaction is affecting the visibility of this
         * tuple, we need to wait for it to complete and then recheck.  For
         * simplicity we do rechecking by just restarting the whole scan ---
         * this case probably doesn't happen often enough to be worth trying
         * harder, and anyway we don't want to hold any index internal locks
         * while waiting.
         */
        xwait = TransactionIdIsValid(DirtySnapshot.xmin) ?
            DirtySnapshot.xmin : DirtySnapshot.xmax;

        if (TransactionIdIsValid(xwait))
        {
            index_endscan(index_scan);
            XactLockTableWait(xwait);
            goto retry;
        }

        /*
         * We have a definite conflict.  Report it.
         */
        error_new = BuildIndexValueDescription(index, values, isnull);
        error_existing = BuildIndexValueDescription(index, existing_values,
                                                    existing_isnull);
        if (newIndex)
            ereport(ERROR,
                    (errcode(ERRCODE_EXCLUSION_VIOLATION),
                     errmsg("could not create exclusion constraint \"%s\"",
                            RelationGetRelationName(index)),
                     errdetail("Key %s conflicts with key %s.",
                               error_new, error_existing),
                     errtableconstraint(heap,
                                        RelationGetRelationName(index))));
        else
            ereport(ERROR,
                    (errcode(ERRCODE_EXCLUSION_VIOLATION),
                     errmsg("conflicting key value violates exclusion constraint \"%s\"",
                            RelationGetRelationName(index)),
                     errdetail("Key %s conflicts with existing key %s.",
                               error_new, error_existing),
                     errtableconstraint(heap,
                                        RelationGetRelationName(index))));
    }

    index_endscan(index_scan);

    /*
     * Ordinarily, at this point the search should have found the originally
     * inserted tuple, unless we exited the loop early because of conflict.
     * However, it is possible to define exclusion constraints for which that
     * wouldn't be true --- for instance, if the operator is <>. So we no
     * longer complain if found_self is still false.
     */

    econtext->ecxt_scantuple = save_scantuple;

    ExecDropSingleTupleTableSlot(existing_slot);

    return !conflict;
}

void CheckValidResultRel ( Relation  resultRel,
CmdType  operation 
)

Definition at line 939 of file execMain.c.

References CMD_DELETE, CMD_INSERT, CMD_UPDATE, elog, ereport, errcode(), errhint(), errmsg(), ERROR, FdwRoutine::ExecForeignDelete, FdwRoutine::ExecForeignInsert, FdwRoutine::ExecForeignUpdate, GetFdwRoutineForRelation(), NULL, RelationData::rd_rel, RelationGetRelationName, RELKIND_FOREIGN_TABLE, RELKIND_MATVIEW, RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_TOASTVALUE, RELKIND_VIEW, TriggerDesc::trig_delete_instead_row, TriggerDesc::trig_insert_instead_row, TriggerDesc::trig_update_instead_row, and RelationData::trigdesc.

Referenced by ExecInitModifyTable().

{
    TriggerDesc *trigDesc = resultRel->trigdesc;
    FdwRoutine *fdwroutine;

    switch (resultRel->rd_rel->relkind)
    {
        case RELKIND_RELATION:
            /* OK */
            break;
        case RELKIND_SEQUENCE:
            ereport(ERROR,
                    (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                     errmsg("cannot change sequence \"%s\"",
                            RelationGetRelationName(resultRel))));
            break;
        case RELKIND_TOASTVALUE:
            ereport(ERROR,
                    (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                     errmsg("cannot change TOAST relation \"%s\"",
                            RelationGetRelationName(resultRel))));
            break;
        case RELKIND_VIEW:
            /*
             * Okay only if there's a suitable INSTEAD OF trigger.  Messages
             * here should match rewriteHandler.c's rewriteTargetView, except
             * that we omit errdetail because we haven't got the information
             * handy (and given that we really shouldn't get here anyway,
             * it's not worth great exertion to get).
             */
            switch (operation)
            {
                case CMD_INSERT:
                    if (!trigDesc || !trigDesc->trig_insert_instead_row)
                        ereport(ERROR,
                          (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
                           errmsg("cannot insert into view \"%s\"",
                                  RelationGetRelationName(resultRel)),
                           errhint("To make the view insertable, provide an unconditional ON INSERT DO INSTEAD rule or an INSTEAD OF INSERT trigger.")));
                    break;
                case CMD_UPDATE:
                    if (!trigDesc || !trigDesc->trig_update_instead_row)
                        ereport(ERROR,
                          (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
                           errmsg("cannot update view \"%s\"",
                                  RelationGetRelationName(resultRel)),
                           errhint("To make the view updatable, provide an unconditional ON UPDATE DO INSTEAD rule or an INSTEAD OF UPDATE trigger.")));
                    break;
                case CMD_DELETE:
                    if (!trigDesc || !trigDesc->trig_delete_instead_row)
                        ereport(ERROR,
                          (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
                           errmsg("cannot delete from view \"%s\"",
                                  RelationGetRelationName(resultRel)),
                           errhint("To make the view updatable, provide an unconditional ON DELETE DO INSTEAD rule or an INSTEAD OF DELETE trigger.")));
                    break;
                default:
                    elog(ERROR, "unrecognized CmdType: %d", (int) operation);
                    break;
            }
            break;
        case RELKIND_MATVIEW:
            ereport(ERROR,
                    (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                     errmsg("cannot change materialized view \"%s\"",
                            RelationGetRelationName(resultRel))));
            break;
        case RELKIND_FOREIGN_TABLE:
            /* Okay only if the FDW supports it */
            fdwroutine = GetFdwRoutineForRelation(resultRel, false);
            switch (operation)
            {
                case CMD_INSERT:
                    if (fdwroutine->ExecForeignInsert == NULL)
                        ereport(ERROR,
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                 errmsg("cannot insert into foreign table \"%s\"",
                                        RelationGetRelationName(resultRel))));
                    break;
                case CMD_UPDATE:
                    if (fdwroutine->ExecForeignUpdate == NULL)
                        ereport(ERROR,
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                 errmsg("cannot update foreign table \"%s\"",
                                        RelationGetRelationName(resultRel))));
                    break;
                case CMD_DELETE:
                    if (fdwroutine->ExecForeignDelete == NULL)
                        ereport(ERROR,
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                 errmsg("cannot delete from foreign table \"%s\"",
                                        RelationGetRelationName(resultRel))));
                    break;
                default:
                    elog(ERROR, "unrecognized CmdType: %d", (int) operation);
                    break;
            }
            break;
        default:
            ereport(ERROR,
                    (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                     errmsg("cannot change relation \"%s\"",
                            RelationGetRelationName(resultRel))));
            break;
    }
}

EState* CreateExecutorState ( void   ) 

Definition at line 81 of file execUtils.c.

References ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, ALLOCSET_DEFAULT_MINSIZE, AllocSetContextCreate(), CurrentMemoryContext, EState::es_auxmodifytables, EState::es_crosscheck_snapshot, EState::es_direction, EState::es_epqScanDone, EState::es_epqTuple, EState::es_epqTupleSet, EState::es_exprcontexts, EState::es_finished, EState::es_instrument, EState::es_junkFilter, EState::es_lastoid, EState::es_num_result_relations, EState::es_output_cid, EState::es_param_exec_vals, EState::es_param_list_info, EState::es_per_tuple_exprcontext, EState::es_plannedstmt, EState::es_processed, EState::es_query_cxt, EState::es_range_table, EState::es_result_relation_info, EState::es_result_relations, EState::es_rowMarks, EState::es_snapshot, EState::es_subplanstates, EState::es_top_eflags, EState::es_trig_newtup_slot, EState::es_trig_oldtup_slot, EState::es_trig_target_relations, EState::es_trig_tuple_slot, EState::es_tupleTable, makeNode, and MemoryContextSwitchTo().

Referenced by afterTriggerInvokeEvents(), ATRewriteTable(), btree_predicate_proof(), compute_index_stats(), CopyFrom(), EvalPlanQualStart(), evaluate_expr(), ExecuteQuery(), ExecuteTruncate(), ExplainExecuteQuery(), get_actual_variable_range(), IndexBuildHeapScan(), IndexCheckExclusion(), plpgsql_create_econtext(), standard_ExecutorStart(), tuplesort_begin_cluster(), validate_index_heapscan(), validateCheckConstraint(), and validateDomainConstraint().

{
    EState     *estate;
    MemoryContext qcontext;
    MemoryContext oldcontext;

    /*
     * Create the per-query context for this Executor run.
     */
    qcontext = AllocSetContextCreate(CurrentMemoryContext,
                                     "ExecutorState",
                                     ALLOCSET_DEFAULT_MINSIZE,
                                     ALLOCSET_DEFAULT_INITSIZE,
                                     ALLOCSET_DEFAULT_MAXSIZE);

    /*
     * Make the EState node within the per-query context.  This way, we don't
     * need a separate pfree() operation for it at shutdown.
     */
    oldcontext = MemoryContextSwitchTo(qcontext);

    estate = makeNode(EState);

    /*
     * Initialize all fields of the Executor State structure
     */
    estate->es_direction = ForwardScanDirection;
    estate->es_snapshot = SnapshotNow;
    estate->es_crosscheck_snapshot = InvalidSnapshot;   /* no crosscheck */
    estate->es_range_table = NIL;
    estate->es_plannedstmt = NULL;

    estate->es_junkFilter = NULL;

    estate->es_output_cid = (CommandId) 0;

    estate->es_result_relations = NULL;
    estate->es_num_result_relations = 0;
    estate->es_result_relation_info = NULL;

    estate->es_trig_target_relations = NIL;
    estate->es_trig_tuple_slot = NULL;
    estate->es_trig_oldtup_slot = NULL;
    estate->es_trig_newtup_slot = NULL;

    estate->es_param_list_info = NULL;
    estate->es_param_exec_vals = NULL;

    estate->es_query_cxt = qcontext;

    estate->es_tupleTable = NIL;

    estate->es_rowMarks = NIL;

    estate->es_processed = 0;
    estate->es_lastoid = InvalidOid;

    estate->es_top_eflags = 0;
    estate->es_instrument = 0;
    estate->es_finished = false;

    estate->es_exprcontexts = NIL;

    estate->es_subplanstates = NIL;

    estate->es_auxmodifytables = NIL;

    estate->es_per_tuple_exprcontext = NULL;

    estate->es_epqTuple = NULL;
    estate->es_epqTupleSet = NULL;
    estate->es_epqScanDone = NULL;

    /*
     * Return the executor state structure
     */
    MemoryContextSwitchTo(oldcontext);

    return estate;
}

ExprContext* CreateExprContext ( EState estate  ) 

Definition at line 218 of file execUtils.c.

References ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, ALLOCSET_DEFAULT_MINSIZE, AllocSetContextCreate(), ExprContext::caseValue_datum, ExprContext::caseValue_isNull, ExprContext::domainValue_datum, ExprContext::domainValue_isNull, ExprContext::ecxt_aggnulls, ExprContext::ecxt_aggvalues, ExprContext::ecxt_callbacks, ExprContext::ecxt_estate, ExprContext::ecxt_innertuple, ExprContext::ecxt_outertuple, ExprContext::ecxt_param_exec_vals, ExprContext::ecxt_param_list_info, ExprContext::ecxt_per_query_memory, ExprContext::ecxt_per_tuple_memory, ExprContext::ecxt_scantuple, EState::es_exprcontexts, EState::es_param_exec_vals, EState::es_param_list_info, EState::es_query_cxt, lcons(), makeNode, and MemoryContextSwitchTo().

Referenced by ExecAssignExprContext(), ExecInitMergeJoin(), ExecInitModifyTable(), ExecInitSubPlan(), MakePerTupleExprContext(), and plpgsql_create_econtext().

{
    ExprContext *econtext;
    MemoryContext oldcontext;

    /* Create the ExprContext node within the per-query memory context */
    oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);

    econtext = makeNode(ExprContext);

    /* Initialize fields of ExprContext */
    econtext->ecxt_scantuple = NULL;
    econtext->ecxt_innertuple = NULL;
    econtext->ecxt_outertuple = NULL;

    econtext->ecxt_per_query_memory = estate->es_query_cxt;

    /*
     * Create working memory for expression evaluation in this context.
     */
    econtext->ecxt_per_tuple_memory =
        AllocSetContextCreate(estate->es_query_cxt,
                              "ExprContext",
                              ALLOCSET_DEFAULT_MINSIZE,
                              ALLOCSET_DEFAULT_INITSIZE,
                              ALLOCSET_DEFAULT_MAXSIZE);

    econtext->ecxt_param_exec_vals = estate->es_param_exec_vals;
    econtext->ecxt_param_list_info = estate->es_param_list_info;

    econtext->ecxt_aggvalues = NULL;
    econtext->ecxt_aggnulls = NULL;

    econtext->caseValue_datum = (Datum) 0;
    econtext->caseValue_isNull = true;

    econtext->domainValue_datum = (Datum) 0;
    econtext->domainValue_isNull = true;

    econtext->ecxt_estate = estate;

    econtext->ecxt_callbacks = NULL;

    /*
     * Link the ExprContext into the EState to ensure it is shut down when the
     * EState is freed.  Because we use lcons(), shutdowns will occur in
     * reverse order of creation, which may not be essential but can't hurt.
     */
    estate->es_exprcontexts = lcons(econtext, estate->es_exprcontexts);

    MemoryContextSwitchTo(oldcontext);

    return econtext;
}

ExprContext* CreateStandaloneExprContext ( void   ) 

Definition at line 292 of file execUtils.c.

References ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, ALLOCSET_DEFAULT_MINSIZE, AllocSetContextCreate(), ExprContext::caseValue_datum, ExprContext::caseValue_isNull, CurrentMemoryContext, ExprContext::domainValue_datum, ExprContext::domainValue_isNull, ExprContext::ecxt_aggnulls, ExprContext::ecxt_aggvalues, ExprContext::ecxt_callbacks, ExprContext::ecxt_estate, ExprContext::ecxt_innertuple, ExprContext::ecxt_outertuple, ExprContext::ecxt_param_exec_vals, ExprContext::ecxt_param_list_info, ExprContext::ecxt_per_query_memory, ExprContext::ecxt_per_tuple_memory, ExprContext::ecxt_scantuple, and makeNode.

Referenced by domain_check_input().

{
    ExprContext *econtext;

    /* Create the ExprContext node within the caller's memory context */
    econtext = makeNode(ExprContext);

    /* Initialize fields of ExprContext */
    econtext->ecxt_scantuple = NULL;
    econtext->ecxt_innertuple = NULL;
    econtext->ecxt_outertuple = NULL;

    econtext->ecxt_per_query_memory = CurrentMemoryContext;

    /*
     * Create working memory for expression evaluation in this context.
     */
    econtext->ecxt_per_tuple_memory =
        AllocSetContextCreate(CurrentMemoryContext,
                              "ExprContext",
                              ALLOCSET_DEFAULT_MINSIZE,
                              ALLOCSET_DEFAULT_INITSIZE,
                              ALLOCSET_DEFAULT_MAXSIZE);

    econtext->ecxt_param_exec_vals = NULL;
    econtext->ecxt_param_list_info = NULL;

    econtext->ecxt_aggvalues = NULL;
    econtext->ecxt_aggnulls = NULL;

    econtext->caseValue_datum = (Datum) 0;
    econtext->caseValue_isNull = true;

    econtext->domainValue_datum = (Datum) 0;
    econtext->domainValue_isNull = true;

    econtext->ecxt_estate = NULL;

    econtext->ecxt_callbacks = NULL;

    return econtext;
}

void do_text_output_multiline ( TupOutputState tstate,
char *  text 
)

Definition at line 1188 of file execTuples.c.

References cstring_to_text_with_len(), DatumGetPointer, do_tup_output(), pfree(), PointerGetDatum, and values.

Referenced by ExplainQuery().

{
    Datum       values[1];
    bool        isnull[1] = {false};

    while (*text)
    {
        char       *eol;
        int         len;

        eol = strchr(text, '\n');
        if (eol)
        {
            len = eol - text;

            eol++;
        }
        else
        {
            len = strlen(text);
            eol += len;
        }

        values[0] = PointerGetDatum(cstring_to_text_with_len(text, len));
        do_tup_output(tstate, values, isnull);
        pfree(DatumGetPointer(values[0]));
        text = eol;
    }
}

void do_tup_output ( TupOutputState tstate,
Datum values,
bool isnull 
)

Definition at line 1160 of file execTuples.c.

References TupOutputState::dest, ExecClearTuple(), ExecStoreVirtualTuple(), tupleDesc::natts, _DestReceiver::receiveSlot, TupOutputState::slot, TupleTableSlot::tts_isnull, TupleTableSlot::tts_tupleDescriptor, and TupleTableSlot::tts_values.

Referenced by do_text_output_multiline(), and ShowAllGUCConfig().

{
    TupleTableSlot *slot = tstate->slot;
    int         natts = slot->tts_tupleDescriptor->natts;

    /* make sure the slot is clear */
    ExecClearTuple(slot);

    /* insert data */
    memcpy(slot->tts_values, values, natts * sizeof(Datum));
    memcpy(slot->tts_isnull, isnull, natts * sizeof(bool));

    /* mark slot as containing a virtual tuple */
    ExecStoreVirtualTuple(slot);

    /* send the tuple to the receiver */
    (*tstate->dest->receiveSlot) (slot, tstate->dest);

    /* clean up */
    ExecClearTuple(slot);
}

void end_tup_output ( TupOutputState tstate  ) 

Definition at line 1219 of file execTuples.c.

References TupOutputState::dest, ExecDropSingleTupleTableSlot(), pfree(), _DestReceiver::rShutdown, and TupOutputState::slot.

Referenced by ExplainQuery(), ShowAllGUCConfig(), and ShowGUCConfigOption().

{
    (*tstate->dest->rShutdown) (tstate->dest);
    /* note that destroying the dest is not ours to do */
    ExecDropSingleTupleTableSlot(tstate->slot);
    pfree(tstate);
}

TupleTableSlot* EvalPlanQual ( EState estate,
EPQState epqstate,
Relation  relation,
Index  rti,
int  lockmode,
ItemPointer  tid,
TransactionId  priorXmax 
)

Definition at line 1765 of file execMain.c.

References Assert, EvalPlanQualBegin(), EvalPlanQualFetch(), EvalPlanQualFetchRowMarks(), EvalPlanQualNext(), EvalPlanQualSetTuple(), ExecMaterializeSlot(), NULL, HeapTupleData::t_self, and TupIsNull.

Referenced by ExecDelete(), ExecUpdate(), and GetTupleForTrigger().

{
    TupleTableSlot *slot;
    HeapTuple   copyTuple;

    Assert(rti > 0);

    /*
     * Get and lock the updated version of the row; if fail, return NULL.
     */
    copyTuple = EvalPlanQualFetch(estate, relation, lockmode,
                                  tid, priorXmax);

    if (copyTuple == NULL)
        return NULL;

    /*
     * For UPDATE/DELETE we have to return tid of actual row we're executing
     * PQ for.
     */
    *tid = copyTuple->t_self;

    /*
     * Need to run a recheck subquery.  Initialize or reinitialize EPQ state.
     */
    EvalPlanQualBegin(epqstate, estate);

    /*
     * Free old test tuple, if any, and store new tuple where relation's scan
     * node will see it
     */
    EvalPlanQualSetTuple(epqstate, rti, copyTuple);

    /*
     * Fetch any non-locked source rows
     */
    EvalPlanQualFetchRowMarks(epqstate);

    /*
     * Run the EPQ query.  We assume it will return at most one tuple.
     */
    slot = EvalPlanQualNext(epqstate);

    /*
     * If we got a tuple, force the slot to materialize the tuple so that it
     * is not dependent on any local state in the EPQ query (in particular,
     * it's highly likely that the slot contains references to any pass-by-ref
     * datums that may be present in copyTuple).  As with the next step, this
     * is to guard against early re-use of the EPQ query.
     */
    if (!TupIsNull(slot))
        (void) ExecMaterializeSlot(slot);

    /*
     * Clear out the test tuple.  This is needed in case the EPQ query is
     * re-used to test a tuple for a different relation.  (Not clear that can
     * really happen, but let's be safe.)
     */
    EvalPlanQualSetTuple(epqstate, rti, NULL);

    return slot;
}

void EvalPlanQualBegin ( EPQState epqstate,
EState parentestate 
)

Definition at line 2230 of file execMain.c.

References bms_add_member(), PlanState::chgParam, EPQState::epqParam, EState::es_epqScanDone, EState::es_param_exec_vals, EState::es_plannedstmt, EState::es_range_table, EPQState::estate, EvalPlanQualStart(), i, ParamExecData::isnull, list_length(), MemSet, PlannedStmt::nParamExec, NULL, EPQState::plan, EPQState::planstate, and ParamExecData::value.

Referenced by EvalPlanQual(), and ExecLockRows().

{
    EState     *estate = epqstate->estate;

    if (estate == NULL)
    {
        /* First time through, so create a child EState */
        EvalPlanQualStart(epqstate, parentestate, epqstate->plan);
    }
    else
    {
        /*
         * We already have a suitable child EPQ tree, so just reset it.
         */
        int         rtsize = list_length(parentestate->es_range_table);
        PlanState  *planstate = epqstate->planstate;

        MemSet(estate->es_epqScanDone, 0, rtsize * sizeof(bool));

        /* Recopy current values of parent parameters */
        if (parentestate->es_plannedstmt->nParamExec > 0)
        {
            int         i = parentestate->es_plannedstmt->nParamExec;

            while (--i >= 0)
            {
                /* copy value if any, but not execPlan link */
                estate->es_param_exec_vals[i].value =
                    parentestate->es_param_exec_vals[i].value;
                estate->es_param_exec_vals[i].isnull =
                    parentestate->es_param_exec_vals[i].isnull;
            }
        }

        /*
         * Mark child plan tree as needing rescan at all scan nodes.  The
         * first ExecProcNode will take care of actually doing the rescan.
         */
        planstate->chgParam = bms_add_member(planstate->chgParam,
                                             epqstate->epqParam);
    }
}

void EvalPlanQualEnd ( EPQState epqstate  ) 

Definition at line 2402 of file execMain.c.

References EState::es_query_cxt, EState::es_subplanstates, EState::es_trig_target_relations, EState::es_tupleTable, EPQState::estate, ExecCloseIndices(), ExecEndNode(), ExecResetTupleTable(), FreeExecutorState(), heap_close, lfirst, MemoryContextSwitchTo(), NoLock, NULL, EPQState::origslot, EPQState::planstate, and ResultRelInfo::ri_RelationDesc.

Referenced by EvalPlanQualSetPlan(), ExecEndLockRows(), and ExecEndModifyTable().

{
    EState     *estate = epqstate->estate;
    MemoryContext oldcontext;
    ListCell   *l;

    if (estate == NULL)
        return;                 /* idle, so nothing to do */

    oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);

    ExecEndNode(epqstate->planstate);

    foreach(l, estate->es_subplanstates)
    {
        PlanState  *subplanstate = (PlanState *) lfirst(l);

        ExecEndNode(subplanstate);
    }

    /* throw away the per-estate tuple table */
    ExecResetTupleTable(estate->es_tupleTable, false);

    /* close any trigger target relations attached to this EState */
    foreach(l, estate->es_trig_target_relations)
    {
        ResultRelInfo *resultRelInfo = (ResultRelInfo *) lfirst(l);

        /* Close indices and then the relation itself */
        ExecCloseIndices(resultRelInfo);
        heap_close(resultRelInfo->ri_RelationDesc, NoLock);
    }

    MemoryContextSwitchTo(oldcontext);

    FreeExecutorState(estate);

    /* Mark EPQState idle */
    epqstate->estate = NULL;
    epqstate->planstate = NULL;
    epqstate->origslot = NULL;
}

HeapTuple EvalPlanQualFetch ( EState estate,
Relation  relation,
int  lockmode,
ItemPointer  tid,
TransactionId  priorXmax 
)

Definition at line 1848 of file execMain.c.

References HeapUpdateFailureData::ctid, elog, ereport, errcode(), errmsg(), ERROR, EState::es_output_cid, heap_copytuple(), heap_fetch(), heap_lock_tuple(), HeapTupleHeaderGetCmin(), HeapTupleHeaderGetUpdateXid, HeapTupleHeaderGetXmin, HeapTupleMayBeUpdated, HeapTupleSelfUpdated, HeapTupleUpdated, InitDirtySnapshot, IsolationUsesXactSnapshot, ItemPointerEquals(), NULL, ReleaseBuffer(), HeapTupleHeaderData::t_ctid, HeapTupleData::t_data, HeapTupleData::t_self, TransactionIdEquals, TransactionIdIsCurrentTransactionId(), TransactionIdIsValid, XactLockTableWait(), HeapUpdateFailureData::xmax, SnapshotData::xmax, and SnapshotData::xmin.

Referenced by EvalPlanQual(), and ExecLockRows().

{
    HeapTuple   copyTuple = NULL;
    HeapTupleData tuple;
    SnapshotData SnapshotDirty;

    /*
     * fetch target tuple
     *
     * Loop here to deal with updated or busy tuples
     */
    InitDirtySnapshot(SnapshotDirty);
    tuple.t_self = *tid;
    for (;;)
    {
        Buffer      buffer;

        if (heap_fetch(relation, &SnapshotDirty, &tuple, &buffer, true, NULL))
        {
            HTSU_Result test;
            HeapUpdateFailureData hufd;

            /*
             * If xmin isn't what we're expecting, the slot must have been
             * recycled and reused for an unrelated tuple.  This implies that
             * the latest version of the row was deleted, so we need do
             * nothing.  (Should be safe to examine xmin without getting
             * buffer's content lock, since xmin never changes in an existing
             * tuple.)
             */
            if (!TransactionIdEquals(HeapTupleHeaderGetXmin(tuple.t_data),
                                     priorXmax))
            {
                ReleaseBuffer(buffer);
                return NULL;
            }

            /* otherwise xmin should not be dirty... */
            if (TransactionIdIsValid(SnapshotDirty.xmin))
                elog(ERROR, "t_xmin is uncommitted in tuple to be updated");

            /*
             * If tuple is being updated by other transaction then we have to
             * wait for its commit/abort.
             */
            if (TransactionIdIsValid(SnapshotDirty.xmax))
            {
                ReleaseBuffer(buffer);
                XactLockTableWait(SnapshotDirty.xmax);
                continue;       /* loop back to repeat heap_fetch */
            }

            /*
             * If tuple was inserted by our own transaction, we have to check
             * cmin against es_output_cid: cmin >= current CID means our
             * command cannot see the tuple, so we should ignore it.
             * Otherwise heap_lock_tuple() will throw an error, and so would
             * any later attempt to update or delete the tuple.  (We need not
             * check cmax because HeapTupleSatisfiesDirty will consider a
             * tuple deleted by our transaction dead, regardless of cmax.)
             * Wee just checked that priorXmax == xmin, so we can test that
             * variable instead of doing HeapTupleHeaderGetXmin again.
             */
            if (TransactionIdIsCurrentTransactionId(priorXmax) &&
                HeapTupleHeaderGetCmin(tuple.t_data) >= estate->es_output_cid)
            {
                ReleaseBuffer(buffer);
                return NULL;
            }

            /*
             * This is a live tuple, so now try to lock it.
             */
            test = heap_lock_tuple(relation, &tuple,
                                   estate->es_output_cid,
                                   lockmode, false /* wait */,
                                   false, &buffer, &hufd);
            /* We now have two pins on the buffer, get rid of one */
            ReleaseBuffer(buffer);

            switch (test)
            {
                case HeapTupleSelfUpdated:
                    /*
                     * The target tuple was already updated or deleted by the
                     * current command, or by a later command in the current
                     * transaction.  We *must* ignore the tuple in the former
                     * case, so as to avoid the "Halloween problem" of
                     * repeated update attempts.  In the latter case it might
                     * be sensible to fetch the updated tuple instead, but
                     * doing so would require changing heap_lock_tuple as well
                     * as heap_update and heap_delete to not complain about
                     * updating "invisible" tuples, which seems pretty scary.
                     * So for now, treat the tuple as deleted and do not
                     * process.
                     */
                    ReleaseBuffer(buffer);
                    return NULL;

                case HeapTupleMayBeUpdated:
                    /* successfully locked */
                    break;

                case HeapTupleUpdated:
                    ReleaseBuffer(buffer);
                    if (IsolationUsesXactSnapshot())
                        ereport(ERROR,
                                (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
                                 errmsg("could not serialize access due to concurrent update")));
                    if (!ItemPointerEquals(&hufd.ctid, &tuple.t_self))
                    {
                        /* it was updated, so look at the updated version */
                        tuple.t_self = hufd.ctid;
                        /* updated row should have xmin matching this xmax */
                        priorXmax = hufd.xmax;
                        continue;
                    }
                    /* tuple was deleted, so give up */
                    return NULL;

                default:
                    ReleaseBuffer(buffer);
                    elog(ERROR, "unrecognized heap_lock_tuple status: %u",
                         test);
                    return NULL;    /* keep compiler quiet */
            }

            /*
             * We got tuple - now copy it for use by recheck query.
             */
            copyTuple = heap_copytuple(&tuple);
            ReleaseBuffer(buffer);
            break;
        }

        /*
         * If the referenced slot was actually empty, the latest version of
         * the row must have been deleted, so we need do nothing.
         */
        if (tuple.t_data == NULL)
        {
            ReleaseBuffer(buffer);
            return NULL;
        }

        /*
         * As above, if xmin isn't what we're expecting, do nothing.
         */
        if (!TransactionIdEquals(HeapTupleHeaderGetXmin(tuple.t_data),
                                 priorXmax))
        {
            ReleaseBuffer(buffer);
            return NULL;
        }

        /*
         * If we get here, the tuple was found but failed SnapshotDirty.
         * Assuming the xmin is either a committed xact or our own xact (as it
         * certainly should be if we're trying to modify the tuple), this must
         * mean that the row was updated or deleted by either a committed xact
         * or our own xact.  If it was deleted, we can ignore it; if it was
         * updated then chain up to the next version and repeat the whole
         * process.
         *
         * As above, it should be safe to examine xmax and t_ctid without the
         * buffer content lock, because they can't be changing.
         */
        if (ItemPointerEquals(&tuple.t_self, &tuple.t_data->t_ctid))
        {
            /* deleted, so forget about it */
            ReleaseBuffer(buffer);
            return NULL;
        }

        /* updated, so look at the updated row */
        tuple.t_self = tuple.t_data->t_ctid;
        /* updated row should have xmin matching this xmax */
        priorXmax = HeapTupleHeaderGetUpdateXid(tuple.t_data);
        ReleaseBuffer(buffer);
        /* loop back to fetch next in chain */
    }

    /*
     * Return the copied tuple
     */
    return copyTuple;
}

void EvalPlanQualFetchRowMarks ( EPQState epqstate  ) 

Definition at line 2115 of file execMain.c.

References EPQState::arowMarks, Assert, ExecAuxRowMark::ctidAttNo, DatumGetHeapTupleHeader, DatumGetObjectId, DatumGetPointer, elog, ERROR, EvalPlanQualSetTuple(), ExecGetJunkAttribute(), heap_copytuple(), heap_fetch(), HeapTupleHeaderGetDatumLength, ItemPointerSetInvalid, lfirst, ExecRowMark::markType, NULL, EPQState::origslot, ExecRowMark::prti, ExecRowMark::relation, RelationGetRelid, ReleaseBuffer(), ROW_MARK_COPY, ROW_MARK_REFERENCE, ExecAuxRowMark::rowmark, RowMarkRequiresRowShareLock, ExecRowMark::rti, SnapshotAny, HeapTupleData::t_data, HeapTupleData::t_len, HeapTupleData::t_self, HeapTupleData::t_tableOid, ExecAuxRowMark::toidAttNo, and ExecAuxRowMark::wholeAttNo.

Referenced by EvalPlanQual(), and ExecLockRows().

{
    ListCell   *l;

    Assert(epqstate->origslot != NULL);

    foreach(l, epqstate->arowMarks)
    {
        ExecAuxRowMark *aerm = (ExecAuxRowMark *) lfirst(l);
        ExecRowMark *erm = aerm->rowmark;
        Datum       datum;
        bool        isNull;
        HeapTupleData tuple;

        if (RowMarkRequiresRowShareLock(erm->markType))
            elog(ERROR, "EvalPlanQual doesn't support locking rowmarks");

        /* clear any leftover test tuple for this rel */
        EvalPlanQualSetTuple(epqstate, erm->rti, NULL);

        if (erm->relation)
        {
            Buffer      buffer;

            Assert(erm->markType == ROW_MARK_REFERENCE);

            /* if child rel, must check whether it produced this row */
            if (erm->rti != erm->prti)
            {
                Oid         tableoid;

                datum = ExecGetJunkAttribute(epqstate->origslot,
                                             aerm->toidAttNo,
                                             &isNull);
                /* non-locked rels could be on the inside of outer joins */
                if (isNull)
                    continue;
                tableoid = DatumGetObjectId(datum);

                if (tableoid != RelationGetRelid(erm->relation))
                {
                    /* this child is inactive right now */
                    continue;
                }
            }

            /* fetch the tuple's ctid */
            datum = ExecGetJunkAttribute(epqstate->origslot,
                                         aerm->ctidAttNo,
                                         &isNull);
            /* non-locked rels could be on the inside of outer joins */
            if (isNull)
                continue;
            tuple.t_self = *((ItemPointer) DatumGetPointer(datum));

            /* okay, fetch the tuple */
            if (!heap_fetch(erm->relation, SnapshotAny, &tuple, &buffer,
                            false, NULL))
                elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck");

            /* successful, copy and store tuple */
            EvalPlanQualSetTuple(epqstate, erm->rti,
                                 heap_copytuple(&tuple));
            ReleaseBuffer(buffer);
        }
        else
        {
            HeapTupleHeader td;

            Assert(erm->markType == ROW_MARK_COPY);

            /* fetch the whole-row Var for the relation */
            datum = ExecGetJunkAttribute(epqstate->origslot,
                                         aerm->wholeAttNo,
                                         &isNull);
            /* non-locked rels could be on the inside of outer joins */
            if (isNull)
                continue;
            td = DatumGetHeapTupleHeader(datum);

            /* build a temporary HeapTuple control structure */
            tuple.t_len = HeapTupleHeaderGetDatumLength(td);
            ItemPointerSetInvalid(&(tuple.t_self));
            tuple.t_tableOid = InvalidOid;
            tuple.t_data = td;

            /* copy and store tuple */
            EvalPlanQualSetTuple(epqstate, erm->rti,
                                 heap_copytuple(&tuple));
        }
    }
}

HeapTuple EvalPlanQualGetTuple ( EPQState epqstate,
Index  rti 
)

Definition at line 2100 of file execMain.c.

References Assert, EState::es_epqTuple, and EPQState::estate.

Referenced by ExecLockRows().

{
    EState     *estate = epqstate->estate;

    Assert(rti > 0);

    return estate->es_epqTuple[rti - 1];
}

void EvalPlanQualInit ( EPQState epqstate,
EState estate,
Plan subplan,
List auxrowmarks,
int  epqParam 
)

Definition at line 2045 of file execMain.c.

References EPQState::arowMarks, EPQState::epqParam, EPQState::estate, EPQState::origslot, EPQState::plan, and EPQState::planstate.

Referenced by ExecInitLockRows(), and ExecInitModifyTable().

{
    /* Mark the EPQ state inactive */
    epqstate->estate = NULL;
    epqstate->planstate = NULL;
    epqstate->origslot = NULL;
    /* ... and remember data that EvalPlanQualBegin will need */
    epqstate->plan = subplan;
    epqstate->arowMarks = auxrowmarks;
    epqstate->epqParam = epqParam;
}

TupleTableSlot* EvalPlanQualNext ( EPQState epqstate  ) 

Definition at line 2214 of file execMain.c.

References EState::es_query_cxt, EPQState::estate, ExecProcNode(), MemoryContextSwitchTo(), and EPQState::planstate.

Referenced by EvalPlanQual(), and ExecLockRows().

{
    MemoryContext oldcontext;
    TupleTableSlot *slot;

    oldcontext = MemoryContextSwitchTo(epqstate->estate->es_query_cxt);
    slot = ExecProcNode(epqstate->planstate);
    MemoryContextSwitchTo(oldcontext);

    return slot;
}

void EvalPlanQualSetPlan ( EPQState epqstate,
Plan subplan,
List auxrowmarks 
)

Definition at line 2064 of file execMain.c.

References EPQState::arowMarks, EvalPlanQualEnd(), and EPQState::plan.

Referenced by ExecInitModifyTable(), and ExecModifyTable().

{
    /* If we have a live EPQ query, shut it down */
    EvalPlanQualEnd(epqstate);
    /* And set/change the plan pointer */
    epqstate->plan = subplan;
    /* The rowmarks depend on the plan, too */
    epqstate->arowMarks = auxrowmarks;
}

void EvalPlanQualSetTuple ( EPQState epqstate,
Index  rti,
HeapTuple  tuple 
)

Definition at line 2080 of file execMain.c.

References Assert, EState::es_epqTuple, EState::es_epqTupleSet, EPQState::estate, heap_freetuple(), and NULL.

Referenced by EvalPlanQual(), EvalPlanQualFetchRowMarks(), and ExecLockRows().

{
    EState     *estate = epqstate->estate;

    Assert(rti > 0);

    /*
     * free old test tuple, if any, and store new tuple where relation's scan
     * node will see it
     */
    if (estate->es_epqTuple[rti - 1] != NULL)
        heap_freetuple(estate->es_epqTuple[rti - 1]);
    estate->es_epqTuple[rti - 1] = tuple;
    estate->es_epqTupleSet[rti - 1] = true;
}

void ExecAssignExprContext ( EState estate,
PlanState planstate 
)
void ExecAssignProjectionInfo ( PlanState planstate,
TupleDesc  inputDesc 
)
void ExecAssignResultType ( PlanState planstate,
TupleDesc  tupDesc 
)

Definition at line 432 of file execUtils.c.

References ExecSetSlotDescriptor(), and PlanState::ps_ResultTupleSlot.

Referenced by ExecAssignResultTypeFromTL(), and ExecInitModifyTable().

{
    TupleTableSlot *slot = planstate->ps_ResultTupleSlot;

    ExecSetSlotDescriptor(slot, tupDesc);
}

void ExecAssignResultTypeFromTL ( PlanState planstate  ) 

Definition at line 444 of file execUtils.c.

References ExecAssignResultType(), ExecContextForcesOids(), ExecTypeFromTL(), PlanState::plan, and Plan::targetlist.

Referenced by ExecInitAgg(), ExecInitAppend(), ExecInitBitmapHeapScan(), ExecInitCteScan(), ExecInitForeignScan(), ExecInitFunctionScan(), ExecInitGroup(), ExecInitHash(), ExecInitHashJoin(), ExecInitIndexOnlyScan(), ExecInitIndexScan(), ExecInitLimit(), ExecInitLockRows(), ExecInitMaterial(), ExecInitMergeAppend(), ExecInitMergeJoin(), ExecInitNestLoop(), ExecInitRecursiveUnion(), ExecInitResult(), ExecInitSeqScan(), ExecInitSetOp(), ExecInitSort(), ExecInitSubqueryScan(), ExecInitTidScan(), ExecInitUnique(), ExecInitValuesScan(), ExecInitWindowAgg(), and ExecInitWorkTableScan().

{
    bool        hasoid;
    TupleDesc   tupDesc;

    if (ExecContextForcesOids(planstate, &hasoid))
    {
        /* context forces OID choice; hasoid is now set correctly */
    }
    else
    {
        /* given free choice, don't leave space for OIDs in result tuples */
        hasoid = false;
    }

    /*
     * ExecTypeFromTL needs the parse-time representation of the tlist, not a
     * list of ExprStates.  This is good because some plan nodes don't bother
     * to set up planstate->targetlist ...
     */
    tupDesc = ExecTypeFromTL(planstate->plan->targetlist, hasoid);
    ExecAssignResultType(planstate, tupDesc);
}

void ExecAssignScanProjectionInfo ( ScanState node  ) 
void ExecAssignScanType ( ScanState scanstate,
TupleDesc  tupDesc 
)
void ExecAssignScanTypeFromOuterPlan ( ScanState scanstate  ) 

Definition at line 750 of file execUtils.c.

References ExecAssignScanType(), ExecGetResultType(), and outerPlanState.

Referenced by ExecInitAgg(), ExecInitGroup(), ExecInitMaterial(), ExecInitSort(), and ExecInitWindowAgg().

{
    PlanState  *outerPlan;
    TupleDesc   tupDesc;

    outerPlan = outerPlanState(scanstate);
    tupDesc = ExecGetResultType(outerPlan);

    ExecAssignScanType(scanstate, tupDesc);
}

ExecAuxRowMark* ExecBuildAuxRowMark ( ExecRowMark erm,
List targetlist 
)

Definition at line 1691 of file execMain.c.

References Assert, AttributeNumberIsValid, ExecAuxRowMark::ctidAttNo, elog, ERROR, ExecFindJunkAttributeInTlist(), ExecRowMark::markType, palloc0(), ExecRowMark::prti, ExecRowMark::relation, ROW_MARK_COPY, ExecAuxRowMark::rowmark, ExecRowMark::rowmarkId, ExecRowMark::rti, snprintf(), ExecAuxRowMark::toidAttNo, and ExecAuxRowMark::wholeAttNo.

Referenced by ExecInitLockRows(), and ExecInitModifyTable().

{
    ExecAuxRowMark *aerm = (ExecAuxRowMark *) palloc0(sizeof(ExecAuxRowMark));
    char        resname[32];

    aerm->rowmark = erm;

    /* Look up the resjunk columns associated with this rowmark */
    if (erm->relation)
    {
        Assert(erm->markType != ROW_MARK_COPY);

        /* if child rel, need tableoid */
        if (erm->rti != erm->prti)
        {
            snprintf(resname, sizeof(resname), "tableoid%u", erm->rowmarkId);
            aerm->toidAttNo = ExecFindJunkAttributeInTlist(targetlist,
                                                           resname);
            if (!AttributeNumberIsValid(aerm->toidAttNo))
                elog(ERROR, "could not find junk %s column", resname);
        }

        /* always need ctid for real relations */
        snprintf(resname, sizeof(resname), "ctid%u", erm->rowmarkId);
        aerm->ctidAttNo = ExecFindJunkAttributeInTlist(targetlist,
                                                       resname);
        if (!AttributeNumberIsValid(aerm->ctidAttNo))
            elog(ERROR, "could not find junk %s column", resname);
    }
    else
    {
        Assert(erm->markType == ROW_MARK_COPY);

        snprintf(resname, sizeof(resname), "wholerow%u", erm->rowmarkId);
        aerm->wholeAttNo = ExecFindJunkAttributeInTlist(targetlist,
                                                        resname);
        if (!AttributeNumberIsValid(aerm->wholeAttNo))
            elog(ERROR, "could not find junk %s column", resname);
    }

    return aerm;
}

ProjectionInfo* ExecBuildProjectionInfo ( List targetList,
ExprContext econtext,
TupleTableSlot slot,
TupleDesc  inputDesc 
)

Definition at line 496 of file execUtils.c.

References GenericExprState::arg, tupleDesc::attrs, ExecTargetListLength(), ExprState::expr, get_last_attnums(), INNER_VAR, IsA, lappend(), lfirst, makeNode, tupleDesc::natts, NIL, NULL, offsetof, OUTER_VAR, palloc(), ProjectionInfo::pi_directMap, ProjectionInfo::pi_exprContext, ProjectionInfo::pi_itemIsDone, ProjectionInfo::pi_lastInnerVar, ProjectionInfo::pi_lastOuterVar, ProjectionInfo::pi_lastScanVar, ProjectionInfo::pi_numSimpleVars, ProjectionInfo::pi_slot, ProjectionInfo::pi_targetlist, ProjectionInfo::pi_varNumbers, ProjectionInfo::pi_varOutputCols, ProjectionInfo::pi_varSlotOffsets, TargetEntry::resno, Var::varattno, Var::varno, Var::vartype, and GenericExprState::xprstate.

Referenced by ExecAssignProjectionInfo(), ExecInitAgg(), ExecInitModifyTable(), and ExecInitSubPlan().

{
    ProjectionInfo *projInfo = makeNode(ProjectionInfo);
    int         len = ExecTargetListLength(targetList);
    int        *workspace;
    int        *varSlotOffsets;
    int        *varNumbers;
    int        *varOutputCols;
    List       *exprlist;
    int         numSimpleVars;
    bool        directMap;
    ListCell   *tl;

    projInfo->pi_exprContext = econtext;
    projInfo->pi_slot = slot;
    /* since these are all int arrays, we need do just one palloc */
    workspace = (int *) palloc(len * 3 * sizeof(int));
    projInfo->pi_varSlotOffsets = varSlotOffsets = workspace;
    projInfo->pi_varNumbers = varNumbers = workspace + len;
    projInfo->pi_varOutputCols = varOutputCols = workspace + len * 2;
    projInfo->pi_lastInnerVar = 0;
    projInfo->pi_lastOuterVar = 0;
    projInfo->pi_lastScanVar = 0;

    /*
     * We separate the target list elements into simple Var references and
     * expressions which require the full ExecTargetList machinery.  To be a
     * simple Var, a Var has to be a user attribute and not mismatch the
     * inputDesc.  (Note: if there is a type mismatch then ExecEvalScalarVar
     * will probably throw an error at runtime, but we leave that to it.)
     */
    exprlist = NIL;
    numSimpleVars = 0;
    directMap = true;
    foreach(tl, targetList)
    {
        GenericExprState *gstate = (GenericExprState *) lfirst(tl);
        Var        *variable = (Var *) gstate->arg->expr;
        bool        isSimpleVar = false;

        if (variable != NULL &&
            IsA(variable, Var) &&
            variable->varattno > 0)
        {
            if (!inputDesc)
                isSimpleVar = true;     /* can't check type, assume OK */
            else if (variable->varattno <= inputDesc->natts)
            {
                Form_pg_attribute attr;

                attr = inputDesc->attrs[variable->varattno - 1];
                if (!attr->attisdropped && variable->vartype == attr->atttypid)
                    isSimpleVar = true;
            }
        }

        if (isSimpleVar)
        {
            TargetEntry *tle = (TargetEntry *) gstate->xprstate.expr;
            AttrNumber  attnum = variable->varattno;

            varNumbers[numSimpleVars] = attnum;
            varOutputCols[numSimpleVars] = tle->resno;
            if (tle->resno != numSimpleVars + 1)
                directMap = false;

            switch (variable->varno)
            {
                case INNER_VAR:
                    varSlotOffsets[numSimpleVars] = offsetof(ExprContext,
                                                             ecxt_innertuple);
                    if (projInfo->pi_lastInnerVar < attnum)
                        projInfo->pi_lastInnerVar = attnum;
                    break;

                case OUTER_VAR:
                    varSlotOffsets[numSimpleVars] = offsetof(ExprContext,
                                                             ecxt_outertuple);
                    if (projInfo->pi_lastOuterVar < attnum)
                        projInfo->pi_lastOuterVar = attnum;
                    break;

                    /* INDEX_VAR is handled by default case */

                default:
                    varSlotOffsets[numSimpleVars] = offsetof(ExprContext,
                                                             ecxt_scantuple);
                    if (projInfo->pi_lastScanVar < attnum)
                        projInfo->pi_lastScanVar = attnum;
                    break;
            }
            numSimpleVars++;
        }
        else
        {
            /* Not a simple variable, add it to generic targetlist */
            exprlist = lappend(exprlist, gstate);
            /* Examine expr to include contained Vars in lastXXXVar counts */
            get_last_attnums((Node *) variable, projInfo);
        }
    }
    projInfo->pi_targetlist = exprlist;
    projInfo->pi_numSimpleVars = numSimpleVars;
    projInfo->pi_directMap = directMap;

    if (exprlist == NIL)
        projInfo->pi_itemIsDone = NULL; /* not needed */
    else
        projInfo->pi_itemIsDone = (ExprDoneCond *)
            palloc(len * sizeof(ExprDoneCond));

    return projInfo;
}

bool ExecCheckRTPerms ( List rangeTable,
bool  ereport_on_violation 
)

Definition at line 504 of file execMain.c.

References ACL_KIND_CLASS, aclcheck_error(), ACLCHECK_NO_PRIV, Assert, ExecCheckRTEPerms(), ExecutorCheckPerms_hook, get_rel_name(), lfirst, RangeTblEntry::relid, RTE_RELATION, and RangeTblEntry::rtekind.

Referenced by DoCopy(), InitPlan(), intorel_startup(), and RI_Initial_Check().

{
    ListCell   *l;
    bool        result = true;

    foreach(l, rangeTable)
    {
        RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);

        result = ExecCheckRTEPerms(rte);
        if (!result)
        {
            Assert(rte->rtekind == RTE_RELATION);
            if (ereport_on_violation)
                aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_CLASS,
                               get_rel_name(rte->relid));
            return false;
        }
    }

    if (ExecutorCheckPerms_hook)
        result = (*ExecutorCheckPerms_hook) (rangeTable,
                                             ereport_on_violation);
    return result;
}

int ExecCleanTargetListLength ( List targetlist  ) 

Definition at line 5173 of file execQual.c.

References Assert, IsA, lfirst, and TargetEntry::resjunk.

Referenced by check_sql_fn_retval(), and ExecTypeFromTLInternal().

{
    int         len = 0;
    ListCell   *tl;

    foreach(tl, targetlist)
    {
        TargetEntry *curTle = (TargetEntry *) lfirst(tl);

        Assert(IsA(curTle, TargetEntry));
        if (!curTle->resjunk)
            len++;
    }
    return len;
}

TupleDesc ExecCleanTypeFromTL ( List targetList,
bool  hasoid 
)

Definition at line 915 of file execTuples.c.

References ExecTypeFromTLInternal().

Referenced by ExecInitJunkFilter(), PlanCacheComputeResultDesc(), and PortalStart().

{
    return ExecTypeFromTLInternal(targetList, hasoid, true);
}

void ExecCloseIndices ( ResultRelInfo resultRelInfo  ) 

Definition at line 956 of file execUtils.c.

References i, index_close(), NULL, ResultRelInfo::ri_IndexRelationDescs, ResultRelInfo::ri_NumIndices, and RowExclusiveLock.

Referenced by afterTriggerInvokeEvents(), CatalogCloseIndexes(), CopyFrom(), EvalPlanQualEnd(), and ExecEndPlan().

{
    int         i;
    int         numIndices;
    RelationPtr indexDescs;

    numIndices = resultRelInfo->ri_NumIndices;
    indexDescs = resultRelInfo->ri_IndexRelationDescs;

    for (i = 0; i < numIndices; i++)
    {
        if (indexDescs[i] == NULL)
            continue;           /* shouldn't happen? */

        /* Drop lock acquired by ExecOpenIndices */
        index_close(indexDescs[i], RowExclusiveLock);
    }

    /*
     * XXX should free indexInfo array here too?  Currently we assume that
     * such stuff will be cleaned up automatically in FreeExecutorState.
     */
}

void ExecCloseScanRelation ( Relation  scanrel  ) 
void ExecConstraints ( ResultRelInfo resultRelInfo,
TupleTableSlot slot,
EState estate 
)

Definition at line 1562 of file execMain.c.

References Assert, tupleDesc::attrs, tupleDesc::constr, ereport, errcode(), errdetail(), errmsg(), ERROR, errtablecol(), errtableconstraint(), ExecBuildSlotValueDescription(), ExecRelCheck(), tupleConstr::has_not_null, NameStr, tupleDesc::natts, NULL, tupleConstr::num_check, RelationData::rd_att, RelationGetRelationName, ResultRelInfo::ri_RelationDesc, and slot_attisnull().

Referenced by CopyFrom(), ExecInsert(), and ExecUpdate().

{
    Relation    rel = resultRelInfo->ri_RelationDesc;
    TupleConstr *constr = rel->rd_att->constr;

    Assert(constr);

    if (constr->has_not_null)
    {
        int         natts = rel->rd_att->natts;
        int         attrChk;

        for (attrChk = 1; attrChk <= natts; attrChk++)
        {
            if (rel->rd_att->attrs[attrChk - 1]->attnotnull &&
                slot_attisnull(slot, attrChk))
                ereport(ERROR,
                        (errcode(ERRCODE_NOT_NULL_VIOLATION),
                         errmsg("null value in column \"%s\" violates not-null constraint",
                          NameStr(rel->rd_att->attrs[attrChk - 1]->attname)),
                         errdetail("Failing row contains %s.",
                                   ExecBuildSlotValueDescription(slot, 64)),
                         errtablecol(rel, attrChk)));
        }
    }

    if (constr->num_check > 0)
    {
        const char *failed;

        if ((failed = ExecRelCheck(resultRelInfo, slot, estate)) != NULL)
            ereport(ERROR,
                    (errcode(ERRCODE_CHECK_VIOLATION),
                     errmsg("new row for relation \"%s\" violates check constraint \"%s\"",
                            RelationGetRelationName(rel), failed),
                     errdetail("Failing row contains %s.",
                               ExecBuildSlotValueDescription(slot, 64)),
                     errtableconstraint(rel, failed)));
    }
}

bool ExecContextForcesOids ( PlanState planstate,
bool hasoids 
)

Definition at line 1259 of file execMain.c.

References EState::es_result_relation_info, EState::es_top_eflags, EXEC_FLAG_WITH_OIDS, EXEC_FLAG_WITHOUT_OIDS, NULL, RelationData::rd_rel, ResultRelInfo::ri_RelationDesc, and PlanState::state.

Referenced by ExecAssignResultTypeFromTL(), and tlist_matches_tupdesc().

{
    ResultRelInfo *ri = planstate->state->es_result_relation_info;

    if (ri != NULL)
    {
        Relation    rel = ri->ri_RelationDesc;

        if (rel != NULL)
        {
            *hasoids = rel->rd_rel->relhasoids;
            return true;
        }
    }

    if (planstate->state->es_top_eflags & EXEC_FLAG_WITH_OIDS)
    {
        *hasoids = true;
        return true;
    }
    if (planstate->state->es_top_eflags & EXEC_FLAG_WITHOUT_OIDS)
    {
        *hasoids = false;
        return true;
    }

    return false;
}

bool execCurrentOf ( CurrentOfExpr cexpr,
ExprContext econtext,
Oid  table_oid,
ItemPointer  current_tid 
)

Definition at line 41 of file execCurrent.c.

References Assert, PortalData::atEnd, PortalData::atStart, ExecRowMark::curCtid, CurrentOfExpr::cursor_name, CurrentOfExpr::cursor_param, DatumGetObjectId, DatumGetPointer, elog, ereport, errcode(), errmsg(), ERROR, EState::es_rowMarks, QueryDesc::estate, fetch_cursor_param_value(), get_rel_name(), GetPortalByName(), ItemPointerIsValid, lfirst, ExecRowMark::markType, NULL, QueryDesc::planstate, PORTAL_ONE_SELECT, PortalGetQueryDesc, PortalIsValid, ExecRowMark::relation, RelationGetRelid, RowMarkRequiresRowShareLock, search_plan_tree(), SelfItemPointerAttributeNumber, slot_getattr(), ScanState::ss_ScanTupleSlot, PortalData::strategy, TableOidAttributeNumber, and TupIsNull.

Referenced by TidListCreate().

{
    char       *cursor_name;
    char       *table_name;
    Portal      portal;
    QueryDesc  *queryDesc;

    /* Get the cursor name --- may have to look up a parameter reference */
    if (cexpr->cursor_name)
        cursor_name = cexpr->cursor_name;
    else
        cursor_name = fetch_cursor_param_value(econtext, cexpr->cursor_param);

    /* Fetch table name for possible use in error messages */
    table_name = get_rel_name(table_oid);
    if (table_name == NULL)
        elog(ERROR, "cache lookup failed for relation %u", table_oid);

    /* Find the cursor's portal */
    portal = GetPortalByName(cursor_name);
    if (!PortalIsValid(portal))
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_CURSOR),
                 errmsg("cursor \"%s\" does not exist", cursor_name)));

    /*
     * We have to watch out for non-SELECT queries as well as held cursors,
     * both of which may have null queryDesc.
     */
    if (portal->strategy != PORTAL_ONE_SELECT)
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_CURSOR_STATE),
                 errmsg("cursor \"%s\" is not a SELECT query",
                        cursor_name)));
    queryDesc = PortalGetQueryDesc(portal);
    if (queryDesc == NULL || queryDesc->estate == NULL)
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_CURSOR_STATE),
                 errmsg("cursor \"%s\" is held from a previous transaction",
                        cursor_name)));

    /*
     * We have two different strategies depending on whether the cursor uses
     * FOR UPDATE/SHARE or not.  The reason for supporting both is that the
     * FOR UPDATE code is able to identify a target table in many cases where
     * the other code can't, while the non-FOR-UPDATE case allows use of WHERE
     * CURRENT OF with an insensitive cursor.
     */
    if (queryDesc->estate->es_rowMarks)
    {
        ExecRowMark *erm;
        ListCell   *lc;

        /*
         * Here, the query must have exactly one FOR UPDATE/SHARE reference to
         * the target table, and we dig the ctid info out of that.
         */
        erm = NULL;
        foreach(lc, queryDesc->estate->es_rowMarks)
        {
            ExecRowMark *thiserm = (ExecRowMark *) lfirst(lc);

            if (!RowMarkRequiresRowShareLock(thiserm->markType))
                continue;       /* ignore non-FOR UPDATE/SHARE items */

            if (RelationGetRelid(thiserm->relation) == table_oid)
            {
                if (erm)
                    ereport(ERROR,
                            (errcode(ERRCODE_INVALID_CURSOR_STATE),
                             errmsg("cursor \"%s\" has multiple FOR UPDATE/SHARE references to table \"%s\"",
                                    cursor_name, table_name)));
                erm = thiserm;
            }
        }

        if (erm == NULL)
            ereport(ERROR,
                    (errcode(ERRCODE_INVALID_CURSOR_STATE),
                     errmsg("cursor \"%s\" does not have a FOR UPDATE/SHARE reference to table \"%s\"",
                            cursor_name, table_name)));

        /*
         * The cursor must have a current result row: per the SQL spec, it's
         * an error if not.
         */
        if (portal->atStart || portal->atEnd)
            ereport(ERROR,
                    (errcode(ERRCODE_INVALID_CURSOR_STATE),
                     errmsg("cursor \"%s\" is not positioned on a row",
                            cursor_name)));

        /* Return the currently scanned TID, if there is one */
        if (ItemPointerIsValid(&(erm->curCtid)))
        {
            *current_tid = erm->curCtid;
            return true;
        }

        /*
         * This table didn't produce the cursor's current row; some other
         * inheritance child of the same parent must have.  Signal caller to
         * do nothing on this table.
         */
        return false;
    }
    else
    {
        ScanState  *scanstate;
        bool        lisnull;
        Oid tuple_tableoid PG_USED_FOR_ASSERTS_ONLY;
        ItemPointer tuple_tid;

        /*
         * Without FOR UPDATE, we dig through the cursor's plan to find the
         * scan node.  Fail if it's not there or buried underneath
         * aggregation.
         */
        scanstate = search_plan_tree(queryDesc->planstate, table_oid);
        if (!scanstate)
            ereport(ERROR,
                    (errcode(ERRCODE_INVALID_CURSOR_STATE),
                     errmsg("cursor \"%s\" is not a simply updatable scan of table \"%s\"",
                            cursor_name, table_name)));

        /*
         * The cursor must have a current result row: per the SQL spec, it's
         * an error if not.  We test this at the top level, rather than at the
         * scan node level, because in inheritance cases any one table scan
         * could easily not be on a row. We want to return false, not raise
         * error, if the passed-in table OID is for one of the inactive scans.
         */
        if (portal->atStart || portal->atEnd)
            ereport(ERROR,
                    (errcode(ERRCODE_INVALID_CURSOR_STATE),
                     errmsg("cursor \"%s\" is not positioned on a row",
                            cursor_name)));

        /* Now OK to return false if we found an inactive scan */
        if (TupIsNull(scanstate->ss_ScanTupleSlot))
            return false;

        /* Use slot_getattr to catch any possible mistakes */
        tuple_tableoid =
            DatumGetObjectId(slot_getattr(scanstate->ss_ScanTupleSlot,
                                          TableOidAttributeNumber,
                                          &lisnull));
        Assert(!lisnull);
        tuple_tid = (ItemPointer)
            DatumGetPointer(slot_getattr(scanstate->ss_ScanTupleSlot,
                                         SelfItemPointerAttributeNumber,
                                         &lisnull));
        Assert(!lisnull);

        Assert(tuple_tableoid == table_oid);

        *current_tid = *tuple_tid;

        return true;
    }
}

void ExecEndNode ( PlanState node  ) 

Definition at line 583 of file execProcnode.c.

References bms_free(), PlanState::chgParam, elog, ERROR, ExecEndAgg(), ExecEndAppend(), ExecEndBitmapAnd(), ExecEndBitmapHeapScan(), ExecEndBitmapIndexScan(), ExecEndBitmapOr(), ExecEndCteScan(), ExecEndForeignScan(), ExecEndFunctionScan(), ExecEndGroup(), ExecEndHash(), ExecEndHashJoin(), ExecEndIndexOnlyScan(), ExecEndIndexScan(), ExecEndLimit(), ExecEndLockRows(), ExecEndMaterial(), ExecEndMergeAppend(), ExecEndMergeJoin(), ExecEndModifyTable(), ExecEndNestLoop(), ExecEndRecursiveUnion(), ExecEndResult(), ExecEndSeqScan(), ExecEndSetOp(), ExecEndSort(), ExecEndSubqueryScan(), ExecEndTidScan(), ExecEndUnique(), ExecEndValuesScan(), ExecEndWindowAgg(), ExecEndWorkTableScan(), nodeTag, NULL, T_AggState, T_AppendState, T_BitmapAndState, T_BitmapHeapScanState, T_BitmapIndexScanState, T_BitmapOrState, T_CteScanState, T_ForeignScanState, T_FunctionScanState, T_GroupState, T_HashJoinState, T_HashState, T_IndexOnlyScanState, T_IndexScanState, T_LimitState, T_LockRowsState, T_MaterialState, T_MergeAppendState, T_MergeJoinState, T_ModifyTableState, T_NestLoopState, T_RecursiveUnionState, T_ResultState, T_SeqScanState, T_SetOpState, T_SortState, T_SubqueryScanState, T_TidScanState, T_UniqueState, T_ValuesScanState, T_WindowAggState, and T_WorkTableScanState.

Referenced by EvalPlanQualEnd(), ExecEndAgg(), ExecEndAppend(), ExecEndBitmapAnd(), ExecEndBitmapHeapScan(), ExecEndBitmapOr(), ExecEndGroup(), ExecEndHash(), ExecEndHashJoin(), ExecEndLimit(), ExecEndLockRows(), ExecEndMaterial(), ExecEndMergeAppend(), ExecEndMergeJoin(), ExecEndModifyTable(), ExecEndNestLoop(), ExecEndPlan(), ExecEndRecursiveUnion(), ExecEndResult(), ExecEndSetOp(), ExecEndSort(), ExecEndSubqueryScan(), ExecEndUnique(), and ExecEndWindowAgg().

{
    /*
     * do nothing when we get to the end of a leaf on tree.
     */
    if (node == NULL)
        return;

    if (node->chgParam != NULL)
    {
        bms_free(node->chgParam);
        node->chgParam = NULL;
    }

    switch (nodeTag(node))
    {
            /*
             * control nodes
             */
        case T_ResultState:
            ExecEndResult((ResultState *) node);
            break;

        case T_ModifyTableState:
            ExecEndModifyTable((ModifyTableState *) node);
            break;

        case T_AppendState:
            ExecEndAppend((AppendState *) node);
            break;

        case T_MergeAppendState:
            ExecEndMergeAppend((MergeAppendState *) node);
            break;

        case T_RecursiveUnionState:
            ExecEndRecursiveUnion((RecursiveUnionState *) node);
            break;

        case T_BitmapAndState:
            ExecEndBitmapAnd((BitmapAndState *) node);
            break;

        case T_BitmapOrState:
            ExecEndBitmapOr((BitmapOrState *) node);
            break;

            /*
             * scan nodes
             */
        case T_SeqScanState:
            ExecEndSeqScan((SeqScanState *) node);
            break;

        case T_IndexScanState:
            ExecEndIndexScan((IndexScanState *) node);
            break;

        case T_IndexOnlyScanState:
            ExecEndIndexOnlyScan((IndexOnlyScanState *) node);
            break;

        case T_BitmapIndexScanState:
            ExecEndBitmapIndexScan((BitmapIndexScanState *) node);
            break;

        case T_BitmapHeapScanState:
            ExecEndBitmapHeapScan((BitmapHeapScanState *) node);
            break;

        case T_TidScanState:
            ExecEndTidScan((TidScanState *) node);
            break;

        case T_SubqueryScanState:
            ExecEndSubqueryScan((SubqueryScanState *) node);
            break;

        case T_FunctionScanState:
            ExecEndFunctionScan((FunctionScanState *) node);
            break;

        case T_ValuesScanState:
            ExecEndValuesScan((ValuesScanState *) node);
            break;

        case T_CteScanState:
            ExecEndCteScan((CteScanState *) node);
            break;

        case T_WorkTableScanState:
            ExecEndWorkTableScan((WorkTableScanState *) node);
            break;

        case T_ForeignScanState:
            ExecEndForeignScan((ForeignScanState *) node);
            break;

            /*
             * join nodes
             */
        case T_NestLoopState:
            ExecEndNestLoop((NestLoopState *) node);
            break;

        case T_MergeJoinState:
            ExecEndMergeJoin((MergeJoinState *) node);
            break;

        case T_HashJoinState:
            ExecEndHashJoin((HashJoinState *) node);
            break;

            /*
             * materialization nodes
             */
        case T_MaterialState:
            ExecEndMaterial((MaterialState *) node);
            break;

        case T_SortState:
            ExecEndSort((SortState *) node);
            break;

        case T_GroupState:
            ExecEndGroup((GroupState *) node);
            break;

        case T_AggState:
            ExecEndAgg((AggState *) node);
            break;

        case T_WindowAggState:
            ExecEndWindowAgg((WindowAggState *) node);
            break;

        case T_UniqueState:
            ExecEndUnique((UniqueState *) node);
            break;

        case T_HashState:
            ExecEndHash((HashState *) node);
            break;

        case T_SetOpState:
            ExecEndSetOp((SetOpState *) node);
            break;

        case T_LockRowsState:
            ExecEndLockRows((LockRowsState *) node);
            break;

        case T_LimitState:
            ExecEndLimit((LimitState *) node);
            break;

        default:
            elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
            break;
    }
}

Datum ExecEvalExprSwitchContext ( ExprState expression,
ExprContext econtext,
bool isNull,
ExprDoneCond isDone 
)
TupleTableSlot* ExecFilterJunk ( JunkFilter junkfilter,
TupleTableSlot slot 
)

Definition at line 262 of file execJunk.c.

References ExecClearTuple(), ExecStoreVirtualTuple(), i, JunkFilter::jf_cleanMap, JunkFilter::jf_cleanTupType, JunkFilter::jf_resultSlot, tupleDesc::natts, slot_getallattrs(), TupleTableSlot::tts_isnull, TupleTableSlot::tts_values, and values.

Referenced by ExecBRUpdateTriggers(), ExecEvalWholeRowFast(), ExecEvalWholeRowSlow(), ExecEvalWholeRowVar(), ExecModifyTable(), ExecUpdate(), ExecutePlan(), and sqlfunction_receive().

{
    TupleTableSlot *resultSlot;
    AttrNumber *cleanMap;
    TupleDesc   cleanTupType;
    int         cleanLength;
    int         i;
    Datum      *values;
    bool       *isnull;
    Datum      *old_values;
    bool       *old_isnull;

    /*
     * Extract all the values of the old tuple.
     */
    slot_getallattrs(slot);
    old_values = slot->tts_values;
    old_isnull = slot->tts_isnull;

    /*
     * get info from the junk filter
     */
    cleanTupType = junkfilter->jf_cleanTupType;
    cleanLength = cleanTupType->natts;
    cleanMap = junkfilter->jf_cleanMap;
    resultSlot = junkfilter->jf_resultSlot;

    /*
     * Prepare to build a virtual result tuple.
     */
    ExecClearTuple(resultSlot);
    values = resultSlot->tts_values;
    isnull = resultSlot->tts_isnull;

    /*
     * Transpose data into proper fields of the new tuple.
     */
    for (i = 0; i < cleanLength; i++)
    {
        int         j = cleanMap[i];

        if (j == 0)
        {
            values[i] = (Datum) 0;
            isnull[i] = true;
        }
        else
        {
            values[i] = old_values[j - 1];
            isnull[i] = old_isnull[j - 1];
        }
    }

    /*
     * And return the virtual tuple.
     */
    return ExecStoreVirtualTuple(resultSlot);
}

AttrNumber ExecFindJunkAttribute ( JunkFilter junkfilter,
const char *  attrName 
)

Definition at line 209 of file execJunk.c.

References ExecFindJunkAttributeInTlist(), and JunkFilter::jf_targetList.

Referenced by ExecInitModifyTable().

{
    return ExecFindJunkAttributeInTlist(junkfilter->jf_targetList, attrName);
}

AttrNumber ExecFindJunkAttributeInTlist ( List targetlist,
const char *  attrName 
)

Definition at line 221 of file execJunk.c.

References lfirst, TargetEntry::resjunk, TargetEntry::resname, and TargetEntry::resno.

Referenced by ExecBuildAuxRowMark(), ExecFindJunkAttribute(), and postgresBeginForeignModify().

{
    ListCell   *t;

    foreach(t, targetlist)
    {
        TargetEntry *tle = lfirst(t);

        if (tle->resjunk && tle->resname &&
            (strcmp(tle->resname, attrName) == 0))
        {
            /* We found it ! */
            return tle->resno;
        }
    }

    return InvalidAttrNumber;
}

ExecRowMark* ExecFindRowMark ( EState estate,
Index  rti 
)

Definition at line 1668 of file execMain.c.

References elog, ERROR, EState::es_rowMarks, lfirst, and ExecRowMark::rti.

Referenced by ExecInitLockRows(), and ExecInitModifyTable().

{
    ListCell   *lc;

    foreach(lc, estate->es_rowMarks)
    {
        ExecRowMark *erm = (ExecRowMark *) lfirst(lc);

        if (erm->rti == rti)
            return erm;
    }
    elog(ERROR, "failed to find ExecRowMark for rangetable index %u", rti);
    return NULL;                /* keep compiler quiet */
}

void ExecFreeExprContext ( PlanState planstate  ) 
Datum ExecGetJunkAttribute ( TupleTableSlot slot,
AttrNumber  attno,
bool isNull 
)

Definition at line 248 of file execJunk.c.

References Assert, and slot_getattr().

Referenced by EvalPlanQualFetchRowMarks(), ExecLockRows(), ExecModifyTable(), postgresExecForeignDelete(), and postgresExecForeignUpdate().

{
    Assert(attno > 0);

    return slot_getattr(slot, attno, isNull);
}

TupleDesc ExecGetResultType ( PlanState planstate  ) 
TupleDesc ExecGetScanType ( ScanState scanstate  ) 

Definition at line 726 of file execUtils.c.

References ScanState::ss_ScanTupleSlot, and TupleTableSlot::tts_tupleDescriptor.

{
    TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;

    return slot->tts_tupleDescriptor;
}

ResultRelInfo* ExecGetTriggerResultRel ( EState estate,
Oid  relid 
)

Definition at line 1170 of file execMain.c.

References EState::es_instrument, EState::es_num_result_relations, EState::es_query_cxt, EState::es_result_relations, EState::es_trig_target_relations, heap_open(), InitResultRelInfo(), lappend(), lfirst, makeNode, MemoryContextSwitchTo(), NoLock, RelationGetRelid, and ResultRelInfo::ri_RelationDesc.

Referenced by afterTriggerInvokeEvents().

{
    ResultRelInfo *rInfo;
    int         nr;
    ListCell   *l;
    Relation    rel;
    MemoryContext oldcontext;

    /* First, search through the query result relations */
    rInfo = estate->es_result_relations;
    nr = estate->es_num_result_relations;
    while (nr > 0)
    {
        if (RelationGetRelid(rInfo->ri_RelationDesc) == relid)
            return rInfo;
        rInfo++;
        nr--;
    }
    /* Nope, but maybe we already made an extra ResultRelInfo for it */
    foreach(l, estate->es_trig_target_relations)
    {
        rInfo = (ResultRelInfo *) lfirst(l);
        if (RelationGetRelid(rInfo->ri_RelationDesc) == relid)
            return rInfo;
    }
    /* Nope, so we need a new one */

    /*
     * Open the target relation's relcache entry.  We assume that an
     * appropriate lock is still held by the backend from whenever the trigger
     * event got queued, so we need take no new lock here.  Also, we need not
     * recheck the relkind, so no need for CheckValidResultRel.
     */
    rel = heap_open(relid, NoLock);

    /*
     * Make the new entry in the right context.
     */
    oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
    rInfo = makeNode(ResultRelInfo);
    InitResultRelInfo(rInfo,
                      rel,
                      0,        /* dummy rangetable index */
                      estate->es_instrument);
    estate->es_trig_target_relations =
        lappend(estate->es_trig_target_relations, rInfo);
    MemoryContextSwitchTo(oldcontext);

    /*
     * Currently, we don't need any index information in ResultRelInfos used
     * only for triggers, so no need to call ExecOpenIndices.
     */

    return rInfo;
}

ExprState* ExecInitExpr ( Expr node,
PlanState parent 
)

Definition at line 4332 of file execQual.c.

References AggState::aggs, ArrayCoerceExprState::amstate, AND_EXPR, CoerceToDomain::arg, CoerceToDomainState::arg, BooleanTest::arg, NullTest::arg, NullTestState::arg, arg, CaseExpr::arg, CaseExprState::arg, ConvertRowtypeExpr::arg, ConvertRowtypeExprState::arg, ArrayCoerceExpr::arg, ArrayCoerceExprState::arg, CoerceViaIO::arg, CoerceViaIOState::arg, RelabelType::arg, GenericExprState::arg, FieldStore::arg, FieldStoreState::arg, FieldSelect::arg, FieldSelectState::arg, NullTestState::argdesc, FieldStoreState::argdesc, FieldSelectState::argdesc, XmlExprState::args, XmlExpr::args, MinMaxExprState::args, MinMaxExpr::args, CoalesceExprState::args, CoalesceExpr::args, RowExprState::args, RowExpr::args, CaseExprState::args, CaseExpr::args, BoolExpr::args, BoolExprState::args, ScalarArrayOpExpr::args, OpExpr::args, FuncExpr::args, FuncExprState::args, WindowFunc::args, WindowFuncExprState::args, Aggref::args, AggrefExprState::args, Assert, tupleDesc::attrs, BlessTupleDesc(), BoolExpr::boolop, BTORDER_PROC, MinMaxExprState::cfunc, check_stack_depth(), TypeCacheEntry::cmp_proc, RowCompareExprState::collations, RowExpr::colnames, CoerceToDomainState::constraints, convert(), CaseExpr::defresult, CaseExprState::defresult, ArrayExprState::elemalign, ArrayExprState::elembyval, ScalarArrayOpExprState::element_type, ArrayExpr::element_typeid, ArrayExprState::elements, ArrayExpr::elements, ArrayCoerceExprState::elemfunc, ArrayExprState::elemlength, elog, ereport, errcode(), errmsg(), ERROR, ExprState::evalfunc, ExecEvalAggref(), ExecEvalAnd(), ExecEvalArray(), ExecEvalArrayCoerceExpr(), ExecEvalArrayRef(), ExecEvalBooleanTest(), ExecEvalCase(), ExecEvalCoalesce(), ExecEvalCoerceToDomain(), ExecEvalCoerceViaIO(), ExecEvalConvertRowtype(), ExecEvalDistinct(), ExecEvalFieldSelect(), ExecEvalFieldStore(), ExecEvalFunc(), ExecEvalMinMax(), ExecEvalNot(), ExecEvalNullIf(), ExecEvalNullTest(), ExecEvalOper(), ExecEvalOr(), ExecEvalRelabelType(), ExecEvalRow(), ExecEvalRowCompare(), ExecEvalScalarArrayOp(), ExecEvalWholeRowVar(), ExecEvalWindowFunc(), ExecEvalXml(), ExecInitAlternativeSubPlan(), ExecInitExpr(), ExecInitSubPlan(), ExecTypeFromExprList(), TargetEntry::expr, CaseWhen::expr, CaseWhenState::expr, ExprState::expr, exprType(), fmgr_info(), FmgrInfo::fn_oid, format_type_be(), forthree, FuncExprState::func, RowCompareExprState::funcs, WindowAggState::funcs, ScalarArrayOpExprState::fxprstate, get_element_type(), get_op_opfamily_properties(), get_opfamily_proc(), get_typlen(), get_typlenbyvalalign(), getBaseType(), GetDomainConstraints(), getTypeInputInfo(), getTypeOutputInfo(), i, CoerceViaIOState::infunc, RowCompareExpr::inputcollids, INT4OID, CoerceViaIOState::intypioparam, InvalidAttrNumber, InvalidOid, IsA, lappend(), RowCompareExprState::largs, RowCompareExpr::largs, lcons(), lfirst, lfirst_oid, list_length(), lookup_rowtype_tupdesc_copy(), lookup_type_cache(), makeNode, makeNullConst(), MinMaxExpr::minmaxtype, XmlExprState::named_args, XmlExpr::named_args, tupleDesc::natts, FieldStore::newvals, FieldStoreState::newvals, nodeTag, NOT_EXPR, NULL, WindowAggState::numaggs, AggState::numaggs, WindowAggState::numfuncs, OidIsValid, RowCompareExpr::opfamilies, RowCompareExpr::opnos, OR_EXPR, CoerceViaIOState::outfunc, palloc(), palloc0(), PARAM_EXEC, PARAM_EXTERN, WholeRowVarExprState::parent, RowCompareExprState::rargs, RowCompareExpr::rargs, RECORDOID, ArrayRef::refarraytype, ArrayRef::refassgnexpr, ArrayRefExprState::refassgnexpr, ArrayRefExprState::refattrlength, ArrayRefExprState::refelemalign, ArrayRefExprState::refelembyval, ArrayRefExprState::refelemlength, ArrayRef::refelemtype, ArrayRef::refexpr, ArrayRefExprState::refexpr, ArrayRef::reflowerindexpr, ArrayRefExprState::reflowerindexpr, ArrayRef::refupperindexpr, ArrayRefExprState::refupperindexpr, CaseWhen::result, CaseWhenState::result, ArrayCoerceExprState::resultelemtype, CoerceToDomain::resulttype, ArrayCoerceExpr::resulttype, CoerceViaIO::resulttype, RowExpr::row_typeid, PlanState::subPlan, T_Aggref, T_AlternativeSubPlan, T_ArrayCoerceExpr, T_ArrayExpr, T_ArrayRef, T_BooleanTest, T_BoolExpr, T_CaseExpr, T_CaseTestExpr, T_CoalesceExpr, T_CoerceToDomain, T_CoerceToDomainValue, T_CoerceViaIO, T_Const, T_ConvertRowtypeExpr, T_CurrentOfExpr, T_DistinctExpr, T_FieldSelect, T_FieldStore, T_FuncExpr, T_List, T_MinMaxExpr, T_NullIfExpr, T_NullTest, T_OpExpr, T_Param, T_RelabelType, T_RowCompareExpr, T_RowExpr, T_ScalarArrayOpExpr, T_SubPlan, T_TargetEntry, T_Var, T_WindowFunc, T_XmlExpr, RowExprState::tupdesc, TYPECACHE_CMP_PROC, WindowFunc::winagg, WholeRowVarExprState::wrv_junkFilter, CoerceToDomainState::xprstate, NullTestState::xprstate, XmlExprState::xprstate, MinMaxExprState::xprstate, CoalesceExprState::xprstate, RowCompareExprState::xprstate, RowExprState::xprstate, ArrayExprState::xprstate, CaseWhenState::xprstate, CaseExprState::xprstate, ConvertRowtypeExprState::xprstate, ArrayCoerceExprState::xprstate, CoerceViaIOState::xprstate, GenericExprState::xprstate, FieldStoreState::xprstate, FieldSelectState::xprstate, BoolExprState::xprstate, FuncExprState::xprstate, ArrayRefExprState::xprstate, WindowFuncExprState::xprstate, and AggrefExprState::xprstate.

Referenced by ATRewriteTable(), BeginCopyFrom(), btree_predicate_proof(), evaluate_expr(), exec_eval_simple_expr(), ExecIndexBuildScanKeys(), ExecInitAgg(), ExecInitAlternativeSubPlan(), ExecInitBitmapHeapScan(), ExecInitCteScan(), ExecInitExpr(), ExecInitForeignScan(), ExecInitFunctionScan(), ExecInitGroup(), ExecInitHash(), ExecInitHashJoin(), ExecInitIndexOnlyScan(), ExecInitIndexScan(), ExecInitLimit(), ExecInitMergeJoin(), ExecInitModifyTable(), ExecInitNestLoop(), ExecInitResult(), ExecInitSeqScan(), ExecInitSubPlan(), ExecInitSubqueryScan(), ExecInitTidScan(), ExecInitValuesScan(), ExecInitWindowAgg(), ExecInitWorkTableScan(), ExecPrepareExpr(), GetDomainConstraints(), MJExamineQuals(), postgresBeginForeignScan(), and ValuesNext().

{
    ExprState  *state;

    if (node == NULL)
        return NULL;

    /* Guard against stack overflow due to overly complex expressions */
    check_stack_depth();

    switch (nodeTag(node))
    {
        case T_Var:
            /* varattno == InvalidAttrNumber means it's a whole-row Var */
            if (((Var *) node)->varattno == InvalidAttrNumber)
            {
                WholeRowVarExprState *wstate = makeNode(WholeRowVarExprState);

                wstate->parent = parent;
                wstate->wrv_junkFilter = NULL;
                state = (ExprState *) wstate;
                state->evalfunc = (ExprStateEvalFunc) ExecEvalWholeRowVar;
            }
            else
            {
                state = (ExprState *) makeNode(ExprState);
                state->evalfunc = ExecEvalScalarVar;
            }
            break;
        case T_Const:
            state = (ExprState *) makeNode(ExprState);
            state->evalfunc = ExecEvalConst;
            break;
        case T_Param:
            state = (ExprState *) makeNode(ExprState);
            switch (((Param *) node)->paramkind)
            {
                case PARAM_EXEC:
                    state->evalfunc = ExecEvalParamExec;
                    break;
                case PARAM_EXTERN:
                    state->evalfunc = ExecEvalParamExtern;
                    break;
                default:
                    elog(ERROR, "unrecognized paramkind: %d",
                         (int) ((Param *) node)->paramkind);
                    break;
            }
            break;
        case T_CoerceToDomainValue:
            state = (ExprState *) makeNode(ExprState);
            state->evalfunc = ExecEvalCoerceToDomainValue;
            break;
        case T_CaseTestExpr:
            state = (ExprState *) makeNode(ExprState);
            state->evalfunc = ExecEvalCaseTestExpr;
            break;
        case T_Aggref:
            {
                Aggref     *aggref = (Aggref *) node;
                AggrefExprState *astate = makeNode(AggrefExprState);

                astate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalAggref;
                if (parent && IsA(parent, AggState))
                {
                    AggState   *aggstate = (AggState *) parent;
                    int         naggs;

                    aggstate->aggs = lcons(astate, aggstate->aggs);
                    naggs = ++aggstate->numaggs;

                    astate->args = (List *) ExecInitExpr((Expr *) aggref->args,
                                                         parent);

                    /*
                     * Complain if the aggregate's arguments contain any
                     * aggregates; nested agg functions are semantically
                     * nonsensical.  (This should have been caught earlier,
                     * but we defend against it here anyway.)
                     */
                    if (naggs != aggstate->numaggs)
                        ereport(ERROR,
                                (errcode(ERRCODE_GROUPING_ERROR),
                        errmsg("aggregate function calls cannot be nested")));
                }
                else
                {
                    /* planner messed up */
                    elog(ERROR, "Aggref found in non-Agg plan node");
                }
                state = (ExprState *) astate;
            }
            break;
        case T_WindowFunc:
            {
                WindowFunc *wfunc = (WindowFunc *) node;
                WindowFuncExprState *wfstate = makeNode(WindowFuncExprState);

                wfstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalWindowFunc;
                if (parent && IsA(parent, WindowAggState))
                {
                    WindowAggState *winstate = (WindowAggState *) parent;
                    int         nfuncs;

                    winstate->funcs = lcons(wfstate, winstate->funcs);
                    nfuncs = ++winstate->numfuncs;
                    if (wfunc->winagg)
                        winstate->numaggs++;

                    wfstate->args = (List *) ExecInitExpr((Expr *) wfunc->args,
                                                          parent);

                    /*
                     * Complain if the windowfunc's arguments contain any
                     * windowfuncs; nested window functions are semantically
                     * nonsensical.  (This should have been caught earlier,
                     * but we defend against it here anyway.)
                     */
                    if (nfuncs != winstate->numfuncs)
                        ereport(ERROR,
                                (errcode(ERRCODE_WINDOWING_ERROR),
                          errmsg("window function calls cannot be nested")));
                }
                else
                {
                    /* planner messed up */
                    elog(ERROR, "WindowFunc found in non-WindowAgg plan node");
                }
                state = (ExprState *) wfstate;
            }
            break;
        case T_ArrayRef:
            {
                ArrayRef   *aref = (ArrayRef *) node;
                ArrayRefExprState *astate = makeNode(ArrayRefExprState);

                astate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalArrayRef;
                astate->refupperindexpr = (List *)
                    ExecInitExpr((Expr *) aref->refupperindexpr, parent);
                astate->reflowerindexpr = (List *)
                    ExecInitExpr((Expr *) aref->reflowerindexpr, parent);
                astate->refexpr = ExecInitExpr(aref->refexpr, parent);
                astate->refassgnexpr = ExecInitExpr(aref->refassgnexpr,
                                                    parent);
                /* do one-time catalog lookups for type info */
                astate->refattrlength = get_typlen(aref->refarraytype);
                get_typlenbyvalalign(aref->refelemtype,
                                     &astate->refelemlength,
                                     &astate->refelembyval,
                                     &astate->refelemalign);
                state = (ExprState *) astate;
            }
            break;
        case T_FuncExpr:
            {
                FuncExpr   *funcexpr = (FuncExpr *) node;
                FuncExprState *fstate = makeNode(FuncExprState);

                fstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalFunc;
                fstate->args = (List *)
                    ExecInitExpr((Expr *) funcexpr->args, parent);
                fstate->func.fn_oid = InvalidOid;       /* not initialized */
                state = (ExprState *) fstate;
            }
            break;
        case T_OpExpr:
            {
                OpExpr     *opexpr = (OpExpr *) node;
                FuncExprState *fstate = makeNode(FuncExprState);

                fstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalOper;
                fstate->args = (List *)
                    ExecInitExpr((Expr *) opexpr->args, parent);
                fstate->func.fn_oid = InvalidOid;       /* not initialized */
                state = (ExprState *) fstate;
            }
            break;
        case T_DistinctExpr:
            {
                DistinctExpr *distinctexpr = (DistinctExpr *) node;
                FuncExprState *fstate = makeNode(FuncExprState);

                fstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalDistinct;
                fstate->args = (List *)
                    ExecInitExpr((Expr *) distinctexpr->args, parent);
                fstate->func.fn_oid = InvalidOid;       /* not initialized */
                state = (ExprState *) fstate;
            }
            break;
        case T_NullIfExpr:
            {
                NullIfExpr *nullifexpr = (NullIfExpr *) node;
                FuncExprState *fstate = makeNode(FuncExprState);

                fstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalNullIf;
                fstate->args = (List *)
                    ExecInitExpr((Expr *) nullifexpr->args, parent);
                fstate->func.fn_oid = InvalidOid;       /* not initialized */
                state = (ExprState *) fstate;
            }
            break;
        case T_ScalarArrayOpExpr:
            {
                ScalarArrayOpExpr *opexpr = (ScalarArrayOpExpr *) node;
                ScalarArrayOpExprState *sstate = makeNode(ScalarArrayOpExprState);

                sstate->fxprstate.xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalScalarArrayOp;
                sstate->fxprstate.args = (List *)
                    ExecInitExpr((Expr *) opexpr->args, parent);
                sstate->fxprstate.func.fn_oid = InvalidOid;     /* not initialized */
                sstate->element_type = InvalidOid;      /* ditto */
                state = (ExprState *) sstate;
            }
            break;
        case T_BoolExpr:
            {
                BoolExpr   *boolexpr = (BoolExpr *) node;
                BoolExprState *bstate = makeNode(BoolExprState);

                switch (boolexpr->boolop)
                {
                    case AND_EXPR:
                        bstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalAnd;
                        break;
                    case OR_EXPR:
                        bstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalOr;
                        break;
                    case NOT_EXPR:
                        bstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalNot;
                        break;
                    default:
                        elog(ERROR, "unrecognized boolop: %d",
                             (int) boolexpr->boolop);
                        break;
                }
                bstate->args = (List *)
                    ExecInitExpr((Expr *) boolexpr->args, parent);
                state = (ExprState *) bstate;
            }
            break;
        case T_SubPlan:
            {
                SubPlan    *subplan = (SubPlan *) node;
                SubPlanState *sstate;

                if (!parent)
                    elog(ERROR, "SubPlan found with no parent plan");

                sstate = ExecInitSubPlan(subplan, parent);

                /* Add SubPlanState nodes to parent->subPlan */
                parent->subPlan = lappend(parent->subPlan, sstate);

                state = (ExprState *) sstate;
            }
            break;
        case T_AlternativeSubPlan:
            {
                AlternativeSubPlan *asplan = (AlternativeSubPlan *) node;
                AlternativeSubPlanState *asstate;

                if (!parent)
                    elog(ERROR, "AlternativeSubPlan found with no parent plan");

                asstate = ExecInitAlternativeSubPlan(asplan, parent);

                state = (ExprState *) asstate;
            }
            break;
        case T_FieldSelect:
            {
                FieldSelect *fselect = (FieldSelect *) node;
                FieldSelectState *fstate = makeNode(FieldSelectState);

                fstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalFieldSelect;
                fstate->arg = ExecInitExpr(fselect->arg, parent);
                fstate->argdesc = NULL;
                state = (ExprState *) fstate;
            }
            break;
        case T_FieldStore:
            {
                FieldStore *fstore = (FieldStore *) node;
                FieldStoreState *fstate = makeNode(FieldStoreState);

                fstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalFieldStore;
                fstate->arg = ExecInitExpr(fstore->arg, parent);
                fstate->newvals = (List *) ExecInitExpr((Expr *) fstore->newvals, parent);
                fstate->argdesc = NULL;
                state = (ExprState *) fstate;
            }
            break;
        case T_RelabelType:
            {
                RelabelType *relabel = (RelabelType *) node;
                GenericExprState *gstate = makeNode(GenericExprState);

                gstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalRelabelType;
                gstate->arg = ExecInitExpr(relabel->arg, parent);
                state = (ExprState *) gstate;
            }
            break;
        case T_CoerceViaIO:
            {
                CoerceViaIO *iocoerce = (CoerceViaIO *) node;
                CoerceViaIOState *iostate = makeNode(CoerceViaIOState);
                Oid         iofunc;
                bool        typisvarlena;

                iostate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalCoerceViaIO;
                iostate->arg = ExecInitExpr(iocoerce->arg, parent);
                /* lookup the result type's input function */
                getTypeInputInfo(iocoerce->resulttype, &iofunc,
                                 &iostate->intypioparam);
                fmgr_info(iofunc, &iostate->infunc);
                /* lookup the input type's output function */
                getTypeOutputInfo(exprType((Node *) iocoerce->arg),
                                  &iofunc, &typisvarlena);
                fmgr_info(iofunc, &iostate->outfunc);
                state = (ExprState *) iostate;
            }
            break;
        case T_ArrayCoerceExpr:
            {
                ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;
                ArrayCoerceExprState *astate = makeNode(ArrayCoerceExprState);

                astate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalArrayCoerceExpr;
                astate->arg = ExecInitExpr(acoerce->arg, parent);
                astate->resultelemtype = get_element_type(acoerce->resulttype);
                if (astate->resultelemtype == InvalidOid)
                    ereport(ERROR,
                            (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                             errmsg("target type is not an array")));
                /* Arrays over domains aren't supported yet */
                Assert(getBaseType(astate->resultelemtype) ==
                       astate->resultelemtype);
                astate->elemfunc.fn_oid = InvalidOid;   /* not initialized */
                astate->amstate = (ArrayMapState *) palloc0(sizeof(ArrayMapState));
                state = (ExprState *) astate;
            }
            break;
        case T_ConvertRowtypeExpr:
            {
                ConvertRowtypeExpr *convert = (ConvertRowtypeExpr *) node;
                ConvertRowtypeExprState *cstate = makeNode(ConvertRowtypeExprState);

                cstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalConvertRowtype;
                cstate->arg = ExecInitExpr(convert->arg, parent);
                state = (ExprState *) cstate;
            }
            break;
        case T_CaseExpr:
            {
                CaseExpr   *caseexpr = (CaseExpr *) node;
                CaseExprState *cstate = makeNode(CaseExprState);
                List       *outlist = NIL;
                ListCell   *l;

                cstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalCase;
                cstate->arg = ExecInitExpr(caseexpr->arg, parent);
                foreach(l, caseexpr->args)
                {
                    CaseWhen   *when = (CaseWhen *) lfirst(l);
                    CaseWhenState *wstate = makeNode(CaseWhenState);

                    Assert(IsA(when, CaseWhen));
                    wstate->xprstate.evalfunc = NULL;   /* not used */
                    wstate->xprstate.expr = (Expr *) when;
                    wstate->expr = ExecInitExpr(when->expr, parent);
                    wstate->result = ExecInitExpr(when->result, parent);
                    outlist = lappend(outlist, wstate);
                }
                cstate->args = outlist;
                cstate->defresult = ExecInitExpr(caseexpr->defresult, parent);
                state = (ExprState *) cstate;
            }
            break;
        case T_ArrayExpr:
            {
                ArrayExpr  *arrayexpr = (ArrayExpr *) node;
                ArrayExprState *astate = makeNode(ArrayExprState);
                List       *outlist = NIL;
                ListCell   *l;

                astate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalArray;
                foreach(l, arrayexpr->elements)
                {
                    Expr       *e = (Expr *) lfirst(l);
                    ExprState  *estate;

                    estate = ExecInitExpr(e, parent);
                    outlist = lappend(outlist, estate);
                }
                astate->elements = outlist;
                /* do one-time catalog lookup for type info */
                get_typlenbyvalalign(arrayexpr->element_typeid,
                                     &astate->elemlength,
                                     &astate->elembyval,
                                     &astate->elemalign);
                state = (ExprState *) astate;
            }
            break;
        case T_RowExpr:
            {
                RowExpr    *rowexpr = (RowExpr *) node;
                RowExprState *rstate = makeNode(RowExprState);
                Form_pg_attribute *attrs;
                List       *outlist = NIL;
                ListCell   *l;
                int         i;

                rstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalRow;
                /* Build tupdesc to describe result tuples */
                if (rowexpr->row_typeid == RECORDOID)
                {
                    /* generic record, use runtime type assignment */
                    rstate->tupdesc = ExecTypeFromExprList(rowexpr->args,
                                                           rowexpr->colnames);
                    BlessTupleDesc(rstate->tupdesc);
                    /* we won't need to redo this at runtime */
                }
                else
                {
                    /* it's been cast to a named type, use that */
                    rstate->tupdesc = lookup_rowtype_tupdesc_copy(rowexpr->row_typeid, -1);
                }
                /* Set up evaluation, skipping any deleted columns */
                Assert(list_length(rowexpr->args) <= rstate->tupdesc->natts);
                attrs = rstate->tupdesc->attrs;
                i = 0;
                foreach(l, rowexpr->args)
                {
                    Expr       *e = (Expr *) lfirst(l);
                    ExprState  *estate;

                    if (!attrs[i]->attisdropped)
                    {
                        /*
                         * Guard against ALTER COLUMN TYPE on rowtype since
                         * the RowExpr was created.  XXX should we check
                         * typmod too?  Not sure we can be sure it'll be the
                         * same.
                         */
                        if (exprType((Node *) e) != attrs[i]->atttypid)
                            ereport(ERROR,
                                    (errcode(ERRCODE_DATATYPE_MISMATCH),
                                     errmsg("ROW() column has type %s instead of type %s",
                                        format_type_be(exprType((Node *) e)),
                                       format_type_be(attrs[i]->atttypid))));
                    }
                    else
                    {
                        /*
                         * Ignore original expression and insert a NULL. We
                         * don't really care what type of NULL it is, so
                         * always make an int4 NULL.
                         */
                        e = (Expr *) makeNullConst(INT4OID, -1, InvalidOid);
                    }
                    estate = ExecInitExpr(e, parent);
                    outlist = lappend(outlist, estate);
                    i++;
                }
                rstate->args = outlist;
                state = (ExprState *) rstate;
            }
            break;
        case T_RowCompareExpr:
            {
                RowCompareExpr *rcexpr = (RowCompareExpr *) node;
                RowCompareExprState *rstate = makeNode(RowCompareExprState);
                int         nopers = list_length(rcexpr->opnos);
                List       *outlist;
                ListCell   *l;
                ListCell   *l2;
                ListCell   *l3;
                int         i;

                rstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalRowCompare;
                Assert(list_length(rcexpr->largs) == nopers);
                outlist = NIL;
                foreach(l, rcexpr->largs)
                {
                    Expr       *e = (Expr *) lfirst(l);
                    ExprState  *estate;

                    estate = ExecInitExpr(e, parent);
                    outlist = lappend(outlist, estate);
                }
                rstate->largs = outlist;
                Assert(list_length(rcexpr->rargs) == nopers);
                outlist = NIL;
                foreach(l, rcexpr->rargs)
                {
                    Expr       *e = (Expr *) lfirst(l);
                    ExprState  *estate;

                    estate = ExecInitExpr(e, parent);
                    outlist = lappend(outlist, estate);
                }
                rstate->rargs = outlist;
                Assert(list_length(rcexpr->opfamilies) == nopers);
                rstate->funcs = (FmgrInfo *) palloc(nopers * sizeof(FmgrInfo));
                rstate->collations = (Oid *) palloc(nopers * sizeof(Oid));
                i = 0;
                forthree(l, rcexpr->opnos, l2, rcexpr->opfamilies, l3, rcexpr->inputcollids)
                {
                    Oid         opno = lfirst_oid(l);
                    Oid         opfamily = lfirst_oid(l2);
                    Oid         inputcollid = lfirst_oid(l3);
                    int         strategy;
                    Oid         lefttype;
                    Oid         righttype;
                    Oid         proc;

                    get_op_opfamily_properties(opno, opfamily, false,
                                               &strategy,
                                               &lefttype,
                                               &righttype);
                    proc = get_opfamily_proc(opfamily,
                                             lefttype,
                                             righttype,
                                             BTORDER_PROC);

                    /*
                     * If we enforced permissions checks on index support
                     * functions, we'd need to make a check here.  But the
                     * index support machinery doesn't do that, and neither
                     * does this code.
                     */
                    fmgr_info(proc, &(rstate->funcs[i]));
                    rstate->collations[i] = inputcollid;
                    i++;
                }
                state = (ExprState *) rstate;
            }
            break;
        case T_CoalesceExpr:
            {
                CoalesceExpr *coalesceexpr = (CoalesceExpr *) node;
                CoalesceExprState *cstate = makeNode(CoalesceExprState);
                List       *outlist = NIL;
                ListCell   *l;

                cstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalCoalesce;
                foreach(l, coalesceexpr->args)
                {
                    Expr       *e = (Expr *) lfirst(l);
                    ExprState  *estate;

                    estate = ExecInitExpr(e, parent);
                    outlist = lappend(outlist, estate);
                }
                cstate->args = outlist;
                state = (ExprState *) cstate;
            }
            break;
        case T_MinMaxExpr:
            {
                MinMaxExpr *minmaxexpr = (MinMaxExpr *) node;
                MinMaxExprState *mstate = makeNode(MinMaxExprState);
                List       *outlist = NIL;
                ListCell   *l;
                TypeCacheEntry *typentry;

                mstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalMinMax;
                foreach(l, minmaxexpr->args)
                {
                    Expr       *e = (Expr *) lfirst(l);
                    ExprState  *estate;

                    estate = ExecInitExpr(e, parent);
                    outlist = lappend(outlist, estate);
                }
                mstate->args = outlist;
                /* Look up the btree comparison function for the datatype */
                typentry = lookup_type_cache(minmaxexpr->minmaxtype,
                                             TYPECACHE_CMP_PROC);
                if (!OidIsValid(typentry->cmp_proc))
                    ereport(ERROR,
                            (errcode(ERRCODE_UNDEFINED_FUNCTION),
                             errmsg("could not identify a comparison function for type %s",
                                    format_type_be(minmaxexpr->minmaxtype))));

                /*
                 * If we enforced permissions checks on index support
                 * functions, we'd need to make a check here.  But the index
                 * support machinery doesn't do that, and neither does this
                 * code.
                 */
                fmgr_info(typentry->cmp_proc, &(mstate->cfunc));
                state = (ExprState *) mstate;
            }
            break;
        case T_XmlExpr:
            {
                XmlExpr    *xexpr = (XmlExpr *) node;
                XmlExprState *xstate = makeNode(XmlExprState);
                List       *outlist;
                ListCell   *arg;

                xstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalXml;
                outlist = NIL;
                foreach(arg, xexpr->named_args)
                {
                    Expr       *e = (Expr *) lfirst(arg);
                    ExprState  *estate;

                    estate = ExecInitExpr(e, parent);
                    outlist = lappend(outlist, estate);
                }
                xstate->named_args = outlist;

                outlist = NIL;
                foreach(arg, xexpr->args)
                {
                    Expr       *e = (Expr *) lfirst(arg);
                    ExprState  *estate;

                    estate = ExecInitExpr(e, parent);
                    outlist = lappend(outlist, estate);
                }
                xstate->args = outlist;

                state = (ExprState *) xstate;
            }
            break;
        case T_NullTest:
            {
                NullTest   *ntest = (NullTest *) node;
                NullTestState *nstate = makeNode(NullTestState);

                nstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalNullTest;
                nstate->arg = ExecInitExpr(ntest->arg, parent);
                nstate->argdesc = NULL;
                state = (ExprState *) nstate;
            }
            break;
        case T_BooleanTest:
            {
                BooleanTest *btest = (BooleanTest *) node;
                GenericExprState *gstate = makeNode(GenericExprState);

                gstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalBooleanTest;
                gstate->arg = ExecInitExpr(btest->arg, parent);
                state = (ExprState *) gstate;
            }
            break;
        case T_CoerceToDomain:
            {
                CoerceToDomain *ctest = (CoerceToDomain *) node;
                CoerceToDomainState *cstate = makeNode(CoerceToDomainState);

                cstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalCoerceToDomain;
                cstate->arg = ExecInitExpr(ctest->arg, parent);
                cstate->constraints = GetDomainConstraints(ctest->resulttype);
                state = (ExprState *) cstate;
            }
            break;
        case T_CurrentOfExpr:
            state = (ExprState *) makeNode(ExprState);
            state->evalfunc = ExecEvalCurrentOfExpr;
            break;
        case T_TargetEntry:
            {
                TargetEntry *tle = (TargetEntry *) node;
                GenericExprState *gstate = makeNode(GenericExprState);

                gstate->xprstate.evalfunc = NULL;       /* not used */
                gstate->arg = ExecInitExpr(tle->expr, parent);
                state = (ExprState *) gstate;
            }
            break;
        case T_List:
            {
                List       *outlist = NIL;
                ListCell   *l;

                foreach(l, (List *) node)
                {
                    outlist = lappend(outlist,
                                      ExecInitExpr((Expr *) lfirst(l),
                                                   parent));
                }
                /* Don't fall through to the "common" code below */
                return (ExprState *) outlist;
            }
        default:
            elog(ERROR, "unrecognized node type: %d",
                 (int) nodeTag(node));
            state = NULL;       /* keep compiler quiet */
            break;
    }

    /* Common code for all state-node types */
    state->expr = node;

    return state;
}

TupleTableSlot* ExecInitExtraTupleSlot ( EState estate  ) 
JunkFilter* ExecInitJunkFilter ( List targetList,
bool  hasoid,
TupleTableSlot slot 
)

Definition at line 61 of file execJunk.c.

References ExecCleanTypeFromTL(), ExecSetSlotDescriptor(), JunkFilter::jf_cleanMap, JunkFilter::jf_cleanTupType, JunkFilter::jf_resultSlot, JunkFilter::jf_targetList, lfirst, makeNode, MakeSingleTupleTableSlot(), tupleDesc::natts, palloc(), TargetEntry::resjunk, and TargetEntry::resno.

Referenced by check_sql_fn_retval(), ExecEvalWholeRowVar(), ExecInitModifyTable(), and InitPlan().

{
    JunkFilter *junkfilter;
    TupleDesc   cleanTupType;
    int         cleanLength;
    AttrNumber *cleanMap;
    ListCell   *t;
    AttrNumber  cleanResno;

    /*
     * Compute the tuple descriptor for the cleaned tuple.
     */
    cleanTupType = ExecCleanTypeFromTL(targetList, hasoid);

    /*
     * Use the given slot, or make a new slot if we weren't given one.
     */
    if (slot)
        ExecSetSlotDescriptor(slot, cleanTupType);
    else
        slot = MakeSingleTupleTableSlot(cleanTupType);

    /*
     * Now calculate the mapping between the original tuple's attributes and
     * the "clean" tuple's attributes.
     *
     * The "map" is an array of "cleanLength" attribute numbers, i.e. one
     * entry for every attribute of the "clean" tuple. The value of this entry
     * is the attribute number of the corresponding attribute of the
     * "original" tuple.  (Zero indicates a NULL output attribute, but we do
     * not use that feature in this routine.)
     */
    cleanLength = cleanTupType->natts;
    if (cleanLength > 0)
    {
        cleanMap = (AttrNumber *) palloc(cleanLength * sizeof(AttrNumber));
        cleanResno = 1;
        foreach(t, targetList)
        {
            TargetEntry *tle = lfirst(t);

            if (!tle->resjunk)
            {
                cleanMap[cleanResno - 1] = tle->resno;
                cleanResno++;
            }
        }
    }
    else
        cleanMap = NULL;

    /*
     * Finally create and initialize the JunkFilter struct.
     */
    junkfilter = makeNode(JunkFilter);

    junkfilter->jf_targetList = targetList;
    junkfilter->jf_cleanTupType = cleanTupType;
    junkfilter->jf_cleanMap = cleanMap;
    junkfilter->jf_resultSlot = slot;

    return junkfilter;
}

JunkFilter* ExecInitJunkFilterConversion ( List targetList,
TupleDesc  cleanTupType,
TupleTableSlot slot 
)

Definition at line 136 of file execJunk.c.

References tupleDesc::attrs, ExecSetSlotDescriptor(), i, JunkFilter::jf_cleanMap, JunkFilter::jf_cleanTupType, JunkFilter::jf_resultSlot, JunkFilter::jf_targetList, lfirst, list_head(), lnext, makeNode, MakeSingleTupleTableSlot(), tupleDesc::natts, palloc0(), TargetEntry::resjunk, and TargetEntry::resno.

Referenced by check_sql_fn_retval().

{
    JunkFilter *junkfilter;
    int         cleanLength;
    AttrNumber *cleanMap;
    ListCell   *t;
    int         i;

    /*
     * Use the given slot, or make a new slot if we weren't given one.
     */
    if (slot)
        ExecSetSlotDescriptor(slot, cleanTupType);
    else
        slot = MakeSingleTupleTableSlot(cleanTupType);

    /*
     * Calculate the mapping between the original tuple's attributes and the
     * "clean" tuple's attributes.
     *
     * The "map" is an array of "cleanLength" attribute numbers, i.e. one
     * entry for every attribute of the "clean" tuple. The value of this entry
     * is the attribute number of the corresponding attribute of the
     * "original" tuple.  We store zero for any deleted attributes, marking
     * that a NULL is needed in the output tuple.
     */
    cleanLength = cleanTupType->natts;
    if (cleanLength > 0)
    {
        cleanMap = (AttrNumber *) palloc0(cleanLength * sizeof(AttrNumber));
        t = list_head(targetList);
        for (i = 0; i < cleanLength; i++)
        {
            if (cleanTupType->attrs[i]->attisdropped)
                continue;       /* map entry is already zero */
            for (;;)
            {
                TargetEntry *tle = lfirst(t);

                t = lnext(t);
                if (!tle->resjunk)
                {
                    cleanMap[i] = tle->resno;
                    break;
                }
            }
        }
    }
    else
        cleanMap = NULL;

    /*
     * Finally create and initialize the JunkFilter struct.
     */
    junkfilter = makeNode(JunkFilter);

    junkfilter->jf_targetList = targetList;
    junkfilter->jf_cleanTupType = cleanTupType;
    junkfilter->jf_cleanMap = cleanMap;
    junkfilter->jf_resultSlot = slot;

    return junkfilter;
}

PlanState* ExecInitNode ( Plan node,
EState estate,
int  eflags 
)

Definition at line 132 of file execProcnode.c.

References Assert, elog, ERROR, EState::es_instrument, ExecInitAgg(), ExecInitAppend(), ExecInitBitmapAnd(), ExecInitBitmapHeapScan(), ExecInitBitmapIndexScan(), ExecInitBitmapOr(), ExecInitCteScan(), ExecInitForeignScan(), ExecInitFunctionScan(), ExecInitGroup(), ExecInitHash(), ExecInitHashJoin(), ExecInitIndexOnlyScan(), ExecInitIndexScan(), ExecInitLimit(), ExecInitLockRows(), ExecInitMaterial(), ExecInitMergeAppend(), ExecInitMergeJoin(), ExecInitModifyTable(), ExecInitNestLoop(), ExecInitRecursiveUnion(), ExecInitResult(), ExecInitSeqScan(), ExecInitSetOp(), ExecInitSort(), ExecInitSubPlan(), ExecInitSubqueryScan(), ExecInitTidScan(), ExecInitUnique(), ExecInitValuesScan(), ExecInitWindowAgg(), ExecInitWorkTableScan(), PlanState::initPlan, Plan::initPlan, InstrAlloc(), PlanState::instrument, IsA, lappend(), lfirst, nodeTag, NULL, T_Agg, T_Append, T_BitmapAnd, T_BitmapHeapScan, T_BitmapIndexScan, T_BitmapOr, T_CteScan, T_ForeignScan, T_FunctionScan, T_Group, T_Hash, T_HashJoin, T_IndexOnlyScan, T_IndexScan, T_Limit, T_LockRows, T_Material, T_MergeAppend, T_MergeJoin, T_ModifyTable, T_NestLoop, T_RecursiveUnion, T_Result, T_SeqScan, T_SetOp, T_Sort, T_SubqueryScan, T_TidScan, T_Unique, T_ValuesScan, T_WindowAgg, and T_WorkTableScan.

Referenced by EvalPlanQualStart(), ExecInitAgg(), ExecInitAppend(), ExecInitBitmapAnd(), ExecInitBitmapHeapScan(), ExecInitBitmapOr(), ExecInitGroup(), ExecInitHash(), ExecInitHashJoin(), ExecInitLimit(), ExecInitLockRows(), ExecInitMaterial(), ExecInitMergeAppend(), ExecInitMergeJoin(), ExecInitModifyTable(), ExecInitNestLoop(), ExecInitRecursiveUnion(), ExecInitResult(), ExecInitSetOp(), ExecInitSort(), ExecInitSubqueryScan(), ExecInitUnique(), ExecInitWindowAgg(), and InitPlan().

{
    PlanState  *result;
    List       *subps;
    ListCell   *l;

    /*
     * do nothing when we get to the end of a leaf on tree.
     */
    if (node == NULL)
        return NULL;

    switch (nodeTag(node))
    {
            /*
             * control nodes
             */
        case T_Result:
            result = (PlanState *) ExecInitResult((Result *) node,
                                                  estate, eflags);
            break;

        case T_ModifyTable:
            result = (PlanState *) ExecInitModifyTable((ModifyTable *) node,
                                                       estate, eflags);
            break;

        case T_Append:
            result = (PlanState *) ExecInitAppend((Append *) node,
                                                  estate, eflags);
            break;

        case T_MergeAppend:
            result = (PlanState *) ExecInitMergeAppend((MergeAppend *) node,
                                                       estate, eflags);
            break;

        case T_RecursiveUnion:
            result = (PlanState *) ExecInitRecursiveUnion((RecursiveUnion *) node,
                                                          estate, eflags);
            break;

        case T_BitmapAnd:
            result = (PlanState *) ExecInitBitmapAnd((BitmapAnd *) node,
                                                     estate, eflags);
            break;

        case T_BitmapOr:
            result = (PlanState *) ExecInitBitmapOr((BitmapOr *) node,
                                                    estate, eflags);
            break;

            /*
             * scan nodes
             */
        case T_SeqScan:
            result = (PlanState *) ExecInitSeqScan((SeqScan *) node,
                                                   estate, eflags);
            break;

        case T_IndexScan:
            result = (PlanState *) ExecInitIndexScan((IndexScan *) node,
                                                     estate, eflags);
            break;

        case T_IndexOnlyScan:
            result = (PlanState *) ExecInitIndexOnlyScan((IndexOnlyScan *) node,
                                                         estate, eflags);
            break;

        case T_BitmapIndexScan:
            result = (PlanState *) ExecInitBitmapIndexScan((BitmapIndexScan *) node,
                                                           estate, eflags);
            break;

        case T_BitmapHeapScan:
            result = (PlanState *) ExecInitBitmapHeapScan((BitmapHeapScan *) node,
                                                          estate, eflags);
            break;

        case T_TidScan:
            result = (PlanState *) ExecInitTidScan((TidScan *) node,
                                                   estate, eflags);
            break;

        case T_SubqueryScan:
            result = (PlanState *) ExecInitSubqueryScan((SubqueryScan *) node,
                                                        estate, eflags);
            break;

        case T_FunctionScan:
            result = (PlanState *) ExecInitFunctionScan((FunctionScan *) node,
                                                        estate, eflags);
            break;

        case T_ValuesScan:
            result = (PlanState *) ExecInitValuesScan((ValuesScan *) node,
                                                      estate, eflags);
            break;

        case T_CteScan:
            result = (PlanState *) ExecInitCteScan((CteScan *) node,
                                                   estate, eflags);
            break;

        case T_WorkTableScan:
            result = (PlanState *) ExecInitWorkTableScan((WorkTableScan *) node,
                                                         estate, eflags);
            break;

        case T_ForeignScan:
            result = (PlanState *) ExecInitForeignScan((ForeignScan *) node,
                                                       estate, eflags);
            break;

            /*
             * join nodes
             */
        case T_NestLoop:
            result = (PlanState *) ExecInitNestLoop((NestLoop *) node,
                                                    estate, eflags);
            break;

        case T_MergeJoin:
            result = (PlanState *) ExecInitMergeJoin((MergeJoin *) node,
                                                     estate, eflags);
            break;

        case T_HashJoin:
            result = (PlanState *) ExecInitHashJoin((HashJoin *) node,
                                                    estate, eflags);
            break;

            /*
             * materialization nodes
             */
        case T_Material:
            result = (PlanState *) ExecInitMaterial((Material *) node,
                                                    estate, eflags);
            break;

        case T_Sort:
            result = (PlanState *) ExecInitSort((Sort *) node,
                                                estate, eflags);
            break;

        case T_Group:
            result = (PlanState *) ExecInitGroup((Group *) node,
                                                 estate, eflags);
            break;

        case T_Agg:
            result = (PlanState *) ExecInitAgg((Agg *) node,
                                               estate, eflags);
            break;

        case T_WindowAgg:
            result = (PlanState *) ExecInitWindowAgg((WindowAgg *) node,
                                                     estate, eflags);
            break;

        case T_Unique:
            result = (PlanState *) ExecInitUnique((Unique *) node,
                                                  estate, eflags);
            break;

        case T_Hash:
            result = (PlanState *) ExecInitHash((Hash *) node,
                                                estate, eflags);
            break;

        case T_SetOp:
            result = (PlanState *) ExecInitSetOp((SetOp *) node,
                                                 estate, eflags);
            break;

        case T_LockRows:
            result = (PlanState *) ExecInitLockRows((LockRows *) node,
                                                    estate, eflags);
            break;

        case T_Limit:
            result = (PlanState *) ExecInitLimit((Limit *) node,
                                                 estate, eflags);
            break;

        default:
            elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
            result = NULL;      /* keep compiler quiet */
            break;
    }

    /*
     * Initialize any initPlans present in this node.  The planner put them in
     * a separate list for us.
     */
    subps = NIL;
    foreach(l, node->initPlan)
    {
        SubPlan    *subplan = (SubPlan *) lfirst(l);
        SubPlanState *sstate;

        Assert(IsA(subplan, SubPlan));
        sstate = ExecInitSubPlan(subplan, result);
        subps = lappend(subps, sstate);
    }
    result->initPlan = subps;

    /* Set up instrumentation for this node if requested */
    if (estate->es_instrument)
        result->instrument = InstrAlloc(1, estate->es_instrument);

    return result;
}

TupleTableSlot* ExecInitNullTupleSlot ( EState estate,
TupleDesc  tupType 
)
void ExecInitResultTupleSlot ( EState estate,
PlanState planstate 
)
void ExecInitScanTupleSlot ( EState estate,
ScanState scanstate 
)
List* ExecInsertIndexTuples ( TupleTableSlot slot,
ItemPointer  tupleid,
EState estate 
)

Definition at line 1001 of file execUtils.c.

References check_exclusion_constraint(), ExprContext::ecxt_scantuple, EState::es_result_relation_info, ExecPrepareExpr(), ExecQual(), FormIndexDatum(), GetPerTupleExprContext, i, IndexInfo::ii_ExclusionOps, IndexInfo::ii_Predicate, IndexInfo::ii_PredicateState, IndexInfo::ii_ReadyForInserts, index_insert(), lappend_oid(), NIL, NULL, RelationData::rd_index, RelationGetRelid, ResultRelInfo::ri_IndexRelationDescs, ResultRelInfo::ri_IndexRelationInfo, ResultRelInfo::ri_NumIndices, ResultRelInfo::ri_RelationDesc, UNIQUE_CHECK_PARTIAL, and values.

Referenced by CopyFrom(), CopyFromInsertBatch(), ExecInsert(), and ExecUpdate().

{
    List       *result = NIL;
    ResultRelInfo *resultRelInfo;
    int         i;
    int         numIndices;
    RelationPtr relationDescs;
    Relation    heapRelation;
    IndexInfo **indexInfoArray;
    ExprContext *econtext;
    Datum       values[INDEX_MAX_KEYS];
    bool        isnull[INDEX_MAX_KEYS];

    /*
     * Get information from the result relation info structure.
     */
    resultRelInfo = estate->es_result_relation_info;
    numIndices = resultRelInfo->ri_NumIndices;
    relationDescs = resultRelInfo->ri_IndexRelationDescs;
    indexInfoArray = resultRelInfo->ri_IndexRelationInfo;
    heapRelation = resultRelInfo->ri_RelationDesc;

    /*
     * We will use the EState's per-tuple context for evaluating predicates
     * and index expressions (creating it if it's not already there).
     */
    econtext = GetPerTupleExprContext(estate);

    /* Arrange for econtext's scan tuple to be the tuple under test */
    econtext->ecxt_scantuple = slot;

    /*
     * for each index, form and insert the index tuple
     */
    for (i = 0; i < numIndices; i++)
    {
        Relation    indexRelation = relationDescs[i];
        IndexInfo  *indexInfo;
        IndexUniqueCheck checkUnique;
        bool        satisfiesConstraint;

        if (indexRelation == NULL)
            continue;

        indexInfo = indexInfoArray[i];

        /* If the index is marked as read-only, ignore it */
        if (!indexInfo->ii_ReadyForInserts)
            continue;

        /* Check for partial index */
        if (indexInfo->ii_Predicate != NIL)
        {
            List       *predicate;

            /*
             * If predicate state not set up yet, create it (in the estate's
             * per-query context)
             */
            predicate = indexInfo->ii_PredicateState;
            if (predicate == NIL)
            {
                predicate = (List *)
                    ExecPrepareExpr((Expr *) indexInfo->ii_Predicate,
                                    estate);
                indexInfo->ii_PredicateState = predicate;
            }

            /* Skip this index-update if the predicate isn't satisfied */
            if (!ExecQual(predicate, econtext, false))
                continue;
        }

        /*
         * FormIndexDatum fills in its values and isnull parameters with the
         * appropriate values for the column(s) of the index.
         */
        FormIndexDatum(indexInfo,
                       slot,
                       estate,
                       values,
                       isnull);

        /*
         * The index AM does the actual insertion, plus uniqueness checking.
         *
         * For an immediate-mode unique index, we just tell the index AM to
         * throw error if not unique.
         *
         * For a deferrable unique index, we tell the index AM to just detect
         * possible non-uniqueness, and we add the index OID to the result
         * list if further checking is needed.
         */
        if (!indexRelation->rd_index->indisunique)
            checkUnique = UNIQUE_CHECK_NO;
        else if (indexRelation->rd_index->indimmediate)
            checkUnique = UNIQUE_CHECK_YES;
        else
            checkUnique = UNIQUE_CHECK_PARTIAL;

        satisfiesConstraint =
            index_insert(indexRelation, /* index relation */
                         values,    /* array of index Datums */
                         isnull,    /* null flags */
                         tupleid,       /* tid of heap tuple */
                         heapRelation,  /* heap relation */
                         checkUnique);  /* type of uniqueness check to do */

        /*
         * If the index has an associated exclusion constraint, check that.
         * This is simpler than the process for uniqueness checks since we
         * always insert first and then check.  If the constraint is deferred,
         * we check now anyway, but don't throw error on violation; instead
         * we'll queue a recheck event.
         *
         * An index for an exclusion constraint can't also be UNIQUE (not an
         * essential property, we just don't allow it in the grammar), so no
         * need to preserve the prior state of satisfiesConstraint.
         */
        if (indexInfo->ii_ExclusionOps != NULL)
        {
            bool        errorOK = !indexRelation->rd_index->indimmediate;

            satisfiesConstraint =
                check_exclusion_constraint(heapRelation,
                                           indexRelation, indexInfo,
                                           tupleid, values, isnull,
                                           estate, false, errorOK);
        }

        if ((checkUnique == UNIQUE_CHECK_PARTIAL ||
             indexInfo->ii_ExclusionOps != NULL) &&
            !satisfiesConstraint)
        {
            /*
             * The tuple potentially violates the uniqueness or exclusion
             * constraint, so make a note of the index so that we can re-check
             * it later.
             */
            result = lappend_oid(result, RelationGetRelid(indexRelation));
        }
    }

    return result;
}

Tuplestorestate* ExecMakeTableFunctionResult ( ExprState funcexpr,
ExprContext econtext,
TupleDesc  expectedDesc,
bool  randomAccess 
)

Definition at line 2012 of file execQual.c.

References ReturnSetInfo::allowedModes, FunctionCallInfoData::argnull, FuncExprState::args, CHECK_FOR_INTERRUPTS, CreateTemplateTupleDesc(), CurrentMemoryContext, DatumGetHeapTupleHeader, ReturnSetInfo::econtext, ExprContext::ecxt_per_query_memory, ExprContext::ecxt_per_tuple_memory, ereport, errcode(), errmsg(), ERROR, ExecEvalExpr, ExecEvalFuncArgs(), ReturnSetInfo::expectedDesc, ExprState::expr, ExprEndResult, ExprMultipleResult, ExprSingleResult, exprType(), FuncExprState::fcinfo_data, FmgrInfo::fn_oid, FmgrInfo::fn_retset, FmgrInfo::fn_strict, FunctionCallInfoData::fncollation, FreeTupleDesc(), FuncExprState::func, FuncExpr::funcid, FunctionCallInvoke, HeapTupleHeaderGetDatumLength, HeapTupleHeaderGetTypeId, HeapTupleHeaderGetTypMod, i, init_fcache(), InitFunctionCallInfoData, FuncExpr::inputcollid, InvalidOid, IsA, ReturnSetInfo::isDone, FunctionCallInfoData::isnull, list_length(), lookup_rowtype_tupdesc_copy(), MemoryContextSwitchTo(), FunctionCallInfoData::nargs, tupleDesc::natts, NULL, palloc(), palloc0(), pgstat_end_function_usage(), pgstat_init_function_usage(), ResetExprContext, ReturnSetInfo::returnMode, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, SFRM_Materialize, SFRM_Materialize_Preferred, SFRM_Materialize_Random, SFRM_ValuePerCall, HeapTupleData::t_data, HeapTupleData::t_len, tupleDesc::tdrefcount, tupleDesc::tdtypeid, tupleDesc::tdtypmod, tupledesc_match(), TupleDescInitEntry(), tuplestore_begin_heap(), tuplestore_puttuple(), tuplestore_putvalues(), ReturnSetInfo::type, type_is_rowtype(), work_mem, and FuncExprState::xprstate.

Referenced by FunctionNext().

{
    Tuplestorestate *tupstore = NULL;
    TupleDesc   tupdesc = NULL;
    Oid         funcrettype;
    bool        returnsTuple;
    bool        returnsSet = false;
    FunctionCallInfoData fcinfo;
    PgStat_FunctionCallUsage fcusage;
    ReturnSetInfo rsinfo;
    HeapTupleData tmptup;
    MemoryContext callerContext;
    MemoryContext oldcontext;
    bool        direct_function_call;
    bool        first_time = true;

    callerContext = CurrentMemoryContext;

    funcrettype = exprType((Node *) funcexpr->expr);

    returnsTuple = type_is_rowtype(funcrettype);

    /*
     * Prepare a resultinfo node for communication.  We always do this even if
     * not expecting a set result, so that we can pass expectedDesc.  In the
     * generic-expression case, the expression doesn't actually get to see the
     * resultinfo, but set it up anyway because we use some of the fields as
     * our own state variables.
     */
    rsinfo.type = T_ReturnSetInfo;
    rsinfo.econtext = econtext;
    rsinfo.expectedDesc = expectedDesc;
    rsinfo.allowedModes = (int) (SFRM_ValuePerCall | SFRM_Materialize | SFRM_Materialize_Preferred);
    if (randomAccess)
        rsinfo.allowedModes |= (int) SFRM_Materialize_Random;
    rsinfo.returnMode = SFRM_ValuePerCall;
    /* isDone is filled below */
    rsinfo.setResult = NULL;
    rsinfo.setDesc = NULL;

    /*
     * Normally the passed expression tree will be a FuncExprState, since the
     * grammar only allows a function call at the top level of a table
     * function reference.  However, if the function doesn't return set then
     * the planner might have replaced the function call via constant-folding
     * or inlining.  So if we see any other kind of expression node, execute
     * it via the general ExecEvalExpr() code; the only difference is that we
     * don't get a chance to pass a special ReturnSetInfo to any functions
     * buried in the expression.
     */
    if (funcexpr && IsA(funcexpr, FuncExprState) &&
        IsA(funcexpr->expr, FuncExpr))
    {
        FuncExprState *fcache = (FuncExprState *) funcexpr;
        ExprDoneCond argDone;

        /*
         * This path is similar to ExecMakeFunctionResult.
         */
        direct_function_call = true;

        /*
         * Initialize function cache if first time through
         */
        if (fcache->func.fn_oid == InvalidOid)
        {
            FuncExpr   *func = (FuncExpr *) fcache->xprstate.expr;

            init_fcache(func->funcid, func->inputcollid, fcache,
                        econtext->ecxt_per_query_memory, false);
        }
        returnsSet = fcache->func.fn_retset;
        InitFunctionCallInfoData(fcinfo, &(fcache->func),
                                 list_length(fcache->args),
                                 fcache->fcinfo_data.fncollation,
                                 NULL, (Node *) &rsinfo);

        /*
         * Evaluate the function's argument list.
         *
         * Note: ideally, we'd do this in the per-tuple context, but then the
         * argument values would disappear when we reset the context in the
         * inner loop.  So do it in caller context.  Perhaps we should make a
         * separate context just to hold the evaluated arguments?
         */
        argDone = ExecEvalFuncArgs(&fcinfo, fcache->args, econtext);
        /* We don't allow sets in the arguments of the table function */
        if (argDone != ExprSingleResult)
            ereport(ERROR,
                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                     errmsg("set-valued function called in context that cannot accept a set")));

        /*
         * If function is strict, and there are any NULL arguments, skip
         * calling the function and act like it returned NULL (or an empty
         * set, in the returns-set case).
         */
        if (fcache->func.fn_strict)
        {
            int         i;

            for (i = 0; i < fcinfo.nargs; i++)
            {
                if (fcinfo.argnull[i])
                    goto no_function_result;
            }
        }
    }
    else
    {
        /* Treat funcexpr as a generic expression */
        direct_function_call = false;
        InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL);
    }

    /*
     * Switch to short-lived context for calling the function or expression.
     */
    MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);

    /*
     * Loop to handle the ValuePerCall protocol (which is also the same
     * behavior needed in the generic ExecEvalExpr path).
     */
    for (;;)
    {
        Datum       result;

        CHECK_FOR_INTERRUPTS();

        /*
         * reset per-tuple memory context before each call of the function or
         * expression. This cleans up any local memory the function may leak
         * when called.
         */
        ResetExprContext(econtext);

        /* Call the function or expression one time */
        if (direct_function_call)
        {
            pgstat_init_function_usage(&fcinfo, &fcusage);

            fcinfo.isnull = false;
            rsinfo.isDone = ExprSingleResult;
            result = FunctionCallInvoke(&fcinfo);

            pgstat_end_function_usage(&fcusage,
                                      rsinfo.isDone != ExprMultipleResult);
        }
        else
        {
            result = ExecEvalExpr(funcexpr, econtext,
                                  &fcinfo.isnull, &rsinfo.isDone);
        }

        /* Which protocol does function want to use? */
        if (rsinfo.returnMode == SFRM_ValuePerCall)
        {
            /*
             * Check for end of result set.
             */
            if (rsinfo.isDone == ExprEndResult)
                break;

            /*
             * Can't do anything very useful with NULL rowtype values. For a
             * function returning set, we consider this a protocol violation
             * (but another alternative would be to just ignore the result and
             * "continue" to get another row).  For a function not returning
             * set, we fall out of the loop; we'll cons up an all-nulls result
             * row below.
             */
            if (returnsTuple && fcinfo.isnull)
            {
                if (!returnsSet)
                    break;
                ereport(ERROR,
                        (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
                         errmsg("function returning set of rows cannot return null value")));
            }

            /*
             * If first time through, build tupdesc and tuplestore for result
             */
            if (first_time)
            {
                oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
                if (returnsTuple)
                {
                    /*
                     * Use the type info embedded in the rowtype Datum to look
                     * up the needed tupdesc.  Make a copy for the query.
                     */
                    HeapTupleHeader td;

                    td = DatumGetHeapTupleHeader(result);
                    tupdesc = lookup_rowtype_tupdesc_copy(HeapTupleHeaderGetTypeId(td),
                                               HeapTupleHeaderGetTypMod(td));
                }
                else
                {
                    /*
                     * Scalar type, so make a single-column descriptor
                     */
                    tupdesc = CreateTemplateTupleDesc(1, false);
                    TupleDescInitEntry(tupdesc,
                                       (AttrNumber) 1,
                                       "column",
                                       funcrettype,
                                       -1,
                                       0);
                }
                tupstore = tuplestore_begin_heap(randomAccess, false, work_mem);
                MemoryContextSwitchTo(oldcontext);
                rsinfo.setResult = tupstore;
                rsinfo.setDesc = tupdesc;
            }

            /*
             * Store current resultset item.
             */
            if (returnsTuple)
            {
                HeapTupleHeader td;

                td = DatumGetHeapTupleHeader(result);

                /*
                 * Verify all returned rows have same subtype; necessary in
                 * case the type is RECORD.
                 */
                if (HeapTupleHeaderGetTypeId(td) != tupdesc->tdtypeid ||
                    HeapTupleHeaderGetTypMod(td) != tupdesc->tdtypmod)
                    ereport(ERROR,
                            (errcode(ERRCODE_DATATYPE_MISMATCH),
                             errmsg("rows returned by function are not all of the same row type")));

                /*
                 * tuplestore_puttuple needs a HeapTuple not a bare
                 * HeapTupleHeader, but it doesn't need all the fields.
                 */
                tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
                tmptup.t_data = td;

                tuplestore_puttuple(tupstore, &tmptup);
            }
            else
                tuplestore_putvalues(tupstore, tupdesc, &result, &fcinfo.isnull);

            /*
             * Are we done?
             */
            if (rsinfo.isDone != ExprMultipleResult)
                break;
        }
        else if (rsinfo.returnMode == SFRM_Materialize)
        {
            /* check we're on the same page as the function author */
            if (!first_time || rsinfo.isDone != ExprSingleResult)
                ereport(ERROR,
                        (errcode(ERRCODE_E_R_I_E_SRF_PROTOCOL_VIOLATED),
                         errmsg("table-function protocol for materialize mode was not followed")));
            /* Done evaluating the set result */
            break;
        }
        else
            ereport(ERROR,
                    (errcode(ERRCODE_E_R_I_E_SRF_PROTOCOL_VIOLATED),
                     errmsg("unrecognized table-function returnMode: %d",
                            (int) rsinfo.returnMode)));

        first_time = false;
    }

no_function_result:

    /*
     * If we got nothing from the function (ie, an empty-set or NULL result),
     * we have to create the tuplestore to return, and if it's a
     * non-set-returning function then insert a single all-nulls row.
     */
    if (rsinfo.setResult == NULL)
    {
        MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
        tupstore = tuplestore_begin_heap(randomAccess, false, work_mem);
        rsinfo.setResult = tupstore;
        if (!returnsSet)
        {
            int         natts = expectedDesc->natts;
            Datum      *nulldatums;
            bool       *nullflags;

            MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
            nulldatums = (Datum *) palloc0(natts * sizeof(Datum));
            nullflags = (bool *) palloc(natts * sizeof(bool));
            memset(nullflags, true, natts * sizeof(bool));
            MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
            tuplestore_putvalues(tupstore, expectedDesc, nulldatums, nullflags);
        }
    }

    /*
     * If function provided a tupdesc, cross-check it.  We only really need to
     * do this for functions returning RECORD, but might as well do it always.
     */
    if (rsinfo.setDesc)
    {
        tupledesc_match(expectedDesc, rsinfo.setDesc);

        /*
         * If it is a dynamically-allocated TupleDesc, free it: it is
         * typically allocated in a per-query context, so we must avoid
         * leaking it across multiple usages.
         */
        if (rsinfo.setDesc->tdrefcount == -1)
            FreeTupleDesc(rsinfo.setDesc);
    }

    MemoryContextSwitchTo(callerContext);

    /* All done, pass back the tuplestore */
    return rsinfo.setResult;
}

void ExecMarkPos ( PlanState node  ) 
bool ExecMaterializesOutput ( NodeTag  plantype  ) 

Definition at line 538 of file execAmi.c.

References T_CteScan, T_FunctionScan, T_Material, T_Sort, and T_WorkTableScan.

Referenced by build_subplan(), cost_subplan(), and match_unsorted_outer().

{
    switch (plantype)
    {
        case T_Material:
        case T_FunctionScan:
        case T_CteScan:
        case T_WorkTableScan:
        case T_Sort:
            return true;

        default:
            break;
    }

    return false;
}

void ExecOpenIndices ( ResultRelInfo resultRelInfo  ) 

Definition at line 888 of file execUtils.c.

References BuildIndexInfo(), i, index_open(), lfirst_oid, list_free(), list_length(), palloc(), RelationGetForm, RelationGetIndexList(), ResultRelInfo::ri_IndexRelationDescs, ResultRelInfo::ri_IndexRelationInfo, ResultRelInfo::ri_NumIndices, ResultRelInfo::ri_RelationDesc, and RowExclusiveLock.

Referenced by CatalogOpenIndexes(), CopyFrom(), and ExecInitModifyTable().

{
    Relation    resultRelation = resultRelInfo->ri_RelationDesc;
    List       *indexoidlist;
    ListCell   *l;
    int         len,
                i;
    RelationPtr relationDescs;
    IndexInfo **indexInfoArray;

    resultRelInfo->ri_NumIndices = 0;

    /* fast path if no indexes */
    if (!RelationGetForm(resultRelation)->relhasindex)
        return;

    /*
     * Get cached list of index OIDs
     */
    indexoidlist = RelationGetIndexList(resultRelation);
    len = list_length(indexoidlist);
    if (len == 0)
        return;

    /*
     * allocate space for result arrays
     */
    relationDescs = (RelationPtr) palloc(len * sizeof(Relation));
    indexInfoArray = (IndexInfo **) palloc(len * sizeof(IndexInfo *));

    resultRelInfo->ri_NumIndices = len;
    resultRelInfo->ri_IndexRelationDescs = relationDescs;
    resultRelInfo->ri_IndexRelationInfo = indexInfoArray;

    /*
     * For each index, open the index relation and save pg_index info. We
     * acquire RowExclusiveLock, signifying we will update the index.
     *
     * Note: we do this even if the index is not IndexIsReady; it's not worth
     * the trouble to optimize for the case where it isn't.
     */
    i = 0;
    foreach(l, indexoidlist)
    {
        Oid         indexOid = lfirst_oid(l);
        Relation    indexDesc;
        IndexInfo  *ii;

        indexDesc = index_open(indexOid, RowExclusiveLock);

        /* extract index key information from the index's pg_index info */
        ii = BuildIndexInfo(indexDesc);

        relationDescs[i] = indexDesc;
        indexInfoArray[i] = ii;
        i++;
    }

    list_free(indexoidlist);
}

Relation ExecOpenScanRelation ( EState estate,
Index  scanrelid,
int  eflags 
)

Definition at line 801 of file execUtils.c.

References ereport, errcode(), errhint(), errmsg(), ERROR, EState::es_range_table, EState::es_rowMarks, EXEC_FLAG_EXPLAIN_ONLY, EXEC_FLAG_WITH_NO_DATA, ExecRelationIsTargetRelation(), getrelid, heap_open(), lfirst, RelationGetRelationName, RelationIsScannable, and ExecRowMark::rti.

Referenced by ExecInitBitmapHeapScan(), ExecInitForeignScan(), ExecInitIndexOnlyScan(), ExecInitIndexScan(), ExecInitTidScan(), and InitScanRelation().

{
    Relation    rel;
    Oid         reloid;
    LOCKMODE    lockmode;

    /*
     * Determine the lock type we need.  First, scan to see if target relation
     * is a result relation.  If not, check if it's a FOR UPDATE/FOR SHARE
     * relation.  In either of those cases, we got the lock already.
     */
    lockmode = AccessShareLock;
    if (ExecRelationIsTargetRelation(estate, scanrelid))
        lockmode = NoLock;
    else
    {
        ListCell   *l;

        foreach(l, estate->es_rowMarks)
        {
            ExecRowMark *erm = lfirst(l);

            if (erm->rti == scanrelid)
            {
                lockmode = NoLock;
                break;
            }
        }
    }

    /* Open the relation and acquire lock as needed */
    reloid = getrelid(scanrelid, estate->es_range_table);
    rel = heap_open(reloid, lockmode);

    /*
     * Complain if we're attempting a scan of an unscannable relation, except
     * when the query won't actually be run.  This is a slightly klugy place
     * to do this, perhaps, but there is no better place.
     */
    if ((eflags & (EXEC_FLAG_EXPLAIN_ONLY | EXEC_FLAG_WITH_NO_DATA)) == 0 &&
        !RelationIsScannable(rel))
        ereport(ERROR,
                (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
                 errmsg("materialized view \"%s\" has not been populated",
                        RelationGetRelationName(rel)),
                 errhint("Use the REFRESH MATERIALIZED VIEW command.")));

    return rel;
}

ExprState* ExecPrepareExpr ( Expr node,
EState estate 
)
TupleTableSlot* ExecProcNode ( PlanState node  ) 

Definition at line 355 of file execProcnode.c.

References CHECK_FOR_INTERRUPTS, PlanState::chgParam, elog, ERROR, ExecAgg(), ExecAppend(), ExecBitmapHeapScan(), ExecCteScan(), ExecForeignScan(), ExecFunctionScan(), ExecGroup(), ExecHash(), ExecHashJoin(), ExecIndexOnlyScan(), ExecIndexScan(), ExecLimit(), ExecLockRows(), ExecMaterial(), ExecMergeAppend(), ExecMergeJoin(), ExecModifyTable(), ExecNestLoop(), ExecRecursiveUnion(), ExecReScan(), ExecResult(), ExecSeqScan(), ExecSetOp(), ExecSort(), ExecSubqueryScan(), ExecTidScan(), ExecUnique(), ExecValuesScan(), ExecWindowAgg(), ExecWorkTableScan(), InstrStartNode(), InstrStopNode(), PlanState::instrument, nodeTag, NULL, T_AggState, T_AppendState, T_BitmapHeapScanState, T_CteScanState, T_ForeignScanState, T_FunctionScanState, T_GroupState, T_HashJoinState, T_HashState, T_IndexOnlyScanState, T_IndexScanState, T_LimitState, T_LockRowsState, T_MaterialState, T_MergeAppendState, T_MergeJoinState, T_ModifyTableState, T_NestLoopState, T_RecursiveUnionState, T_ResultState, T_SeqScanState, T_SetOpState, T_SortState, T_SubqueryScanState, T_TidScanState, T_UniqueState, T_ValuesScanState, T_WindowAggState, T_WorkTableScanState, and TupIsNull.

Referenced by agg_fill_hash_table(), agg_retrieve_direct(), begin_partition(), buildSubPlanHash(), CteScanNext(), EvalPlanQualNext(), ExecAppend(), ExecGroup(), ExecHashJoin(), ExecHashJoinOuterGetTuple(), ExecLimit(), ExecLockRows(), ExecMaterial(), ExecMergeAppend(), ExecMergeJoin(), ExecModifyTable(), ExecNestLoop(), ExecPostprocessPlan(), ExecRecursiveUnion(), ExecResult(), ExecScanSubPlan(), ExecSetParamPlan(), ExecSort(), ExecUnique(), ExecutePlan(), MultiExecHash(), setop_fill_hash_table(), setop_retrieve_direct(), spool_tuples(), and SubqueryNext().

{
    TupleTableSlot *result;

    CHECK_FOR_INTERRUPTS();

    if (node->chgParam != NULL) /* something changed */
        ExecReScan(node);       /* let ReScan handle this */

    if (node->instrument)
        InstrStartNode(node->instrument);

    switch (nodeTag(node))
    {
            /*
             * control nodes
             */
        case T_ResultState:
            result = ExecResult((ResultState *) node);
            break;

        case T_ModifyTableState:
            result = ExecModifyTable((ModifyTableState *) node);
            break;

        case T_AppendState:
            result = ExecAppend((AppendState *) node);
            break;

        case T_MergeAppendState:
            result = ExecMergeAppend((MergeAppendState *) node);
            break;

        case T_RecursiveUnionState:
            result = ExecRecursiveUnion((RecursiveUnionState *) node);
            break;

            /* BitmapAndState does not yield tuples */

            /* BitmapOrState does not yield tuples */

            /*
             * scan nodes
             */
        case T_SeqScanState:
            result = ExecSeqScan((SeqScanState *) node);
            break;

        case T_IndexScanState:
            result = ExecIndexScan((IndexScanState *) node);
            break;

        case T_IndexOnlyScanState:
            result = ExecIndexOnlyScan((IndexOnlyScanState *) node);
            break;

            /* BitmapIndexScanState does not yield tuples */

        case T_BitmapHeapScanState:
            result = ExecBitmapHeapScan((BitmapHeapScanState *) node);
            break;

        case T_TidScanState:
            result = ExecTidScan((TidScanState *) node);
            break;

        case T_SubqueryScanState:
            result = ExecSubqueryScan((SubqueryScanState *) node);
            break;

        case T_FunctionScanState:
            result = ExecFunctionScan((FunctionScanState *) node);
            break;

        case T_ValuesScanState:
            result = ExecValuesScan((ValuesScanState *) node);
            break;

        case T_CteScanState:
            result = ExecCteScan((CteScanState *) node);
            break;

        case T_WorkTableScanState:
            result = ExecWorkTableScan((WorkTableScanState *) node);
            break;

        case T_ForeignScanState:
            result = ExecForeignScan((ForeignScanState *) node);
            break;

            /*
             * join nodes
             */
        case T_NestLoopState:
            result = ExecNestLoop((NestLoopState *) node);
            break;

        case T_MergeJoinState:
            result = ExecMergeJoin((MergeJoinState *) node);
            break;

        case T_HashJoinState:
            result = ExecHashJoin((HashJoinState *) node);
            break;

            /*
             * materialization nodes
             */
        case T_MaterialState:
            result = ExecMaterial((MaterialState *) node);
            break;

        case T_SortState:
            result = ExecSort((SortState *) node);
            break;

        case T_GroupState:
            result = ExecGroup((GroupState *) node);
            break;

        case T_AggState:
            result = ExecAgg((AggState *) node);
            break;

        case T_WindowAggState:
            result = ExecWindowAgg((WindowAggState *) node);
            break;

        case T_UniqueState:
            result = ExecUnique((UniqueState *) node);
            break;

        case T_HashState:
            result = ExecHash((HashState *) node);
            break;

        case T_SetOpState:
            result = ExecSetOp((SetOpState *) node);
            break;

        case T_LockRowsState:
            result = ExecLockRows((LockRowsState *) node);
            break;

        case T_LimitState:
            result = ExecLimit((LimitState *) node);
            break;

        default:
            elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
            result = NULL;
            break;
    }

    if (node->instrument)
        InstrStopNode(node->instrument, TupIsNull(result) ? 0.0 : 1.0);

    return result;
}

TupleTableSlot* ExecProject ( ProjectionInfo projInfo,
ExprDoneCond isDone 
)

Definition at line 5352 of file execQual.c.

References Assert, ExprContext::ecxt_innertuple, ExprContext::ecxt_outertuple, ExprContext::ecxt_scantuple, ExecClearTuple(), ExecStoreVirtualTuple(), ExecTargetList(), i, NULL, ProjectionInfo::pi_directMap, ProjectionInfo::pi_exprContext, ProjectionInfo::pi_itemIsDone, ProjectionInfo::pi_lastInnerVar, ProjectionInfo::pi_lastOuterVar, ProjectionInfo::pi_lastScanVar, ProjectionInfo::pi_numSimpleVars, ProjectionInfo::pi_slot, ProjectionInfo::pi_targetlist, ProjectionInfo::pi_varNumbers, ProjectionInfo::pi_varOutputCols, ProjectionInfo::pi_varSlotOffsets, slot_getsomeattrs(), TupleTableSlot::tts_isnull, TupleTableSlot::tts_values, and values.

Referenced by advance_aggregates(), agg_retrieve_direct(), agg_retrieve_hash_table(), buildSubPlanHash(), ExecAgg(), ExecGroup(), ExecHashJoin(), ExecHashSubPlan(), ExecMergeJoin(), ExecNestLoop(), ExecProcessReturning(), ExecResult(), ExecScan(), ExecWindowAgg(), MJFillInner(), and MJFillOuter().

{
    TupleTableSlot *slot;
    ExprContext *econtext;
    int         numSimpleVars;

    /*
     * sanity checks
     */
    Assert(projInfo != NULL);

    /*
     * get the projection info we want
     */
    slot = projInfo->pi_slot;
    econtext = projInfo->pi_exprContext;

    /* Assume single result row until proven otherwise */
    if (isDone)
        *isDone = ExprSingleResult;

    /*
     * Clear any former contents of the result slot.  This makes it safe for
     * us to use the slot's Datum/isnull arrays as workspace. (Also, we can
     * return the slot as-is if we decide no rows can be projected.)
     */
    ExecClearTuple(slot);

    /*
     * Force extraction of all input values that we'll need.  The
     * Var-extraction loops below depend on this, and we are also prefetching
     * all attributes that will be referenced in the generic expressions.
     */
    if (projInfo->pi_lastInnerVar > 0)
        slot_getsomeattrs(econtext->ecxt_innertuple,
                          projInfo->pi_lastInnerVar);
    if (projInfo->pi_lastOuterVar > 0)
        slot_getsomeattrs(econtext->ecxt_outertuple,
                          projInfo->pi_lastOuterVar);
    if (projInfo->pi_lastScanVar > 0)
        slot_getsomeattrs(econtext->ecxt_scantuple,
                          projInfo->pi_lastScanVar);

    /*
     * Assign simple Vars to result by direct extraction of fields from source
     * slots ... a mite ugly, but fast ...
     */
    numSimpleVars = projInfo->pi_numSimpleVars;
    if (numSimpleVars > 0)
    {
        Datum      *values = slot->tts_values;
        bool       *isnull = slot->tts_isnull;
        int        *varSlotOffsets = projInfo->pi_varSlotOffsets;
        int        *varNumbers = projInfo->pi_varNumbers;
        int         i;

        if (projInfo->pi_directMap)
        {
            /* especially simple case where vars go to output in order */
            for (i = 0; i < numSimpleVars; i++)
            {
                char       *slotptr = ((char *) econtext) + varSlotOffsets[i];
                TupleTableSlot *varSlot = *((TupleTableSlot **) slotptr);
                int         varNumber = varNumbers[i] - 1;

                values[i] = varSlot->tts_values[varNumber];
                isnull[i] = varSlot->tts_isnull[varNumber];
            }
        }
        else
        {
            /* we have to pay attention to varOutputCols[] */
            int        *varOutputCols = projInfo->pi_varOutputCols;

            for (i = 0; i < numSimpleVars; i++)
            {
                char       *slotptr = ((char *) econtext) + varSlotOffsets[i];
                TupleTableSlot *varSlot = *((TupleTableSlot **) slotptr);
                int         varNumber = varNumbers[i] - 1;
                int         varOutputCol = varOutputCols[i] - 1;

                values[varOutputCol] = varSlot->tts_values[varNumber];
                isnull[varOutputCol] = varSlot->tts_isnull[varNumber];
            }
        }
    }

    /*
     * If there are any generic expressions, evaluate them.  It's possible
     * that there are set-returning functions in such expressions; if so and
     * we have reached the end of the set, we return the result slot, which we
     * already marked empty.
     */
    if (projInfo->pi_targetlist)
    {
        if (!ExecTargetList(projInfo->pi_targetlist,
                            econtext,
                            slot->tts_values,
                            slot->tts_isnull,
                            projInfo->pi_itemIsDone,
                            isDone))
            return slot;        /* no more result rows, return empty slot */
    }

    /*
     * Successfully formed a result row.  Mark the result slot as containing a
     * valid virtual tuple.
     */
    return ExecStoreVirtualTuple(slot);
}

bool ExecQual ( List qual,
ExprContext econtext,
bool  resultForNull 
)

Definition at line 5096 of file execQual.c.

References DatumGetBool, ExprContext::ecxt_per_tuple_memory, EV_nodeDisplay, EV_printf, ExecEvalExpr, lfirst, MemoryContextSwitchTo(), and NULL.

Referenced by agg_retrieve_direct(), agg_retrieve_hash_table(), ATRewriteTable(), BitmapHeapNext(), BitmapHeapRecheck(), compute_index_stats(), ExecGroup(), ExecHashJoin(), ExecInsertIndexTuples(), ExecMergeJoin(), ExecNestLoop(), ExecRelCheck(), ExecResult(), ExecScan(), ExecScanHashBucket(), IndexBuildHeapScan(), IndexCheckExclusion(), IndexNext(), IndexOnlyNext(), IndexRecheck(), MJFillInner(), MJFillOuter(), TriggerEnabled(), validate_index_heapscan(), and validateCheckConstraint().

{
    bool        result;
    MemoryContext oldContext;
    ListCell   *l;

    /*
     * debugging stuff
     */
    EV_printf("ExecQual: qual is ");
    EV_nodeDisplay(qual);
    EV_printf("\n");

    /*
     * Run in short-lived per-tuple context while computing expressions.
     */
    oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);

    /*
     * Evaluate the qual conditions one at a time.  If we find a FALSE result,
     * we can stop evaluating and return FALSE --- the AND result must be
     * FALSE.  Also, if we find a NULL result when resultForNull is FALSE, we
     * can stop and return FALSE --- the AND result must be FALSE or NULL in
     * that case, and the caller doesn't care which.
     *
     * If we get to the end of the list, we can return TRUE.  This will happen
     * when the AND result is indeed TRUE, or when the AND result is NULL (one
     * or more NULL subresult, with all the rest TRUE) and the caller has
     * specified resultForNull = TRUE.
     */
    result = true;

    foreach(l, qual)
    {
        ExprState  *clause = (ExprState *) lfirst(l);
        Datum       expr_value;
        bool        isNull;

        expr_value = ExecEvalExpr(clause, econtext, &isNull, NULL);

        if (isNull)
        {
            if (resultForNull == false)
            {
                result = false; /* treat NULL as FALSE */
                break;
            }
        }
        else
        {
            if (!DatumGetBool(expr_value))
            {
                result = false; /* definitely FALSE */
                break;
            }
        }
    }

    MemoryContextSwitchTo(oldContext);

    return result;
}

bool ExecRelationIsTargetRelation ( EState estate,
Index  scanrelid 
)

Definition at line 775 of file execUtils.c.

References EState::es_num_result_relations, EState::es_result_relations, and i.

Referenced by ExecInitBitmapIndexScan(), ExecInitIndexOnlyScan(), ExecInitIndexScan(), and ExecOpenScanRelation().

{
    ResultRelInfo *resultRelInfos;
    int         i;

    resultRelInfos = estate->es_result_relations;
    for (i = 0; i < estate->es_num_result_relations; i++)
    {
        if (resultRelInfos[i].ri_RangeTableIndex == scanrelid)
            return true;
    }
    return false;
}

void ExecReScan ( PlanState node  ) 

Definition at line 68 of file execAmi.c.

References bms_free(), PlanState::chgParam, elog, ERROR, ExecReScanAgg(), ExecReScanAppend(), ExecReScanBitmapAnd(), ExecReScanBitmapHeapScan(), ExecReScanBitmapIndexScan(), ExecReScanBitmapOr(), ExecReScanCteScan(), ExecReScanForeignScan(), ExecReScanFunctionScan(), ExecReScanGroup(), ExecReScanHash(), ExecReScanHashJoin(), ExecReScanIndexOnlyScan(), ExecReScanIndexScan(), ExecReScanLimit(), ExecReScanLockRows(), ExecReScanMaterial(), ExecReScanMergeAppend(), ExecReScanMergeJoin(), ExecReScanModifyTable(), ExecReScanNestLoop(), ExecReScanRecursiveUnion(), ExecReScanResult(), ExecReScanSeqScan(), ExecReScanSetOp(), ExecReScanSetParamPlan(), ExecReScanSort(), ExecReScanSubqueryScan(), ExecReScanTidScan(), ExecReScanUnique(), ExecReScanValuesScan(), ExecReScanWindowAgg(), ExecReScanWorkTableScan(), Plan::extParam, PlanState::initPlan, InstrEndLoop(), PlanState::instrument, PlanState::lefttree, lfirst, nodeTag, NULL, PlanState::plan, SubPlanState::planstate, PlanState::ps_ExprContext, ReScanExprContext(), PlanState::righttree, splan, PlanState::subPlan, T_AggState, T_AppendState, T_BitmapAndState, T_BitmapHeapScanState, T_BitmapIndexScanState, T_BitmapOrState, T_CteScanState, T_ForeignScanState, T_FunctionScanState, T_GroupState, T_HashJoinState, T_HashState, T_IndexOnlyScanState, T_IndexScanState, T_LimitState, T_LockRowsState, T_MaterialState, T_MergeAppendState, T_MergeJoinState, T_ModifyTableState, T_NestLoopState, T_RecursiveUnionState, T_ResultState, T_SeqScanState, T_SetOpState, T_SortState, T_SubqueryScanState, T_TidScanState, T_UniqueState, T_ValuesScanState, T_WindowAggState, T_WorkTableScanState, and UpdateChangedParamSet().

Referenced by buildSubPlanHash(), ExecIndexOnlyScan(), ExecIndexScan(), ExecNestLoop(), ExecProcNode(), ExecReScanAgg(), ExecReScanAppend(), ExecReScanBitmapAnd(), ExecReScanBitmapHeapScan(), ExecReScanBitmapOr(), ExecReScanGroup(), ExecReScanHash(), ExecReScanHashJoin(), ExecReScanLimit(), ExecReScanLockRows(), ExecReScanMaterial(), ExecReScanMergeAppend(), ExecReScanMergeJoin(), ExecReScanNestLoop(), ExecReScanRecursiveUnion(), ExecReScanResult(), ExecReScanSetOp(), ExecReScanSort(), ExecReScanSubqueryScan(), ExecReScanUnique(), ExecReScanWindowAgg(), ExecScanSubPlan(), ExecutorRewind(), MultiExecBitmapIndexScan(), and MultiExecProcNode().

{
    /* If collecting timing stats, update them */
    if (node->instrument)
        InstrEndLoop(node->instrument);

    /*
     * If we have changed parameters, propagate that info.
     *
     * Note: ExecReScanSetParamPlan() can add bits to node->chgParam,
     * corresponding to the output param(s) that the InitPlan will update.
     * Since we make only one pass over the list, that means that an InitPlan
     * can depend on the output param(s) of a sibling InitPlan only if that
     * sibling appears earlier in the list.  This is workable for now given
     * the limited ways in which one InitPlan could depend on another, but
     * eventually we might need to work harder (or else make the planner
     * enlarge the extParam/allParam sets to include the params of depended-on
     * InitPlans).
     */
    if (node->chgParam != NULL)
    {
        ListCell   *l;

        foreach(l, node->initPlan)
        {
            SubPlanState *sstate = (SubPlanState *) lfirst(l);
            PlanState  *splan = sstate->planstate;

            if (splan->plan->extParam != NULL)  /* don't care about child
                                                 * local Params */
                UpdateChangedParamSet(splan, node->chgParam);
            if (splan->chgParam != NULL)
                ExecReScanSetParamPlan(sstate, node);
        }
        foreach(l, node->subPlan)
        {
            SubPlanState *sstate = (SubPlanState *) lfirst(l);
            PlanState  *splan = sstate->planstate;

            if (splan->plan->extParam != NULL)
                UpdateChangedParamSet(splan, node->chgParam);
        }
        /* Well. Now set chgParam for left/right trees. */
        if (node->lefttree != NULL)
            UpdateChangedParamSet(node->lefttree, node->chgParam);
        if (node->righttree != NULL)
            UpdateChangedParamSet(node->righttree, node->chgParam);
    }

    /* Shut down any SRFs in the plan node's targetlist */
    if (node->ps_ExprContext)
        ReScanExprContext(node->ps_ExprContext);

    /* And do node-type-specific processing */
    switch (nodeTag(node))
    {
        case T_ResultState:
            ExecReScanResult((ResultState *) node);
            break;

        case T_ModifyTableState:
            ExecReScanModifyTable((ModifyTableState *) node);
            break;

        case T_AppendState:
            ExecReScanAppend((AppendState *) node);
            break;

        case T_MergeAppendState:
            ExecReScanMergeAppend((MergeAppendState *) node);
            break;

        case T_RecursiveUnionState:
            ExecReScanRecursiveUnion((RecursiveUnionState *) node);
            break;

        case T_BitmapAndState:
            ExecReScanBitmapAnd((BitmapAndState *) node);
            break;

        case T_BitmapOrState:
            ExecReScanBitmapOr((BitmapOrState *) node);
            break;

        case T_SeqScanState:
            ExecReScanSeqScan((SeqScanState *) node);
            break;

        case T_IndexScanState:
            ExecReScanIndexScan((IndexScanState *) node);
            break;

        case T_IndexOnlyScanState:
            ExecReScanIndexOnlyScan((IndexOnlyScanState *) node);
            break;

        case T_BitmapIndexScanState:
            ExecReScanBitmapIndexScan((BitmapIndexScanState *) node);
            break;

        case T_BitmapHeapScanState:
            ExecReScanBitmapHeapScan((BitmapHeapScanState *) node);
            break;

        case T_TidScanState:
            ExecReScanTidScan((TidScanState *) node);
            break;

        case T_SubqueryScanState:
            ExecReScanSubqueryScan((SubqueryScanState *) node);
            break;

        case T_FunctionScanState:
            ExecReScanFunctionScan((FunctionScanState *) node);
            break;

        case T_ValuesScanState:
            ExecReScanValuesScan((ValuesScanState *) node);
            break;

        case T_CteScanState:
            ExecReScanCteScan((CteScanState *) node);
            break;

        case T_WorkTableScanState:
            ExecReScanWorkTableScan((WorkTableScanState *) node);
            break;

        case T_ForeignScanState:
            ExecReScanForeignScan((ForeignScanState *) node);
            break;

        case T_NestLoopState:
            ExecReScanNestLoop((NestLoopState *) node);
            break;

        case T_MergeJoinState:
            ExecReScanMergeJoin((MergeJoinState *) node);
            break;

        case T_HashJoinState:
            ExecReScanHashJoin((HashJoinState *) node);
            break;

        case T_MaterialState:
            ExecReScanMaterial((MaterialState *) node);
            break;

        case T_SortState:
            ExecReScanSort((SortState *) node);
            break;

        case T_GroupState:
            ExecReScanGroup((GroupState *) node);
            break;

        case T_AggState:
            ExecReScanAgg((AggState *) node);
            break;

        case T_WindowAggState:
            ExecReScanWindowAgg((WindowAggState *) node);
            break;

        case T_UniqueState:
            ExecReScanUnique((UniqueState *) node);
            break;

        case T_HashState:
            ExecReScanHash((HashState *) node);
            break;

        case T_SetOpState:
            ExecReScanSetOp((SetOpState *) node);
            break;

        case T_LockRowsState:
            ExecReScanLockRows((LockRowsState *) node);
            break;

        case T_LimitState:
            ExecReScanLimit((LimitState *) node);
            break;

        default:
            elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
            break;
    }

    if (node->chgParam != NULL)
    {
        bms_free(node->chgParam);
        node->chgParam = NULL;
    }
}

void ExecRestrPos ( PlanState node  ) 
TupleTableSlot* ExecScan ( ScanState node,
ExecScanAccessMtd  accessMtd,
ExecScanRecheckMtd  recheckMtd 
)

Definition at line 108 of file execScan.c.

References Assert, CHECK_FOR_INTERRUPTS, ExprContext::ecxt_scantuple, ExecClearTuple(), ExecProject(), ExecQual(), ExecScanFetch(), ExprEndResult, ExprMultipleResult, InstrCountFiltered1, ProjectionInfo::pi_slot, ScanState::ps, PlanState::ps_ExprContext, PlanState::ps_ProjInfo, PlanState::ps_TupFromTlist, PlanState::qual, ResetExprContext, and TupIsNull.

Referenced by ExecBitmapHeapScan(), ExecCteScan(), ExecForeignScan(), ExecFunctionScan(), ExecIndexOnlyScan(), ExecIndexScan(), ExecSeqScan(), ExecSubqueryScan(), ExecTidScan(), ExecValuesScan(), and ExecWorkTableScan().

{
    ExprContext *econtext;
    List       *qual;
    ProjectionInfo *projInfo;
    ExprDoneCond isDone;
    TupleTableSlot *resultSlot;

    /*
     * Fetch data from node
     */
    qual = node->ps.qual;
    projInfo = node->ps.ps_ProjInfo;
    econtext = node->ps.ps_ExprContext;

    /*
     * If we have neither a qual to check nor a projection to do, just skip
     * all the overhead and return the raw scan tuple.
     */
    if (!qual && !projInfo)
    {
        ResetExprContext(econtext);
        return ExecScanFetch(node, accessMtd, recheckMtd);
    }

    /*
     * Check to see if we're still projecting out tuples from a previous scan
     * tuple (because there is a function-returning-set in the projection
     * expressions).  If so, try to project another one.
     */
    if (node->ps.ps_TupFromTlist)
    {
        Assert(projInfo);       /* can't get here if not projecting */
        resultSlot = ExecProject(projInfo, &isDone);
        if (isDone == ExprMultipleResult)
            return resultSlot;
        /* Done with that source tuple... */
        node->ps.ps_TupFromTlist = false;
    }

    /*
     * Reset per-tuple memory context to free any expression evaluation
     * storage allocated in the previous tuple cycle.  Note this can't happen
     * until we're done projecting out tuples from a scan tuple.
     */
    ResetExprContext(econtext);

    /*
     * get a tuple from the access method.  Loop until we obtain a tuple that
     * passes the qualification.
     */
    for (;;)
    {
        TupleTableSlot *slot;

        CHECK_FOR_INTERRUPTS();

        slot = ExecScanFetch(node, accessMtd, recheckMtd);

        /*
         * if the slot returned by the accessMtd contains NULL, then it means
         * there is nothing more to scan so we just return an empty slot,
         * being careful to use the projection result slot so it has correct
         * tupleDesc.
         */
        if (TupIsNull(slot))
        {
            if (projInfo)
                return ExecClearTuple(projInfo->pi_slot);
            else
                return slot;
        }

        /*
         * place the current tuple into the expr context
         */
        econtext->ecxt_scantuple = slot;

        /*
         * check that the current tuple satisfies the qual-clause
         *
         * check for non-nil qual here to avoid a function call to ExecQual()
         * when the qual is nil ... saves only a few cycles, but they add up
         * ...
         */
        if (!qual || ExecQual(qual, econtext, false))
        {
            /*
             * Found a satisfactory scan tuple.
             */
            if (projInfo)
            {
                /*
                 * Form a projection tuple, store it in the result tuple slot
                 * and return it --- unless we find we can project no tuples
                 * from this scan tuple, in which case continue scan.
                 */
                resultSlot = ExecProject(projInfo, &isDone);
                if (isDone != ExprEndResult)
                {
                    node->ps.ps_TupFromTlist = (isDone == ExprMultipleResult);
                    return resultSlot;
                }
            }
            else
            {
                /*
                 * Here, we aren't projecting, so just return scan tuple.
                 */
                return slot;
            }
        }
        else
            InstrCountFiltered1(node, 1);

        /*
         * Tuple fails qual, so free per-tuple memory and try again.
         */
        ResetExprContext(econtext);
    }
}

void ExecScanReScan ( ScanState node  ) 

Definition at line 333 of file execScan.c.

References Assert, EState::es_epqScanDone, NULL, PlanState::plan, ScanState::ps, PlanState::ps_TupFromTlist, and PlanState::state.

Referenced by ExecReScanBitmapHeapScan(), ExecReScanCteScan(), ExecReScanForeignScan(), ExecReScanFunctionScan(), ExecReScanIndexOnlyScan(), ExecReScanIndexScan(), ExecReScanSeqScan(), ExecReScanSubqueryScan(), ExecReScanTidScan(), ExecReScanValuesScan(), and ExecReScanWorkTableScan().

{
    EState     *estate = node->ps.state;

    /* Stop projecting any tuples from SRFs in the targetlist */
    node->ps.ps_TupFromTlist = false;

    /* Rescan EvalPlanQual tuple if we're inside an EvalPlanQual recheck */
    if (estate->es_epqScanDone != NULL)
    {
        Index       scanrelid = ((Scan *) node->ps.plan)->scanrelid;

        Assert(scanrelid > 0);

        estate->es_epqScanDone[scanrelid - 1] = false;
    }
}

bool ExecSupportsBackwardScan ( Plan node  ) 

Definition at line 422 of file execAmi.c.

References ExecSupportsBackwardScan(), IndexSupportsBackwardScan(), lfirst, nodeTag, NULL, outerPlan, T_Append, T_CteScan, T_FunctionScan, T_IndexOnlyScan, T_IndexScan, T_Limit, T_LockRows, T_Material, T_Result, T_SeqScan, T_Sort, T_SubqueryScan, T_TidScan, T_ValuesScan, Plan::targetlist, and TargetListSupportsBackwardScan().

Referenced by ExecSupportsBackwardScan(), PerformCursorOpen(), SPI_cursor_open_internal(), and standard_planner().

{
    if (node == NULL)
        return false;

    switch (nodeTag(node))
    {
        case T_Result:
            if (outerPlan(node) != NULL)
                return ExecSupportsBackwardScan(outerPlan(node)) &&
                    TargetListSupportsBackwardScan(node->targetlist);
            else
                return false;

        case T_Append:
            {
                ListCell   *l;

                foreach(l, ((Append *) node)->appendplans)
                {
                    if (!ExecSupportsBackwardScan((Plan *) lfirst(l)))
                        return false;
                }
                /* need not check tlist because Append doesn't evaluate it */
                return true;
            }

        case T_SeqScan:
        case T_TidScan:
        case T_FunctionScan:
        case T_ValuesScan:
        case T_CteScan:
            return TargetListSupportsBackwardScan(node->targetlist);

        case T_IndexScan:
            return IndexSupportsBackwardScan(((IndexScan *) node)->indexid) &&
                TargetListSupportsBackwardScan(node->targetlist);

        case T_IndexOnlyScan:
            return IndexSupportsBackwardScan(((IndexOnlyScan *) node)->indexid) &&
                TargetListSupportsBackwardScan(node->targetlist);

        case T_SubqueryScan:
            return ExecSupportsBackwardScan(((SubqueryScan *) node)->subplan) &&
                TargetListSupportsBackwardScan(node->targetlist);

        case T_Material:
        case T_Sort:
            /* these don't evaluate tlist */
            return true;

        case T_LockRows:
        case T_Limit:
            /* these don't evaluate tlist */
            return ExecSupportsBackwardScan(outerPlan(node));

        default:
            return false;
    }
}

bool ExecSupportsMarkRestore ( NodeTag  plantype  ) 

Definition at line 382 of file execAmi.c.

References T_IndexOnlyScan, T_IndexScan, T_Material, T_Result, T_SeqScan, T_Sort, T_TidScan, and T_ValuesScan.

Referenced by final_cost_mergejoin().

{
    switch (plantype)
    {
        case T_SeqScan:
        case T_IndexScan:
        case T_IndexOnlyScan:
        case T_TidScan:
        case T_ValuesScan:
        case T_Material:
        case T_Sort:
            return true;

        case T_Result:

            /*
             * T_Result only supports mark/restore if it has a child plan that
             * does, so we do not have enough information to give a really
             * correct answer.  However, for current uses it's enough to
             * always say "false", because this routine is not asked about
             * gating Result plans, only base-case Results.
             */
            return false;

        default:
            break;
    }

    return false;
}

int ExecTargetListLength ( List targetlist  ) 

Definition at line 5163 of file execQual.c.

References list_length().

Referenced by ExecBuildProjectionInfo(), and ExecTypeFromTLInternal().

{
    /* This used to be more complex, but fjoins are dead */
    return list_length(targetlist);
}

void execTuplesHashPrepare ( int  numCols,
Oid eqOperators,
FmgrInfo **  eqFunctions,
FmgrInfo **  hashFunctions 
)

Definition at line 218 of file execGrouping.c.

References Assert, elog, ERROR, fmgr_info(), get_op_hash_functions(), get_opcode(), i, and palloc().

Referenced by ExecInitAgg(), ExecInitRecursiveUnion(), and ExecInitSetOp().

{
    int         i;

    *eqFunctions = (FmgrInfo *) palloc(numCols * sizeof(FmgrInfo));
    *hashFunctions = (FmgrInfo *) palloc(numCols * sizeof(FmgrInfo));

    for (i = 0; i < numCols; i++)
    {
        Oid         eq_opr = eqOperators[i];
        Oid         eq_function;
        Oid         left_hash_function;
        Oid         right_hash_function;

        eq_function = get_opcode(eq_opr);
        if (!get_op_hash_functions(eq_opr,
                                   &left_hash_function, &right_hash_function))
            elog(ERROR, "could not find hash function for hash operator %u",
                 eq_opr);
        /* We're not supporting cross-type cases here */
        Assert(left_hash_function == right_hash_function);
        fmgr_info(eq_function, &(*eqFunctions)[i]);
        fmgr_info(right_hash_function, &(*hashFunctions)[i]);
    }
}

bool execTuplesMatch ( TupleTableSlot slot1,
TupleTableSlot slot2,
int  numCols,
AttrNumber matchColIdx,
FmgrInfo eqfunctions,
MemoryContext  evalContext 
)

Definition at line 54 of file execGrouping.c.

References DatumGetBool, FunctionCall2, i, MemoryContextReset(), MemoryContextSwitchTo(), and slot_getattr().

Referenced by agg_retrieve_direct(), are_peers(), ExecGroup(), ExecUnique(), process_ordered_aggregate_multi(), setop_retrieve_direct(), spool_tuples(), and TupleHashTableMatch().

{
    MemoryContext oldContext;
    bool        result;
    int         i;

    /* Reset and switch into the temp context. */
    MemoryContextReset(evalContext);
    oldContext = MemoryContextSwitchTo(evalContext);

    /*
     * We cannot report a match without checking all the fields, but we can
     * report a non-match as soon as we find unequal fields.  So, start
     * comparing at the last field (least significant sort key). That's the
     * most likely to be different if we are dealing with sorted input.
     */
    result = true;

    for (i = numCols; --i >= 0;)
    {
        AttrNumber  att = matchColIdx[i];
        Datum       attr1,
                    attr2;
        bool        isNull1,
                    isNull2;

        attr1 = slot_getattr(slot1, att, &isNull1);

        attr2 = slot_getattr(slot2, att, &isNull2);

        if (isNull1 != isNull2)
        {
            result = false;     /* one null and one not; they aren't equal */
            break;
        }

        if (isNull1)
            continue;           /* both are null, treat as equal */

        /* Apply the type-specific equality function */

        if (!DatumGetBool(FunctionCall2(&eqfunctions[i],
                                        attr1, attr2)))
        {
            result = false;     /* they aren't equal */
            break;
        }
    }

    MemoryContextSwitchTo(oldContext);

    return result;
}

FmgrInfo* execTuplesMatchPrepare ( int  numCols,
Oid eqOperators 
)

Definition at line 189 of file execGrouping.c.

References fmgr_info(), get_opcode(), i, and palloc().

Referenced by ExecInitAgg(), ExecInitGroup(), ExecInitSetOp(), ExecInitUnique(), and ExecInitWindowAgg().

{
    FmgrInfo   *eqFunctions = (FmgrInfo *) palloc(numCols * sizeof(FmgrInfo));
    int         i;

    for (i = 0; i < numCols; i++)
    {
        Oid         eq_opr = eqOperators[i];
        Oid         eq_function;

        eq_function = get_opcode(eq_opr);
        fmgr_info(eq_function, &eqFunctions[i]);
    }

    return eqFunctions;
}

bool execTuplesUnequal ( TupleTableSlot slot1,
TupleTableSlot slot2,
int  numCols,
AttrNumber matchColIdx,
FmgrInfo eqfunctions,
MemoryContext  evalContext 
)

Definition at line 124 of file execGrouping.c.

References DatumGetBool, FunctionCall2, i, MemoryContextReset(), MemoryContextSwitchTo(), and slot_getattr().

Referenced by findPartialMatch().

{
    MemoryContext oldContext;
    bool        result;
    int         i;

    /* Reset and switch into the temp context. */
    MemoryContextReset(evalContext);
    oldContext = MemoryContextSwitchTo(evalContext);

    /*
     * We cannot report a match without checking all the fields, but we can
     * report a non-match as soon as we find unequal fields.  So, start
     * comparing at the last field (least significant sort key). That's the
     * most likely to be different if we are dealing with sorted input.
     */
    result = false;

    for (i = numCols; --i >= 0;)
    {
        AttrNumber  att = matchColIdx[i];
        Datum       attr1,
                    attr2;
        bool        isNull1,
                    isNull2;

        attr1 = slot_getattr(slot1, att, &isNull1);

        if (isNull1)
            continue;           /* can't prove anything here */

        attr2 = slot_getattr(slot2, att, &isNull2);

        if (isNull2)
            continue;           /* can't prove anything here */

        /* Apply the type-specific equality function */

        if (!DatumGetBool(FunctionCall2(&eqfunctions[i],
                                        attr1, attr2)))
        {
            result = true;      /* they are unequal */
            break;
        }
    }

    MemoryContextSwitchTo(oldContext);

    return result;
}

TupleDesc ExecTypeFromExprList ( List exprList,
List namesList 
)

Definition at line 961 of file execTuples.c.

References Assert, CreateTemplateTupleDesc(), exprCollation(), exprType(), exprTypmod(), forboth, lfirst, list_length(), strVal, TupleDescInitEntry(), and TupleDescInitEntryCollation().

Referenced by ExecInitExpr(), and ExecInitValuesScan().

{
    TupleDesc   typeInfo;
    ListCell   *le;
    ListCell   *ln;
    int         cur_resno = 1;

    Assert(list_length(exprList) == list_length(namesList));

    typeInfo = CreateTemplateTupleDesc(list_length(exprList), false);

    forboth(le, exprList, ln, namesList)
    {
        Node       *e = lfirst(le);
        char       *n = strVal(lfirst(ln));

        TupleDescInitEntry(typeInfo,
                           cur_resno,
                           n,
                           exprType(e),
                           exprTypmod(e),
                           0);
        TupleDescInitEntryCollation(typeInfo,
                                    cur_resno,
                                    exprCollation(e));
        cur_resno++;
    }

    return typeInfo;
}

TupleDesc ExecTypeFromTL ( List targetList,
bool  hasoid 
)

Definition at line 903 of file execTuples.c.

References ExecTypeFromTLInternal().

Referenced by ExecAssignResultTypeFromTL(), ExecInitAgg(), ExecInitIndexOnlyScan(), ExecInitModifyTable(), and ExecInitSubPlan().

{
    return ExecTypeFromTLInternal(targetList, hasoid, false);
}

void ExecutorEnd ( QueryDesc queryDesc  ) 
void ExecutorFinish ( QueryDesc queryDesc  ) 
void ExecutorRewind ( QueryDesc queryDesc  ) 

Definition at line 467 of file execMain.c.

References Assert, CMD_SELECT, EState::es_query_cxt, QueryDesc::estate, ExecReScan(), MemoryContextSwitchTo(), NULL, QueryDesc::operation, and QueryDesc::planstate.

Referenced by DoPortalRewind(), and PersistHoldablePortal().

{
    EState     *estate;
    MemoryContext oldcontext;

    /* sanity checks */
    Assert(queryDesc != NULL);

    estate = queryDesc->estate;

    Assert(estate != NULL);

    /* It's probably not sensible to rescan updating queries */
    Assert(queryDesc->operation == CMD_SELECT);

    /*
     * Switch into per-query memory context
     */
    oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);

    /*
     * rescan plan
     */
    ExecReScan(queryDesc->planstate);

    MemoryContextSwitchTo(oldcontext);
}

void ExecutorRun ( QueryDesc queryDesc,
ScanDirection  direction,
long  count 
)

Definition at line 248 of file execMain.c.

References ExecutorRun_hook, and standard_ExecutorRun().

Referenced by _SPI_pquery(), CopyTo(), ExecCreateTableAs(), execute_sql_string(), ExplainOnePlan(), PersistHoldablePortal(), PortalRunSelect(), postquel_getnext(), ProcessQuery(), and refresh_matview_datafill().

{
    if (ExecutorRun_hook)
        (*ExecutorRun_hook) (queryDesc, direction, count);
    else
        standard_ExecutorRun(queryDesc, direction, count);
}

void ExecutorStart ( QueryDesc queryDesc,
int  eflags 
)

Definition at line 115 of file execMain.c.

References ExecutorStart_hook, and standard_ExecutorStart().

Referenced by _SPI_pquery(), BeginCopy(), ExecCreateTableAs(), execute_sql_string(), ExplainOnePlan(), PortalStart(), postquel_start(), ProcessQuery(), and refresh_matview_datafill().

{
    if (ExecutorStart_hook)
        (*ExecutorStart_hook) (queryDesc, eflags);
    else
        standard_ExecutorStart(queryDesc, eflags);
}

TupleHashEntry FindTupleHashEntry ( TupleHashTable  hashtable,
TupleTableSlot slot,
FmgrInfo eqfunctions,
FmgrInfo hashfunctions 
)

Definition at line 422 of file execGrouping.c.

References TupleHashTableData::cur_eq_funcs, TupleHashEntryData::firstTuple, HASH_FIND, hash_search(), TupleHashTableData::hashtab, TupleHashTableData::in_hash_funcs, TupleHashTableData::inputslot, MemoryContextSwitchTo(), NULL, and TupleHashTableData::tempcxt.

Referenced by ExecHashSubPlan().

{
    TupleHashEntry entry;
    MemoryContext oldContext;
    TupleHashTable saveCurHT;
    TupleHashEntryData dummy;

    /* Need to run the hash functions in short-lived context */
    oldContext = MemoryContextSwitchTo(hashtable->tempcxt);

    /*
     * Set up data needed by hash and match functions
     *
     * We save and restore CurTupleHashTable just in case someone manages to
     * invoke this code re-entrantly.
     */
    hashtable->inputslot = slot;
    hashtable->in_hash_funcs = hashfunctions;
    hashtable->cur_eq_funcs = eqfunctions;

    saveCurHT = CurTupleHashTable;
    CurTupleHashTable = hashtable;

    /* Search the hash table */
    dummy.firstTuple = NULL;    /* flag to reference inputslot */
    entry = (TupleHashEntry) hash_search(hashtable->hashtab,
                                         &dummy,
                                         HASH_FIND,
                                         NULL);

    CurTupleHashTable = saveCurHT;

    MemoryContextSwitchTo(oldContext);

    return entry;
}

void FreeExecutorState ( EState estate  ) 

Definition at line 178 of file execUtils.c.

References EState::es_exprcontexts, EState::es_query_cxt, FreeExprContext(), linitial, and MemoryContextDelete().

Referenced by afterTriggerInvokeEvents(), ATRewriteTable(), btree_predicate_proof(), compute_index_stats(), CopyFrom(), EvalPlanQualEnd(), evaluate_expr(), ExecuteQuery(), ExecuteTruncate(), ExplainExecuteQuery(), get_actual_variable_range(), IndexBuildHeapScan(), IndexCheckExclusion(), plpgsql_xact_cb(), standard_ExecutorEnd(), tuplesort_end(), validate_index_heapscan(), validateCheckConstraint(), and validateDomainConstraint().

{
    /*
     * Shut down and free any remaining ExprContexts.  We do this explicitly
     * to ensure that any remaining shutdown callbacks get called (since they
     * might need to release resources that aren't simply memory within the
     * per-query memory context).
     */
    while (estate->es_exprcontexts)
    {
        /*
         * XXX: seems there ought to be a faster way to implement this than
         * repeated list_delete(), no?
         */
        FreeExprContext((ExprContext *) linitial(estate->es_exprcontexts),
                        true);
        /* FreeExprContext removed the list link for us */
    }

    /*
     * Free the per-query memory context, thereby releasing all working
     * memory, including the EState node itself.
     */
    MemoryContextDelete(estate->es_query_cxt);
}

void FreeExprContext ( ExprContext econtext,
bool  isCommit 
)

Definition at line 353 of file execUtils.c.

References ExprContext::ecxt_estate, ExprContext::ecxt_per_tuple_memory, EState::es_exprcontexts, list_delete_ptr(), MemoryContextDelete(), pfree(), and ShutdownExprContext().

Referenced by ExecEndBitmapIndexScan(), ExecEndIndexOnlyScan(), ExecEndIndexScan(), FreeExecutorState(), plpgsql_destroy_econtext(), and plpgsql_subxact_cb().

{
    EState     *estate;

    /* Call any registered callbacks */
    ShutdownExprContext(econtext, isCommit);
    /* And clean up the memory used */
    MemoryContextDelete(econtext->ecxt_per_tuple_memory);
    /* Unlink self from owning EState, if any */
    estate = econtext->ecxt_estate;
    if (estate)
        estate->es_exprcontexts = list_delete_ptr(estate->es_exprcontexts,
                                                  econtext);
    /* And delete the ExprContext node */
    pfree(econtext);
}

Datum GetAttributeByName ( HeapTupleHeader  tuple,
const char *  attname,
bool isNull 
)

Definition at line 1220 of file execQual.c.

References tupleDesc::attrs, elog, ERROR, heap_getattr, HeapTupleHeaderGetDatumLength, HeapTupleHeaderGetTypeId, HeapTupleHeaderGetTypMod, i, InvalidAttrNumber, ItemPointerSetInvalid, lookup_rowtype_tupdesc(), namestrcmp(), tupleDesc::natts, NULL, ReleaseTupleDesc, HeapTupleData::t_data, HeapTupleData::t_len, HeapTupleData::t_self, and HeapTupleData::t_tableOid.

Referenced by c_overpaid(), and overpaid().

{
    AttrNumber  attrno;
    Datum       result;
    Oid         tupType;
    int32       tupTypmod;
    TupleDesc   tupDesc;
    HeapTupleData tmptup;
    int         i;

    if (attname == NULL)
        elog(ERROR, "invalid attribute name");

    if (isNull == NULL)
        elog(ERROR, "a NULL isNull pointer was passed");

    if (tuple == NULL)
    {
        /* Kinda bogus but compatible with old behavior... */
        *isNull = true;
        return (Datum) 0;
    }

    tupType = HeapTupleHeaderGetTypeId(tuple);
    tupTypmod = HeapTupleHeaderGetTypMod(tuple);
    tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod);

    attrno = InvalidAttrNumber;
    for (i = 0; i < tupDesc->natts; i++)
    {
        if (namestrcmp(&(tupDesc->attrs[i]->attname), attname) == 0)
        {
            attrno = tupDesc->attrs[i]->attnum;
            break;
        }
    }

    if (attrno == InvalidAttrNumber)
        elog(ERROR, "attribute \"%s\" does not exist", attname);

    /*
     * heap_getattr needs a HeapTuple not a bare HeapTupleHeader.  We set all
     * the fields in the struct just in case user tries to inspect system
     * columns.
     */
    tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
    ItemPointerSetInvalid(&(tmptup.t_self));
    tmptup.t_tableOid = InvalidOid;
    tmptup.t_data = tuple;

    result = heap_getattr(&tmptup,
                          attrno,
                          tupDesc,
                          isNull);

    ReleaseTupleDesc(tupDesc);

    return result;
}

Datum GetAttributeByNum ( HeapTupleHeader  tuple,
AttrNumber  attrno,
bool isNull 
)

Definition at line 1172 of file execQual.c.

References AttributeNumberIsValid, elog, ERROR, heap_getattr, HeapTupleHeaderGetDatumLength, HeapTupleHeaderGetTypeId, HeapTupleHeaderGetTypMod, ItemPointerSetInvalid, lookup_rowtype_tupdesc(), NULL, ReleaseTupleDesc, HeapTupleData::t_data, HeapTupleData::t_len, HeapTupleData::t_self, and HeapTupleData::t_tableOid.

{
    Datum       result;
    Oid         tupType;
    int32       tupTypmod;
    TupleDesc   tupDesc;
    HeapTupleData tmptup;

    if (!AttributeNumberIsValid(attrno))
        elog(ERROR, "invalid attribute number %d", attrno);

    if (isNull == NULL)
        elog(ERROR, "a NULL isNull pointer was passed");

    if (tuple == NULL)
    {
        /* Kinda bogus but compatible with old behavior... */
        *isNull = true;
        return (Datum) 0;
    }

    tupType = HeapTupleHeaderGetTypeId(tuple);
    tupTypmod = HeapTupleHeaderGetTypMod(tuple);
    tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod);

    /*
     * heap_getattr needs a HeapTuple not a bare HeapTupleHeader.  We set all
     * the fields in the struct just in case user tries to inspect system
     * columns.
     */
    tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
    ItemPointerSetInvalid(&(tmptup.t_self));
    tmptup.t_tableOid = InvalidOid;
    tmptup.t_data = tuple;

    result = heap_getattr(&tmptup,
                          attrno,
                          tupDesc,
                          isNull);

    ReleaseTupleDesc(tupDesc);

    return result;
}

void InitResultRelInfo ( ResultRelInfo resultRelInfo,
Relation  resultRelationDesc,
Index  resultRelationIndex,
int  instrument_options 
)

Definition at line 1112 of file execMain.c.

References CopyTriggerDesc(), GetFdwRoutineForRelation(), InstrAlloc(), MemSet, TriggerDesc::numtriggers, palloc0(), RelationData::rd_rel, RELKIND_FOREIGN_TABLE, ResultRelInfo::ri_ConstraintExprs, ResultRelInfo::ri_FdwRoutine, ResultRelInfo::ri_FdwState, ResultRelInfo::ri_IndexRelationDescs, ResultRelInfo::ri_IndexRelationInfo, ResultRelInfo::ri_junkFilter, ResultRelInfo::ri_NumIndices, ResultRelInfo::ri_projectReturning, ResultRelInfo::ri_RangeTableIndex, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_TrigDesc, ResultRelInfo::ri_TrigFunctions, ResultRelInfo::ri_TrigInstrument, ResultRelInfo::ri_TrigWhenExprs, RelationData::trigdesc, and ResultRelInfo::type.

Referenced by CopyFrom(), ExecGetTriggerResultRel(), ExecuteTruncate(), and InitPlan().

{
    MemSet(resultRelInfo, 0, sizeof(ResultRelInfo));
    resultRelInfo->type = T_ResultRelInfo;
    resultRelInfo->ri_RangeTableIndex = resultRelationIndex;
    resultRelInfo->ri_RelationDesc = resultRelationDesc;
    resultRelInfo->ri_NumIndices = 0;
    resultRelInfo->ri_IndexRelationDescs = NULL;
    resultRelInfo->ri_IndexRelationInfo = NULL;
    /* make a copy so as not to depend on relcache info not changing... */
    resultRelInfo->ri_TrigDesc = CopyTriggerDesc(resultRelationDesc->trigdesc);
    if (resultRelInfo->ri_TrigDesc)
    {
        int         n = resultRelInfo->ri_TrigDesc->numtriggers;

        resultRelInfo->ri_TrigFunctions = (FmgrInfo *)
            palloc0(n * sizeof(FmgrInfo));
        resultRelInfo->ri_TrigWhenExprs = (List **)
            palloc0(n * sizeof(List *));
        if (instrument_options)
            resultRelInfo->ri_TrigInstrument = InstrAlloc(n, instrument_options);
    }
    else
    {
        resultRelInfo->ri_TrigFunctions = NULL;
        resultRelInfo->ri_TrigWhenExprs = NULL;
        resultRelInfo->ri_TrigInstrument = NULL;
    }
    if (resultRelationDesc->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
        resultRelInfo->ri_FdwRoutine = GetFdwRoutineForRelation(resultRelationDesc, true);
    else
        resultRelInfo->ri_FdwRoutine = NULL;
    resultRelInfo->ri_FdwState = NULL;
    resultRelInfo->ri_ConstraintExprs = NULL;
    resultRelInfo->ri_junkFilter = NULL;
    resultRelInfo->ri_projectReturning = NULL;
}

TupleHashEntry LookupTupleHashEntry ( TupleHashTable  hashtable,
TupleTableSlot slot,
bool isnew 
)

Definition at line 331 of file execGrouping.c.

References CreateTupleDescCopy(), TupleHashTableData::cur_eq_funcs, TupleHashTableData::entrysize, ExecCopySlotMinimalTuple(), TupleHashEntryData::firstTuple, HASH_ENTER, HASH_FIND, hash_search(), TupleHashTableData::hashtab, TupleHashTableData::in_hash_funcs, TupleHashTableData::inputslot, MakeSingleTupleTableSlot(), MemoryContextSwitchTo(), MemSet, NULL, TupleHashTableData::tab_eq_funcs, TupleHashTableData::tab_hash_funcs, TupleHashTableData::tablecxt, TupleHashTableData::tableslot, TupleHashTableData::tempcxt, and TupleTableSlot::tts_tupleDescriptor.

Referenced by buildSubPlanHash(), ExecRecursiveUnion(), lookup_hash_entry(), and setop_fill_hash_table().

{
    TupleHashEntry entry;
    MemoryContext oldContext;
    TupleHashTable saveCurHT;
    TupleHashEntryData dummy;
    bool        found;

    /* If first time through, clone the input slot to make table slot */
    if (hashtable->tableslot == NULL)
    {
        TupleDesc   tupdesc;

        oldContext = MemoryContextSwitchTo(hashtable->tablecxt);

        /*
         * We copy the input tuple descriptor just for safety --- we assume
         * all input tuples will have equivalent descriptors.
         */
        tupdesc = CreateTupleDescCopy(slot->tts_tupleDescriptor);
        hashtable->tableslot = MakeSingleTupleTableSlot(tupdesc);
        MemoryContextSwitchTo(oldContext);
    }

    /* Need to run the hash functions in short-lived context */
    oldContext = MemoryContextSwitchTo(hashtable->tempcxt);

    /*
     * Set up data needed by hash and match functions
     *
     * We save and restore CurTupleHashTable just in case someone manages to
     * invoke this code re-entrantly.
     */
    hashtable->inputslot = slot;
    hashtable->in_hash_funcs = hashtable->tab_hash_funcs;
    hashtable->cur_eq_funcs = hashtable->tab_eq_funcs;

    saveCurHT = CurTupleHashTable;
    CurTupleHashTable = hashtable;

    /* Search the hash table */
    dummy.firstTuple = NULL;    /* flag to reference inputslot */
    entry = (TupleHashEntry) hash_search(hashtable->hashtab,
                                         &dummy,
                                         isnew ? HASH_ENTER : HASH_FIND,
                                         &found);

    if (isnew)
    {
        if (found)
        {
            /* found pre-existing entry */
            *isnew = false;
        }
        else
        {
            /*
             * created new entry
             *
             * Zero any caller-requested space in the entry.  (This zaps the
             * "key data" dynahash.c copied into the new entry, but we don't
             * care since we're about to overwrite it anyway.)
             */
            MemSet(entry, 0, hashtable->entrysize);

            /* Copy the first tuple into the table context */
            MemoryContextSwitchTo(hashtable->tablecxt);
            entry->firstTuple = ExecCopySlotMinimalTuple(slot);

            *isnew = true;
        }
    }

    CurTupleHashTable = saveCurHT;

    MemoryContextSwitchTo(oldContext);

    return entry;
}

ExprContext* MakePerTupleExprContext ( EState estate  ) 

Definition at line 395 of file execUtils.c.

References CreateExprContext(), EState::es_per_tuple_exprcontext, and NULL.

Node* MultiExecProcNode ( PlanState node  ) 

Definition at line 530 of file execProcnode.c.

References CHECK_FOR_INTERRUPTS, PlanState::chgParam, elog, ERROR, ExecReScan(), MultiExecBitmapAnd(), MultiExecBitmapIndexScan(), MultiExecBitmapOr(), MultiExecHash(), nodeTag, NULL, T_BitmapAndState, T_BitmapIndexScanState, T_BitmapOrState, and T_HashState.

Referenced by BitmapHeapNext(), ExecHashJoin(), MultiExecBitmapAnd(), and MultiExecBitmapOr().

{
    Node       *result;

    CHECK_FOR_INTERRUPTS();

    if (node->chgParam != NULL) /* something changed */
        ExecReScan(node);       /* let ReScan handle this */

    switch (nodeTag(node))
    {
            /*
             * Only node types that actually support multiexec will be listed
             */

        case T_HashState:
            result = MultiExecHash((HashState *) node);
            break;

        case T_BitmapIndexScanState:
            result = MultiExecBitmapIndexScan((BitmapIndexScanState *) node);
            break;

        case T_BitmapAndState:
            result = MultiExecBitmapAnd((BitmapAndState *) node);
            break;

        case T_BitmapOrState:
            result = MultiExecBitmapOr((BitmapOrState *) node);
            break;

        default:
            elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
            result = NULL;
            break;
    }

    return result;
}

void RegisterExprContextCallback ( ExprContext econtext,
ExprContextCallbackFunction  function,
Datum  arg 
)

Definition at line 1421 of file execUtils.c.

References ExprContext_CB::arg, ExprContext::ecxt_callbacks, ExprContext::ecxt_per_query_memory, ExprContext_CB::function, MemoryContextAlloc(), and ExprContext_CB::next.

Referenced by ExecMakeFunctionResult(), ExecPrepareTuplestoreResult(), fmgr_sql(), get_cached_rowtype(), and init_MultiFuncCall().

{
    ExprContext_CB *ecxt_callback;

    /* Save the info in appropriate memory context */
    ecxt_callback = (ExprContext_CB *)
        MemoryContextAlloc(econtext->ecxt_per_query_memory,
                           sizeof(ExprContext_CB));

    ecxt_callback->function = function;
    ecxt_callback->arg = arg;

    /* link to front of list for appropriate execution order */
    ecxt_callback->next = econtext->ecxt_callbacks;
    econtext->ecxt_callbacks = ecxt_callback;
}

void ReScanExprContext ( ExprContext econtext  ) 

Definition at line 380 of file execUtils.c.

References ExprContext::ecxt_per_tuple_memory, MemoryContextReset(), and ShutdownExprContext().

Referenced by domain_check_input(), ExecReScan(), and ValuesNext().

{
    /* Call any registered callbacks */
    ShutdownExprContext(econtext, true);
    /* And clean up the memory used */
    MemoryContextReset(econtext->ecxt_per_tuple_memory);
}

void standard_ExecutorEnd ( QueryDesc queryDesc  ) 

Definition at line 410 of file execMain.c.

References Assert, EState::es_crosscheck_snapshot, EState::es_finished, EState::es_query_cxt, EState::es_snapshot, EState::es_top_eflags, QueryDesc::estate, EXEC_FLAG_EXPLAIN_ONLY, ExecEndPlan(), FreeExecutorState(), MemoryContextSwitchTo(), NULL, QueryDesc::planstate, QueryDesc::totaltime, QueryDesc::tupDesc, and UnregisterSnapshot().

Referenced by ExecutorEnd(), explain_ExecutorEnd(), and pgss_ExecutorEnd().

{
    EState     *estate;
    MemoryContext oldcontext;

    /* sanity checks */
    Assert(queryDesc != NULL);

    estate = queryDesc->estate;

    Assert(estate != NULL);

    /*
     * Check that ExecutorFinish was called, unless in EXPLAIN-only mode. This
     * Assert is needed because ExecutorFinish is new as of 9.1, and callers
     * might forget to call it.
     */
    Assert(estate->es_finished ||
           (estate->es_top_eflags & EXEC_FLAG_EXPLAIN_ONLY));

    /*
     * Switch into per-query memory context to run ExecEndPlan
     */
    oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);

    ExecEndPlan(queryDesc->planstate, estate);

    /* do away with our snapshots */
    UnregisterSnapshot(estate->es_snapshot);
    UnregisterSnapshot(estate->es_crosscheck_snapshot);

    /*
     * Must switch out of context before destroying it
     */
    MemoryContextSwitchTo(oldcontext);

    /*
     * Release EState and per-query memory context.  This should release
     * everything the executor has allocated.
     */
    FreeExecutorState(estate);

    /* Reset queryDesc fields that no longer point to anything */
    queryDesc->tupDesc = NULL;
    queryDesc->estate = NULL;
    queryDesc->planstate = NULL;
    queryDesc->totaltime = NULL;
}

void standard_ExecutorFinish ( QueryDesc queryDesc  ) 

Definition at line 350 of file execMain.c.

References AfterTriggerEndQuery(), Assert, EState::es_finished, EState::es_query_cxt, EState::es_top_eflags, QueryDesc::estate, EXEC_FLAG_EXPLAIN_ONLY, EXEC_FLAG_SKIP_TRIGGERS, ExecPostprocessPlan(), InstrStartNode(), InstrStopNode(), MemoryContextSwitchTo(), NULL, and QueryDesc::totaltime.

Referenced by ExecutorFinish(), explain_ExecutorFinish(), and pgss_ExecutorFinish().

{
    EState     *estate;
    MemoryContext oldcontext;

    /* sanity checks */
    Assert(queryDesc != NULL);

    estate = queryDesc->estate;

    Assert(estate != NULL);
    Assert(!(estate->es_top_eflags & EXEC_FLAG_EXPLAIN_ONLY));

    /* This should be run once and only once per Executor instance */
    Assert(!estate->es_finished);

    /* Switch into per-query memory context */
    oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);

    /* Allow instrumentation of Executor overall runtime */
    if (queryDesc->totaltime)
        InstrStartNode(queryDesc->totaltime);

    /* Run ModifyTable nodes to completion */
    ExecPostprocessPlan(estate);

    /* Execute queued AFTER triggers, unless told not to */
    if (!(estate->es_top_eflags & EXEC_FLAG_SKIP_TRIGGERS))
        AfterTriggerEndQuery(estate);

    if (queryDesc->totaltime)
        InstrStopNode(queryDesc->totaltime, 0);

    MemoryContextSwitchTo(oldcontext);

    estate->es_finished = true;
}

void standard_ExecutorRun ( QueryDesc queryDesc,
ScanDirection  direction,
long  count 
)

Definition at line 258 of file execMain.c.

References Assert, CMD_SELECT, QueryDesc::dest, EState::es_lastoid, EState::es_processed, EState::es_query_cxt, EState::es_top_eflags, QueryDesc::estate, EXEC_FLAG_EXPLAIN_ONLY, ExecutePlan(), PlannedStmt::hasReturning, InstrStartNode(), InstrStopNode(), MemoryContextSwitchTo(), NULL, QueryDesc::operation, QueryDesc::plannedstmt, QueryDesc::planstate, _DestReceiver::rShutdown, _DestReceiver::rStartup, ScanDirectionIsNoMovement, QueryDesc::totaltime, and QueryDesc::tupDesc.

Referenced by ExecutorRun(), explain_ExecutorRun(), and pgss_ExecutorRun().

{
    EState     *estate;
    CmdType     operation;
    DestReceiver *dest;
    bool        sendTuples;
    MemoryContext oldcontext;

    /* sanity checks */
    Assert(queryDesc != NULL);

    estate = queryDesc->estate;

    Assert(estate != NULL);
    Assert(!(estate->es_top_eflags & EXEC_FLAG_EXPLAIN_ONLY));

    /*
     * Switch into per-query memory context
     */
    oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);

    /* Allow instrumentation of Executor overall runtime */
    if (queryDesc->totaltime)
        InstrStartNode(queryDesc->totaltime);

    /*
     * extract information from the query descriptor and the query feature.
     */
    operation = queryDesc->operation;
    dest = queryDesc->dest;

    /*
     * startup tuple receiver, if we will be emitting tuples
     */
    estate->es_processed = 0;
    estate->es_lastoid = InvalidOid;

    sendTuples = (operation == CMD_SELECT ||
                  queryDesc->plannedstmt->hasReturning);

    if (sendTuples)
        (*dest->rStartup) (dest, operation, queryDesc->tupDesc);

    /*
     * run plan
     */
    if (!ScanDirectionIsNoMovement(direction))
        ExecutePlan(estate,
                    queryDesc->planstate,
                    operation,
                    sendTuples,
                    count,
                    direction,
                    dest);

    /*
     * shutdown tuple receiver, if we started it
     */
    if (sendTuples)
        (*dest->rShutdown) (dest);

    if (queryDesc->totaltime)
        InstrStopNode(queryDesc->totaltime, estate->es_processed);

    MemoryContextSwitchTo(oldcontext);
}

void standard_ExecutorStart ( QueryDesc queryDesc,
int  eflags 
)

Definition at line 124 of file execMain.c.

References AfterTriggerBeginQuery(), Assert, CMD_DELETE, CMD_INSERT, CMD_SELECT, CMD_UPDATE, CreateExecutorState(), QueryDesc::crosscheck_snapshot, elog, ERROR, EState::es_crosscheck_snapshot, EState::es_instrument, EState::es_output_cid, EState::es_param_exec_vals, EState::es_param_list_info, EState::es_query_cxt, EState::es_snapshot, EState::es_top_eflags, QueryDesc::estate, EXEC_FLAG_EXPLAIN_ONLY, EXEC_FLAG_SKIP_TRIGGERS, ExecCheckXactReadOnly(), GetCurrentCommandId(), PlannedStmt::hasModifyingCTE, InitPlan(), QueryDesc::instrument_options, MemoryContextSwitchTo(), NIL, PlannedStmt::nParamExec, NULL, QueryDesc::operation, palloc0(), QueryDesc::params, QueryDesc::plannedstmt, RegisterSnapshot(), PlannedStmt::rowMarks, QueryDesc::snapshot, and XactReadOnly.

Referenced by ExecutorStart(), explain_ExecutorStart(), and pgss_ExecutorStart().

{
    EState     *estate;
    MemoryContext oldcontext;

    /* sanity checks: queryDesc must not be started already */
    Assert(queryDesc != NULL);
    Assert(queryDesc->estate == NULL);

    /*
     * If the transaction is read-only, we need to check if any writes are
     * planned to non-temporary tables.  EXPLAIN is considered read-only.
     */
    if (XactReadOnly && !(eflags & EXEC_FLAG_EXPLAIN_ONLY))
        ExecCheckXactReadOnly(queryDesc->plannedstmt);

    /*
     * Build EState, switch into per-query memory context for startup.
     */
    estate = CreateExecutorState();
    queryDesc->estate = estate;

    oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);

    /*
     * Fill in external parameters, if any, from queryDesc; and allocate
     * workspace for internal parameters
     */
    estate->es_param_list_info = queryDesc->params;

    if (queryDesc->plannedstmt->nParamExec > 0)
        estate->es_param_exec_vals = (ParamExecData *)
            palloc0(queryDesc->plannedstmt->nParamExec * sizeof(ParamExecData));

    /*
     * If non-read-only query, set the command ID to mark output tuples with
     */
    switch (queryDesc->operation)
    {
        case CMD_SELECT:

            /*
             * SELECT FOR [KEY] UPDATE/SHARE and modifying CTEs need to mark
             * tuples
             */
            if (queryDesc->plannedstmt->rowMarks != NIL ||
                queryDesc->plannedstmt->hasModifyingCTE)
                estate->es_output_cid = GetCurrentCommandId(true);

            /*
             * A SELECT without modifying CTEs can't possibly queue triggers,
             * so force skip-triggers mode. This is just a marginal efficiency
             * hack, since AfterTriggerBeginQuery/AfterTriggerEndQuery aren't
             * all that expensive, but we might as well do it.
             */
            if (!queryDesc->plannedstmt->hasModifyingCTE)
                eflags |= EXEC_FLAG_SKIP_TRIGGERS;
            break;

        case CMD_INSERT:
        case CMD_DELETE:
        case CMD_UPDATE:
            estate->es_output_cid = GetCurrentCommandId(true);
            break;

        default:
            elog(ERROR, "unrecognized operation code: %d",
                 (int) queryDesc->operation);
            break;
    }

    /*
     * Copy other important information into the EState
     */
    estate->es_snapshot = RegisterSnapshot(queryDesc->snapshot);
    estate->es_crosscheck_snapshot = RegisterSnapshot(queryDesc->crosscheck_snapshot);
    estate->es_top_eflags = eflags;
    estate->es_instrument = queryDesc->instrument_options;

    /*
     * Initialize the plan state tree
     */
    InitPlan(queryDesc, eflags);

    /*
     * Set up an AFTER-trigger statement context, unless told not to, or
     * unless it's EXPLAIN-only mode (when ExecutorFinish won't be called).
     */
    if (!(eflags & (EXEC_FLAG_SKIP_TRIGGERS | EXEC_FLAG_EXPLAIN_ONLY)))
        AfterTriggerBeginQuery();

    MemoryContextSwitchTo(oldcontext);
}

void UnregisterExprContextCallback ( ExprContext econtext,
ExprContextCallbackFunction  function,
Datum  arg 
)

Definition at line 1447 of file execUtils.c.

References ExprContext_CB::arg, ExprContext::ecxt_callbacks, ExprContext_CB::function, ExprContext_CB::next, NULL, and pfree().

Referenced by end_MultiFuncCall(), and fmgr_sql().

{
    ExprContext_CB **prev_callback;
    ExprContext_CB *ecxt_callback;

    prev_callback = &econtext->ecxt_callbacks;

    while ((ecxt_callback = *prev_callback) != NULL)
    {
        if (ecxt_callback->function == function && ecxt_callback->arg == arg)
        {
            *prev_callback = ecxt_callback->next;
            pfree(ecxt_callback);
        }
        else
            prev_callback = &ecxt_callback->next;
    }
}

void UpdateChangedParamSet ( PlanState node,
Bitmapset newchg 
)

Definition at line 1390 of file execUtils.c.

References Plan::allParam, bms_free(), bms_intersect(), bms_is_empty(), bms_join(), PlanState::chgParam, and PlanState::plan.

Referenced by ExecReScan(), ExecReScanAppend(), ExecReScanBitmapAnd(), ExecReScanBitmapOr(), ExecReScanMergeAppend(), and ExecReScanSubqueryScan().

{
    Bitmapset  *parmset;

    /*
     * The plan node only depends on params listed in its allParam set. Don't
     * include anything else into its chgParam set.
     */
    parmset = bms_intersect(node->plan->allParam, newchg);

    /*
     * Keep node->chgParam == NULL if there's not actually any members; this
     * allows the simplest possible tests in executor node files.
     */
    if (!bms_is_empty(parmset))
        node->chgParam = bms_join(node->chgParam, parmset);
    else
        bms_free(parmset);
}


Variable Documentation

Definition at line 69 of file execMain.c.

Referenced by _PG_init(), and ExecCheckRTPerms().

Definition at line 66 of file execMain.c.

Referenced by _PG_fini(), _PG_init(), and ExecutorEnd().

Definition at line 65 of file execMain.c.

Referenced by _PG_fini(), _PG_init(), and ExecutorFinish().

Definition at line 64 of file execMain.c.

Referenced by _PG_fini(), _PG_init(), and ExecutorRun().

Definition at line 63 of file execMain.c.

Referenced by _PG_fini(), _PG_init(), and ExecutorStart().