summaryrefslogtreecommitdiffstats
path: root/src/include/nodes
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 13:44:03 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 13:44:03 +0000
commit293913568e6a7a86fd1479e1cff8e2ecb58d6568 (patch)
treefc3b469a3ec5ab71b36ea97cc7aaddb838423a0c /src/include/nodes
parentInitial commit. (diff)
downloadpostgresql-16-293913568e6a7a86fd1479e1cff8e2ecb58d6568.tar.xz
postgresql-16-293913568e6a7a86fd1479e1cff8e2ecb58d6568.zip
Adding upstream version 16.2.upstream/16.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/include/nodes')
-rw-r--r--src/include/nodes/.gitignore2
-rw-r--r--src/include/nodes/bitmapset.h126
-rw-r--r--src/include/nodes/execnodes.h2768
-rw-r--r--src/include/nodes/extensible.h164
-rw-r--r--src/include/nodes/lockoptions.h61
-rw-r--r--src/include/nodes/makefuncs.h121
-rw-r--r--src/include/nodes/memnodes.h113
-rw-r--r--src/include/nodes/meson.build65
-rw-r--r--src/include/nodes/miscnodes.h56
-rw-r--r--src/include/nodes/multibitmapset.h39
-rw-r--r--src/include/nodes/nodeFuncs.h222
-rw-r--r--src/include/nodes/nodes.h446
-rw-r--r--src/include/nodes/params.h170
-rw-r--r--src/include/nodes/parsenodes.h4050
-rw-r--r--src/include/nodes/pathnodes.h3384
-rw-r--r--src/include/nodes/pg_list.h635
-rw-r--r--src/include/nodes/plannodes.h1592
-rw-r--r--src/include/nodes/primnodes.h2041
-rw-r--r--src/include/nodes/print.h34
-rw-r--r--src/include/nodes/queryjumble.h86
-rw-r--r--src/include/nodes/readfuncs.h38
-rw-r--r--src/include/nodes/replnodes.h111
-rw-r--r--src/include/nodes/subscripting.h167
-rw-r--r--src/include/nodes/supportnodes.h346
-rw-r--r--src/include/nodes/tidbitmap.h75
-rw-r--r--src/include/nodes/value.h90
26 files changed, 17002 insertions, 0 deletions
diff --git a/src/include/nodes/.gitignore b/src/include/nodes/.gitignore
new file mode 100644
index 0000000..99fb1d3
--- /dev/null
+++ b/src/include/nodes/.gitignore
@@ -0,0 +1,2 @@
+/nodetags.h
+/header-stamp
diff --git a/src/include/nodes/bitmapset.h b/src/include/nodes/bitmapset.h
new file mode 100644
index 0000000..14de6a9
--- /dev/null
+++ b/src/include/nodes/bitmapset.h
@@ -0,0 +1,126 @@
+/*-------------------------------------------------------------------------
+ *
+ * bitmapset.h
+ * PostgreSQL generic bitmap set package
+ *
+ * A bitmap set can represent any set of nonnegative integers, although
+ * it is mainly intended for sets where the maximum value is not large,
+ * say at most a few hundred. By convention, we always represent the
+ * empty set by a NULL pointer.
+ *
+ *
+ * Copyright (c) 2003-2023, PostgreSQL Global Development Group
+ *
+ * src/include/nodes/bitmapset.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef BITMAPSET_H
+#define BITMAPSET_H
+
+#include "nodes/nodes.h"
+
+/*
+ * Forward decl to save including pg_list.h
+ */
+struct List;
+
+/*
+ * Data representation
+ *
+ * Larger bitmap word sizes generally give better performance, so long as
+ * they're not wider than the processor can handle efficiently. We use
+ * 64-bit words if pointers are that large, else 32-bit words.
+ */
+#if SIZEOF_VOID_P >= 8
+
+#define BITS_PER_BITMAPWORD 64
+typedef uint64 bitmapword; /* must be an unsigned type */
+typedef int64 signedbitmapword; /* must be the matching signed type */
+
+#else
+
+#define BITS_PER_BITMAPWORD 32
+typedef uint32 bitmapword; /* must be an unsigned type */
+typedef int32 signedbitmapword; /* must be the matching signed type */
+
+#endif
+
+typedef struct Bitmapset
+{
+ pg_node_attr(custom_copy_equal, special_read_write, no_query_jumble)
+
+ NodeTag type;
+ int nwords; /* number of words in array */
+ bitmapword words[FLEXIBLE_ARRAY_MEMBER]; /* really [nwords] */
+} Bitmapset;
+
+
+/* result of bms_subset_compare */
+typedef enum
+{
+ BMS_EQUAL, /* sets are equal */
+ BMS_SUBSET1, /* first set is a subset of the second */
+ BMS_SUBSET2, /* second set is a subset of the first */
+ BMS_DIFFERENT /* neither set is a subset of the other */
+} BMS_Comparison;
+
+/* result of bms_membership */
+typedef enum
+{
+ BMS_EMPTY_SET, /* 0 members */
+ BMS_SINGLETON, /* 1 member */
+ BMS_MULTIPLE /* >1 member */
+} BMS_Membership;
+
+
+/*
+ * function prototypes in nodes/bitmapset.c
+ */
+
+extern Bitmapset *bms_copy(const Bitmapset *a);
+extern bool bms_equal(const Bitmapset *a, const Bitmapset *b);
+extern int bms_compare(const Bitmapset *a, const Bitmapset *b);
+extern Bitmapset *bms_make_singleton(int x);
+extern void bms_free(Bitmapset *a);
+
+extern Bitmapset *bms_union(const Bitmapset *a, const Bitmapset *b);
+extern Bitmapset *bms_intersect(const Bitmapset *a, const Bitmapset *b);
+extern Bitmapset *bms_difference(const Bitmapset *a, const Bitmapset *b);
+extern bool bms_is_subset(const Bitmapset *a, const Bitmapset *b);
+extern BMS_Comparison bms_subset_compare(const Bitmapset *a, const Bitmapset *b);
+extern bool bms_is_member(int x, const Bitmapset *a);
+extern int bms_member_index(Bitmapset *a, int x);
+extern bool bms_overlap(const Bitmapset *a, const Bitmapset *b);
+extern bool bms_overlap_list(const Bitmapset *a, const struct List *b);
+extern bool bms_nonempty_difference(const Bitmapset *a, const Bitmapset *b);
+extern int bms_singleton_member(const Bitmapset *a);
+extern bool bms_get_singleton_member(const Bitmapset *a, int *member);
+extern int bms_num_members(const Bitmapset *a);
+
+/* optimized tests when we don't need to know exact membership count: */
+extern BMS_Membership bms_membership(const Bitmapset *a);
+
+/* NULL is now the only allowed representation of an empty bitmapset */
+#define bms_is_empty(a) ((a) == NULL)
+
+/* these routines recycle (modify or free) their non-const inputs: */
+
+extern Bitmapset *bms_add_member(Bitmapset *a, int x);
+extern Bitmapset *bms_del_member(Bitmapset *a, int x);
+extern Bitmapset *bms_add_members(Bitmapset *a, const Bitmapset *b);
+extern Bitmapset *bms_add_range(Bitmapset *a, int lower, int upper);
+extern Bitmapset *bms_int_members(Bitmapset *a, const Bitmapset *b);
+extern Bitmapset *bms_del_members(Bitmapset *a, const Bitmapset *b);
+extern Bitmapset *bms_join(Bitmapset *a, Bitmapset *b);
+
+/* support for iterating through the integer elements of a set: */
+extern int bms_next_member(const Bitmapset *a, int prevbit);
+extern int bms_prev_member(const Bitmapset *a, int prevbit);
+
+/* support for hashtables using Bitmapsets as keys: */
+extern uint32 bms_hash_value(const Bitmapset *a);
+extern uint32 bitmap_hash(const void *key, Size keysize);
+extern int bitmap_match(const void *key1, const void *key2, Size keysize);
+
+#endif /* BITMAPSET_H */
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
new file mode 100644
index 0000000..869465d
--- /dev/null
+++ b/src/include/nodes/execnodes.h
@@ -0,0 +1,2768 @@
+/*-------------------------------------------------------------------------
+ *
+ * execnodes.h
+ * definitions for executor state nodes
+ *
+ * Most plan node types declared in plannodes.h have a corresponding
+ * execution-state node type declared here. An exception is that
+ * expression nodes (subtypes of Expr) are usually represented by steps
+ * of an ExprState, and fully handled within execExpr* - but sometimes
+ * their state needs to be shared with other parts of the executor, as
+ * for example with SubPlanState, which nodeSubplan.c has to modify.
+ *
+ * Node types declared in this file do not have any copy/equal/out/read
+ * support. (That is currently hard-wired in gen_node_support.pl, rather
+ * than being explicitly represented by pg_node_attr decorations here.)
+ * There is no need for copy, equal, or read support for executor trees.
+ * Output support could be useful for debugging; but there are a lot of
+ * specialized fields that would require custom code, so for now it's
+ * not provided.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/nodes/execnodes.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef EXECNODES_H
+#define EXECNODES_H
+
+#include "access/tupconvert.h"
+#include "executor/instrument.h"
+#include "fmgr.h"
+#include "lib/ilist.h"
+#include "lib/pairingheap.h"
+#include "nodes/params.h"
+#include "nodes/plannodes.h"
+#include "nodes/tidbitmap.h"
+#include "partitioning/partdefs.h"
+#include "storage/condition_variable.h"
+#include "utils/hsearch.h"
+#include "utils/queryenvironment.h"
+#include "utils/reltrigger.h"
+#include "utils/sharedtuplestore.h"
+#include "utils/snapshot.h"
+#include "utils/sortsupport.h"
+#include "utils/tuplesort.h"
+#include "utils/tuplestore.h"
+
+struct PlanState; /* forward references in this file */
+struct ParallelHashJoinState;
+struct ExecRowMark;
+struct ExprState;
+struct ExprContext;
+struct RangeTblEntry; /* avoid including parsenodes.h here */
+struct ExprEvalStep; /* avoid including execExpr.h everywhere */
+struct CopyMultiInsertBuffer;
+struct LogicalTapeSet;
+
+
+/* ----------------
+ * ExprState node
+ *
+ * ExprState represents the evaluation state for a whole expression tree.
+ * It contains instructions (in ->steps) to evaluate the expression.
+ * ----------------
+ */
+typedef Datum (*ExprStateEvalFunc) (struct ExprState *expression,
+ struct ExprContext *econtext,
+ bool *isNull);
+
+/* Bits in ExprState->flags (see also execExpr.h for private flag bits): */
+/* expression is for use with ExecQual() */
+#define EEO_FLAG_IS_QUAL (1 << 0)
+
+typedef struct ExprState
+{
+ NodeTag type;
+
+ uint8 flags; /* bitmask of EEO_FLAG_* bits, see above */
+
+ /*
+ * Storage for result value of a scalar expression, or for individual
+ * column results within expressions built by ExecBuildProjectionInfo().
+ */
+#define FIELDNO_EXPRSTATE_RESNULL 2
+ bool resnull;
+#define FIELDNO_EXPRSTATE_RESVALUE 3
+ Datum resvalue;
+
+ /*
+ * If projecting a tuple result, this slot holds the result; else NULL.
+ */
+#define FIELDNO_EXPRSTATE_RESULTSLOT 4
+ TupleTableSlot *resultslot;
+
+ /*
+ * Instructions to compute expression's return value.
+ */
+ struct ExprEvalStep *steps;
+
+ /*
+ * Function that actually evaluates the expression. This can be set to
+ * different values depending on the complexity of the expression.
+ */
+ ExprStateEvalFunc evalfunc;
+
+ /* original expression tree, for debugging only */
+ Expr *expr;
+
+ /* private state for an evalfunc */
+ void *evalfunc_private;
+
+ /*
+ * XXX: following fields only needed during "compilation" (ExecInitExpr);
+ * could be thrown away afterwards.
+ */
+
+ int steps_len; /* number of steps currently */
+ int steps_alloc; /* allocated length of steps array */
+
+#define FIELDNO_EXPRSTATE_PARENT 11
+ struct PlanState *parent; /* parent PlanState node, if any */
+ ParamListInfo ext_params; /* for compiling PARAM_EXTERN nodes */
+
+ Datum *innermost_caseval;
+ bool *innermost_casenull;
+
+ Datum *innermost_domainval;
+ bool *innermost_domainnull;
+} ExprState;
+
+
+/* ----------------
+ * IndexInfo information
+ *
+ * this struct holds the information needed to construct new index
+ * entries for a particular index. Used for both index_build and
+ * retail creation of index entries.
+ *
+ * NumIndexAttrs total number of columns in this index
+ * NumIndexKeyAttrs number of key columns in index
+ * IndexAttrNumbers underlying-rel attribute numbers used as keys
+ * (zeroes indicate expressions). It also contains
+ * info about included columns.
+ * Expressions expr trees for expression entries, or NIL if none
+ * ExpressionsState exec state for expressions, or NIL if none
+ * Predicate partial-index predicate, or NIL if none
+ * PredicateState exec state for predicate, or NIL if none
+ * ExclusionOps Per-column exclusion operators, or NULL if none
+ * ExclusionProcs Underlying function OIDs for ExclusionOps
+ * ExclusionStrats Opclass strategy numbers for ExclusionOps
+ * UniqueOps These are like Exclusion*, but for unique indexes
+ * UniqueProcs
+ * UniqueStrats
+ * Unique is it a unique index?
+ * OpclassOptions opclass-specific options, or NULL if none
+ * ReadyForInserts is it valid for inserts?
+ * CheckedUnchanged IndexUnchanged status determined yet?
+ * IndexUnchanged aminsert hint, cached for retail inserts
+ * Concurrent are we doing a concurrent index build?
+ * BrokenHotChain did we detect any broken HOT chains?
+ * Summarizing is it a summarizing index?
+ * ParallelWorkers # of workers requested (excludes leader)
+ * Am Oid of index AM
+ * AmCache private cache area for index AM
+ * Context memory context holding this IndexInfo
+ *
+ * ii_Concurrent, ii_BrokenHotChain, and ii_ParallelWorkers are used only
+ * during index build; they're conventionally zeroed otherwise.
+ * ----------------
+ */
+typedef struct IndexInfo
+{
+ NodeTag type;
+ int ii_NumIndexAttrs; /* total number of columns in index */
+ int ii_NumIndexKeyAttrs; /* number of key columns in index */
+ AttrNumber ii_IndexAttrNumbers[INDEX_MAX_KEYS];
+ List *ii_Expressions; /* list of Expr */
+ List *ii_ExpressionsState; /* list of ExprState */
+ List *ii_Predicate; /* list of Expr */
+ ExprState *ii_PredicateState;
+ Oid *ii_ExclusionOps; /* array with one entry per column */
+ Oid *ii_ExclusionProcs; /* array with one entry per column */
+ uint16 *ii_ExclusionStrats; /* array with one entry per column */
+ Oid *ii_UniqueOps; /* array with one entry per column */
+ Oid *ii_UniqueProcs; /* array with one entry per column */
+ uint16 *ii_UniqueStrats; /* array with one entry per column */
+ Datum *ii_OpclassOptions; /* array with one entry per column */
+ bool ii_Unique;
+ bool ii_NullsNotDistinct;
+ bool ii_ReadyForInserts;
+ bool ii_CheckedUnchanged;
+ bool ii_IndexUnchanged;
+ bool ii_Concurrent;
+ bool ii_BrokenHotChain;
+ bool ii_Summarizing;
+ int ii_ParallelWorkers;
+ Oid ii_Am;
+ void *ii_AmCache;
+ MemoryContext ii_Context;
+} IndexInfo;
+
+/* ----------------
+ * ExprContext_CB
+ *
+ * List of callbacks to be called at ExprContext shutdown.
+ * ----------------
+ */
+typedef void (*ExprContextCallbackFunction) (Datum arg);
+
+typedef struct ExprContext_CB
+{
+ struct ExprContext_CB *next;
+ ExprContextCallbackFunction function;
+ Datum arg;
+} ExprContext_CB;
+
+/* ----------------
+ * ExprContext
+ *
+ * This class holds the "current context" information
+ * needed to evaluate expressions for doing tuple qualifications
+ * and tuple projections. For example, if an expression refers
+ * to an attribute in the current inner tuple then we need to know
+ * what the current inner tuple is and so we look at the expression
+ * context.
+ *
+ * There are two memory contexts associated with an ExprContext:
+ * * ecxt_per_query_memory is a query-lifespan context, typically the same
+ * context the ExprContext node itself is allocated in. This context
+ * can be used for purposes such as storing function call cache info.
+ * * ecxt_per_tuple_memory is a short-term context for expression results.
+ * As the name suggests, it will typically be reset once per tuple,
+ * before we begin to evaluate expressions for that tuple. Each
+ * ExprContext normally has its very own per-tuple memory context.
+ *
+ * CurrentMemoryContext should be set to ecxt_per_tuple_memory before
+ * calling ExecEvalExpr() --- see ExecEvalExprSwitchContext().
+ * ----------------
+ */
+typedef struct ExprContext
+{
+ NodeTag type;
+
+ /* Tuples that Var nodes in expression may refer to */
+#define FIELDNO_EXPRCONTEXT_SCANTUPLE 1
+ TupleTableSlot *ecxt_scantuple;
+#define FIELDNO_EXPRCONTEXT_INNERTUPLE 2
+ TupleTableSlot *ecxt_innertuple;
+#define FIELDNO_EXPRCONTEXT_OUTERTUPLE 3
+ TupleTableSlot *ecxt_outertuple;
+
+ /* Memory contexts for expression evaluation --- see notes above */
+ MemoryContext ecxt_per_query_memory;
+ MemoryContext ecxt_per_tuple_memory;
+
+ /* Values to substitute for Param nodes in expression */
+ ParamExecData *ecxt_param_exec_vals; /* for PARAM_EXEC params */
+ ParamListInfo ecxt_param_list_info; /* for other param types */
+
+ /*
+ * Values to substitute for Aggref nodes in the expressions of an Agg
+ * node, or for WindowFunc nodes within a WindowAgg node.
+ */
+#define FIELDNO_EXPRCONTEXT_AGGVALUES 8
+ Datum *ecxt_aggvalues; /* precomputed values for aggs/windowfuncs */
+#define FIELDNO_EXPRCONTEXT_AGGNULLS 9
+ bool *ecxt_aggnulls; /* null flags for aggs/windowfuncs */
+
+ /* Value to substitute for CaseTestExpr nodes in expression */
+#define FIELDNO_EXPRCONTEXT_CASEDATUM 10
+ Datum caseValue_datum;
+#define FIELDNO_EXPRCONTEXT_CASENULL 11
+ bool caseValue_isNull;
+
+ /* Value to substitute for CoerceToDomainValue nodes in expression */
+#define FIELDNO_EXPRCONTEXT_DOMAINDATUM 12
+ Datum domainValue_datum;
+#define FIELDNO_EXPRCONTEXT_DOMAINNULL 13
+ bool domainValue_isNull;
+
+ /* Link to containing EState (NULL if a standalone ExprContext) */
+ struct EState *ecxt_estate;
+
+ /* Functions to call back when ExprContext is shut down or rescanned */
+ ExprContext_CB *ecxt_callbacks;
+} ExprContext;
+
+/*
+ * Set-result status used when evaluating functions potentially returning a
+ * set.
+ */
+typedef enum
+{
+ ExprSingleResult, /* expression does not return a set */
+ ExprMultipleResult, /* this result is an element of a set */
+ ExprEndResult /* there are no more elements in the set */
+} ExprDoneCond;
+
+/*
+ * Return modes for functions returning sets. Note values must be chosen
+ * as separate bits so that a bitmask can be formed to indicate supported
+ * modes. SFRM_Materialize_Random and SFRM_Materialize_Preferred are
+ * auxiliary flags about SFRM_Materialize mode, rather than separate modes.
+ */
+typedef enum
+{
+ SFRM_ValuePerCall = 0x01, /* one value returned per call */
+ SFRM_Materialize = 0x02, /* result set instantiated in Tuplestore */
+ SFRM_Materialize_Random = 0x04, /* Tuplestore needs randomAccess */
+ SFRM_Materialize_Preferred = 0x08 /* caller prefers Tuplestore */
+} SetFunctionReturnMode;
+
+/*
+ * When calling a function that might return a set (multiple rows),
+ * a node of this type is passed as fcinfo->resultinfo to allow
+ * return status to be passed back. A function returning set should
+ * raise an error if no such resultinfo is provided.
+ */
+typedef struct ReturnSetInfo
+{
+ NodeTag type;
+ /* values set by caller: */
+ ExprContext *econtext; /* context function is being called in */
+ TupleDesc expectedDesc; /* tuple descriptor expected by caller */
+ int allowedModes; /* bitmask: return modes caller can handle */
+ /* result status from function (but pre-initialized by caller): */
+ SetFunctionReturnMode returnMode; /* actual return mode */
+ ExprDoneCond isDone; /* status for ValuePerCall mode */
+ /* fields filled by function in Materialize return mode: */
+ Tuplestorestate *setResult; /* holds the complete returned tuple set */
+ TupleDesc setDesc; /* actual descriptor for returned tuples */
+} ReturnSetInfo;
+
+/* ----------------
+ * ProjectionInfo node information
+ *
+ * This is all the information needed to perform projections ---
+ * that is, form new tuples by evaluation of targetlist expressions.
+ * Nodes which need to do projections create one of these.
+ *
+ * The target tuple slot is kept in ProjectionInfo->pi_state.resultslot.
+ * ExecProject() evaluates the tlist, forms a tuple, and stores it
+ * in the given slot. Note that the result will be a "virtual" tuple
+ * unless ExecMaterializeSlot() is then called to force it to be
+ * converted to a physical tuple. The slot must have a tupledesc
+ * that matches the output of the tlist!
+ * ----------------
+ */
+typedef struct ProjectionInfo
+{
+ NodeTag type;
+ /* instructions to evaluate projection */
+ ExprState pi_state;
+ /* expression context in which to evaluate expression */
+ ExprContext *pi_exprContext;
+} ProjectionInfo;
+
+/* ----------------
+ * JunkFilter
+ *
+ * This class is used to store information regarding junk attributes.
+ * A junk attribute is an attribute in a tuple that is needed only for
+ * storing intermediate information in the executor, and does not belong
+ * in emitted tuples. For example, when we do an UPDATE query,
+ * the planner adds a "junk" entry to the targetlist so that the tuples
+ * returned to ExecutePlan() contain an extra attribute: the ctid of
+ * the tuple to be updated. This is needed to do the update, but we
+ * don't want the ctid to be part of the stored new tuple! So, we
+ * apply a "junk filter" to remove the junk attributes and form the
+ * real output tuple. The junkfilter code also provides routines to
+ * extract the values of the junk attribute(s) from the input tuple.
+ *
+ * targetList: the original target list (including junk attributes).
+ * cleanTupType: the tuple descriptor for the "clean" tuple (with
+ * junk attributes removed).
+ * cleanMap: A map with the correspondence between the non-junk
+ * attribute numbers of the "original" tuple and the
+ * attribute numbers of the "clean" tuple.
+ * resultSlot: tuple slot used to hold cleaned tuple.
+ * ----------------
+ */
+typedef struct JunkFilter
+{
+ NodeTag type;
+ List *jf_targetList;
+ TupleDesc jf_cleanTupType;
+ AttrNumber *jf_cleanMap;
+ TupleTableSlot *jf_resultSlot;
+} JunkFilter;
+
+/*
+ * OnConflictSetState
+ *
+ * Executor state of an ON CONFLICT DO UPDATE operation.
+ */
+typedef struct OnConflictSetState
+{
+ NodeTag type;
+
+ TupleTableSlot *oc_Existing; /* slot to store existing target tuple in */
+ TupleTableSlot *oc_ProjSlot; /* CONFLICT ... SET ... projection target */
+ ProjectionInfo *oc_ProjInfo; /* for ON CONFLICT DO UPDATE SET */
+ ExprState *oc_WhereClause; /* state for the WHERE clause */
+} OnConflictSetState;
+
+/* ----------------
+ * MergeActionState information
+ *
+ * Executor state for a MERGE action.
+ * ----------------
+ */
+typedef struct MergeActionState
+{
+ NodeTag type;
+
+ MergeAction *mas_action; /* associated MergeAction node */
+ ProjectionInfo *mas_proj; /* projection of the action's targetlist for
+ * this rel */
+ ExprState *mas_whenqual; /* WHEN [NOT] MATCHED AND conditions */
+} MergeActionState;
+
+/*
+ * ResultRelInfo
+ *
+ * Whenever we update an existing relation, we have to update indexes on the
+ * relation, and perhaps also fire triggers. ResultRelInfo holds all the
+ * information needed about a result relation, including indexes.
+ *
+ * Normally, a ResultRelInfo refers to a table that is in the query's range
+ * table; then ri_RangeTableIndex is the RT index and ri_RelationDesc is
+ * just a copy of the relevant es_relations[] entry. However, in some
+ * situations we create ResultRelInfos for relations that are not in the
+ * range table, namely for targets of tuple routing in a partitioned table,
+ * and when firing triggers in tables other than the target tables (See
+ * ExecGetTriggerResultRel). In these situations, ri_RangeTableIndex is 0
+ * and ri_RelationDesc is a separately-opened relcache pointer that needs to
+ * be separately closed.
+ */
+typedef struct ResultRelInfo
+{
+ NodeTag type;
+
+ /* result relation's range table index, or 0 if not in range table */
+ Index ri_RangeTableIndex;
+
+ /* relation descriptor for result relation */
+ Relation ri_RelationDesc;
+
+ /* # of indices existing on result relation */
+ int ri_NumIndices;
+
+ /* array of relation descriptors for indices */
+ RelationPtr ri_IndexRelationDescs;
+
+ /* array of key/attr info for indices */
+ IndexInfo **ri_IndexRelationInfo;
+
+ /*
+ * For UPDATE/DELETE result relations, the attribute number of the row
+ * identity junk attribute in the source plan's output tuples
+ */
+ AttrNumber ri_RowIdAttNo;
+
+ /* For UPDATE, attnums of generated columns to be computed */
+ Bitmapset *ri_extraUpdatedCols;
+
+ /* Projection to generate new tuple in an INSERT/UPDATE */
+ ProjectionInfo *ri_projectNew;
+ /* Slot to hold that tuple */
+ TupleTableSlot *ri_newTupleSlot;
+ /* Slot to hold the old tuple being updated */
+ TupleTableSlot *ri_oldTupleSlot;
+ /* Have the projection and the slots above been initialized? */
+ bool ri_projectNewInfoValid;
+
+ /* triggers to be fired, if any */
+ TriggerDesc *ri_TrigDesc;
+
+ /* cached lookup info for trigger functions */
+ FmgrInfo *ri_TrigFunctions;
+
+ /* array of trigger WHEN expr states */
+ ExprState **ri_TrigWhenExprs;
+
+ /* optional runtime measurements for triggers */
+ Instrumentation *ri_TrigInstrument;
+
+ /* On-demand created slots for triggers / returning processing */
+ TupleTableSlot *ri_ReturningSlot; /* for trigger output tuples */
+ TupleTableSlot *ri_TrigOldSlot; /* for a trigger's old tuple */
+ TupleTableSlot *ri_TrigNewSlot; /* for a trigger's new tuple */
+
+ /* FDW callback functions, if foreign table */
+ struct FdwRoutine *ri_FdwRoutine;
+
+ /* available to save private state of FDW */
+ void *ri_FdwState;
+
+ /* true when modifying foreign table directly */
+ bool ri_usesFdwDirectModify;
+
+ /* batch insert stuff */
+ int ri_NumSlots; /* number of slots in the array */
+ int ri_NumSlotsInitialized; /* number of initialized slots */
+ int ri_BatchSize; /* max slots inserted in a single batch */
+ TupleTableSlot **ri_Slots; /* input tuples for batch insert */
+ TupleTableSlot **ri_PlanSlots;
+
+ /* list of WithCheckOption's to be checked */
+ List *ri_WithCheckOptions;
+
+ /* list of WithCheckOption expr states */
+ List *ri_WithCheckOptionExprs;
+
+ /* array of constraint-checking expr states */
+ ExprState **ri_ConstraintExprs;
+
+ /* arrays of stored generated columns expr states, for INSERT and UPDATE */
+ ExprState **ri_GeneratedExprsI;
+ ExprState **ri_GeneratedExprsU;
+
+ /* number of stored generated columns we need to compute */
+ int ri_NumGeneratedNeededI;
+ int ri_NumGeneratedNeededU;
+
+ /* list of RETURNING expressions */
+ List *ri_returningList;
+
+ /* for computing a RETURNING list */
+ ProjectionInfo *ri_projectReturning;
+
+ /* list of arbiter indexes to use to check conflicts */
+ List *ri_onConflictArbiterIndexes;
+
+ /* ON CONFLICT evaluation state */
+ OnConflictSetState *ri_onConflict;
+
+ /* for MERGE, lists of MergeActionState */
+ List *ri_matchedMergeAction;
+ List *ri_notMatchedMergeAction;
+
+ /* partition check expression state (NULL if not set up yet) */
+ ExprState *ri_PartitionCheckExpr;
+
+ /*
+ * Map to convert child result relation tuples to the format of the table
+ * actually mentioned in the query (called "root"). Computed only if
+ * needed. A NULL map value indicates that no conversion is needed, so we
+ * must have a separate flag to show if the map has been computed.
+ */
+ TupleConversionMap *ri_ChildToRootMap;
+ bool ri_ChildToRootMapValid;
+
+ /*
+ * As above, but in the other direction.
+ */
+ TupleConversionMap *ri_RootToChildMap;
+ bool ri_RootToChildMapValid;
+
+ /*
+ * Information needed by tuple routing target relations
+ *
+ * RootResultRelInfo gives the target relation mentioned in the query, if
+ * it's a partitioned table. It is not set if the target relation
+ * mentioned in the query is an inherited table, nor when tuple routing is
+ * not needed.
+ *
+ * PartitionTupleSlot is non-NULL if RootToChild conversion is needed and
+ * the relation is a partition.
+ */
+ struct ResultRelInfo *ri_RootResultRelInfo;
+ TupleTableSlot *ri_PartitionTupleSlot;
+
+ /* for use by copyfrom.c when performing multi-inserts */
+ struct CopyMultiInsertBuffer *ri_CopyMultiInsertBuffer;
+
+ /*
+ * Used when a leaf partition is involved in a cross-partition update of
+ * one of its ancestors; see ExecCrossPartitionUpdateForeignKey().
+ */
+ List *ri_ancestorResultRels;
+} ResultRelInfo;
+
+/* ----------------
+ * AsyncRequest
+ *
+ * State for an asynchronous tuple request.
+ * ----------------
+ */
+typedef struct AsyncRequest
+{
+ struct PlanState *requestor; /* Node that wants a tuple */
+ struct PlanState *requestee; /* Node from which a tuple is wanted */
+ int request_index; /* Scratch space for requestor */
+ bool callback_pending; /* Callback is needed */
+ bool request_complete; /* Request complete, result valid */
+ TupleTableSlot *result; /* Result (NULL or an empty slot if no more
+ * tuples) */
+} AsyncRequest;
+
+/* ----------------
+ * EState information
+ *
+ * Working state for an Executor invocation
+ * ----------------
+ */
+typedef struct EState
+{
+ NodeTag type;
+
+ /* Basic state for all query types: */
+ ScanDirection es_direction; /* current scan direction */
+ Snapshot es_snapshot; /* time qual to use */
+ Snapshot es_crosscheck_snapshot; /* crosscheck time qual for RI */
+ List *es_range_table; /* List of RangeTblEntry */
+ Index es_range_table_size; /* size of the range table arrays */
+ Relation *es_relations; /* Array of per-range-table-entry Relation
+ * pointers, or NULL if not yet opened */
+ struct ExecRowMark **es_rowmarks; /* Array of per-range-table-entry
+ * ExecRowMarks, or NULL if none */
+ List *es_rteperminfos; /* List of RTEPermissionInfo */
+ PlannedStmt *es_plannedstmt; /* link to top of plan tree */
+ const char *es_sourceText; /* Source text from QueryDesc */
+
+ JunkFilter *es_junkFilter; /* top-level junk filter, if any */
+
+ /* If query can insert/delete tuples, the command ID to mark them with */
+ CommandId es_output_cid;
+
+ /* Info about target table(s) for insert/update/delete queries: */
+ ResultRelInfo **es_result_relations; /* Array of per-range-table-entry
+ * ResultRelInfo pointers, or NULL
+ * if not a target table */
+ List *es_opened_result_relations; /* List of non-NULL entries in
+ * es_result_relations in no
+ * specific order */
+
+ PartitionDirectory es_partition_directory; /* for PartitionDesc lookup */
+
+ /*
+ * The following list contains ResultRelInfos created by the tuple routing
+ * code for partitions that aren't found in the es_result_relations array.
+ */
+ List *es_tuple_routing_result_relations;
+
+ /* Stuff used for firing triggers: */
+ List *es_trig_target_relations; /* trigger-only ResultRelInfos */
+
+ /* Parameter info: */
+ ParamListInfo es_param_list_info; /* values of external params */
+ ParamExecData *es_param_exec_vals; /* values of internal params */
+
+ QueryEnvironment *es_queryEnv; /* query environment */
+
+ /* Other working state: */
+ MemoryContext es_query_cxt; /* per-query context in which EState lives */
+
+ List *es_tupleTable; /* List of TupleTableSlots */
+
+ uint64 es_processed; /* # of tuples processed during one
+ * ExecutorRun() call. */
+ uint64 es_total_processed; /* total # of tuples aggregated across all
+ * ExecutorRun() calls. */
+
+ int es_top_eflags; /* eflags passed to ExecutorStart */
+ int es_instrument; /* OR of InstrumentOption flags */
+ bool es_finished; /* true when ExecutorFinish is done */
+
+ List *es_exprcontexts; /* List of ExprContexts within EState */
+
+ List *es_subplanstates; /* List of PlanState for SubPlans */
+
+ List *es_auxmodifytables; /* List of secondary ModifyTableStates */
+
+ /*
+ * this ExprContext is for per-output-tuple operations, such as constraint
+ * checks and index-value computations. It will be reset for each output
+ * tuple. Note that it will be created only if needed.
+ */
+ ExprContext *es_per_tuple_exprcontext;
+
+ /*
+ * If not NULL, this is an EPQState's EState. This is a field in EState
+ * both to allow EvalPlanQual aware executor nodes to detect that they
+ * need to perform EPQ related work, and to provide necessary information
+ * to do so.
+ */
+ struct EPQState *es_epq_active;
+
+ bool es_use_parallel_mode; /* can we use parallel workers? */
+
+ /* The per-query shared memory area to use for parallel execution. */
+ struct dsa_area *es_query_dsa;
+
+ /*
+ * JIT information. es_jit_flags indicates whether JIT should be performed
+ * and with which options. es_jit is created on-demand when JITing is
+ * performed.
+ *
+ * es_jit_worker_instr is the combined, on demand allocated,
+ * instrumentation from all workers. The leader's instrumentation is kept
+ * separate, and is combined on demand by ExplainPrintJITSummary().
+ */
+ int es_jit_flags;
+ struct JitContext *es_jit;
+ struct JitInstrumentation *es_jit_worker_instr;
+
+ /*
+ * Lists of ResultRelInfos for foreign tables on which batch-inserts are
+ * to be executed and owning ModifyTableStates, stored in the same order.
+ */
+ List *es_insert_pending_result_relations;
+ List *es_insert_pending_modifytables;
+} EState;
+
+
+/*
+ * ExecRowMark -
+ * runtime representation of FOR [KEY] UPDATE/SHARE clauses
+ *
+ * When doing UPDATE/DELETE/MERGE/SELECT FOR [KEY] UPDATE/SHARE, we will have
+ * an ExecRowMark for each non-target relation in the query (except inheritance
+ * parent RTEs, which can be ignored at runtime). Virtual relations such as
+ * subqueries-in-FROM will have an ExecRowMark with relation == NULL. See
+ * PlanRowMark for details about most of the fields. In addition to fields
+ * directly derived from PlanRowMark, we store an activity flag (to denote
+ * inactive children of inheritance trees), curCtid, which is used by the
+ * WHERE CURRENT OF code, and ermExtra, which is available for use by the plan
+ * node that sources the relation (e.g., for a foreign table the FDW can use
+ * ermExtra to hold information).
+ *
+ * EState->es_rowmarks is an array of these structs, indexed by RT index,
+ * with NULLs for irrelevant RT indexes. es_rowmarks itself is NULL if
+ * there are no rowmarks.
+ */
+typedef struct ExecRowMark
+{
+ Relation relation; /* opened and suitably locked relation */
+ Oid relid; /* its OID (or InvalidOid, if subquery) */
+ Index rti; /* its range table index */
+ Index prti; /* parent range table index, if child */
+ Index rowmarkId; /* unique identifier for resjunk columns */
+ RowMarkType markType; /* see enum in nodes/plannodes.h */
+ LockClauseStrength strength; /* LockingClause's strength, or LCS_NONE */
+ LockWaitPolicy waitPolicy; /* NOWAIT and SKIP LOCKED */
+ bool ermActive; /* is this mark relevant for current tuple? */
+ ItemPointerData curCtid; /* ctid of currently locked tuple, if any */
+ void *ermExtra; /* available for use by relation source node */
+} ExecRowMark;
+
+/*
+ * ExecAuxRowMark -
+ * additional runtime representation of FOR [KEY] UPDATE/SHARE clauses
+ *
+ * Each LockRows and ModifyTable node keeps a list of the rowmarks it needs to
+ * deal with. In addition to a pointer to the related entry in es_rowmarks,
+ * this struct carries the column number(s) of the resjunk columns associated
+ * with the rowmark (see comments for PlanRowMark for more detail).
+ */
+typedef struct ExecAuxRowMark
+{
+ ExecRowMark *rowmark; /* related entry in es_rowmarks */
+ AttrNumber ctidAttNo; /* resno of ctid junk attribute, if any */
+ AttrNumber toidAttNo; /* resno of tableoid junk attribute, if any */
+ AttrNumber wholeAttNo; /* resno of whole-row junk attribute, if any */
+} ExecAuxRowMark;
+
+
+/* ----------------------------------------------------------------
+ * Tuple Hash Tables
+ *
+ * All-in-memory tuple hash tables are used for a number of purposes.
+ *
+ * Note: tab_hash_funcs are for the key datatype(s) stored in the table,
+ * and tab_eq_funcs are non-cross-type equality operators for those types.
+ * Normally these are the only functions used, but FindTupleHashEntry()
+ * supports searching a hashtable using cross-data-type hashing. For that,
+ * the caller must supply hash functions for the LHS datatype as well as
+ * the cross-type equality operators to use. in_hash_funcs and cur_eq_func
+ * are set to point to the caller's function arrays while doing such a search.
+ * During LookupTupleHashEntry(), they point to tab_hash_funcs and
+ * tab_eq_func respectively.
+ * ----------------------------------------------------------------
+ */
+typedef struct TupleHashEntryData *TupleHashEntry;
+typedef struct TupleHashTableData *TupleHashTable;
+
+typedef struct TupleHashEntryData
+{
+ MinimalTuple firstTuple; /* copy of first tuple in this group */
+ void *additional; /* user data */
+ uint32 status; /* hash status */
+ uint32 hash; /* hash value (cached) */
+} TupleHashEntryData;
+
+/* define parameters necessary to generate the tuple hash table interface */
+#define SH_PREFIX tuplehash
+#define SH_ELEMENT_TYPE TupleHashEntryData
+#define SH_KEY_TYPE MinimalTuple
+#define SH_SCOPE extern
+#define SH_DECLARE
+#include "lib/simplehash.h"
+
+typedef struct TupleHashTableData
+{
+ tuplehash_hash *hashtab; /* underlying hash table */
+ int numCols; /* number of columns in lookup key */
+ AttrNumber *keyColIdx; /* attr numbers of key columns */
+ FmgrInfo *tab_hash_funcs; /* hash functions for table datatype(s) */
+ ExprState *tab_eq_func; /* comparator for table datatype(s) */
+ Oid *tab_collations; /* collations for hash and comparison */
+ MemoryContext tablecxt; /* memory context containing table */
+ MemoryContext tempcxt; /* context for function evaluations */
+ Size entrysize; /* actual size to make each hash entry */
+ TupleTableSlot *tableslot; /* slot for referencing table entries */
+ /* The following fields are set transiently for each table search: */
+ TupleTableSlot *inputslot; /* current input tuple's slot */
+ FmgrInfo *in_hash_funcs; /* hash functions for input datatype(s) */
+ ExprState *cur_eq_func; /* comparator for input vs. table */
+ uint32 hash_iv; /* hash-function IV */
+ ExprContext *exprcontext; /* expression context */
+} TupleHashTableData;
+
+typedef tuplehash_iterator TupleHashIterator;
+
+/*
+ * Use InitTupleHashIterator/TermTupleHashIterator for a read/write scan.
+ * Use ResetTupleHashIterator if the table can be frozen (in this case no
+ * explicit scan termination is needed).
+ */
+#define InitTupleHashIterator(htable, iter) \
+ tuplehash_start_iterate(htable->hashtab, iter)
+#define TermTupleHashIterator(iter) \
+ ((void) 0)
+#define ResetTupleHashIterator(htable, iter) \
+ InitTupleHashIterator(htable, iter)
+#define ScanTupleHashTable(htable, iter) \
+ tuplehash_iterate(htable->hashtab, iter)
+
+
+/* ----------------------------------------------------------------
+ * Expression State Nodes
+ *
+ * Formerly, there was a separate executor expression state node corresponding
+ * to each node in a planned expression tree. That's no longer the case; for
+ * common expression node types, all the execution info is embedded into
+ * step(s) in a single ExprState node. But we still have a few executor state
+ * node types for selected expression node types, mostly those in which info
+ * has to be shared with other parts of the execution state tree.
+ * ----------------------------------------------------------------
+ */
+
+/* ----------------
+ * WindowFuncExprState node
+ * ----------------
+ */
+typedef struct WindowFuncExprState
+{
+ NodeTag type;
+ WindowFunc *wfunc; /* expression plan node */
+ List *args; /* ExprStates for argument expressions */
+ ExprState *aggfilter; /* FILTER expression */
+ int wfuncno; /* ID number for wfunc within its plan node */
+} WindowFuncExprState;
+
+
+/* ----------------
+ * SetExprState node
+ *
+ * State for evaluating a potentially set-returning expression (like FuncExpr
+ * or OpExpr). In some cases, like some of the expressions in ROWS FROM(...)
+ * the expression might not be a SRF, but nonetheless it uses the same
+ * machinery as SRFs; it will be treated as a SRF returning a single row.
+ * ----------------
+ */
+typedef struct SetExprState
+{
+ NodeTag type;
+ Expr *expr; /* expression plan node */
+ List *args; /* ExprStates for argument expressions */
+
+ /*
+ * In ROWS FROM, functions can be inlined, removing the FuncExpr normally
+ * inside. In such a case this is the compiled expression (which cannot
+ * return a set), which'll be evaluated using regular ExecEvalExpr().
+ */
+ ExprState *elidedFuncState;
+
+ /*
+ * Function manager's lookup info for the target function. If func.fn_oid
+ * is InvalidOid, we haven't initialized it yet (nor any of the following
+ * fields, except funcReturnsSet).
+ */
+ FmgrInfo func;
+
+ /*
+ * For a set-returning function (SRF) that returns a tuplestore, we keep
+ * the tuplestore here and dole out the result rows one at a time. The
+ * slot holds the row currently being returned.
+ */
+ Tuplestorestate *funcResultStore;
+ TupleTableSlot *funcResultSlot;
+
+ /*
+ * In some cases we need to compute a tuple descriptor for the function's
+ * output. If so, it's stored here.
+ */
+ TupleDesc funcResultDesc;
+ bool funcReturnsTuple; /* valid when funcResultDesc isn't NULL */
+
+ /*
+ * Remember whether the function is declared to return a set. This is set
+ * by ExecInitExpr, and is valid even before the FmgrInfo is set up.
+ */
+ bool funcReturnsSet;
+
+ /*
+ * setArgsValid is true when we are evaluating a set-returning function
+ * that uses value-per-call mode and we are in the middle of a call
+ * series; we want to pass the same argument values to the function again
+ * (and again, until it returns ExprEndResult). This indicates that
+ * fcinfo_data already contains valid argument data.
+ */
+ bool setArgsValid;
+
+ /*
+ * Flag to remember whether we have registered a shutdown callback for
+ * this SetExprState. We do so only if funcResultStore or setArgsValid
+ * has been set at least once (since all the callback is for is to release
+ * the tuplestore or clear setArgsValid).
+ */
+ bool shutdown_reg; /* a shutdown callback is registered */
+
+ /*
+ * Call parameter structure for the function. This has been initialized
+ * (by InitFunctionCallInfoData) if func.fn_oid is valid. It also saves
+ * argument values between calls, when setArgsValid is true.
+ */
+ FunctionCallInfo fcinfo;
+} SetExprState;
+
+/* ----------------
+ * SubPlanState node
+ * ----------------
+ */
+typedef struct SubPlanState
+{
+ NodeTag type;
+ SubPlan *subplan; /* expression plan node */
+ struct PlanState *planstate; /* subselect plan's state tree */
+ struct PlanState *parent; /* parent plan node's state tree */
+ ExprState *testexpr; /* state of combining expression */
+ List *args; /* states of argument expression(s) */
+ HeapTuple curTuple; /* copy of most recent tuple from subplan */
+ Datum curArray; /* most recent array from ARRAY() subplan */
+ /* these are used when hashing the subselect's output: */
+ TupleDesc descRight; /* subselect desc after projection */
+ ProjectionInfo *projLeft; /* for projecting lefthand exprs */
+ ProjectionInfo *projRight; /* for projecting subselect output */
+ TupleHashTable hashtable; /* hash table for no-nulls subselect rows */
+ TupleHashTable hashnulls; /* hash table for rows with null(s) */
+ bool havehashrows; /* true if hashtable is not empty */
+ bool havenullrows; /* true if hashnulls is not empty */
+ MemoryContext hashtablecxt; /* memory context containing hash tables */
+ MemoryContext hashtempcxt; /* temp memory context for hash tables */
+ ExprContext *innerecontext; /* econtext for computing inner tuples */
+ int numCols; /* number of columns being hashed */
+ /* each of the remaining fields is an array of length numCols: */
+ AttrNumber *keyColIdx; /* control data for hash tables */
+ Oid *tab_eq_funcoids; /* equality func oids for table
+ * datatype(s) */
+ Oid *tab_collations; /* collations for hash and comparison */
+ FmgrInfo *tab_hash_funcs; /* hash functions for table datatype(s) */
+ FmgrInfo *tab_eq_funcs; /* equality functions for table datatype(s) */
+ FmgrInfo *lhs_hash_funcs; /* hash functions for lefthand datatype(s) */
+ FmgrInfo *cur_eq_funcs; /* equality functions for LHS vs. table */
+ ExprState *cur_eq_comp; /* equality comparator for LHS vs. table */
+} SubPlanState;
+
+/*
+ * DomainConstraintState - one item to check during CoerceToDomain
+ *
+ * Note: we consider this to be part of an ExprState tree, so we give it
+ * a name following the xxxState convention. But there's no directly
+ * associated plan-tree node.
+ */
+typedef enum DomainConstraintType
+{
+ DOM_CONSTRAINT_NOTNULL,
+ DOM_CONSTRAINT_CHECK
+} DomainConstraintType;
+
+typedef struct DomainConstraintState
+{
+ NodeTag type;
+ DomainConstraintType constrainttype; /* constraint type */
+ char *name; /* name of constraint (for error msgs) */
+ Expr *check_expr; /* for CHECK, a boolean expression */
+ ExprState *check_exprstate; /* check_expr's eval state, or NULL */
+} DomainConstraintState;
+
+
+/* ----------------------------------------------------------------
+ * Executor State Trees
+ *
+ * An executing query has a PlanState tree paralleling the Plan tree
+ * that describes the plan.
+ * ----------------------------------------------------------------
+ */
+
+/* ----------------
+ * ExecProcNodeMtd
+ *
+ * This is the method called by ExecProcNode to return the next tuple
+ * from an executor node. It returns NULL, or an empty TupleTableSlot,
+ * if no more tuples are available.
+ * ----------------
+ */
+typedef TupleTableSlot *(*ExecProcNodeMtd) (struct PlanState *pstate);
+
+/* ----------------
+ * PlanState node
+ *
+ * We never actually instantiate any PlanState nodes; this is just the common
+ * abstract superclass for all PlanState-type nodes.
+ * ----------------
+ */
+typedef struct PlanState
+{
+ pg_node_attr(abstract)
+
+ NodeTag type;
+
+ Plan *plan; /* associated Plan node */
+
+ EState *state; /* at execution time, states of individual
+ * nodes point to one EState for the whole
+ * top-level plan */
+
+ ExecProcNodeMtd ExecProcNode; /* function to return next tuple */
+ ExecProcNodeMtd ExecProcNodeReal; /* actual function, if above is a
+ * wrapper */
+
+ Instrumentation *instrument; /* Optional runtime stats for this node */
+ WorkerInstrumentation *worker_instrument; /* per-worker instrumentation */
+
+ /* Per-worker JIT instrumentation */
+ struct SharedJitInstrumentation *worker_jit_instrument;
+
+ /*
+ * Common structural data for all Plan types. These links to subsidiary
+ * state trees parallel links in the associated plan tree (except for the
+ * subPlan list, which does not exist in the plan tree).
+ */
+ ExprState *qual; /* boolean qual condition */
+ struct PlanState *lefttree; /* input plan tree(s) */
+ struct PlanState *righttree;
+
+ List *initPlan; /* Init SubPlanState nodes (un-correlated expr
+ * subselects) */
+ List *subPlan; /* SubPlanState nodes in my expressions */
+
+ /*
+ * State for management of parameter-change-driven rescanning
+ */
+ Bitmapset *chgParam; /* set of IDs of changed Params */
+
+ /*
+ * Other run-time state needed by most if not all node types.
+ */
+ TupleDesc ps_ResultTupleDesc; /* node's return type */
+ TupleTableSlot *ps_ResultTupleSlot; /* slot for my result tuples */
+ ExprContext *ps_ExprContext; /* node's expression-evaluation context */
+ ProjectionInfo *ps_ProjInfo; /* info for doing tuple projection */
+
+ bool async_capable; /* true if node is async-capable */
+
+ /*
+ * Scanslot's descriptor if known. This is a bit of a hack, but otherwise
+ * it's hard for expression compilation to optimize based on the
+ * descriptor, without encoding knowledge about all executor nodes.
+ */
+ TupleDesc scandesc;
+
+ /*
+ * Define the slot types for inner, outer and scanslots for expression
+ * contexts with this state as a parent. If *opsset is set, then
+ * *opsfixed indicates whether *ops is guaranteed to be the type of slot
+ * used. That means that every slot in the corresponding
+ * ExprContext.ecxt_*tuple will point to a slot of that type, while
+ * evaluating the expression. If *opsfixed is false, but *ops is set,
+ * that indicates the most likely type of slot.
+ *
+ * The scan* fields are set by ExecInitScanTupleSlot(). If that's not
+ * called, nodes can initialize the fields themselves.
+ *
+ * If outer/inneropsset is false, the information is inferred on-demand
+ * using ExecGetResultSlotOps() on ->righttree/lefttree, using the
+ * corresponding node's resultops* fields.
+ *
+ * The result* fields are automatically set when ExecInitResultSlot is
+ * used (be it directly or when the slot is created by
+ * ExecAssignScanProjectionInfo() /
+ * ExecConditionalAssignProjectionInfo()). If no projection is necessary
+ * ExecConditionalAssignProjectionInfo() defaults those fields to the scan
+ * operations.
+ */
+ const TupleTableSlotOps *scanops;
+ const TupleTableSlotOps *outerops;
+ const TupleTableSlotOps *innerops;
+ const TupleTableSlotOps *resultops;
+ bool scanopsfixed;
+ bool outeropsfixed;
+ bool inneropsfixed;
+ bool resultopsfixed;
+ bool scanopsset;
+ bool outeropsset;
+ bool inneropsset;
+ bool resultopsset;
+} PlanState;
+
+/* ----------------
+ * these are defined to avoid confusion problems with "left"
+ * and "right" and "inner" and "outer". The convention is that
+ * the "left" plan is the "outer" plan and the "right" plan is
+ * the inner plan, but these make the code more readable.
+ * ----------------
+ */
+#define innerPlanState(node) (((PlanState *)(node))->righttree)
+#define outerPlanState(node) (((PlanState *)(node))->lefttree)
+
+/* Macros for inline access to certain instrumentation counters */
+#define InstrCountTuples2(node, delta) \
+ do { \
+ if (((PlanState *)(node))->instrument) \
+ ((PlanState *)(node))->instrument->ntuples2 += (delta); \
+ } while (0)
+#define InstrCountFiltered1(node, delta) \
+ do { \
+ if (((PlanState *)(node))->instrument) \
+ ((PlanState *)(node))->instrument->nfiltered1 += (delta); \
+ } while(0)
+#define InstrCountFiltered2(node, delta) \
+ do { \
+ if (((PlanState *)(node))->instrument) \
+ ((PlanState *)(node))->instrument->nfiltered2 += (delta); \
+ } while(0)
+
+/*
+ * EPQState is state for executing an EvalPlanQual recheck on a candidate
+ * tuples e.g. in ModifyTable or LockRows.
+ *
+ * To execute EPQ a separate EState is created (stored in ->recheckestate),
+ * which shares some resources, like the rangetable, with the main query's
+ * EState (stored in ->parentestate). The (sub-)tree of the plan that needs to
+ * be rechecked (in ->plan), is separately initialized (into
+ * ->recheckplanstate), but shares plan nodes with the corresponding nodes in
+ * the main query. The scan nodes in that separate executor tree are changed
+ * to return only the current tuple of interest for the respective
+ * table. Those tuples are either provided by the caller (using
+ * EvalPlanQualSlot), and/or found using the rowmark mechanism (non-locking
+ * rowmarks by the EPQ machinery itself, locking ones by the caller).
+ *
+ * While the plan to be checked may be changed using EvalPlanQualSetPlan(),
+ * all such plans need to share the same EState.
+ */
+typedef struct EPQState
+{
+ /* These are initialized by EvalPlanQualInit() and do not change later: */
+ EState *parentestate; /* main query's EState */
+ int epqParam; /* ID of Param to force scan node re-eval */
+ List *resultRelations; /* integer list of RT indexes, or NIL */
+
+ /*
+ * relsubs_slot[scanrelid - 1] holds the EPQ test tuple to be returned by
+ * the scan node for the scanrelid'th RT index, in place of performing an
+ * actual table scan. Callers should use EvalPlanQualSlot() to fetch
+ * these slots.
+ */
+ List *tuple_table; /* tuple table for relsubs_slot */
+ TupleTableSlot **relsubs_slot;
+
+ /*
+ * Initialized by EvalPlanQualInit(), may be changed later with
+ * EvalPlanQualSetPlan():
+ */
+
+ Plan *plan; /* plan tree to be executed */
+ List *arowMarks; /* ExecAuxRowMarks (non-locking only) */
+
+
+ /*
+ * The original output tuple to be rechecked. Set by
+ * EvalPlanQualSetSlot(), before EvalPlanQualNext() or EvalPlanQual() may
+ * be called.
+ */
+ TupleTableSlot *origslot;
+
+
+ /* Initialized or reset by EvalPlanQualBegin(): */
+
+ EState *recheckestate; /* EState for EPQ execution, see above */
+
+ /*
+ * Rowmarks that can be fetched on-demand using
+ * EvalPlanQualFetchRowMark(), indexed by scanrelid - 1. Only non-locking
+ * rowmarks.
+ */
+ ExecAuxRowMark **relsubs_rowmark;
+
+ /*
+ * relsubs_done[scanrelid - 1] is true if there is no EPQ tuple for this
+ * target relation or it has already been fetched in the current scan of
+ * this target relation within the current EvalPlanQual test.
+ */
+ bool *relsubs_done;
+
+ /*
+ * relsubs_blocked[scanrelid - 1] is true if there is no EPQ tuple for
+ * this target relation during the current EvalPlanQual test. We keep
+ * these flags set for all relids listed in resultRelations, but
+ * transiently clear the one for the relation whose tuple is actually
+ * passed to EvalPlanQual().
+ */
+ bool *relsubs_blocked;
+
+ PlanState *recheckplanstate; /* EPQ specific exec nodes, for ->plan */
+} EPQState;
+
+
+/* ----------------
+ * ResultState information
+ * ----------------
+ */
+typedef struct ResultState
+{
+ PlanState ps; /* its first field is NodeTag */
+ ExprState *resconstantqual;
+ bool rs_done; /* are we done? */
+ bool rs_checkqual; /* do we need to check the qual? */
+} ResultState;
+
+/* ----------------
+ * ProjectSetState information
+ *
+ * Note: at least one of the "elems" will be a SetExprState; the rest are
+ * regular ExprStates.
+ * ----------------
+ */
+typedef struct ProjectSetState
+{
+ PlanState ps; /* its first field is NodeTag */
+ Node **elems; /* array of expression states */
+ ExprDoneCond *elemdone; /* array of per-SRF is-done states */
+ int nelems; /* length of elemdone[] array */
+ bool pending_srf_tuples; /* still evaluating srfs in tlist? */
+ MemoryContext argcontext; /* context for SRF arguments */
+} ProjectSetState;
+
+
+/* flags for mt_merge_subcommands */
+#define MERGE_INSERT 0x01
+#define MERGE_UPDATE 0x02
+#define MERGE_DELETE 0x04
+
+/* ----------------
+ * ModifyTableState information
+ * ----------------
+ */
+typedef struct ModifyTableState
+{
+ PlanState ps; /* its first field is NodeTag */
+ CmdType operation; /* INSERT, UPDATE, DELETE, or MERGE */
+ bool canSetTag; /* do we set the command tag/es_processed? */
+ bool mt_done; /* are we done? */
+ int mt_nrels; /* number of entries in resultRelInfo[] */
+ ResultRelInfo *resultRelInfo; /* info about target relation(s) */
+
+ /*
+ * Target relation mentioned in the original statement, used to fire
+ * statement-level triggers and as the root for tuple routing. (This
+ * might point to one of the resultRelInfo[] entries, but it can also be a
+ * distinct struct.)
+ */
+ ResultRelInfo *rootResultRelInfo;
+
+ EPQState mt_epqstate; /* for evaluating EvalPlanQual rechecks */
+ bool fireBSTriggers; /* do we need to fire stmt triggers? */
+
+ /*
+ * These fields are used for inherited UPDATE and DELETE, to track which
+ * target relation a given tuple is from. If there are a lot of target
+ * relations, we use a hash table to translate table OIDs to
+ * resultRelInfo[] indexes; otherwise mt_resultOidHash is NULL.
+ */
+ int mt_resultOidAttno; /* resno of "tableoid" junk attr */
+ Oid mt_lastResultOid; /* last-seen value of tableoid */
+ int mt_lastResultIndex; /* corresponding index in resultRelInfo[] */
+ HTAB *mt_resultOidHash; /* optional hash table to speed lookups */
+
+ /*
+ * Slot for storing tuples in the root partitioned table's rowtype during
+ * an UPDATE of a partitioned table.
+ */
+ TupleTableSlot *mt_root_tuple_slot;
+
+ /* Tuple-routing support info */
+ struct PartitionTupleRouting *mt_partition_tuple_routing;
+
+ /* controls transition table population for specified operation */
+ struct TransitionCaptureState *mt_transition_capture;
+
+ /* controls transition table population for INSERT...ON CONFLICT UPDATE */
+ struct TransitionCaptureState *mt_oc_transition_capture;
+
+ /* Flags showing which subcommands are present INS/UPD/DEL/DO NOTHING */
+ int mt_merge_subcommands;
+
+ /* tuple counters for MERGE */
+ double mt_merge_inserted;
+ double mt_merge_updated;
+ double mt_merge_deleted;
+} ModifyTableState;
+
+/* ----------------
+ * AppendState information
+ *
+ * nplans how many plans are in the array
+ * whichplan which synchronous plan is being executed (0 .. n-1)
+ * or a special negative value. See nodeAppend.c.
+ * prune_state details required to allow partitions to be
+ * eliminated from the scan, or NULL if not possible.
+ * valid_subplans for runtime pruning, valid synchronous appendplans
+ * indexes to scan.
+ * ----------------
+ */
+
+struct AppendState;
+typedef struct AppendState AppendState;
+struct ParallelAppendState;
+typedef struct ParallelAppendState ParallelAppendState;
+struct PartitionPruneState;
+
+struct AppendState
+{
+ PlanState ps; /* its first field is NodeTag */
+ PlanState **appendplans; /* array of PlanStates for my inputs */
+ int as_nplans;
+ int as_whichplan;
+ bool as_begun; /* false means need to initialize */
+ Bitmapset *as_asyncplans; /* asynchronous plans indexes */
+ int as_nasyncplans; /* # of asynchronous plans */
+ AsyncRequest **as_asyncrequests; /* array of AsyncRequests */
+ TupleTableSlot **as_asyncresults; /* unreturned results of async plans */
+ int as_nasyncresults; /* # of valid entries in as_asyncresults */
+ bool as_syncdone; /* true if all synchronous plans done in
+ * asynchronous mode, else false */
+ int as_nasyncremain; /* # of remaining asynchronous plans */
+ Bitmapset *as_needrequest; /* asynchronous plans needing a new request */
+ struct WaitEventSet *as_eventset; /* WaitEventSet used to configure file
+ * descriptor wait events */
+ int as_first_partial_plan; /* Index of 'appendplans' containing
+ * the first partial plan */
+ ParallelAppendState *as_pstate; /* parallel coordination info */
+ Size pstate_len; /* size of parallel coordination info */
+ struct PartitionPruneState *as_prune_state;
+ bool as_valid_subplans_identified; /* is as_valid_subplans valid? */
+ Bitmapset *as_valid_subplans;
+ Bitmapset *as_valid_asyncplans; /* valid asynchronous plans indexes */
+ bool (*choose_next_subplan) (AppendState *);
+};
+
+/* ----------------
+ * MergeAppendState information
+ *
+ * nplans how many plans are in the array
+ * nkeys number of sort key columns
+ * sortkeys sort keys in SortSupport representation
+ * slots current output tuple of each subplan
+ * heap heap of active tuples
+ * initialized true if we have fetched first tuple from each subplan
+ * prune_state details required to allow partitions to be
+ * eliminated from the scan, or NULL if not possible.
+ * valid_subplans for runtime pruning, valid mergeplans indexes to
+ * scan.
+ * ----------------
+ */
+typedef struct MergeAppendState
+{
+ PlanState ps; /* its first field is NodeTag */
+ PlanState **mergeplans; /* array of PlanStates for my inputs */
+ int ms_nplans;
+ int ms_nkeys;
+ SortSupport ms_sortkeys; /* array of length ms_nkeys */
+ TupleTableSlot **ms_slots; /* array of length ms_nplans */
+ struct binaryheap *ms_heap; /* binary heap of slot indices */
+ bool ms_initialized; /* are subplans started? */
+ struct PartitionPruneState *ms_prune_state;
+ Bitmapset *ms_valid_subplans;
+} MergeAppendState;
+
+/* ----------------
+ * RecursiveUnionState information
+ *
+ * RecursiveUnionState is used for performing a recursive union.
+ *
+ * recursing T when we're done scanning the non-recursive term
+ * intermediate_empty T if intermediate_table is currently empty
+ * working_table working table (to be scanned by recursive term)
+ * intermediate_table current recursive output (next generation of WT)
+ * ----------------
+ */
+typedef struct RecursiveUnionState
+{
+ PlanState ps; /* its first field is NodeTag */
+ bool recursing;
+ bool intermediate_empty;
+ Tuplestorestate *working_table;
+ Tuplestorestate *intermediate_table;
+ /* Remaining fields are unused in UNION ALL case */
+ Oid *eqfuncoids; /* per-grouping-field equality fns */
+ FmgrInfo *hashfunctions; /* per-grouping-field hash fns */
+ MemoryContext tempContext; /* short-term context for comparisons */
+ TupleHashTable hashtable; /* hash table for tuples already seen */
+ MemoryContext tableContext; /* memory context containing hash table */
+} RecursiveUnionState;
+
+/* ----------------
+ * BitmapAndState information
+ * ----------------
+ */
+typedef struct BitmapAndState
+{
+ PlanState ps; /* its first field is NodeTag */
+ PlanState **bitmapplans; /* array of PlanStates for my inputs */
+ int nplans; /* number of input plans */
+} BitmapAndState;
+
+/* ----------------
+ * BitmapOrState information
+ * ----------------
+ */
+typedef struct BitmapOrState
+{
+ PlanState ps; /* its first field is NodeTag */
+ PlanState **bitmapplans; /* array of PlanStates for my inputs */
+ int nplans; /* number of input plans */
+} BitmapOrState;
+
+/* ----------------------------------------------------------------
+ * Scan State Information
+ * ----------------------------------------------------------------
+ */
+
+/* ----------------
+ * ScanState information
+ *
+ * ScanState extends PlanState for node types that represent
+ * scans of an underlying relation. It can also be used for nodes
+ * that scan the output of an underlying plan node --- in that case,
+ * only ScanTupleSlot is actually useful, and it refers to the tuple
+ * retrieved from the subplan.
+ *
+ * currentRelation relation being scanned (NULL if none)
+ * currentScanDesc current scan descriptor for scan (NULL if none)
+ * ScanTupleSlot pointer to slot in tuple table holding scan tuple
+ * ----------------
+ */
+typedef struct ScanState
+{
+ PlanState ps; /* its first field is NodeTag */
+ Relation ss_currentRelation;
+ struct TableScanDescData *ss_currentScanDesc;
+ TupleTableSlot *ss_ScanTupleSlot;
+} ScanState;
+
+/* ----------------
+ * SeqScanState information
+ * ----------------
+ */
+typedef struct SeqScanState
+{
+ ScanState ss; /* its first field is NodeTag */
+ Size pscan_len; /* size of parallel heap scan descriptor */
+} SeqScanState;
+
+/* ----------------
+ * SampleScanState information
+ * ----------------
+ */
+typedef struct SampleScanState
+{
+ ScanState ss;
+ List *args; /* expr states for TABLESAMPLE params */
+ ExprState *repeatable; /* expr state for REPEATABLE expr */
+ /* use struct pointer to avoid including tsmapi.h here */
+ struct TsmRoutine *tsmroutine; /* descriptor for tablesample method */
+ void *tsm_state; /* tablesample method can keep state here */
+ bool use_bulkread; /* use bulkread buffer access strategy? */
+ bool use_pagemode; /* use page-at-a-time visibility checking? */
+ bool begun; /* false means need to call BeginSampleScan */
+ uint32 seed; /* random seed */
+ int64 donetuples; /* number of tuples already returned */
+ bool haveblock; /* has a block for sampling been determined */
+ bool done; /* exhausted all tuples? */
+} SampleScanState;
+
+/*
+ * These structs store information about index quals that don't have simple
+ * constant right-hand sides. See comments for ExecIndexBuildScanKeys()
+ * for discussion.
+ */
+typedef struct
+{
+ struct ScanKeyData *scan_key; /* scankey to put value into */
+ ExprState *key_expr; /* expr to evaluate to get value */
+ bool key_toastable; /* is expr's result a toastable datatype? */
+} IndexRuntimeKeyInfo;
+
+typedef struct
+{
+ struct ScanKeyData *scan_key; /* scankey to put value into */
+ ExprState *array_expr; /* expr to evaluate to get array value */
+ int next_elem; /* next array element to use */
+ int num_elems; /* number of elems in current array value */
+ Datum *elem_values; /* array of num_elems Datums */
+ bool *elem_nulls; /* array of num_elems is-null flags */
+} IndexArrayKeyInfo;
+
+/* ----------------
+ * IndexScanState information
+ *
+ * indexqualorig execution state for indexqualorig expressions
+ * indexorderbyorig execution state for indexorderbyorig expressions
+ * ScanKeys Skey structures for index quals
+ * NumScanKeys number of ScanKeys
+ * OrderByKeys Skey structures for index ordering operators
+ * NumOrderByKeys number of OrderByKeys
+ * RuntimeKeys info about Skeys that must be evaluated at runtime
+ * NumRuntimeKeys number of RuntimeKeys
+ * RuntimeKeysReady true if runtime Skeys have been computed
+ * RuntimeContext expr context for evaling runtime Skeys
+ * RelationDesc index relation descriptor
+ * ScanDesc index scan descriptor
+ *
+ * ReorderQueue tuples that need reordering due to re-check
+ * ReachedEnd have we fetched all tuples from index already?
+ * OrderByValues values of ORDER BY exprs of last fetched tuple
+ * OrderByNulls null flags for OrderByValues
+ * SortSupport for reordering ORDER BY exprs
+ * OrderByTypByVals is the datatype of order by expression pass-by-value?
+ * OrderByTypLens typlens of the datatypes of order by expressions
+ * PscanLen size of parallel index scan descriptor
+ * ----------------
+ */
+typedef struct IndexScanState
+{
+ ScanState ss; /* its first field is NodeTag */
+ ExprState *indexqualorig;
+ List *indexorderbyorig;
+ struct ScanKeyData *iss_ScanKeys;
+ int iss_NumScanKeys;
+ struct ScanKeyData *iss_OrderByKeys;
+ int iss_NumOrderByKeys;
+ IndexRuntimeKeyInfo *iss_RuntimeKeys;
+ int iss_NumRuntimeKeys;
+ bool iss_RuntimeKeysReady;
+ ExprContext *iss_RuntimeContext;
+ Relation iss_RelationDesc;
+ struct IndexScanDescData *iss_ScanDesc;
+
+ /* These are needed for re-checking ORDER BY expr ordering */
+ pairingheap *iss_ReorderQueue;
+ bool iss_ReachedEnd;
+ Datum *iss_OrderByValues;
+ bool *iss_OrderByNulls;
+ SortSupport iss_SortSupport;
+ bool *iss_OrderByTypByVals;
+ int16 *iss_OrderByTypLens;
+ Size iss_PscanLen;
+} IndexScanState;
+
+/* ----------------
+ * IndexOnlyScanState information
+ *
+ * recheckqual execution state for recheckqual expressions
+ * ScanKeys Skey structures for index quals
+ * NumScanKeys number of ScanKeys
+ * OrderByKeys Skey structures for index ordering operators
+ * NumOrderByKeys number of OrderByKeys
+ * RuntimeKeys info about Skeys that must be evaluated at runtime
+ * NumRuntimeKeys number of RuntimeKeys
+ * RuntimeKeysReady true if runtime Skeys have been computed
+ * RuntimeContext expr context for evaling runtime Skeys
+ * RelationDesc index relation descriptor
+ * ScanDesc index scan descriptor
+ * TableSlot slot for holding tuples fetched from the table
+ * VMBuffer buffer in use for visibility map testing, if any
+ * PscanLen size of parallel index-only scan descriptor
+ * ----------------
+ */
+typedef struct IndexOnlyScanState
+{
+ ScanState ss; /* its first field is NodeTag */
+ ExprState *recheckqual;
+ struct ScanKeyData *ioss_ScanKeys;
+ int ioss_NumScanKeys;
+ struct ScanKeyData *ioss_OrderByKeys;
+ int ioss_NumOrderByKeys;
+ IndexRuntimeKeyInfo *ioss_RuntimeKeys;
+ int ioss_NumRuntimeKeys;
+ bool ioss_RuntimeKeysReady;
+ ExprContext *ioss_RuntimeContext;
+ Relation ioss_RelationDesc;
+ struct IndexScanDescData *ioss_ScanDesc;
+ TupleTableSlot *ioss_TableSlot;
+ Buffer ioss_VMBuffer;
+ Size ioss_PscanLen;
+} IndexOnlyScanState;
+
+/* ----------------
+ * BitmapIndexScanState information
+ *
+ * result bitmap to return output into, or NULL
+ * ScanKeys Skey structures for index quals
+ * NumScanKeys number of ScanKeys
+ * RuntimeKeys info about Skeys that must be evaluated at runtime
+ * NumRuntimeKeys number of RuntimeKeys
+ * ArrayKeys info about Skeys that come from ScalarArrayOpExprs
+ * NumArrayKeys number of ArrayKeys
+ * RuntimeKeysReady true if runtime Skeys have been computed
+ * RuntimeContext expr context for evaling runtime Skeys
+ * RelationDesc index relation descriptor
+ * ScanDesc index scan descriptor
+ * ----------------
+ */
+typedef struct BitmapIndexScanState
+{
+ ScanState ss; /* its first field is NodeTag */
+ TIDBitmap *biss_result;
+ struct ScanKeyData *biss_ScanKeys;
+ int biss_NumScanKeys;
+ IndexRuntimeKeyInfo *biss_RuntimeKeys;
+ int biss_NumRuntimeKeys;
+ IndexArrayKeyInfo *biss_ArrayKeys;
+ int biss_NumArrayKeys;
+ bool biss_RuntimeKeysReady;
+ ExprContext *biss_RuntimeContext;
+ Relation biss_RelationDesc;
+ struct IndexScanDescData *biss_ScanDesc;
+} BitmapIndexScanState;
+
+/* ----------------
+ * SharedBitmapState information
+ *
+ * BM_INITIAL TIDBitmap creation is not yet started, so first worker
+ * to see this state will set the state to BM_INPROGRESS
+ * and that process will be responsible for creating
+ * TIDBitmap.
+ * BM_INPROGRESS TIDBitmap creation is in progress; workers need to
+ * sleep until it's finished.
+ * BM_FINISHED TIDBitmap creation is done, so now all workers can
+ * proceed to iterate over TIDBitmap.
+ * ----------------
+ */
+typedef enum
+{
+ BM_INITIAL,
+ BM_INPROGRESS,
+ BM_FINISHED
+} SharedBitmapState;
+
+/* ----------------
+ * ParallelBitmapHeapState information
+ * tbmiterator iterator for scanning current pages
+ * prefetch_iterator iterator for prefetching ahead of current page
+ * mutex mutual exclusion for the prefetching variable
+ * and state
+ * prefetch_pages # pages prefetch iterator is ahead of current
+ * prefetch_target current target prefetch distance
+ * state current state of the TIDBitmap
+ * cv conditional wait variable
+ * phs_snapshot_data snapshot data shared to workers
+ * ----------------
+ */
+typedef struct ParallelBitmapHeapState
+{
+ dsa_pointer tbmiterator;
+ dsa_pointer prefetch_iterator;
+ slock_t mutex;
+ int prefetch_pages;
+ int prefetch_target;
+ SharedBitmapState state;
+ ConditionVariable cv;
+ char phs_snapshot_data[FLEXIBLE_ARRAY_MEMBER];
+} ParallelBitmapHeapState;
+
+/* ----------------
+ * BitmapHeapScanState information
+ *
+ * bitmapqualorig execution state for bitmapqualorig expressions
+ * tbm bitmap obtained from child index scan(s)
+ * tbmiterator iterator for scanning current pages
+ * tbmres current-page data
+ * can_skip_fetch can we potentially skip tuple fetches in this scan?
+ * return_empty_tuples number of empty tuples to return
+ * vmbuffer buffer for visibility-map lookups
+ * pvmbuffer ditto, for prefetched pages
+ * exact_pages total number of exact pages retrieved
+ * lossy_pages total number of lossy pages retrieved
+ * prefetch_iterator iterator for prefetching ahead of current page
+ * prefetch_pages # pages prefetch iterator is ahead of current
+ * prefetch_target current target prefetch distance
+ * prefetch_maximum maximum value for prefetch_target
+ * pscan_len size of the shared memory for parallel bitmap
+ * initialized is node is ready to iterate
+ * shared_tbmiterator shared iterator
+ * shared_prefetch_iterator shared iterator for prefetching
+ * pstate shared state for parallel bitmap scan
+ * ----------------
+ */
+typedef struct BitmapHeapScanState
+{
+ ScanState ss; /* its first field is NodeTag */
+ ExprState *bitmapqualorig;
+ TIDBitmap *tbm;
+ TBMIterator *tbmiterator;
+ TBMIterateResult *tbmres;
+ bool can_skip_fetch;
+ int return_empty_tuples;
+ Buffer vmbuffer;
+ Buffer pvmbuffer;
+ long exact_pages;
+ long lossy_pages;
+ TBMIterator *prefetch_iterator;
+ int prefetch_pages;
+ int prefetch_target;
+ int prefetch_maximum;
+ Size pscan_len;
+ bool initialized;
+ TBMSharedIterator *shared_tbmiterator;
+ TBMSharedIterator *shared_prefetch_iterator;
+ ParallelBitmapHeapState *pstate;
+} BitmapHeapScanState;
+
+/* ----------------
+ * TidScanState information
+ *
+ * tidexprs list of TidExpr structs (see nodeTidscan.c)
+ * isCurrentOf scan has a CurrentOfExpr qual
+ * NumTids number of tids in this scan
+ * TidPtr index of currently fetched tid
+ * TidList evaluated item pointers (array of size NumTids)
+ * htup currently-fetched tuple, if any
+ * ----------------
+ */
+typedef struct TidScanState
+{
+ ScanState ss; /* its first field is NodeTag */
+ List *tss_tidexprs;
+ bool tss_isCurrentOf;
+ int tss_NumTids;
+ int tss_TidPtr;
+ ItemPointerData *tss_TidList;
+ HeapTupleData tss_htup;
+} TidScanState;
+
+/* ----------------
+ * TidRangeScanState information
+ *
+ * trss_tidexprs list of TidOpExpr structs (see nodeTidrangescan.c)
+ * trss_mintid the lowest TID in the scan range
+ * trss_maxtid the highest TID in the scan range
+ * trss_inScan is a scan currently in progress?
+ * ----------------
+ */
+typedef struct TidRangeScanState
+{
+ ScanState ss; /* its first field is NodeTag */
+ List *trss_tidexprs;
+ ItemPointerData trss_mintid;
+ ItemPointerData trss_maxtid;
+ bool trss_inScan;
+} TidRangeScanState;
+
+/* ----------------
+ * SubqueryScanState information
+ *
+ * SubqueryScanState is used for scanning a sub-query in the range table.
+ * ScanTupleSlot references the current output tuple of the sub-query.
+ * ----------------
+ */
+typedef struct SubqueryScanState
+{
+ ScanState ss; /* its first field is NodeTag */
+ PlanState *subplan;
+} SubqueryScanState;
+
+/* ----------------
+ * FunctionScanState information
+ *
+ * Function nodes are used to scan the results of a
+ * function appearing in FROM (typically a function returning set).
+ *
+ * eflags node's capability flags
+ * ordinality is this scan WITH ORDINALITY?
+ * simple true if we have 1 function and no ordinality
+ * ordinal current ordinal column value
+ * nfuncs number of functions being executed
+ * funcstates per-function execution states (private in
+ * nodeFunctionscan.c)
+ * argcontext memory context to evaluate function arguments in
+ * ----------------
+ */
+struct FunctionScanPerFuncState;
+
+typedef struct FunctionScanState
+{
+ ScanState ss; /* its first field is NodeTag */
+ int eflags;
+ bool ordinality;
+ bool simple;
+ int64 ordinal;
+ int nfuncs;
+ struct FunctionScanPerFuncState *funcstates; /* array of length nfuncs */
+ MemoryContext argcontext;
+} FunctionScanState;
+
+/* ----------------
+ * ValuesScanState information
+ *
+ * ValuesScan nodes are used to scan the results of a VALUES list
+ *
+ * rowcontext per-expression-list context
+ * exprlists array of expression lists being evaluated
+ * exprstatelists array of expression state lists, for SubPlans only
+ * array_len size of above arrays
+ * curr_idx current array index (0-based)
+ *
+ * Note: ss.ps.ps_ExprContext is used to evaluate any qual or projection
+ * expressions attached to the node. We create a second ExprContext,
+ * rowcontext, in which to build the executor expression state for each
+ * Values sublist. Resetting this context lets us get rid of expression
+ * state for each row, avoiding major memory leakage over a long values list.
+ * However, that doesn't work for sublists containing SubPlans, because a
+ * SubPlan has to be connected up to the outer plan tree to work properly.
+ * Therefore, for only those sublists containing SubPlans, we do expression
+ * state construction at executor start, and store those pointers in
+ * exprstatelists[]. NULL entries in that array correspond to simple
+ * subexpressions that are handled as described above.
+ * ----------------
+ */
+typedef struct ValuesScanState
+{
+ ScanState ss; /* its first field is NodeTag */
+ ExprContext *rowcontext;
+ List **exprlists;
+ List **exprstatelists;
+ int array_len;
+ int curr_idx;
+} ValuesScanState;
+
+/* ----------------
+ * TableFuncScanState node
+ *
+ * Used in table-expression functions like XMLTABLE.
+ * ----------------
+ */
+typedef struct TableFuncScanState
+{
+ ScanState ss; /* its first field is NodeTag */
+ ExprState *docexpr; /* state for document expression */
+ ExprState *rowexpr; /* state for row-generating expression */
+ List *colexprs; /* state for column-generating expression */
+ List *coldefexprs; /* state for column default expressions */
+ List *ns_names; /* same as TableFunc.ns_names */
+ List *ns_uris; /* list of states of namespace URI exprs */
+ Bitmapset *notnulls; /* nullability flag for each output column */
+ void *opaque; /* table builder private space */
+ const struct TableFuncRoutine *routine; /* table builder methods */
+ FmgrInfo *in_functions; /* input function for each column */
+ Oid *typioparams; /* typioparam for each column */
+ int64 ordinal; /* row number to be output next */
+ MemoryContext perTableCxt; /* per-table context */
+ Tuplestorestate *tupstore; /* output tuple store */
+} TableFuncScanState;
+
+/* ----------------
+ * CteScanState information
+ *
+ * CteScan nodes are used to scan a CommonTableExpr query.
+ *
+ * Multiple CteScan nodes can read out from the same CTE query. We use
+ * a tuplestore to hold rows that have been read from the CTE query but
+ * not yet consumed by all readers.
+ * ----------------
+ */
+typedef struct CteScanState
+{
+ ScanState ss; /* its first field is NodeTag */
+ int eflags; /* capability flags to pass to tuplestore */
+ int readptr; /* index of my tuplestore read pointer */
+ PlanState *cteplanstate; /* PlanState for the CTE query itself */
+ /* Link to the "leader" CteScanState (possibly this same node) */
+ struct CteScanState *leader;
+ /* The remaining fields are only valid in the "leader" CteScanState */
+ Tuplestorestate *cte_table; /* rows already read from the CTE query */
+ bool eof_cte; /* reached end of CTE query? */
+} CteScanState;
+
+/* ----------------
+ * NamedTuplestoreScanState information
+ *
+ * NamedTuplestoreScan nodes are used to scan a Tuplestore created and
+ * named prior to execution of the query. An example is a transition
+ * table for an AFTER trigger.
+ *
+ * Multiple NamedTuplestoreScan nodes can read out from the same Tuplestore.
+ * ----------------
+ */
+typedef struct NamedTuplestoreScanState
+{
+ ScanState ss; /* its first field is NodeTag */
+ int readptr; /* index of my tuplestore read pointer */
+ TupleDesc tupdesc; /* format of the tuples in the tuplestore */
+ Tuplestorestate *relation; /* the rows */
+} NamedTuplestoreScanState;
+
+/* ----------------
+ * WorkTableScanState information
+ *
+ * WorkTableScan nodes are used to scan the work table created by
+ * a RecursiveUnion node. We locate the RecursiveUnion node
+ * during executor startup.
+ * ----------------
+ */
+typedef struct WorkTableScanState
+{
+ ScanState ss; /* its first field is NodeTag */
+ RecursiveUnionState *rustate;
+} WorkTableScanState;
+
+/* ----------------
+ * ForeignScanState information
+ *
+ * ForeignScan nodes are used to scan foreign-data tables.
+ * ----------------
+ */
+typedef struct ForeignScanState
+{
+ ScanState ss; /* its first field is NodeTag */
+ ExprState *fdw_recheck_quals; /* original quals not in ss.ps.qual */
+ Size pscan_len; /* size of parallel coordination information */
+ ResultRelInfo *resultRelInfo; /* result rel info, if UPDATE or DELETE */
+ /* use struct pointer to avoid including fdwapi.h here */
+ struct FdwRoutine *fdwroutine;
+ void *fdw_state; /* foreign-data wrapper can keep state here */
+} ForeignScanState;
+
+/* ----------------
+ * CustomScanState information
+ *
+ * CustomScan nodes are used to execute custom code within executor.
+ *
+ * Core code must avoid assuming that the CustomScanState is only as large as
+ * the structure declared here; providers are allowed to make it the first
+ * element in a larger structure, and typically would need to do so. The
+ * struct is actually allocated by the CreateCustomScanState method associated
+ * with the plan node. Any additional fields can be initialized there, or in
+ * the BeginCustomScan method.
+ * ----------------
+ */
+struct CustomExecMethods;
+
+typedef struct CustomScanState
+{
+ ScanState ss;
+ uint32 flags; /* mask of CUSTOMPATH_* flags, see
+ * nodes/extensible.h */
+ List *custom_ps; /* list of child PlanState nodes, if any */
+ Size pscan_len; /* size of parallel coordination information */
+ const struct CustomExecMethods *methods;
+ const struct TupleTableSlotOps *slotOps;
+} CustomScanState;
+
+/* ----------------------------------------------------------------
+ * Join State Information
+ * ----------------------------------------------------------------
+ */
+
+/* ----------------
+ * JoinState information
+ *
+ * Superclass for state nodes of join plans.
+ * ----------------
+ */
+typedef struct JoinState
+{
+ PlanState ps;
+ JoinType jointype;
+ bool single_match; /* True if we should skip to next outer tuple
+ * after finding one inner match */
+ ExprState *joinqual; /* JOIN quals (in addition to ps.qual) */
+} JoinState;
+
+/* ----------------
+ * NestLoopState information
+ *
+ * NeedNewOuter true if need new outer tuple on next call
+ * MatchedOuter true if found a join match for current outer tuple
+ * NullInnerTupleSlot prepared null tuple for left outer joins
+ * ----------------
+ */
+typedef struct NestLoopState
+{
+ JoinState js; /* its first field is NodeTag */
+ bool nl_NeedNewOuter;
+ bool nl_MatchedOuter;
+ TupleTableSlot *nl_NullInnerTupleSlot;
+} NestLoopState;
+
+/* ----------------
+ * MergeJoinState information
+ *
+ * NumClauses number of mergejoinable join clauses
+ * Clauses info for each mergejoinable clause
+ * JoinState current state of ExecMergeJoin state machine
+ * SkipMarkRestore true if we may skip Mark and Restore operations
+ * ExtraMarks true to issue extra Mark operations on inner scan
+ * ConstFalseJoin true if we have a constant-false joinqual
+ * FillOuter true if should emit unjoined outer tuples anyway
+ * FillInner true if should emit unjoined inner tuples anyway
+ * MatchedOuter true if found a join match for current outer tuple
+ * MatchedInner true if found a join match for current inner tuple
+ * OuterTupleSlot slot in tuple table for cur outer tuple
+ * InnerTupleSlot slot in tuple table for cur inner tuple
+ * MarkedTupleSlot slot in tuple table for marked tuple
+ * NullOuterTupleSlot prepared null tuple for right outer joins
+ * NullInnerTupleSlot prepared null tuple for left outer joins
+ * OuterEContext workspace for computing outer tuple's join values
+ * InnerEContext workspace for computing inner tuple's join values
+ * ----------------
+ */
+/* private in nodeMergejoin.c: */
+typedef struct MergeJoinClauseData *MergeJoinClause;
+
+typedef struct MergeJoinState
+{
+ JoinState js; /* its first field is NodeTag */
+ int mj_NumClauses;
+ MergeJoinClause mj_Clauses; /* array of length mj_NumClauses */
+ int mj_JoinState;
+ bool mj_SkipMarkRestore;
+ bool mj_ExtraMarks;
+ bool mj_ConstFalseJoin;
+ bool mj_FillOuter;
+ bool mj_FillInner;
+ bool mj_MatchedOuter;
+ bool mj_MatchedInner;
+ TupleTableSlot *mj_OuterTupleSlot;
+ TupleTableSlot *mj_InnerTupleSlot;
+ TupleTableSlot *mj_MarkedTupleSlot;
+ TupleTableSlot *mj_NullOuterTupleSlot;
+ TupleTableSlot *mj_NullInnerTupleSlot;
+ ExprContext *mj_OuterEContext;
+ ExprContext *mj_InnerEContext;
+} MergeJoinState;
+
+/* ----------------
+ * HashJoinState information
+ *
+ * hashclauses original form of the hashjoin condition
+ * hj_OuterHashKeys the outer hash keys in the hashjoin condition
+ * hj_HashOperators the join operators in the hashjoin condition
+ * hj_HashTable hash table for the hashjoin
+ * (NULL if table not built yet)
+ * hj_CurHashValue hash value for current outer tuple
+ * hj_CurBucketNo regular bucket# for current outer tuple
+ * hj_CurSkewBucketNo skew bucket# for current outer tuple
+ * hj_CurTuple last inner tuple matched to current outer
+ * tuple, or NULL if starting search
+ * (hj_CurXXX variables are undefined if
+ * OuterTupleSlot is empty!)
+ * hj_OuterTupleSlot tuple slot for outer tuples
+ * hj_HashTupleSlot tuple slot for inner (hashed) tuples
+ * hj_NullOuterTupleSlot prepared null tuple for right/right-anti/full
+ * outer joins
+ * hj_NullInnerTupleSlot prepared null tuple for left/full outer joins
+ * hj_FirstOuterTupleSlot first tuple retrieved from outer plan
+ * hj_JoinState current state of ExecHashJoin state machine
+ * hj_MatchedOuter true if found a join match for current outer
+ * hj_OuterNotEmpty true if outer relation known not empty
+ * ----------------
+ */
+
+/* these structs are defined in executor/hashjoin.h: */
+typedef struct HashJoinTupleData *HashJoinTuple;
+typedef struct HashJoinTableData *HashJoinTable;
+
+typedef struct HashJoinState
+{
+ JoinState js; /* its first field is NodeTag */
+ ExprState *hashclauses;
+ List *hj_OuterHashKeys; /* list of ExprState nodes */
+ List *hj_HashOperators; /* list of operator OIDs */
+ List *hj_Collations;
+ HashJoinTable hj_HashTable;
+ uint32 hj_CurHashValue;
+ int hj_CurBucketNo;
+ int hj_CurSkewBucketNo;
+ HashJoinTuple hj_CurTuple;
+ TupleTableSlot *hj_OuterTupleSlot;
+ TupleTableSlot *hj_HashTupleSlot;
+ TupleTableSlot *hj_NullOuterTupleSlot;
+ TupleTableSlot *hj_NullInnerTupleSlot;
+ TupleTableSlot *hj_FirstOuterTupleSlot;
+ int hj_JoinState;
+ bool hj_MatchedOuter;
+ bool hj_OuterNotEmpty;
+} HashJoinState;
+
+
+/* ----------------------------------------------------------------
+ * Materialization State Information
+ * ----------------------------------------------------------------
+ */
+
+/* ----------------
+ * MaterialState information
+ *
+ * materialize nodes are used to materialize the results
+ * of a subplan into a temporary file.
+ *
+ * ss.ss_ScanTupleSlot refers to output of underlying plan.
+ * ----------------
+ */
+typedef struct MaterialState
+{
+ ScanState ss; /* its first field is NodeTag */
+ int eflags; /* capability flags to pass to tuplestore */
+ bool eof_underlying; /* reached end of underlying plan? */
+ Tuplestorestate *tuplestorestate;
+} MaterialState;
+
+struct MemoizeEntry;
+struct MemoizeTuple;
+struct MemoizeKey;
+
+typedef struct MemoizeInstrumentation
+{
+ uint64 cache_hits; /* number of rescans where we've found the
+ * scan parameter values to be cached */
+ uint64 cache_misses; /* number of rescans where we've not found the
+ * scan parameter values to be cached. */
+ uint64 cache_evictions; /* number of cache entries removed due to
+ * the need to free memory */
+ uint64 cache_overflows; /* number of times we've had to bypass the
+ * cache when filling it due to not being
+ * able to free enough space to store the
+ * current scan's tuples. */
+ uint64 mem_peak; /* peak memory usage in bytes */
+} MemoizeInstrumentation;
+
+/* ----------------
+ * Shared memory container for per-worker memoize information
+ * ----------------
+ */
+typedef struct SharedMemoizeInfo
+{
+ int num_workers;
+ MemoizeInstrumentation sinstrument[FLEXIBLE_ARRAY_MEMBER];
+} SharedMemoizeInfo;
+
+/* ----------------
+ * MemoizeState information
+ *
+ * memoize nodes are used to cache recent and commonly seen results from
+ * a parameterized scan.
+ * ----------------
+ */
+typedef struct MemoizeState
+{
+ ScanState ss; /* its first field is NodeTag */
+ int mstatus; /* value of ExecMemoize state machine */
+ int nkeys; /* number of cache keys */
+ struct memoize_hash *hashtable; /* hash table for cache entries */
+ TupleDesc hashkeydesc; /* tuple descriptor for cache keys */
+ TupleTableSlot *tableslot; /* min tuple slot for existing cache entries */
+ TupleTableSlot *probeslot; /* virtual slot used for hash lookups */
+ ExprState *cache_eq_expr; /* Compare exec params to hash key */
+ ExprState **param_exprs; /* exprs containing the parameters to this
+ * node */
+ FmgrInfo *hashfunctions; /* lookup data for hash funcs nkeys in size */
+ Oid *collations; /* collation for comparisons nkeys in size */
+ uint64 mem_used; /* bytes of memory used by cache */
+ uint64 mem_limit; /* memory limit in bytes for the cache */
+ MemoryContext tableContext; /* memory context to store cache data */
+ dlist_head lru_list; /* least recently used entry list */
+ struct MemoizeTuple *last_tuple; /* Used to point to the last tuple
+ * returned during a cache hit and the
+ * tuple we last stored when
+ * populating the cache. */
+ struct MemoizeEntry *entry; /* the entry that 'last_tuple' belongs to or
+ * NULL if 'last_tuple' is NULL. */
+ bool singlerow; /* true if the cache entry is to be marked as
+ * complete after caching the first tuple. */
+ bool binary_mode; /* true when cache key should be compared bit
+ * by bit, false when using hash equality ops */
+ MemoizeInstrumentation stats; /* execution statistics */
+ SharedMemoizeInfo *shared_info; /* statistics for parallel workers */
+ Bitmapset *keyparamids; /* Param->paramids of expressions belonging to
+ * param_exprs */
+} MemoizeState;
+
+/* ----------------
+ * When performing sorting by multiple keys, it's possible that the input
+ * dataset is already sorted on a prefix of those keys. We call these
+ * "presorted keys".
+ * PresortedKeyData represents information about one such key.
+ * ----------------
+ */
+typedef struct PresortedKeyData
+{
+ FmgrInfo flinfo; /* comparison function info */
+ FunctionCallInfo fcinfo; /* comparison function call info */
+ OffsetNumber attno; /* attribute number in tuple */
+} PresortedKeyData;
+
+/* ----------------
+ * Shared memory container for per-worker sort information
+ * ----------------
+ */
+typedef struct SharedSortInfo
+{
+ int num_workers;
+ TuplesortInstrumentation sinstrument[FLEXIBLE_ARRAY_MEMBER];
+} SharedSortInfo;
+
+/* ----------------
+ * SortState information
+ * ----------------
+ */
+typedef struct SortState
+{
+ ScanState ss; /* its first field is NodeTag */
+ bool randomAccess; /* need random access to sort output? */
+ bool bounded; /* is the result set bounded? */
+ int64 bound; /* if bounded, how many tuples are needed */
+ bool sort_Done; /* sort completed yet? */
+ bool bounded_Done; /* value of bounded we did the sort with */
+ int64 bound_Done; /* value of bound we did the sort with */
+ void *tuplesortstate; /* private state of tuplesort.c */
+ bool am_worker; /* are we a worker? */
+ bool datumSort; /* Datum sort instead of tuple sort? */
+ SharedSortInfo *shared_info; /* one entry per worker */
+} SortState;
+
+/* ----------------
+ * Instrumentation information for IncrementalSort
+ * ----------------
+ */
+typedef struct IncrementalSortGroupInfo
+{
+ int64 groupCount;
+ int64 maxDiskSpaceUsed;
+ int64 totalDiskSpaceUsed;
+ int64 maxMemorySpaceUsed;
+ int64 totalMemorySpaceUsed;
+ bits32 sortMethods; /* bitmask of TuplesortMethod */
+} IncrementalSortGroupInfo;
+
+typedef struct IncrementalSortInfo
+{
+ IncrementalSortGroupInfo fullsortGroupInfo;
+ IncrementalSortGroupInfo prefixsortGroupInfo;
+} IncrementalSortInfo;
+
+/* ----------------
+ * Shared memory container for per-worker incremental sort information
+ * ----------------
+ */
+typedef struct SharedIncrementalSortInfo
+{
+ int num_workers;
+ IncrementalSortInfo sinfo[FLEXIBLE_ARRAY_MEMBER];
+} SharedIncrementalSortInfo;
+
+/* ----------------
+ * IncrementalSortState information
+ * ----------------
+ */
+typedef enum
+{
+ INCSORT_LOADFULLSORT,
+ INCSORT_LOADPREFIXSORT,
+ INCSORT_READFULLSORT,
+ INCSORT_READPREFIXSORT,
+} IncrementalSortExecutionStatus;
+
+typedef struct IncrementalSortState
+{
+ ScanState ss; /* its first field is NodeTag */
+ bool bounded; /* is the result set bounded? */
+ int64 bound; /* if bounded, how many tuples are needed */
+ bool outerNodeDone; /* finished fetching tuples from outer node */
+ int64 bound_Done; /* value of bound we did the sort with */
+ IncrementalSortExecutionStatus execution_status;
+ int64 n_fullsort_remaining;
+ Tuplesortstate *fullsort_state; /* private state of tuplesort.c */
+ Tuplesortstate *prefixsort_state; /* private state of tuplesort.c */
+ /* the keys by which the input path is already sorted */
+ PresortedKeyData *presorted_keys;
+
+ IncrementalSortInfo incsort_info;
+
+ /* slot for pivot tuple defining values of presorted keys within group */
+ TupleTableSlot *group_pivot;
+ TupleTableSlot *transfer_tuple;
+ bool am_worker; /* are we a worker? */
+ SharedIncrementalSortInfo *shared_info; /* one entry per worker */
+} IncrementalSortState;
+
+/* ---------------------
+ * GroupState information
+ * ---------------------
+ */
+typedef struct GroupState
+{
+ ScanState ss; /* its first field is NodeTag */
+ ExprState *eqfunction; /* equality function */
+ bool grp_done; /* indicates completion of Group scan */
+} GroupState;
+
+/* ---------------------
+ * per-worker aggregate information
+ * ---------------------
+ */
+typedef struct AggregateInstrumentation
+{
+ Size hash_mem_peak; /* peak hash table memory usage */
+ uint64 hash_disk_used; /* kB of disk space used */
+ int hash_batches_used; /* batches used during entire execution */
+} AggregateInstrumentation;
+
+/* ----------------
+ * Shared memory container for per-worker aggregate information
+ * ----------------
+ */
+typedef struct SharedAggInfo
+{
+ int num_workers;
+ AggregateInstrumentation sinstrument[FLEXIBLE_ARRAY_MEMBER];
+} SharedAggInfo;
+
+/* ---------------------
+ * AggState information
+ *
+ * ss.ss_ScanTupleSlot refers to output of underlying plan.
+ *
+ * Note: ss.ps.ps_ExprContext contains ecxt_aggvalues and
+ * ecxt_aggnulls arrays, which hold the computed agg values for the current
+ * input group during evaluation of an Agg node's output tuple(s). We
+ * create a second ExprContext, tmpcontext, in which to evaluate input
+ * expressions and run the aggregate transition functions.
+ * ---------------------
+ */
+/* these structs are private in nodeAgg.c: */
+typedef struct AggStatePerAggData *AggStatePerAgg;
+typedef struct AggStatePerTransData *AggStatePerTrans;
+typedef struct AggStatePerGroupData *AggStatePerGroup;
+typedef struct AggStatePerPhaseData *AggStatePerPhase;
+typedef struct AggStatePerHashData *AggStatePerHash;
+
+typedef struct AggState
+{
+ ScanState ss; /* its first field is NodeTag */
+ List *aggs; /* all Aggref nodes in targetlist & quals */
+ int numaggs; /* length of list (could be zero!) */
+ int numtrans; /* number of pertrans items */
+ AggStrategy aggstrategy; /* strategy mode */
+ AggSplit aggsplit; /* agg-splitting mode, see nodes.h */
+ AggStatePerPhase phase; /* pointer to current phase data */
+ int numphases; /* number of phases (including phase 0) */
+ int current_phase; /* current phase number */
+ AggStatePerAgg peragg; /* per-Aggref information */
+ AggStatePerTrans pertrans; /* per-Trans state information */
+ ExprContext *hashcontext; /* econtexts for long-lived data (hashtable) */
+ ExprContext **aggcontexts; /* econtexts for long-lived data (per GS) */
+ ExprContext *tmpcontext; /* econtext for input expressions */
+#define FIELDNO_AGGSTATE_CURAGGCONTEXT 14
+ ExprContext *curaggcontext; /* currently active aggcontext */
+ AggStatePerAgg curperagg; /* currently active aggregate, if any */
+#define FIELDNO_AGGSTATE_CURPERTRANS 16
+ AggStatePerTrans curpertrans; /* currently active trans state, if any */
+ bool input_done; /* indicates end of input */
+ bool agg_done; /* indicates completion of Agg scan */
+ int projected_set; /* The last projected grouping set */
+#define FIELDNO_AGGSTATE_CURRENT_SET 20
+ int current_set; /* The current grouping set being evaluated */
+ Bitmapset *grouped_cols; /* grouped cols in current projection */
+ List *all_grouped_cols; /* list of all grouped cols in DESC order */
+ Bitmapset *colnos_needed; /* all columns needed from the outer plan */
+ int max_colno_needed; /* highest colno needed from outer plan */
+ bool all_cols_needed; /* are all cols from outer plan needed? */
+ /* These fields are for grouping set phase data */
+ int maxsets; /* The max number of sets in any phase */
+ AggStatePerPhase phases; /* array of all phases */
+ Tuplesortstate *sort_in; /* sorted input to phases > 1 */
+ Tuplesortstate *sort_out; /* input is copied here for next phase */
+ TupleTableSlot *sort_slot; /* slot for sort results */
+ /* these fields are used in AGG_PLAIN and AGG_SORTED modes: */
+ AggStatePerGroup *pergroups; /* grouping set indexed array of per-group
+ * pointers */
+ HeapTuple grp_firstTuple; /* copy of first tuple of current group */
+ /* these fields are used in AGG_HASHED and AGG_MIXED modes: */
+ bool table_filled; /* hash table filled yet? */
+ int num_hashes;
+ MemoryContext hash_metacxt; /* memory for hash table itself */
+ struct LogicalTapeSet *hash_tapeset; /* tape set for hash spill tapes */
+ struct HashAggSpill *hash_spills; /* HashAggSpill for each grouping set,
+ * exists only during first pass */
+ TupleTableSlot *hash_spill_rslot; /* for reading spill files */
+ TupleTableSlot *hash_spill_wslot; /* for writing spill files */
+ List *hash_batches; /* hash batches remaining to be processed */
+ bool hash_ever_spilled; /* ever spilled during this execution? */
+ bool hash_spill_mode; /* we hit a limit during the current batch
+ * and we must not create new groups */
+ Size hash_mem_limit; /* limit before spilling hash table */
+ uint64 hash_ngroups_limit; /* limit before spilling hash table */
+ int hash_planned_partitions; /* number of partitions planned
+ * for first pass */
+ double hashentrysize; /* estimate revised during execution */
+ Size hash_mem_peak; /* peak hash table memory usage */
+ uint64 hash_ngroups_current; /* number of groups currently in
+ * memory in all hash tables */
+ uint64 hash_disk_used; /* kB of disk space used */
+ int hash_batches_used; /* batches used during entire execution */
+
+ AggStatePerHash perhash; /* array of per-hashtable data */
+ AggStatePerGroup *hash_pergroup; /* grouping set indexed array of
+ * per-group pointers */
+
+ /* support for evaluation of agg input expressions: */
+#define FIELDNO_AGGSTATE_ALL_PERGROUPS 53
+ AggStatePerGroup *all_pergroups; /* array of first ->pergroups, than
+ * ->hash_pergroup */
+ ProjectionInfo *combinedproj; /* projection machinery */
+ SharedAggInfo *shared_info; /* one entry per worker */
+} AggState;
+
+/* ----------------
+ * WindowAggState information
+ * ----------------
+ */
+/* these structs are private in nodeWindowAgg.c: */
+typedef struct WindowStatePerFuncData *WindowStatePerFunc;
+typedef struct WindowStatePerAggData *WindowStatePerAgg;
+
+/*
+ * WindowAggStatus -- Used to track the status of WindowAggState
+ */
+typedef enum WindowAggStatus
+{
+ WINDOWAGG_DONE, /* No more processing to do */
+ WINDOWAGG_RUN, /* Normal processing of window funcs */
+ WINDOWAGG_PASSTHROUGH, /* Don't eval window funcs */
+ WINDOWAGG_PASSTHROUGH_STRICT /* Pass-through plus don't store new
+ * tuples during spool */
+} WindowAggStatus;
+
+typedef struct WindowAggState
+{
+ ScanState ss; /* its first field is NodeTag */
+
+ /* these fields are filled in by ExecInitExpr: */
+ List *funcs; /* all WindowFunc nodes in targetlist */
+ int numfuncs; /* total number of window functions */
+ int numaggs; /* number that are plain aggregates */
+
+ WindowStatePerFunc perfunc; /* per-window-function information */
+ WindowStatePerAgg peragg; /* per-plain-aggregate information */
+ ExprState *partEqfunction; /* equality funcs for partition columns */
+ ExprState *ordEqfunction; /* equality funcs for ordering columns */
+ Tuplestorestate *buffer; /* stores rows of current partition */
+ int current_ptr; /* read pointer # for current row */
+ int framehead_ptr; /* read pointer # for frame head, if used */
+ int frametail_ptr; /* read pointer # for frame tail, if used */
+ int grouptail_ptr; /* read pointer # for group tail, if used */
+ int64 spooled_rows; /* total # of rows in buffer */
+ int64 currentpos; /* position of current row in partition */
+ int64 frameheadpos; /* current frame head position */
+ int64 frametailpos; /* current frame tail position (frame end+1) */
+ /* use struct pointer to avoid including windowapi.h here */
+ struct WindowObjectData *agg_winobj; /* winobj for aggregate fetches */
+ int64 aggregatedbase; /* start row for current aggregates */
+ int64 aggregatedupto; /* rows before this one are aggregated */
+ WindowAggStatus status; /* run status of WindowAggState */
+
+ int frameOptions; /* frame_clause options, see WindowDef */
+ ExprState *startOffset; /* expression for starting bound offset */
+ ExprState *endOffset; /* expression for ending bound offset */
+ Datum startOffsetValue; /* result of startOffset evaluation */
+ Datum endOffsetValue; /* result of endOffset evaluation */
+
+ /* these fields are used with RANGE offset PRECEDING/FOLLOWING: */
+ FmgrInfo startInRangeFunc; /* in_range function for startOffset */
+ FmgrInfo endInRangeFunc; /* in_range function for endOffset */
+ Oid inRangeColl; /* collation for in_range tests */
+ bool inRangeAsc; /* use ASC sort order for in_range tests? */
+ bool inRangeNullsFirst; /* nulls sort first for in_range tests? */
+
+ /* these fields are used in GROUPS mode: */
+ int64 currentgroup; /* peer group # of current row in partition */
+ int64 frameheadgroup; /* peer group # of frame head row */
+ int64 frametailgroup; /* peer group # of frame tail row */
+ int64 groupheadpos; /* current row's peer group head position */
+ int64 grouptailpos; /* " " " " tail position (group end+1) */
+
+ MemoryContext partcontext; /* context for partition-lifespan data */
+ MemoryContext aggcontext; /* shared context for aggregate working data */
+ MemoryContext curaggcontext; /* current aggregate's working data */
+ ExprContext *tmpcontext; /* short-term evaluation context */
+
+ ExprState *runcondition; /* Condition which must remain true otherwise
+ * execution of the WindowAgg will finish or
+ * go into pass-through mode. NULL when there
+ * is no such condition. */
+
+ bool use_pass_through; /* When false, stop execution when
+ * runcondition is no longer true. Else
+ * just stop evaluating window funcs. */
+ bool top_window; /* true if this is the top-most WindowAgg or
+ * the only WindowAgg in this query level */
+ bool all_first; /* true if the scan is starting */
+ bool partition_spooled; /* true if all tuples in current partition
+ * have been spooled into tuplestore */
+ bool more_partitions; /* true if there's more partitions after
+ * this one */
+ bool framehead_valid; /* true if frameheadpos is known up to
+ * date for current row */
+ bool frametail_valid; /* true if frametailpos is known up to
+ * date for current row */
+ bool grouptail_valid; /* true if grouptailpos is known up to
+ * date for current row */
+
+ TupleTableSlot *first_part_slot; /* first tuple of current or next
+ * partition */
+ TupleTableSlot *framehead_slot; /* first tuple of current frame */
+ TupleTableSlot *frametail_slot; /* first tuple after current frame */
+
+ /* temporary slots for tuples fetched back from tuplestore */
+ TupleTableSlot *agg_row_slot;
+ TupleTableSlot *temp_slot_1;
+ TupleTableSlot *temp_slot_2;
+} WindowAggState;
+
+/* ----------------
+ * UniqueState information
+ *
+ * Unique nodes are used "on top of" sort nodes to discard
+ * duplicate tuples returned from the sort phase. Basically
+ * all it does is compare the current tuple from the subplan
+ * with the previously fetched tuple (stored in its result slot).
+ * If the two are identical in all interesting fields, then
+ * we just fetch another tuple from the sort and try again.
+ * ----------------
+ */
+typedef struct UniqueState
+{
+ PlanState ps; /* its first field is NodeTag */
+ ExprState *eqfunction; /* tuple equality qual */
+} UniqueState;
+
+/* ----------------
+ * GatherState information
+ *
+ * Gather nodes launch 1 or more parallel workers, run a subplan
+ * in those workers, and collect the results.
+ * ----------------
+ */
+typedef struct GatherState
+{
+ PlanState ps; /* its first field is NodeTag */
+ bool initialized; /* workers launched? */
+ bool need_to_scan_locally; /* need to read from local plan? */
+ int64 tuples_needed; /* tuple bound, see ExecSetTupleBound */
+ /* these fields are set up once: */
+ TupleTableSlot *funnel_slot;
+ struct ParallelExecutorInfo *pei;
+ /* all remaining fields are reinitialized during a rescan: */
+ int nworkers_launched; /* original number of workers */
+ int nreaders; /* number of still-active workers */
+ int nextreader; /* next one to try to read from */
+ struct TupleQueueReader **reader; /* array with nreaders active entries */
+} GatherState;
+
+/* ----------------
+ * GatherMergeState information
+ *
+ * Gather merge nodes launch 1 or more parallel workers, run a
+ * subplan which produces sorted output in each worker, and then
+ * merge the results into a single sorted stream.
+ * ----------------
+ */
+struct GMReaderTupleBuffer; /* private in nodeGatherMerge.c */
+
+typedef struct GatherMergeState
+{
+ PlanState ps; /* its first field is NodeTag */
+ bool initialized; /* workers launched? */
+ bool gm_initialized; /* gather_merge_init() done? */
+ bool need_to_scan_locally; /* need to read from local plan? */
+ int64 tuples_needed; /* tuple bound, see ExecSetTupleBound */
+ /* these fields are set up once: */
+ TupleDesc tupDesc; /* descriptor for subplan result tuples */
+ int gm_nkeys; /* number of sort columns */
+ SortSupport gm_sortkeys; /* array of length gm_nkeys */
+ struct ParallelExecutorInfo *pei;
+ /* all remaining fields are reinitialized during a rescan */
+ /* (but the arrays are not reallocated, just cleared) */
+ int nworkers_launched; /* original number of workers */
+ int nreaders; /* number of active workers */
+ TupleTableSlot **gm_slots; /* array with nreaders+1 entries */
+ struct TupleQueueReader **reader; /* array with nreaders active entries */
+ struct GMReaderTupleBuffer *gm_tuple_buffers; /* nreaders tuple buffers */
+ struct binaryheap *gm_heap; /* binary heap of slot indices */
+} GatherMergeState;
+
+/* ----------------
+ * Values displayed by EXPLAIN ANALYZE
+ * ----------------
+ */
+typedef struct HashInstrumentation
+{
+ int nbuckets; /* number of buckets at end of execution */
+ int nbuckets_original; /* planned number of buckets */
+ int nbatch; /* number of batches at end of execution */
+ int nbatch_original; /* planned number of batches */
+ Size space_peak; /* peak memory usage in bytes */
+} HashInstrumentation;
+
+/* ----------------
+ * Shared memory container for per-worker hash information
+ * ----------------
+ */
+typedef struct SharedHashInfo
+{
+ int num_workers;
+ HashInstrumentation hinstrument[FLEXIBLE_ARRAY_MEMBER];
+} SharedHashInfo;
+
+/* ----------------
+ * HashState information
+ * ----------------
+ */
+typedef struct HashState
+{
+ PlanState ps; /* its first field is NodeTag */
+ HashJoinTable hashtable; /* hash table for the hashjoin */
+ List *hashkeys; /* list of ExprState nodes */
+
+ /*
+ * In a parallelized hash join, the leader retains a pointer to the
+ * shared-memory stats area in its shared_info field, and then copies the
+ * shared-memory info back to local storage before DSM shutdown. The
+ * shared_info field remains NULL in workers, or in non-parallel joins.
+ */
+ SharedHashInfo *shared_info;
+
+ /*
+ * If we are collecting hash stats, this points to an initially-zeroed
+ * collection area, which could be either local storage or in shared
+ * memory; either way it's for just one process.
+ */
+ HashInstrumentation *hinstrument;
+
+ /* Parallel hash state. */
+ struct ParallelHashJoinState *parallel_state;
+} HashState;
+
+/* ----------------
+ * SetOpState information
+ *
+ * Even in "sorted" mode, SetOp nodes are more complex than a simple
+ * Unique, since we have to count how many duplicates to return. But
+ * we also support hashing, so this is really more like a cut-down
+ * form of Agg.
+ * ----------------
+ */
+/* this struct is private in nodeSetOp.c: */
+typedef struct SetOpStatePerGroupData *SetOpStatePerGroup;
+
+typedef struct SetOpState
+{
+ PlanState ps; /* its first field is NodeTag */
+ ExprState *eqfunction; /* equality comparator */
+ Oid *eqfuncoids; /* per-grouping-field equality fns */
+ FmgrInfo *hashfunctions; /* per-grouping-field hash fns */
+ bool setop_done; /* indicates completion of output scan */
+ long numOutput; /* number of dups left to output */
+ /* these fields are used in SETOP_SORTED mode: */
+ SetOpStatePerGroup pergroup; /* per-group working state */
+ HeapTuple grp_firstTuple; /* copy of first tuple of current group */
+ /* these fields are used in SETOP_HASHED mode: */
+ TupleHashTable hashtable; /* hash table with one entry per group */
+ MemoryContext tableContext; /* memory context containing hash table */
+ bool table_filled; /* hash table filled yet? */
+ TupleHashIterator hashiter; /* for iterating through hash table */
+} SetOpState;
+
+/* ----------------
+ * LockRowsState information
+ *
+ * LockRows nodes are used to enforce FOR [KEY] UPDATE/SHARE locking.
+ * ----------------
+ */
+typedef struct LockRowsState
+{
+ PlanState ps; /* its first field is NodeTag */
+ List *lr_arowMarks; /* List of ExecAuxRowMarks */
+ EPQState lr_epqstate; /* for evaluating EvalPlanQual rechecks */
+} LockRowsState;
+
+/* ----------------
+ * LimitState information
+ *
+ * Limit nodes are used to enforce LIMIT/OFFSET clauses.
+ * They just select the desired subrange of their subplan's output.
+ *
+ * offset is the number of initial tuples to skip (0 does nothing).
+ * count is the number of tuples to return after skipping the offset tuples.
+ * If no limit count was specified, count is undefined and noCount is true.
+ * When lstate == LIMIT_INITIAL, offset/count/noCount haven't been set yet.
+ * ----------------
+ */
+typedef enum
+{
+ LIMIT_INITIAL, /* initial state for LIMIT node */
+ LIMIT_RESCAN, /* rescan after recomputing parameters */
+ LIMIT_EMPTY, /* there are no returnable rows */
+ LIMIT_INWINDOW, /* have returned a row in the window */
+ LIMIT_WINDOWEND_TIES, /* have returned a tied row */
+ LIMIT_SUBPLANEOF, /* at EOF of subplan (within window) */
+ LIMIT_WINDOWEND, /* stepped off end of window */
+ LIMIT_WINDOWSTART /* stepped off beginning of window */
+} LimitStateCond;
+
+typedef struct LimitState
+{
+ PlanState ps; /* its first field is NodeTag */
+ ExprState *limitOffset; /* OFFSET parameter, or NULL if none */
+ ExprState *limitCount; /* COUNT parameter, or NULL if none */
+ LimitOption limitOption; /* limit specification type */
+ int64 offset; /* current OFFSET value */
+ int64 count; /* current COUNT, if any */
+ bool noCount; /* if true, ignore count */
+ LimitStateCond lstate; /* state machine status, as above */
+ int64 position; /* 1-based index of last tuple returned */
+ TupleTableSlot *subSlot; /* tuple last obtained from subplan */
+ ExprState *eqfunction; /* tuple equality qual in case of WITH TIES
+ * option */
+ TupleTableSlot *last_slot; /* slot for evaluation of ties */
+} LimitState;
+
+#endif /* EXECNODES_H */
diff --git a/src/include/nodes/extensible.h b/src/include/nodes/extensible.h
new file mode 100644
index 0000000..7d51c60
--- /dev/null
+++ b/src/include/nodes/extensible.h
@@ -0,0 +1,164 @@
+/*-------------------------------------------------------------------------
+ *
+ * extensible.h
+ * Definitions for extensible nodes and custom scans
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/nodes/extensible.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef EXTENSIBLE_H
+#define EXTENSIBLE_H
+
+#include "access/parallel.h"
+#include "commands/explain.h"
+#include "nodes/execnodes.h"
+#include "nodes/pathnodes.h"
+#include "nodes/plannodes.h"
+
+/* maximum length of an extensible node identifier */
+#define EXTNODENAME_MAX_LEN 64
+
+/*
+ * An extensible node is a new type of node defined by an extension. The
+ * type is always T_ExtensibleNode, while the extnodename identifies the
+ * specific type of node. extnodename can be looked up to find the
+ * ExtensibleNodeMethods for this node type.
+ */
+typedef struct ExtensibleNode
+{
+ pg_node_attr(custom_copy_equal, custom_read_write)
+
+ NodeTag type;
+ const char *extnodename; /* identifier of ExtensibleNodeMethods */
+} ExtensibleNode;
+
+/*
+ * node_size is the size of an extensible node of this type in bytes.
+ *
+ * nodeCopy is a function which performs a deep copy from oldnode to newnode.
+ * It does not need to copy type or extnodename, which are copied by the
+ * core system.
+ *
+ * nodeEqual is a function which performs a deep equality comparison between
+ * a and b and returns true or false accordingly. It does not need to compare
+ * type or extnodename, which are compared by the core system.
+ *
+ * nodeOut is a serialization function for the node type. It should use the
+ * output conventions typical for outfuncs.c. It does not need to output
+ * type or extnodename; the core system handles those.
+ *
+ * nodeRead is a deserialization function for the node type. It does not need
+ * to read type or extnodename; the core system handles those. It should fetch
+ * the next token using pg_strtok() from the current input stream, and then
+ * reconstruct the private fields according to the manner in readfuncs.c.
+ *
+ * All callbacks are mandatory.
+ */
+typedef struct ExtensibleNodeMethods
+{
+ const char *extnodename;
+ Size node_size;
+ void (*nodeCopy) (struct ExtensibleNode *newnode,
+ const struct ExtensibleNode *oldnode);
+ bool (*nodeEqual) (const struct ExtensibleNode *a,
+ const struct ExtensibleNode *b);
+ void (*nodeOut) (struct StringInfoData *str,
+ const struct ExtensibleNode *node);
+ void (*nodeRead) (struct ExtensibleNode *node);
+} ExtensibleNodeMethods;
+
+extern void RegisterExtensibleNodeMethods(const ExtensibleNodeMethods *methods);
+extern const ExtensibleNodeMethods *GetExtensibleNodeMethods(const char *extnodename,
+ bool missing_ok);
+
+/*
+ * Flags for custom paths, indicating what capabilities the resulting scan
+ * will have. The flags fields of CustomPath and CustomScan nodes are
+ * bitmasks of these flags.
+ */
+#define CUSTOMPATH_SUPPORT_BACKWARD_SCAN 0x0001
+#define CUSTOMPATH_SUPPORT_MARK_RESTORE 0x0002
+#define CUSTOMPATH_SUPPORT_PROJECTION 0x0004
+
+/*
+ * Custom path methods. Mostly, we just need to know how to convert a
+ * CustomPath to a plan.
+ */
+typedef struct CustomPathMethods
+{
+ const char *CustomName;
+
+ /* Convert Path to a Plan */
+ struct Plan *(*PlanCustomPath) (PlannerInfo *root,
+ RelOptInfo *rel,
+ struct CustomPath *best_path,
+ List *tlist,
+ List *clauses,
+ List *custom_plans);
+ struct List *(*ReparameterizeCustomPathByChild) (PlannerInfo *root,
+ List *custom_private,
+ RelOptInfo *child_rel);
+} CustomPathMethods;
+
+/*
+ * Custom scan. Here again, there's not much to do: we need to be able to
+ * generate a ScanState corresponding to the scan.
+ */
+typedef struct CustomScanMethods
+{
+ const char *CustomName;
+
+ /* Create execution state (CustomScanState) from a CustomScan plan node */
+ Node *(*CreateCustomScanState) (CustomScan *cscan);
+} CustomScanMethods;
+
+/*
+ * Execution-time methods for a CustomScanState. This is more complex than
+ * what we need for a custom path or scan.
+ */
+typedef struct CustomExecMethods
+{
+ const char *CustomName;
+
+ /* Required executor methods */
+ void (*BeginCustomScan) (CustomScanState *node,
+ EState *estate,
+ int eflags);
+ TupleTableSlot *(*ExecCustomScan) (CustomScanState *node);
+ void (*EndCustomScan) (CustomScanState *node);
+ void (*ReScanCustomScan) (CustomScanState *node);
+
+ /* Optional methods: needed if mark/restore is supported */
+ void (*MarkPosCustomScan) (CustomScanState *node);
+ void (*RestrPosCustomScan) (CustomScanState *node);
+
+ /* Optional methods: needed if parallel execution is supported */
+ Size (*EstimateDSMCustomScan) (CustomScanState *node,
+ ParallelContext *pcxt);
+ void (*InitializeDSMCustomScan) (CustomScanState *node,
+ ParallelContext *pcxt,
+ void *coordinate);
+ void (*ReInitializeDSMCustomScan) (CustomScanState *node,
+ ParallelContext *pcxt,
+ void *coordinate);
+ void (*InitializeWorkerCustomScan) (CustomScanState *node,
+ shm_toc *toc,
+ void *coordinate);
+ void (*ShutdownCustomScan) (CustomScanState *node);
+
+ /* Optional: print additional information in EXPLAIN */
+ void (*ExplainCustomScan) (CustomScanState *node,
+ List *ancestors,
+ ExplainState *es);
+} CustomExecMethods;
+
+extern void RegisterCustomScanMethods(const CustomScanMethods *methods);
+extern const CustomScanMethods *GetCustomScanMethods(const char *CustomName,
+ bool missing_ok);
+
+#endif /* EXTENSIBLE_H */
diff --git a/src/include/nodes/lockoptions.h b/src/include/nodes/lockoptions.h
new file mode 100644
index 0000000..bc5e983
--- /dev/null
+++ b/src/include/nodes/lockoptions.h
@@ -0,0 +1,61 @@
+/*-------------------------------------------------------------------------
+ *
+ * lockoptions.h
+ * Common header for some locking-related declarations.
+ *
+ *
+ * Copyright (c) 2014-2023, PostgreSQL Global Development Group
+ *
+ * src/include/nodes/lockoptions.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef LOCKOPTIONS_H
+#define LOCKOPTIONS_H
+
+/*
+ * This enum represents the different strengths of FOR UPDATE/SHARE clauses.
+ * The ordering here is important, because the highest numerical value takes
+ * precedence when a RTE is specified multiple ways. See applyLockingClause.
+ */
+typedef enum LockClauseStrength
+{
+ LCS_NONE, /* no such clause - only used in PlanRowMark */
+ LCS_FORKEYSHARE, /* FOR KEY SHARE */
+ LCS_FORSHARE, /* FOR SHARE */
+ LCS_FORNOKEYUPDATE, /* FOR NO KEY UPDATE */
+ LCS_FORUPDATE /* FOR UPDATE */
+} LockClauseStrength;
+
+/*
+ * This enum controls how to deal with rows being locked by FOR UPDATE/SHARE
+ * clauses (i.e., it represents the NOWAIT and SKIP LOCKED options).
+ * The ordering here is important, because the highest numerical value takes
+ * precedence when a RTE is specified multiple ways. See applyLockingClause.
+ */
+typedef enum LockWaitPolicy
+{
+ /* Wait for the lock to become available (default behavior) */
+ LockWaitBlock,
+ /* Skip rows that can't be locked (SKIP LOCKED) */
+ LockWaitSkip,
+ /* Raise an error if a row cannot be locked (NOWAIT) */
+ LockWaitError
+} LockWaitPolicy;
+
+/*
+ * Possible lock modes for a tuple.
+ */
+typedef enum LockTupleMode
+{
+ /* SELECT FOR KEY SHARE */
+ LockTupleKeyShare,
+ /* SELECT FOR SHARE */
+ LockTupleShare,
+ /* SELECT FOR NO KEY UPDATE, and UPDATEs that don't modify key columns */
+ LockTupleNoKeyExclusive,
+ /* SELECT FOR UPDATE, UPDATEs that modify key columns, and DELETE */
+ LockTupleExclusive
+} LockTupleMode;
+
+#endif /* LOCKOPTIONS_H */
diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h
new file mode 100644
index 0000000..3180703
--- /dev/null
+++ b/src/include/nodes/makefuncs.h
@@ -0,0 +1,121 @@
+/*-------------------------------------------------------------------------
+ *
+ * makefuncs.h
+ * prototypes for the creator functions of various nodes
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/nodes/makefuncs.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef MAKEFUNC_H
+#define MAKEFUNC_H
+
+#include "nodes/execnodes.h"
+#include "nodes/parsenodes.h"
+
+
+extern A_Expr *makeA_Expr(A_Expr_Kind kind, List *name,
+ Node *lexpr, Node *rexpr, int location);
+
+extern A_Expr *makeSimpleA_Expr(A_Expr_Kind kind, char *name,
+ Node *lexpr, Node *rexpr, int location);
+
+extern Var *makeVar(int varno,
+ AttrNumber varattno,
+ Oid vartype,
+ int32 vartypmod,
+ Oid varcollid,
+ Index varlevelsup);
+
+extern Var *makeVarFromTargetEntry(int varno,
+ TargetEntry *tle);
+
+extern Var *makeWholeRowVar(RangeTblEntry *rte,
+ int varno,
+ Index varlevelsup,
+ bool allowScalar);
+
+extern TargetEntry *makeTargetEntry(Expr *expr,
+ AttrNumber resno,
+ char *resname,
+ bool resjunk);
+
+extern TargetEntry *flatCopyTargetEntry(TargetEntry *src_tle);
+
+extern FromExpr *makeFromExpr(List *fromlist, Node *quals);
+
+extern Const *makeConst(Oid consttype,
+ int32 consttypmod,
+ Oid constcollid,
+ int constlen,
+ Datum constvalue,
+ bool constisnull,
+ bool constbyval);
+
+extern Const *makeNullConst(Oid consttype, int32 consttypmod, Oid constcollid);
+
+extern Node *makeBoolConst(bool value, bool isnull);
+
+extern Expr *makeBoolExpr(BoolExprType boolop, List *args, int location);
+
+extern Alias *makeAlias(const char *aliasname, List *colnames);
+
+extern RelabelType *makeRelabelType(Expr *arg, Oid rtype, int32 rtypmod,
+ Oid rcollid, CoercionForm rformat);
+
+extern RangeVar *makeRangeVar(char *schemaname, char *relname, int location);
+
+extern TypeName *makeTypeName(char *typnam);
+extern TypeName *makeTypeNameFromNameList(List *names);
+extern TypeName *makeTypeNameFromOid(Oid typeOid, int32 typmod);
+
+extern ColumnDef *makeColumnDef(const char *colname,
+ Oid typeOid, int32 typmod, Oid collOid);
+
+extern FuncExpr *makeFuncExpr(Oid funcid, Oid rettype, List *args,
+ Oid funccollid, Oid inputcollid, CoercionForm fformat);
+
+extern FuncCall *makeFuncCall(List *name, List *args,
+ CoercionForm funcformat, int location);
+
+extern Expr *make_opclause(Oid opno, Oid opresulttype, bool opretset,
+ Expr *leftop, Expr *rightop,
+ Oid opcollid, Oid inputcollid);
+
+extern Expr *make_andclause(List *andclauses);
+extern Expr *make_orclause(List *orclauses);
+extern Expr *make_notclause(Expr *notclause);
+
+extern Node *make_and_qual(Node *qual1, Node *qual2);
+extern Expr *make_ands_explicit(List *andclauses);
+extern List *make_ands_implicit(Expr *clause);
+
+extern IndexInfo *makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid,
+ List *expressions, List *predicates,
+ bool unique, bool nulls_not_distinct,
+ bool isready, bool concurrent,
+ bool summarizing);
+
+extern DefElem *makeDefElem(char *name, Node *arg, int location);
+extern DefElem *makeDefElemExtended(char *nameSpace, char *name, Node *arg,
+ DefElemAction defaction, int location);
+
+extern GroupingSet *makeGroupingSet(GroupingSetKind kind, List *content, int location);
+
+extern VacuumRelation *makeVacuumRelation(RangeVar *relation, Oid oid, List *va_cols);
+
+extern JsonFormat *makeJsonFormat(JsonFormatType type, JsonEncoding encoding,
+ int location);
+extern JsonValueExpr *makeJsonValueExpr(Expr *raw_expr, Expr *formatted_expr,
+ JsonFormat *format);
+extern Node *makeJsonKeyValue(Node *key, Node *value);
+extern Node *makeJsonIsPredicate(Node *expr, JsonFormat *format,
+ JsonValueType item_type, bool unique_keys,
+ int location);
+extern JsonEncoding makeJsonEncoding(char *name);
+
+#endif /* MAKEFUNC_H */
diff --git a/src/include/nodes/memnodes.h b/src/include/nodes/memnodes.h
new file mode 100644
index 0000000..ff6453b
--- /dev/null
+++ b/src/include/nodes/memnodes.h
@@ -0,0 +1,113 @@
+/*-------------------------------------------------------------------------
+ *
+ * memnodes.h
+ * POSTGRES memory context node definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/nodes/memnodes.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef MEMNODES_H
+#define MEMNODES_H
+
+#include "nodes/nodes.h"
+
+/*
+ * MemoryContextCounters
+ * Summarization state for MemoryContextStats collection.
+ *
+ * The set of counters in this struct is biased towards AllocSet; if we ever
+ * add any context types that are based on fundamentally different approaches,
+ * we might need more or different counters here. A possible API spec then
+ * would be to print only nonzero counters, but for now we just summarize in
+ * the format historically used by AllocSet.
+ */
+typedef struct MemoryContextCounters
+{
+ Size nblocks; /* Total number of malloc blocks */
+ Size freechunks; /* Total number of free chunks */
+ Size totalspace; /* Total bytes requested from malloc */
+ Size freespace; /* The unused portion of totalspace */
+} MemoryContextCounters;
+
+/*
+ * MemoryContext
+ * A logical context in which memory allocations occur.
+ *
+ * MemoryContext itself is an abstract type that can have multiple
+ * implementations.
+ * The function pointers in MemoryContextMethods define one specific
+ * implementation of MemoryContext --- they are a virtual function table
+ * in C++ terms.
+ *
+ * Node types that are actual implementations of memory contexts must
+ * begin with the same fields as MemoryContextData.
+ *
+ * Note: for largely historical reasons, typedef MemoryContext is a pointer
+ * to the context struct rather than the struct type itself.
+ */
+
+typedef void (*MemoryStatsPrintFunc) (MemoryContext context, void *passthru,
+ const char *stats_string,
+ bool print_to_stderr);
+
+typedef struct MemoryContextMethods
+{
+ void *(*alloc) (MemoryContext context, Size size);
+ /* call this free_p in case someone #define's free() */
+ void (*free_p) (void *pointer);
+ void *(*realloc) (void *pointer, Size size);
+ void (*reset) (MemoryContext context);
+ void (*delete_context) (MemoryContext context);
+ MemoryContext (*get_chunk_context) (void *pointer);
+ Size (*get_chunk_space) (void *pointer);
+ bool (*is_empty) (MemoryContext context);
+ void (*stats) (MemoryContext context,
+ MemoryStatsPrintFunc printfunc, void *passthru,
+ MemoryContextCounters *totals,
+ bool print_to_stderr);
+#ifdef MEMORY_CONTEXT_CHECKING
+ void (*check) (MemoryContext context);
+#endif
+} MemoryContextMethods;
+
+
+typedef struct MemoryContextData
+{
+ pg_node_attr(abstract) /* there are no nodes of this type */
+
+ NodeTag type; /* identifies exact kind of context */
+ /* these two fields are placed here to minimize alignment wastage: */
+ bool isReset; /* T = no space alloced since last reset */
+ bool allowInCritSection; /* allow palloc in critical section */
+ Size mem_allocated; /* track memory allocated for this context */
+ const MemoryContextMethods *methods; /* virtual function table */
+ MemoryContext parent; /* NULL if no parent (toplevel context) */
+ MemoryContext firstchild; /* head of linked list of children */
+ MemoryContext prevchild; /* previous child of same parent */
+ MemoryContext nextchild; /* next child of same parent */
+ const char *name; /* context name (just for debugging) */
+ const char *ident; /* context ID if any (just for debugging) */
+ MemoryContextCallback *reset_cbs; /* list of reset/delete callbacks */
+} MemoryContextData;
+
+/* utils/palloc.h contains typedef struct MemoryContextData *MemoryContext */
+
+
+/*
+ * MemoryContextIsValid
+ * True iff memory context is valid.
+ *
+ * Add new context types to the set accepted by this macro.
+ */
+#define MemoryContextIsValid(context) \
+ ((context) != NULL && \
+ (IsA((context), AllocSetContext) || \
+ IsA((context), SlabContext) || \
+ IsA((context), GenerationContext)))
+
+#endif /* MEMNODES_H */
diff --git a/src/include/nodes/meson.build b/src/include/nodes/meson.build
new file mode 100644
index 0000000..626dc69
--- /dev/null
+++ b/src/include/nodes/meson.build
@@ -0,0 +1,65 @@
+# Copyright (c) 2022-2023, PostgreSQL Global Development Group
+
+node_support_input_i = [
+ 'nodes/nodes.h',
+ 'nodes/primnodes.h',
+ 'nodes/parsenodes.h',
+ 'nodes/pathnodes.h',
+ 'nodes/plannodes.h',
+ 'nodes/execnodes.h',
+ 'access/amapi.h',
+ 'access/sdir.h',
+ 'access/tableam.h',
+ 'access/tsmapi.h',
+ 'commands/event_trigger.h',
+ 'commands/trigger.h',
+ 'executor/tuptable.h',
+ 'foreign/fdwapi.h',
+ 'nodes/bitmapset.h',
+ 'nodes/extensible.h',
+ 'nodes/lockoptions.h',
+ 'nodes/miscnodes.h',
+ 'nodes/replnodes.h',
+ 'nodes/supportnodes.h',
+ 'nodes/value.h',
+ 'utils/rel.h',
+]
+
+node_support_input = []
+foreach i : node_support_input_i
+ node_support_input += meson.source_root() / 'src' / 'include' / i
+endforeach
+
+node_support_output = [
+ 'nodetags.h',
+ 'outfuncs.funcs.c', 'outfuncs.switch.c',
+ 'readfuncs.funcs.c', 'readfuncs.switch.c',
+ 'copyfuncs.funcs.c', 'copyfuncs.switch.c',
+ 'equalfuncs.funcs.c', 'equalfuncs.switch.c',
+ 'queryjumblefuncs.funcs.c', 'queryjumblefuncs.switch.c',
+]
+node_support_install = [
+ dir_include_server / 'nodes',
+ false, false,
+ false, false,
+ false, false,
+ false, false,
+ false, false,
+]
+
+generated_nodes = custom_target('nodetags.h',
+ input: node_support_input,
+ output: node_support_output,
+ depend_files: catalog_pm,
+ command: [
+ perl, files('../../backend/nodes/gen_node_support.pl'),
+ '-o', '@OUTDIR@',
+ '@INPUT@'],
+ install: true,
+ install_dir: node_support_install,
+)
+generated_headers += generated_nodes[0]
+
+# autoconf generates the file there, ensure we get a conflict
+generated_sources_ac += {'src/backend/nodes': node_support_output + ['node-support-stamp']}
+generated_sources_ac += {'src/include/nodes': ['header-stamp']}
diff --git a/src/include/nodes/miscnodes.h b/src/include/nodes/miscnodes.h
new file mode 100644
index 0000000..79cc0db
--- /dev/null
+++ b/src/include/nodes/miscnodes.h
@@ -0,0 +1,56 @@
+/*-------------------------------------------------------------------------
+ *
+ * miscnodes.h
+ * Definitions for hard-to-classify node types.
+ *
+ * Node types declared here are not part of parse trees, plan trees,
+ * or execution state trees. We only assign them NodeTag values because
+ * IsA() tests provide a convenient way to disambiguate what kind of
+ * structure is being passed through assorted APIs, such as function
+ * "context" pointers.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/nodes/miscnodes.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef MISCNODES_H
+#define MISCNODES_H
+
+#include "nodes/nodes.h"
+
+/*
+ * ErrorSaveContext -
+ * function call context node for handling of "soft" errors
+ *
+ * A caller wishing to trap soft errors must initialize a struct like this
+ * with all fields zero/NULL except for the NodeTag. Optionally, set
+ * details_wanted = true if more than the bare knowledge that a soft error
+ * occurred is required. The struct is then passed to a SQL-callable function
+ * via the FunctionCallInfo.context field; or below the level of SQL calls,
+ * it could be passed to a subroutine directly.
+ *
+ * After calling code that might report an error this way, check
+ * error_occurred to see if an error happened. If so, and if details_wanted
+ * is true, error_data has been filled with error details (stored in the
+ * callee's memory context!). FreeErrorData() can be called to release
+ * error_data, although that step is typically not necessary if the called
+ * code was run in a short-lived context.
+ */
+typedef struct ErrorSaveContext
+{
+ NodeTag type;
+ bool error_occurred; /* set to true if we detect a soft error */
+ bool details_wanted; /* does caller want more info than that? */
+ ErrorData *error_data; /* details of error, if so */
+} ErrorSaveContext;
+
+/* Often-useful macro for checking if a soft error was reported */
+#define SOFT_ERROR_OCCURRED(escontext) \
+ ((escontext) != NULL && IsA(escontext, ErrorSaveContext) && \
+ ((ErrorSaveContext *) (escontext))->error_occurred)
+
+#endif /* MISCNODES_H */
diff --git a/src/include/nodes/multibitmapset.h b/src/include/nodes/multibitmapset.h
new file mode 100644
index 0000000..505f017
--- /dev/null
+++ b/src/include/nodes/multibitmapset.h
@@ -0,0 +1,39 @@
+/*-------------------------------------------------------------------------
+ *
+ * multibitmapset.h
+ * Lists of Bitmapsets
+ *
+ * A multibitmapset is useful in situations where members of a set can
+ * be identified by two small integers; for example, varno and varattno
+ * of a group of Vars within a query. The implementation is a List of
+ * Bitmapsets, so that the empty set can be represented by NIL. (But,
+ * as with Bitmapsets, that's not the only allowed representation.)
+ * The zero-based index of a List element is the first identifying value,
+ * and the (also zero-based) index of a bit within that Bitmapset is
+ * the second identifying value. There is no expectation that the
+ * Bitmapsets should all be the same size.
+ *
+ * The available operations on multibitmapsets are intended to parallel
+ * those on bitmapsets, for example union and intersection. So far only
+ * a small fraction of that has been built out; we'll add more as needed.
+ *
+ *
+ * Copyright (c) 2022-2023, PostgreSQL Global Development Group
+ *
+ * src/include/nodes/multibitmapset.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef MULTIBITMAPSET_H
+#define MULTIBITMAPSET_H
+
+#include "nodes/bitmapset.h"
+#include "nodes/pg_list.h"
+
+extern List *mbms_add_member(List *a, int listidx, int bitidx);
+extern List *mbms_add_members(List *a, const List *b);
+extern List *mbms_int_members(List *a, const List *b);
+extern bool mbms_is_member(int listidx, int bitidx, const List *a);
+extern Bitmapset *mbms_overlap_sets(const List *a, const List *b);
+
+#endif /* MULTIBITMAPSET_H */
diff --git a/src/include/nodes/nodeFuncs.h b/src/include/nodes/nodeFuncs.h
new file mode 100644
index 0000000..20921b4
--- /dev/null
+++ b/src/include/nodes/nodeFuncs.h
@@ -0,0 +1,222 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeFuncs.h
+ * Various general-purpose manipulations of Node trees
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/nodes/nodeFuncs.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEFUNCS_H
+#define NODEFUNCS_H
+
+#include "nodes/parsenodes.h"
+
+struct PlanState; /* avoid including execnodes.h too */
+
+
+/* flags bits for query_tree_walker and query_tree_mutator */
+#define QTW_IGNORE_RT_SUBQUERIES 0x01 /* subqueries in rtable */
+#define QTW_IGNORE_CTE_SUBQUERIES 0x02 /* subqueries in cteList */
+#define QTW_IGNORE_RC_SUBQUERIES 0x03 /* both of above */
+#define QTW_IGNORE_JOINALIASES 0x04 /* JOIN alias var lists */
+#define QTW_IGNORE_RANGE_TABLE 0x08 /* skip rangetable entirely */
+#define QTW_EXAMINE_RTES_BEFORE 0x10 /* examine RTE nodes before their
+ * contents */
+#define QTW_EXAMINE_RTES_AFTER 0x20 /* examine RTE nodes after their
+ * contents */
+#define QTW_DONT_COPY_QUERY 0x40 /* do not copy top Query */
+#define QTW_EXAMINE_SORTGROUP 0x80 /* include SortGroupClause lists */
+
+/* callback function for check_functions_in_node */
+typedef bool (*check_function_callback) (Oid func_id, void *context);
+
+/* callback functions for tree walkers */
+typedef bool (*tree_walker_callback) (Node *node, void *context);
+typedef bool (*planstate_tree_walker_callback) (struct PlanState *planstate,
+ void *context);
+
+/* callback functions for tree mutators */
+typedef Node *(*tree_mutator_callback) (Node *node, void *context);
+
+
+extern Oid exprType(const Node *expr);
+extern int32 exprTypmod(const Node *expr);
+extern bool exprIsLengthCoercion(const Node *expr, int32 *coercedTypmod);
+extern Node *applyRelabelType(Node *arg, Oid rtype, int32 rtypmod, Oid rcollid,
+ CoercionForm rformat, int rlocation,
+ bool overwrite_ok);
+extern Node *relabel_to_typmod(Node *expr, int32 typmod);
+extern Node *strip_implicit_coercions(Node *node);
+extern bool expression_returns_set(Node *clause);
+
+extern Oid exprCollation(const Node *expr);
+extern Oid exprInputCollation(const Node *expr);
+extern void exprSetCollation(Node *expr, Oid collation);
+extern void exprSetInputCollation(Node *expr, Oid inputcollation);
+
+extern int exprLocation(const Node *expr);
+
+extern void fix_opfuncids(Node *node);
+extern void set_opfuncid(OpExpr *opexpr);
+extern void set_sa_opfuncid(ScalarArrayOpExpr *opexpr);
+
+/* Is clause a FuncExpr clause? */
+static inline bool
+is_funcclause(const void *clause)
+{
+ return clause != NULL && IsA(clause, FuncExpr);
+}
+
+/* Is clause an OpExpr clause? */
+static inline bool
+is_opclause(const void *clause)
+{
+ return clause != NULL && IsA(clause, OpExpr);
+}
+
+/* Extract left arg of a binary opclause, or only arg of a unary opclause */
+static inline Node *
+get_leftop(const void *clause)
+{
+ const OpExpr *expr = (const OpExpr *) clause;
+
+ if (expr->args != NIL)
+ return (Node *) linitial(expr->args);
+ else
+ return NULL;
+}
+
+/* Extract right arg of a binary opclause (NULL if it's a unary opclause) */
+static inline Node *
+get_rightop(const void *clause)
+{
+ const OpExpr *expr = (const OpExpr *) clause;
+
+ if (list_length(expr->args) >= 2)
+ return (Node *) lsecond(expr->args);
+ else
+ return NULL;
+}
+
+/* Is clause an AND clause? */
+static inline bool
+is_andclause(const void *clause)
+{
+ return (clause != NULL &&
+ IsA(clause, BoolExpr) &&
+ ((const BoolExpr *) clause)->boolop == AND_EXPR);
+}
+
+/* Is clause an OR clause? */
+static inline bool
+is_orclause(const void *clause)
+{
+ return (clause != NULL &&
+ IsA(clause, BoolExpr) &&
+ ((const BoolExpr *) clause)->boolop == OR_EXPR);
+}
+
+/* Is clause a NOT clause? */
+static inline bool
+is_notclause(const void *clause)
+{
+ return (clause != NULL &&
+ IsA(clause, BoolExpr) &&
+ ((const BoolExpr *) clause)->boolop == NOT_EXPR);
+}
+
+/* Extract argument from a clause known to be a NOT clause */
+static inline Expr *
+get_notclausearg(const void *notclause)
+{
+ return (Expr *) linitial(((const BoolExpr *) notclause)->args);
+}
+
+extern bool check_functions_in_node(Node *node, check_function_callback checker,
+ void *context);
+
+/*
+ * The following functions are usually passed walker or mutator callbacks
+ * that are declared like "bool walker(Node *node, my_struct *context)"
+ * rather than "bool walker(Node *node, void *context)" as a strict reading
+ * of the C standard would require. Changing the callbacks' declarations
+ * to "void *" would create serious hazards of passing them the wrong context
+ * struct type, so we respectfully decline to support the standard's position
+ * that a pointer to struct is incompatible with "void *". Instead, silence
+ * related compiler warnings by inserting casts into these macro wrappers.
+ */
+
+#define expression_tree_walker(n, w, c) \
+ expression_tree_walker_impl(n, (tree_walker_callback) (w), c)
+#define expression_tree_mutator(n, m, c) \
+ expression_tree_mutator_impl(n, (tree_mutator_callback) (m), c)
+
+#define query_tree_walker(q, w, c, f) \
+ query_tree_walker_impl(q, (tree_walker_callback) (w), c, f)
+#define query_tree_mutator(q, m, c, f) \
+ query_tree_mutator_impl(q, (tree_mutator_callback) (m), c, f)
+
+#define range_table_walker(rt, w, c, f) \
+ range_table_walker_impl(rt, (tree_walker_callback) (w), c, f)
+#define range_table_mutator(rt, m, c, f) \
+ range_table_mutator_impl(rt, (tree_mutator_callback) (m), c, f)
+
+#define range_table_entry_walker(r, w, c, f) \
+ range_table_entry_walker_impl(r, (tree_walker_callback) (w), c, f)
+
+#define query_or_expression_tree_walker(n, w, c, f) \
+ query_or_expression_tree_walker_impl(n, (tree_walker_callback) (w), c, f)
+#define query_or_expression_tree_mutator(n, m, c, f) \
+ query_or_expression_tree_mutator_impl(n, (tree_mutator_callback) (m), c, f)
+
+#define raw_expression_tree_walker(n, w, c) \
+ raw_expression_tree_walker_impl(n, (tree_walker_callback) (w), c)
+
+#define planstate_tree_walker(ps, w, c) \
+ planstate_tree_walker_impl(ps, (planstate_tree_walker_callback) (w), c)
+
+extern bool expression_tree_walker_impl(Node *node,
+ tree_walker_callback walker,
+ void *context);
+extern Node *expression_tree_mutator_impl(Node *node,
+ tree_mutator_callback mutator,
+ void *context);
+
+extern bool query_tree_walker_impl(Query *query,
+ tree_walker_callback walker,
+ void *context, int flags);
+extern Query *query_tree_mutator_impl(Query *query,
+ tree_mutator_callback mutator,
+ void *context, int flags);
+
+extern bool range_table_walker_impl(List *rtable,
+ tree_walker_callback walker,
+ void *context, int flags);
+extern List *range_table_mutator_impl(List *rtable,
+ tree_mutator_callback mutator,
+ void *context, int flags);
+
+extern bool range_table_entry_walker_impl(RangeTblEntry *rte,
+ tree_walker_callback walker,
+ void *context, int flags);
+
+extern bool query_or_expression_tree_walker_impl(Node *node,
+ tree_walker_callback walker,
+ void *context, int flags);
+extern Node *query_or_expression_tree_mutator_impl(Node *node,
+ tree_mutator_callback mutator,
+ void *context, int flags);
+
+extern bool raw_expression_tree_walker_impl(Node *node,
+ tree_walker_callback walker,
+ void *context);
+
+extern bool planstate_tree_walker_impl(struct PlanState *planstate,
+ planstate_tree_walker_callback walker,
+ void *context);
+
+#endif /* NODEFUNCS_H */
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
new file mode 100644
index 0000000..f8e8fe6
--- /dev/null
+++ b/src/include/nodes/nodes.h
@@ -0,0 +1,446 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodes.h
+ * Definitions for tagged nodes.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/nodes/nodes.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODES_H
+#define NODES_H
+
+/*
+ * The first field of every node is NodeTag. Each node created (with makeNode)
+ * will have one of the following tags as the value of its first field.
+ *
+ * Note that inserting or deleting node types changes the numbers of other
+ * node types later in the list. This is no problem during development, since
+ * the node numbers are never stored on disk. But don't do it in a released
+ * branch, because that would represent an ABI break for extensions.
+ */
+typedef enum NodeTag
+{
+ T_Invalid = 0,
+
+#include "nodes/nodetags.h"
+} NodeTag;
+
+/*
+ * pg_node_attr() - Used in node definitions to set extra information for
+ * gen_node_support.pl
+ *
+ * Attributes can be attached to a node as a whole (place the attribute
+ * specification on the first line after the struct's opening brace)
+ * or to a specific field (place it at the end of that field's line). The
+ * argument is a comma-separated list of attributes. Unrecognized attributes
+ * cause an error.
+ *
+ * Valid node attributes:
+ *
+ * - abstract: Abstract types are types that cannot be instantiated but that
+ * can be supertypes of other types. We track their fields, so that
+ * subtypes can use them, but we don't emit a node tag, so you can't
+ * instantiate them.
+ *
+ * - custom_copy_equal: Has custom implementations in copyfuncs.c and
+ * equalfuncs.c.
+ *
+ * - custom_read_write: Has custom implementations in outfuncs.c and
+ * readfuncs.c.
+ *
+ * - custom_query_jumble: Has custom implementation in queryjumblefuncs.c.
+ *
+ * - no_copy: Does not support copyObject() at all.
+ *
+ * - no_equal: Does not support equal() at all.
+ *
+ * - no_copy_equal: Shorthand for both no_copy and no_equal.
+ *
+ * - no_query_jumble: Does not support JumbleQuery() at all.
+ *
+ * - no_read: Does not support nodeRead() at all.
+ *
+ * - nodetag_only: Does not support copyObject(), equal(), jumbleQuery()
+ * outNode() or nodeRead().
+ *
+ * - special_read_write: Has special treatment in outNode() and nodeRead().
+ *
+ * - nodetag_number(VALUE): assign the specified nodetag number instead of
+ * an auto-generated number. Typically this would only be used in stable
+ * branches, to give a newly-added node type a number without breaking ABI
+ * by changing the numbers of existing node types.
+ *
+ * Node types can be supertypes of other types whether or not they are marked
+ * abstract: if a node struct appears as the first field of another struct
+ * type, then it is the supertype of that type. The no_copy, no_equal,
+ * no_query_jumble and no_read node attributes are automatically inherited
+ * from the supertype. (Notice that nodetag_only does not inherit, so it's
+ * not quite equivalent to a combination of other attributes.)
+ *
+ * Valid node field attributes:
+ *
+ * - array_size(OTHERFIELD): This field is a dynamically allocated array with
+ * size indicated by the mentioned other field. The other field is either a
+ * scalar or a list, in which case the length of the list is used.
+ *
+ * - copy_as(VALUE): In copyObject(), replace the field's value with VALUE.
+ *
+ * - copy_as_scalar: In copyObject(), copy the field as a scalar value
+ * (e.g. a pointer) even if it is a node-type pointer.
+ *
+ * - equal_as_scalar: In equal(), compare the field as a scalar value
+ * even if it is a node-type pointer.
+ *
+ * - equal_ignore: Ignore the field for equality.
+ *
+ * - equal_ignore_if_zero: Ignore the field for equality if it is zero.
+ * (Otherwise, compare normally.)
+ *
+ * - query_jumble_ignore: Ignore the field for the query jumbling. Note
+ * that typmod and collation information are usually irrelevant for the
+ * query jumbling.
+ *
+ * - query_jumble_location: Mark the field as a location to track. This is
+ * only allowed for integer fields that include "location" in their name.
+ *
+ * - read_as(VALUE): In nodeRead(), replace the field's value with VALUE.
+ *
+ * - read_write_ignore: Ignore the field for read/write. This is only allowed
+ * if the node type is marked no_read or read_as() is also specified.
+ *
+ * - write_only_relids, write_only_nondefault_pathtarget, write_only_req_outer:
+ * Special handling for Path struct; see there.
+ *
+ */
+#define pg_node_attr(...)
+
+/*
+ * The first field of a node of any type is guaranteed to be the NodeTag.
+ * Hence the type of any node can be gotten by casting it to Node. Declaring
+ * a variable to be of Node * (instead of void *) can also facilitate
+ * debugging.
+ */
+typedef struct Node
+{
+ NodeTag type;
+} Node;
+
+#define nodeTag(nodeptr) (((const Node*)(nodeptr))->type)
+
+/*
+ * newNode -
+ * create a new node of the specified size and tag the node with the
+ * specified tag.
+ *
+ * !WARNING!: Avoid using newNode directly. You should be using the
+ * macro makeNode. eg. to create a Query node, use makeNode(Query)
+ *
+ * Note: the size argument should always be a compile-time constant, so the
+ * apparent risk of multiple evaluation doesn't matter in practice.
+ */
+#ifdef __GNUC__
+
+/* With GCC, we can use a compound statement within an expression */
+#define newNode(size, tag) \
+({ Node *_result; \
+ AssertMacro((size) >= sizeof(Node)); /* need the tag, at least */ \
+ _result = (Node *) palloc0fast(size); \
+ _result->type = (tag); \
+ _result; \
+})
+#else
+
+/*
+ * There is no way to dereference the palloc'ed pointer to assign the
+ * tag, and also return the pointer itself, so we need a holder variable.
+ * Fortunately, this macro isn't recursive so we just define
+ * a global variable for this purpose.
+ */
+extern PGDLLIMPORT Node *newNodeMacroHolder;
+
+#define newNode(size, tag) \
+( \
+ AssertMacro((size) >= sizeof(Node)), /* need the tag, at least */ \
+ newNodeMacroHolder = (Node *) palloc0fast(size), \
+ newNodeMacroHolder->type = (tag), \
+ newNodeMacroHolder \
+)
+#endif /* __GNUC__ */
+
+
+#define makeNode(_type_) ((_type_ *) newNode(sizeof(_type_),T_##_type_))
+#define NodeSetTag(nodeptr,t) (((Node*)(nodeptr))->type = (t))
+
+#define IsA(nodeptr,_type_) (nodeTag(nodeptr) == T_##_type_)
+
+/*
+ * castNode(type, ptr) casts ptr to "type *", and if assertions are enabled,
+ * verifies that the node has the appropriate type (using its nodeTag()).
+ *
+ * Use an inline function when assertions are enabled, to avoid multiple
+ * evaluations of the ptr argument (which could e.g. be a function call).
+ */
+#ifdef USE_ASSERT_CHECKING
+static inline Node *
+castNodeImpl(NodeTag type, void *ptr)
+{
+ Assert(ptr == NULL || nodeTag(ptr) == type);
+ return (Node *) ptr;
+}
+#define castNode(_type_, nodeptr) ((_type_ *) castNodeImpl(T_##_type_, nodeptr))
+#else
+#define castNode(_type_, nodeptr) ((_type_ *) (nodeptr))
+#endif /* USE_ASSERT_CHECKING */
+
+
+/* ----------------------------------------------------------------
+ * extern declarations follow
+ * ----------------------------------------------------------------
+ */
+
+/*
+ * nodes/{outfuncs.c,print.c}
+ */
+struct Bitmapset; /* not to include bitmapset.h here */
+struct StringInfoData; /* not to include stringinfo.h here */
+
+extern void outNode(struct StringInfoData *str, const void *obj);
+extern void outToken(struct StringInfoData *str, const char *s);
+extern void outBitmapset(struct StringInfoData *str,
+ const struct Bitmapset *bms);
+extern void outDatum(struct StringInfoData *str, uintptr_t value,
+ int typlen, bool typbyval);
+extern char *nodeToString(const void *obj);
+extern char *bmsToString(const struct Bitmapset *bms);
+
+/*
+ * nodes/{readfuncs.c,read.c}
+ */
+extern void *stringToNode(const char *str);
+#ifdef WRITE_READ_PARSE_PLAN_TREES
+extern void *stringToNodeWithLocations(const char *str);
+#endif
+extern struct Bitmapset *readBitmapset(void);
+extern uintptr_t readDatum(bool typbyval);
+extern bool *readBoolCols(int numCols);
+extern int *readIntCols(int numCols);
+extern Oid *readOidCols(int numCols);
+extern int16 *readAttrNumberCols(int numCols);
+
+/*
+ * nodes/copyfuncs.c
+ */
+extern void *copyObjectImpl(const void *from);
+
+/* cast result back to argument type, if supported by compiler */
+#ifdef HAVE_TYPEOF
+#define copyObject(obj) ((typeof(obj)) copyObjectImpl(obj))
+#else
+#define copyObject(obj) copyObjectImpl(obj)
+#endif
+
+/*
+ * nodes/equalfuncs.c
+ */
+extern bool equal(const void *a, const void *b);
+
+
+/*
+ * Typedefs for identifying qualifier selectivities and plan costs as such.
+ * These are just plain "double"s, but declaring a variable as Selectivity
+ * or Cost makes the intent more obvious.
+ *
+ * These could have gone into plannodes.h or some such, but many files
+ * depend on them...
+ */
+typedef double Selectivity; /* fraction of tuples a qualifier will pass */
+typedef double Cost; /* execution cost (in page-access units) */
+typedef double Cardinality; /* (estimated) number of rows or other integer
+ * count */
+
+
+/*
+ * CmdType -
+ * enums for type of operation represented by a Query or PlannedStmt
+ *
+ * This is needed in both parsenodes.h and plannodes.h, so put it here...
+ */
+typedef enum CmdType
+{
+ CMD_UNKNOWN,
+ CMD_SELECT, /* select stmt */
+ CMD_UPDATE, /* update stmt */
+ CMD_INSERT, /* insert stmt */
+ CMD_DELETE, /* delete stmt */
+ CMD_MERGE, /* merge stmt */
+ CMD_UTILITY, /* cmds like create, destroy, copy, vacuum,
+ * etc. */
+ CMD_NOTHING /* dummy command for instead nothing rules
+ * with qual */
+} CmdType;
+
+
+/*
+ * JoinType -
+ * enums for types of relation joins
+ *
+ * JoinType determines the exact semantics of joining two relations using
+ * a matching qualification. For example, it tells what to do with a tuple
+ * that has no match in the other relation.
+ *
+ * This is needed in both parsenodes.h and plannodes.h, so put it here...
+ */
+typedef enum JoinType
+{
+ /*
+ * The canonical kinds of joins according to the SQL JOIN syntax. Only
+ * these codes can appear in parser output (e.g., JoinExpr nodes).
+ */
+ JOIN_INNER, /* matching tuple pairs only */
+ JOIN_LEFT, /* pairs + unmatched LHS tuples */
+ JOIN_FULL, /* pairs + unmatched LHS + unmatched RHS */
+ JOIN_RIGHT, /* pairs + unmatched RHS tuples */
+
+ /*
+ * Semijoins and anti-semijoins (as defined in relational theory) do not
+ * appear in the SQL JOIN syntax, but there are standard idioms for
+ * representing them (e.g., using EXISTS). The planner recognizes these
+ * cases and converts them to joins. So the planner and executor must
+ * support these codes. NOTE: in JOIN_SEMI output, it is unspecified
+ * which matching RHS row is joined to. In JOIN_ANTI output, the row is
+ * guaranteed to be null-extended.
+ */
+ JOIN_SEMI, /* 1 copy of each LHS row that has match(es) */
+ JOIN_ANTI, /* 1 copy of each LHS row that has no match */
+ JOIN_RIGHT_ANTI, /* 1 copy of each RHS row that has no match */
+
+ /*
+ * These codes are used internally in the planner, but are not supported
+ * by the executor (nor, indeed, by most of the planner).
+ */
+ JOIN_UNIQUE_OUTER, /* LHS path must be made unique */
+ JOIN_UNIQUE_INNER /* RHS path must be made unique */
+
+ /*
+ * We might need additional join types someday.
+ */
+} JoinType;
+
+/*
+ * OUTER joins are those for which pushed-down quals must behave differently
+ * from the join's own quals. This is in fact everything except INNER and
+ * SEMI joins. However, this macro must also exclude the JOIN_UNIQUE symbols
+ * since those are temporary proxies for what will eventually be an INNER
+ * join.
+ *
+ * Note: semijoins are a hybrid case, but we choose to treat them as not
+ * being outer joins. This is okay principally because the SQL syntax makes
+ * it impossible to have a pushed-down qual that refers to the inner relation
+ * of a semijoin; so there is no strong need to distinguish join quals from
+ * pushed-down quals. This is convenient because for almost all purposes,
+ * quals attached to a semijoin can be treated the same as innerjoin quals.
+ */
+#define IS_OUTER_JOIN(jointype) \
+ (((1 << (jointype)) & \
+ ((1 << JOIN_LEFT) | \
+ (1 << JOIN_FULL) | \
+ (1 << JOIN_RIGHT) | \
+ (1 << JOIN_ANTI) | \
+ (1 << JOIN_RIGHT_ANTI))) != 0)
+
+/*
+ * AggStrategy -
+ * overall execution strategies for Agg plan nodes
+ *
+ * This is needed in both pathnodes.h and plannodes.h, so put it here...
+ */
+typedef enum AggStrategy
+{
+ AGG_PLAIN, /* simple agg across all input rows */
+ AGG_SORTED, /* grouped agg, input must be sorted */
+ AGG_HASHED, /* grouped agg, use internal hashtable */
+ AGG_MIXED /* grouped agg, hash and sort both used */
+} AggStrategy;
+
+/*
+ * AggSplit -
+ * splitting (partial aggregation) modes for Agg plan nodes
+ *
+ * This is needed in both pathnodes.h and plannodes.h, so put it here...
+ */
+
+/* Primitive options supported by nodeAgg.c: */
+#define AGGSPLITOP_COMBINE 0x01 /* substitute combinefn for transfn */
+#define AGGSPLITOP_SKIPFINAL 0x02 /* skip finalfn, return state as-is */
+#define AGGSPLITOP_SERIALIZE 0x04 /* apply serialfn to output */
+#define AGGSPLITOP_DESERIALIZE 0x08 /* apply deserialfn to input */
+
+/* Supported operating modes (i.e., useful combinations of these options): */
+typedef enum AggSplit
+{
+ /* Basic, non-split aggregation: */
+ AGGSPLIT_SIMPLE = 0,
+ /* Initial phase of partial aggregation, with serialization: */
+ AGGSPLIT_INITIAL_SERIAL = AGGSPLITOP_SKIPFINAL | AGGSPLITOP_SERIALIZE,
+ /* Final phase of partial aggregation, with deserialization: */
+ AGGSPLIT_FINAL_DESERIAL = AGGSPLITOP_COMBINE | AGGSPLITOP_DESERIALIZE
+} AggSplit;
+
+/* Test whether an AggSplit value selects each primitive option: */
+#define DO_AGGSPLIT_COMBINE(as) (((as) & AGGSPLITOP_COMBINE) != 0)
+#define DO_AGGSPLIT_SKIPFINAL(as) (((as) & AGGSPLITOP_SKIPFINAL) != 0)
+#define DO_AGGSPLIT_SERIALIZE(as) (((as) & AGGSPLITOP_SERIALIZE) != 0)
+#define DO_AGGSPLIT_DESERIALIZE(as) (((as) & AGGSPLITOP_DESERIALIZE) != 0)
+
+/*
+ * SetOpCmd and SetOpStrategy -
+ * overall semantics and execution strategies for SetOp plan nodes
+ *
+ * This is needed in both pathnodes.h and plannodes.h, so put it here...
+ */
+typedef enum SetOpCmd
+{
+ SETOPCMD_INTERSECT,
+ SETOPCMD_INTERSECT_ALL,
+ SETOPCMD_EXCEPT,
+ SETOPCMD_EXCEPT_ALL
+} SetOpCmd;
+
+typedef enum SetOpStrategy
+{
+ SETOP_SORTED, /* input must be sorted */
+ SETOP_HASHED /* use internal hashtable */
+} SetOpStrategy;
+
+/*
+ * OnConflictAction -
+ * "ON CONFLICT" clause type of query
+ *
+ * This is needed in both parsenodes.h and plannodes.h, so put it here...
+ */
+typedef enum OnConflictAction
+{
+ ONCONFLICT_NONE, /* No "ON CONFLICT" clause */
+ ONCONFLICT_NOTHING, /* ON CONFLICT ... DO NOTHING */
+ ONCONFLICT_UPDATE /* ON CONFLICT ... DO UPDATE */
+} OnConflictAction;
+
+/*
+ * LimitOption -
+ * LIMIT option of query
+ *
+ * This is needed in both parsenodes.h and plannodes.h, so put it here...
+ */
+typedef enum LimitOption
+{
+ LIMIT_OPTION_COUNT, /* FETCH FIRST... ONLY */
+ LIMIT_OPTION_WITH_TIES, /* FETCH FIRST... WITH TIES */
+ LIMIT_OPTION_DEFAULT, /* No limit present */
+} LimitOption;
+
+#endif /* NODES_H */
diff --git a/src/include/nodes/params.h b/src/include/nodes/params.h
new file mode 100644
index 0000000..ad23113
--- /dev/null
+++ b/src/include/nodes/params.h
@@ -0,0 +1,170 @@
+/*-------------------------------------------------------------------------
+ *
+ * params.h
+ * Support for finding the values associated with Param nodes.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/nodes/params.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARAMS_H
+#define PARAMS_H
+
+/* Forward declarations, to avoid including other headers */
+struct Bitmapset;
+struct ExprState;
+struct Param;
+struct ParseState;
+
+
+/*
+ * ParamListInfo
+ *
+ * ParamListInfo structures are used to pass parameters into the executor
+ * for parameterized plans. We support two basic approaches to supplying
+ * parameter values, the "static" way and the "dynamic" way.
+ *
+ * In the static approach, per-parameter data is stored in an array of
+ * ParamExternData structs appended to the ParamListInfo struct.
+ * Each entry in the array defines the value to be substituted for a
+ * PARAM_EXTERN parameter. The "paramid" of a PARAM_EXTERN Param
+ * can range from 1 to numParams.
+ *
+ * Although parameter numbers are normally consecutive, we allow
+ * ptype == InvalidOid to signal an unused array entry.
+ *
+ * pflags is a flags field. Currently the only used bit is:
+ * PARAM_FLAG_CONST signals the planner that it may treat this parameter
+ * as a constant (i.e., generate a plan that works only for this value
+ * of the parameter).
+ *
+ * In the dynamic approach, all access to parameter values is done through
+ * hook functions found in the ParamListInfo struct. In this case,
+ * the ParamExternData array is typically unused and not allocated;
+ * but the legal range of paramid is still 1 to numParams.
+ *
+ * Although the data structure is really an array, not a list, we keep
+ * the old typedef name to avoid unnecessary code changes.
+ *
+ * There are 3 hook functions that can be associated with a ParamListInfo
+ * structure:
+ *
+ * If paramFetch isn't null, it is called to fetch the ParamExternData
+ * for a particular param ID, rather than accessing the relevant element
+ * of the ParamExternData array. This supports the case where the array
+ * isn't there at all, as well as cases where the data in the array
+ * might be obsolete or lazily evaluated. paramFetch must return the
+ * address of a ParamExternData struct describing the specified param ID;
+ * the convention above about ptype == InvalidOid signaling an invalid
+ * param ID still applies. The returned struct can either be placed in
+ * the "workspace" supplied by the caller, or it can be in storage
+ * controlled by the paramFetch hook if that's more convenient.
+ * (In either case, the struct is not expected to be long-lived.)
+ * If "speculative" is true, the paramFetch hook should not risk errors
+ * in trying to fetch the parameter value, and should report an invalid
+ * parameter instead.
+ *
+ * If paramCompile isn't null, then it controls what execExpr.c compiles
+ * for PARAM_EXTERN Param nodes --- typically, this hook would emit a
+ * EEOP_PARAM_CALLBACK step. This allows unnecessary work to be
+ * optimized away in compiled expressions.
+ *
+ * If parserSetup isn't null, then it is called to re-instantiate the
+ * original parsing hooks when a query needs to be re-parsed/planned.
+ * This is especially useful if the types of parameters might change
+ * from time to time, since it can replace the need to supply a fixed
+ * list of parameter types to the parser.
+ *
+ * Notice that the paramFetch and paramCompile hooks are actually passed
+ * the ParamListInfo struct's address; they can therefore access all
+ * three of the "arg" fields, and the distinction between paramFetchArg
+ * and paramCompileArg is rather arbitrary.
+ */
+
+#define PARAM_FLAG_CONST 0x0001 /* parameter is constant */
+
+typedef struct ParamExternData
+{
+ Datum value; /* parameter value */
+ bool isnull; /* is it NULL? */
+ uint16 pflags; /* flag bits, see above */
+ Oid ptype; /* parameter's datatype, or 0 */
+} ParamExternData;
+
+typedef struct ParamListInfoData *ParamListInfo;
+
+typedef ParamExternData *(*ParamFetchHook) (ParamListInfo params,
+ int paramid, bool speculative,
+ ParamExternData *workspace);
+
+typedef void (*ParamCompileHook) (ParamListInfo params, struct Param *param,
+ struct ExprState *state,
+ Datum *resv, bool *resnull);
+
+typedef void (*ParserSetupHook) (struct ParseState *pstate, void *arg);
+
+typedef struct ParamListInfoData
+{
+ ParamFetchHook paramFetch; /* parameter fetch hook */
+ void *paramFetchArg;
+ ParamCompileHook paramCompile; /* parameter compile hook */
+ void *paramCompileArg;
+ ParserSetupHook parserSetup; /* parser setup hook */
+ void *parserSetupArg;
+ char *paramValuesStr; /* params as a single string for errors */
+ int numParams; /* nominal/maximum # of Params represented */
+
+ /*
+ * params[] may be of length zero if paramFetch is supplied; otherwise it
+ * must be of length numParams.
+ */
+ ParamExternData params[FLEXIBLE_ARRAY_MEMBER];
+} ParamListInfoData;
+
+
+/* ----------------
+ * ParamExecData
+ *
+ * ParamExecData entries are used for executor internal parameters
+ * (that is, values being passed into or out of a sub-query). The
+ * paramid of a PARAM_EXEC Param is a (zero-based) index into an
+ * array of ParamExecData records, which is referenced through
+ * es_param_exec_vals or ecxt_param_exec_vals.
+ *
+ * If execPlan is not NULL, it points to a SubPlanState node that needs
+ * to be executed to produce the value. (This is done so that we can have
+ * lazy evaluation of InitPlans: they aren't executed until/unless a
+ * result value is needed.) Otherwise the value is assumed to be valid
+ * when needed.
+ * ----------------
+ */
+
+typedef struct ParamExecData
+{
+ void *execPlan; /* should be "SubPlanState *" */
+ Datum value;
+ bool isnull;
+} ParamExecData;
+
+/* type of argument for ParamsErrorCallback */
+typedef struct ParamsErrorCbData
+{
+ const char *portalName;
+ ParamListInfo params;
+} ParamsErrorCbData;
+
+/* Functions found in src/backend/nodes/params.c */
+extern ParamListInfo makeParamList(int numParams);
+extern ParamListInfo copyParamList(ParamListInfo from);
+extern Size EstimateParamListSpace(ParamListInfo paramLI);
+extern void SerializeParamList(ParamListInfo paramLI, char **start_address);
+extern ParamListInfo RestoreParamList(char **start_address);
+extern char *BuildParamLogString(ParamListInfo params, char **knownTextValues,
+ int maxlen);
+extern void ParamsErrorCallback(void *arg);
+
+#endif /* PARAMS_H */
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
new file mode 100644
index 0000000..9dca3b6
--- /dev/null
+++ b/src/include/nodes/parsenodes.h
@@ -0,0 +1,4050 @@
+/*-------------------------------------------------------------------------
+ *
+ * parsenodes.h
+ * definitions for parse tree nodes
+ *
+ * Many of the node types used in parsetrees include a "location" field.
+ * This is a byte (not character) offset in the original source text, to be
+ * used for positioning an error cursor when there is an error related to
+ * the node. Access to the original source text is needed to make use of
+ * the location. At the topmost (statement) level, we also provide a
+ * statement length, likewise measured in bytes, for convenience in
+ * identifying statement boundaries in multi-statement source strings.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/nodes/parsenodes.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSENODES_H
+#define PARSENODES_H
+
+#include "common/relpath.h"
+#include "nodes/bitmapset.h"
+#include "nodes/lockoptions.h"
+#include "nodes/primnodes.h"
+#include "nodes/value.h"
+#include "partitioning/partdefs.h"
+
+
+typedef enum OverridingKind
+{
+ OVERRIDING_NOT_SET = 0,
+ OVERRIDING_USER_VALUE,
+ OVERRIDING_SYSTEM_VALUE
+} OverridingKind;
+
+/* Possible sources of a Query */
+typedef enum QuerySource
+{
+ QSRC_ORIGINAL, /* original parsetree (explicit query) */
+ QSRC_PARSER, /* added by parse analysis (now unused) */
+ QSRC_INSTEAD_RULE, /* added by unconditional INSTEAD rule */
+ QSRC_QUAL_INSTEAD_RULE, /* added by conditional INSTEAD rule */
+ QSRC_NON_INSTEAD_RULE /* added by non-INSTEAD rule */
+} QuerySource;
+
+/* Sort ordering options for ORDER BY and CREATE INDEX */
+typedef enum SortByDir
+{
+ SORTBY_DEFAULT,
+ SORTBY_ASC,
+ SORTBY_DESC,
+ SORTBY_USING /* not allowed in CREATE INDEX ... */
+} SortByDir;
+
+typedef enum SortByNulls
+{
+ SORTBY_NULLS_DEFAULT,
+ SORTBY_NULLS_FIRST,
+ SORTBY_NULLS_LAST
+} SortByNulls;
+
+/* Options for [ ALL | DISTINCT ] */
+typedef enum SetQuantifier
+{
+ SET_QUANTIFIER_DEFAULT,
+ SET_QUANTIFIER_ALL,
+ SET_QUANTIFIER_DISTINCT
+} SetQuantifier;
+
+/*
+ * Grantable rights are encoded so that we can OR them together in a bitmask.
+ * The present representation of AclItem limits us to 32 distinct rights,
+ * even though AclMode is defined as uint64. See utils/acl.h.
+ *
+ * Caution: changing these codes breaks stored ACLs, hence forces initdb.
+ */
+typedef uint64 AclMode; /* a bitmask of privilege bits */
+
+#define ACL_INSERT (1<<0) /* for relations */
+#define ACL_SELECT (1<<1)
+#define ACL_UPDATE (1<<2)
+#define ACL_DELETE (1<<3)
+#define ACL_TRUNCATE (1<<4)
+#define ACL_REFERENCES (1<<5)
+#define ACL_TRIGGER (1<<6)
+#define ACL_EXECUTE (1<<7) /* for functions */
+#define ACL_USAGE (1<<8) /* for various object types */
+#define ACL_CREATE (1<<9) /* for namespaces and databases */
+#define ACL_CREATE_TEMP (1<<10) /* for databases */
+#define ACL_CONNECT (1<<11) /* for databases */
+#define ACL_SET (1<<12) /* for configuration parameters */
+#define ACL_ALTER_SYSTEM (1<<13) /* for configuration parameters */
+#define N_ACL_RIGHTS 14 /* 1 plus the last 1<<x */
+#define ACL_NO_RIGHTS 0
+/* Currently, SELECT ... FOR [KEY] UPDATE/SHARE requires UPDATE privileges */
+#define ACL_SELECT_FOR_UPDATE ACL_UPDATE
+
+
+/*****************************************************************************
+ * Query Tree
+ *****************************************************************************/
+
+/*
+ * Query -
+ * Parse analysis turns all statements into a Query tree
+ * for further processing by the rewriter and planner.
+ *
+ * Utility statements (i.e. non-optimizable statements) have the
+ * utilityStmt field set, and the rest of the Query is mostly dummy.
+ *
+ * Planning converts a Query tree into a Plan tree headed by a PlannedStmt
+ * node --- the Query structure is not used by the executor.
+ *
+ * All the fields ignored for the query jumbling are not semantically
+ * significant (such as alias names), as is ignored anything that can
+ * be deduced from child nodes (else we'd just be double-hashing that
+ * piece of information).
+ */
+typedef struct Query
+{
+ NodeTag type;
+
+ CmdType commandType; /* select|insert|update|delete|merge|utility */
+
+ /* where did I come from? */
+ QuerySource querySource pg_node_attr(query_jumble_ignore);
+
+ /*
+ * query identifier (can be set by plugins); ignored for equal, as it
+ * might not be set; also not stored. This is the result of the query
+ * jumble, hence ignored.
+ */
+ uint64 queryId pg_node_attr(equal_ignore, query_jumble_ignore, read_write_ignore, read_as(0));
+
+ /* do I set the command result tag? */
+ bool canSetTag pg_node_attr(query_jumble_ignore);
+
+ Node *utilityStmt; /* non-null if commandType == CMD_UTILITY */
+
+ /*
+ * rtable index of target relation for INSERT/UPDATE/DELETE/MERGE; 0 for
+ * SELECT. This is ignored in the query jumble as unrelated to the
+ * compilation of the query ID.
+ */
+ int resultRelation pg_node_attr(query_jumble_ignore);
+
+ /* has aggregates in tlist or havingQual */
+ bool hasAggs pg_node_attr(query_jumble_ignore);
+ /* has window functions in tlist */
+ bool hasWindowFuncs pg_node_attr(query_jumble_ignore);
+ /* has set-returning functions in tlist */
+ bool hasTargetSRFs pg_node_attr(query_jumble_ignore);
+ /* has subquery SubLink */
+ bool hasSubLinks pg_node_attr(query_jumble_ignore);
+ /* distinctClause is from DISTINCT ON */
+ bool hasDistinctOn pg_node_attr(query_jumble_ignore);
+ /* WITH RECURSIVE was specified */
+ bool hasRecursive pg_node_attr(query_jumble_ignore);
+ /* has INSERT/UPDATE/DELETE in WITH */
+ bool hasModifyingCTE pg_node_attr(query_jumble_ignore);
+ /* FOR [KEY] UPDATE/SHARE was specified */
+ bool hasForUpdate pg_node_attr(query_jumble_ignore);
+ /* rewriter has applied some RLS policy */
+ bool hasRowSecurity pg_node_attr(query_jumble_ignore);
+ /* is a RETURN statement */
+ bool isReturn pg_node_attr(query_jumble_ignore);
+
+ List *cteList; /* WITH list (of CommonTableExpr's) */
+
+ List *rtable; /* list of range table entries */
+
+ /*
+ * list of RTEPermissionInfo nodes for the rtable entries having
+ * perminfoindex > 0
+ */
+ List *rteperminfos pg_node_attr(query_jumble_ignore);
+ FromExpr *jointree; /* table join tree (FROM and WHERE clauses);
+ * also USING clause for MERGE */
+
+ List *mergeActionList; /* list of actions for MERGE (only) */
+ /* whether to use outer join */
+ bool mergeUseOuterJoin pg_node_attr(query_jumble_ignore);
+
+ List *targetList; /* target list (of TargetEntry) */
+
+ /* OVERRIDING clause */
+ OverridingKind override pg_node_attr(query_jumble_ignore);
+
+ OnConflictExpr *onConflict; /* ON CONFLICT DO [NOTHING | UPDATE] */
+
+ List *returningList; /* return-values list (of TargetEntry) */
+
+ List *groupClause; /* a list of SortGroupClause's */
+ bool groupDistinct; /* is the group by clause distinct? */
+
+ List *groupingSets; /* a list of GroupingSet's if present */
+
+ Node *havingQual; /* qualifications applied to groups */
+
+ List *windowClause; /* a list of WindowClause's */
+
+ List *distinctClause; /* a list of SortGroupClause's */
+
+ List *sortClause; /* a list of SortGroupClause's */
+
+ Node *limitOffset; /* # of result tuples to skip (int8 expr) */
+ Node *limitCount; /* # of result tuples to return (int8 expr) */
+ LimitOption limitOption; /* limit type */
+
+ List *rowMarks; /* a list of RowMarkClause's */
+
+ Node *setOperations; /* set-operation tree if this is top level of
+ * a UNION/INTERSECT/EXCEPT query */
+
+ /*
+ * A list of pg_constraint OIDs that the query depends on to be
+ * semantically valid
+ */
+ List *constraintDeps pg_node_attr(query_jumble_ignore);
+
+ /* a list of WithCheckOption's (added during rewrite) */
+ List *withCheckOptions pg_node_attr(query_jumble_ignore);
+
+ /*
+ * The following two fields identify the portion of the source text string
+ * containing this query. They are typically only populated in top-level
+ * Queries, not in sub-queries. When not set, they might both be zero, or
+ * both be -1 meaning "unknown".
+ */
+ /* start location, or -1 if unknown */
+ int stmt_location;
+ /* length in bytes; 0 means "rest of string" */
+ int stmt_len pg_node_attr(query_jumble_ignore);
+} Query;
+
+
+/****************************************************************************
+ * Supporting data structures for Parse Trees
+ *
+ * Most of these node types appear in raw parsetrees output by the grammar,
+ * and get transformed to something else by the analyzer. A few of them
+ * are used as-is in transformed querytrees.
+ ****************************************************************************/
+
+/*
+ * TypeName - specifies a type in definitions
+ *
+ * For TypeName structures generated internally, it is often easier to
+ * specify the type by OID than by name. If "names" is NIL then the
+ * actual type OID is given by typeOid, otherwise typeOid is unused.
+ * Similarly, if "typmods" is NIL then the actual typmod is expected to
+ * be prespecified in typemod, otherwise typemod is unused.
+ *
+ * If pct_type is true, then names is actually a field name and we look up
+ * the type of that field. Otherwise (the normal case), names is a type
+ * name possibly qualified with schema and database name.
+ */
+typedef struct TypeName
+{
+ NodeTag type;
+ List *names; /* qualified name (list of String nodes) */
+ Oid typeOid; /* type identified by OID */
+ bool setof; /* is a set? */
+ bool pct_type; /* %TYPE specified? */
+ List *typmods; /* type modifier expression(s) */
+ int32 typemod; /* prespecified type modifier */
+ List *arrayBounds; /* array bounds */
+ int location; /* token location, or -1 if unknown */
+} TypeName;
+
+/*
+ * ColumnRef - specifies a reference to a column, or possibly a whole tuple
+ *
+ * The "fields" list must be nonempty. It can contain String nodes
+ * (representing names) and A_Star nodes (representing occurrence of a '*').
+ * Currently, A_Star must appear only as the last list element --- the grammar
+ * is responsible for enforcing this!
+ *
+ * Note: any container subscripting or selection of fields from composite columns
+ * is represented by an A_Indirection node above the ColumnRef. However,
+ * for simplicity in the normal case, initial field selection from a table
+ * name is represented within ColumnRef and not by adding A_Indirection.
+ */
+typedef struct ColumnRef
+{
+ NodeTag type;
+ List *fields; /* field names (String nodes) or A_Star */
+ int location; /* token location, or -1 if unknown */
+} ColumnRef;
+
+/*
+ * ParamRef - specifies a $n parameter reference
+ */
+typedef struct ParamRef
+{
+ NodeTag type;
+ int number; /* the number of the parameter */
+ int location; /* token location, or -1 if unknown */
+} ParamRef;
+
+/*
+ * A_Expr - infix, prefix, and postfix expressions
+ */
+typedef enum A_Expr_Kind
+{
+ AEXPR_OP, /* normal operator */
+ AEXPR_OP_ANY, /* scalar op ANY (array) */
+ AEXPR_OP_ALL, /* scalar op ALL (array) */
+ AEXPR_DISTINCT, /* IS DISTINCT FROM - name must be "=" */
+ AEXPR_NOT_DISTINCT, /* IS NOT DISTINCT FROM - name must be "=" */
+ AEXPR_NULLIF, /* NULLIF - name must be "=" */
+ AEXPR_IN, /* [NOT] IN - name must be "=" or "<>" */
+ AEXPR_LIKE, /* [NOT] LIKE - name must be "~~" or "!~~" */
+ AEXPR_ILIKE, /* [NOT] ILIKE - name must be "~~*" or "!~~*" */
+ AEXPR_SIMILAR, /* [NOT] SIMILAR - name must be "~" or "!~" */
+ AEXPR_BETWEEN, /* name must be "BETWEEN" */
+ AEXPR_NOT_BETWEEN, /* name must be "NOT BETWEEN" */
+ AEXPR_BETWEEN_SYM, /* name must be "BETWEEN SYMMETRIC" */
+ AEXPR_NOT_BETWEEN_SYM /* name must be "NOT BETWEEN SYMMETRIC" */
+} A_Expr_Kind;
+
+typedef struct A_Expr
+{
+ pg_node_attr(custom_read_write)
+
+ NodeTag type;
+ A_Expr_Kind kind; /* see above */
+ List *name; /* possibly-qualified name of operator */
+ Node *lexpr; /* left argument, or NULL if none */
+ Node *rexpr; /* right argument, or NULL if none */
+ int location; /* token location, or -1 if unknown */
+} A_Expr;
+
+/*
+ * A_Const - a literal constant
+ *
+ * Value nodes are inline for performance. You can treat 'val' as a node,
+ * as in IsA(&val, Integer). 'val' is not valid if isnull is true.
+ */
+union ValUnion
+{
+ Node node;
+ Integer ival;
+ Float fval;
+ Boolean boolval;
+ String sval;
+ BitString bsval;
+};
+
+typedef struct A_Const
+{
+ pg_node_attr(custom_copy_equal, custom_read_write, custom_query_jumble)
+
+ NodeTag type;
+ union ValUnion val;
+ bool isnull; /* SQL NULL constant */
+ int location; /* token location, or -1 if unknown */
+} A_Const;
+
+/*
+ * TypeCast - a CAST expression
+ */
+typedef struct TypeCast
+{
+ NodeTag type;
+ Node *arg; /* the expression being casted */
+ TypeName *typeName; /* the target type */
+ int location; /* token location, or -1 if unknown */
+} TypeCast;
+
+/*
+ * CollateClause - a COLLATE expression
+ */
+typedef struct CollateClause
+{
+ NodeTag type;
+ Node *arg; /* input expression */
+ List *collname; /* possibly-qualified collation name */
+ int location; /* token location, or -1 if unknown */
+} CollateClause;
+
+/*
+ * RoleSpec - a role name or one of a few special values.
+ */
+typedef enum RoleSpecType
+{
+ ROLESPEC_CSTRING, /* role name is stored as a C string */
+ ROLESPEC_CURRENT_ROLE, /* role spec is CURRENT_ROLE */
+ ROLESPEC_CURRENT_USER, /* role spec is CURRENT_USER */
+ ROLESPEC_SESSION_USER, /* role spec is SESSION_USER */
+ ROLESPEC_PUBLIC /* role name is "public" */
+} RoleSpecType;
+
+typedef struct RoleSpec
+{
+ NodeTag type;
+ RoleSpecType roletype; /* Type of this rolespec */
+ char *rolename; /* filled only for ROLESPEC_CSTRING */
+ int location; /* token location, or -1 if unknown */
+} RoleSpec;
+
+/*
+ * FuncCall - a function or aggregate invocation
+ *
+ * agg_order (if not NIL) indicates we saw 'foo(... ORDER BY ...)', or if
+ * agg_within_group is true, it was 'foo(...) WITHIN GROUP (ORDER BY ...)'.
+ * agg_star indicates we saw a 'foo(*)' construct, while agg_distinct
+ * indicates we saw 'foo(DISTINCT ...)'. In any of these cases, the
+ * construct *must* be an aggregate call. Otherwise, it might be either an
+ * aggregate or some other kind of function. However, if FILTER or OVER is
+ * present it had better be an aggregate or window function.
+ *
+ * Normally, you'd initialize this via makeFuncCall() and then only change the
+ * parts of the struct its defaults don't match afterwards, as needed.
+ */
+typedef struct FuncCall
+{
+ NodeTag type;
+ List *funcname; /* qualified name of function */
+ List *args; /* the arguments (list of exprs) */
+ List *agg_order; /* ORDER BY (list of SortBy) */
+ Node *agg_filter; /* FILTER clause, if any */
+ struct WindowDef *over; /* OVER clause, if any */
+ bool agg_within_group; /* ORDER BY appeared in WITHIN GROUP */
+ bool agg_star; /* argument was really '*' */
+ bool agg_distinct; /* arguments were labeled DISTINCT */
+ bool func_variadic; /* last argument was labeled VARIADIC */
+ CoercionForm funcformat; /* how to display this node */
+ int location; /* token location, or -1 if unknown */
+} FuncCall;
+
+/*
+ * A_Star - '*' representing all columns of a table or compound field
+ *
+ * This can appear within ColumnRef.fields, A_Indirection.indirection, and
+ * ResTarget.indirection lists.
+ */
+typedef struct A_Star
+{
+ NodeTag type;
+} A_Star;
+
+/*
+ * A_Indices - array subscript or slice bounds ([idx] or [lidx:uidx])
+ *
+ * In slice case, either or both of lidx and uidx can be NULL (omitted).
+ * In non-slice case, uidx holds the single subscript and lidx is always NULL.
+ */
+typedef struct A_Indices
+{
+ NodeTag type;
+ bool is_slice; /* true if slice (i.e., colon present) */
+ Node *lidx; /* slice lower bound, if any */
+ Node *uidx; /* subscript, or slice upper bound if any */
+} A_Indices;
+
+/*
+ * A_Indirection - select a field and/or array element from an expression
+ *
+ * The indirection list can contain A_Indices nodes (representing
+ * subscripting), String nodes (representing field selection --- the
+ * string value is the name of the field to select), and A_Star nodes
+ * (representing selection of all fields of a composite type).
+ * For example, a complex selection operation like
+ * (foo).field1[42][7].field2
+ * would be represented with a single A_Indirection node having a 4-element
+ * indirection list.
+ *
+ * Currently, A_Star must appear only as the last list element --- the grammar
+ * is responsible for enforcing this!
+ */
+typedef struct A_Indirection
+{
+ NodeTag type;
+ Node *arg; /* the thing being selected from */
+ List *indirection; /* subscripts and/or field names and/or * */
+} A_Indirection;
+
+/*
+ * A_ArrayExpr - an ARRAY[] construct
+ */
+typedef struct A_ArrayExpr
+{
+ NodeTag type;
+ List *elements; /* array element expressions */
+ int location; /* token location, or -1 if unknown */
+} A_ArrayExpr;
+
+/*
+ * ResTarget -
+ * result target (used in target list of pre-transformed parse trees)
+ *
+ * In a SELECT target list, 'name' is the column label from an
+ * 'AS ColumnLabel' clause, or NULL if there was none, and 'val' is the
+ * value expression itself. The 'indirection' field is not used.
+ *
+ * INSERT uses ResTarget in its target-column-names list. Here, 'name' is
+ * the name of the destination column, 'indirection' stores any subscripts
+ * attached to the destination, and 'val' is not used.
+ *
+ * In an UPDATE target list, 'name' is the name of the destination column,
+ * 'indirection' stores any subscripts attached to the destination, and
+ * 'val' is the expression to assign.
+ *
+ * See A_Indirection for more info about what can appear in 'indirection'.
+ */
+typedef struct ResTarget
+{
+ NodeTag type;
+ char *name; /* column name or NULL */
+ List *indirection; /* subscripts, field names, and '*', or NIL */
+ Node *val; /* the value expression to compute or assign */
+ int location; /* token location, or -1 if unknown */
+} ResTarget;
+
+/*
+ * MultiAssignRef - element of a row source expression for UPDATE
+ *
+ * In an UPDATE target list, when we have SET (a,b,c) = row-valued-expression,
+ * we generate separate ResTarget items for each of a,b,c. Their "val" trees
+ * are MultiAssignRef nodes numbered 1..n, linking to a common copy of the
+ * row-valued-expression (which parse analysis will process only once, when
+ * handling the MultiAssignRef with colno=1).
+ */
+typedef struct MultiAssignRef
+{
+ NodeTag type;
+ Node *source; /* the row-valued expression */
+ int colno; /* column number for this target (1..n) */
+ int ncolumns; /* number of targets in the construct */
+} MultiAssignRef;
+
+/*
+ * SortBy - for ORDER BY clause
+ */
+typedef struct SortBy
+{
+ NodeTag type;
+ Node *node; /* expression to sort on */
+ SortByDir sortby_dir; /* ASC/DESC/USING/default */
+ SortByNulls sortby_nulls; /* NULLS FIRST/LAST */
+ List *useOp; /* name of op to use, if SORTBY_USING */
+ int location; /* operator location, or -1 if none/unknown */
+} SortBy;
+
+/*
+ * WindowDef - raw representation of WINDOW and OVER clauses
+ *
+ * For entries in a WINDOW list, "name" is the window name being defined.
+ * For OVER clauses, we use "name" for the "OVER window" syntax, or "refname"
+ * for the "OVER (window)" syntax, which is subtly different --- the latter
+ * implies overriding the window frame clause.
+ */
+typedef struct WindowDef
+{
+ NodeTag type;
+ char *name; /* window's own name */
+ char *refname; /* referenced window name, if any */
+ List *partitionClause; /* PARTITION BY expression list */
+ List *orderClause; /* ORDER BY (list of SortBy) */
+ int frameOptions; /* frame_clause options, see below */
+ Node *startOffset; /* expression for starting bound, if any */
+ Node *endOffset; /* expression for ending bound, if any */
+ int location; /* parse location, or -1 if none/unknown */
+} WindowDef;
+
+/*
+ * frameOptions is an OR of these bits. The NONDEFAULT and BETWEEN bits are
+ * used so that ruleutils.c can tell which properties were specified and
+ * which were defaulted; the correct behavioral bits must be set either way.
+ * The START_foo and END_foo options must come in pairs of adjacent bits for
+ * the convenience of gram.y, even though some of them are useless/invalid.
+ */
+#define FRAMEOPTION_NONDEFAULT 0x00001 /* any specified? */
+#define FRAMEOPTION_RANGE 0x00002 /* RANGE behavior */
+#define FRAMEOPTION_ROWS 0x00004 /* ROWS behavior */
+#define FRAMEOPTION_GROUPS 0x00008 /* GROUPS behavior */
+#define FRAMEOPTION_BETWEEN 0x00010 /* BETWEEN given? */
+#define FRAMEOPTION_START_UNBOUNDED_PRECEDING 0x00020 /* start is U. P. */
+#define FRAMEOPTION_END_UNBOUNDED_PRECEDING 0x00040 /* (disallowed) */
+#define FRAMEOPTION_START_UNBOUNDED_FOLLOWING 0x00080 /* (disallowed) */
+#define FRAMEOPTION_END_UNBOUNDED_FOLLOWING 0x00100 /* end is U. F. */
+#define FRAMEOPTION_START_CURRENT_ROW 0x00200 /* start is C. R. */
+#define FRAMEOPTION_END_CURRENT_ROW 0x00400 /* end is C. R. */
+#define FRAMEOPTION_START_OFFSET_PRECEDING 0x00800 /* start is O. P. */
+#define FRAMEOPTION_END_OFFSET_PRECEDING 0x01000 /* end is O. P. */
+#define FRAMEOPTION_START_OFFSET_FOLLOWING 0x02000 /* start is O. F. */
+#define FRAMEOPTION_END_OFFSET_FOLLOWING 0x04000 /* end is O. F. */
+#define FRAMEOPTION_EXCLUDE_CURRENT_ROW 0x08000 /* omit C.R. */
+#define FRAMEOPTION_EXCLUDE_GROUP 0x10000 /* omit C.R. & peers */
+#define FRAMEOPTION_EXCLUDE_TIES 0x20000 /* omit C.R.'s peers */
+
+#define FRAMEOPTION_START_OFFSET \
+ (FRAMEOPTION_START_OFFSET_PRECEDING | FRAMEOPTION_START_OFFSET_FOLLOWING)
+#define FRAMEOPTION_END_OFFSET \
+ (FRAMEOPTION_END_OFFSET_PRECEDING | FRAMEOPTION_END_OFFSET_FOLLOWING)
+#define FRAMEOPTION_EXCLUSION \
+ (FRAMEOPTION_EXCLUDE_CURRENT_ROW | FRAMEOPTION_EXCLUDE_GROUP | \
+ FRAMEOPTION_EXCLUDE_TIES)
+
+#define FRAMEOPTION_DEFAULTS \
+ (FRAMEOPTION_RANGE | FRAMEOPTION_START_UNBOUNDED_PRECEDING | \
+ FRAMEOPTION_END_CURRENT_ROW)
+
+/*
+ * RangeSubselect - subquery appearing in a FROM clause
+ */
+typedef struct RangeSubselect
+{
+ NodeTag type;
+ bool lateral; /* does it have LATERAL prefix? */
+ Node *subquery; /* the untransformed sub-select clause */
+ Alias *alias; /* table alias & optional column aliases */
+} RangeSubselect;
+
+/*
+ * RangeFunction - function call appearing in a FROM clause
+ *
+ * functions is a List because we use this to represent the construct
+ * ROWS FROM(func1(...), func2(...), ...). Each element of this list is a
+ * two-element sublist, the first element being the untransformed function
+ * call tree, and the second element being a possibly-empty list of ColumnDef
+ * nodes representing any columndef list attached to that function within the
+ * ROWS FROM() syntax.
+ *
+ * alias and coldeflist represent any alias and/or columndef list attached
+ * at the top level. (We disallow coldeflist appearing both here and
+ * per-function, but that's checked in parse analysis, not by the grammar.)
+ */
+typedef struct RangeFunction
+{
+ NodeTag type;
+ bool lateral; /* does it have LATERAL prefix? */
+ bool ordinality; /* does it have WITH ORDINALITY suffix? */
+ bool is_rowsfrom; /* is result of ROWS FROM() syntax? */
+ List *functions; /* per-function information, see above */
+ Alias *alias; /* table alias & optional column aliases */
+ List *coldeflist; /* list of ColumnDef nodes to describe result
+ * of function returning RECORD */
+} RangeFunction;
+
+/*
+ * RangeTableFunc - raw form of "table functions" such as XMLTABLE
+ */
+typedef struct RangeTableFunc
+{
+ NodeTag type;
+ bool lateral; /* does it have LATERAL prefix? */
+ Node *docexpr; /* document expression */
+ Node *rowexpr; /* row generator expression */
+ List *namespaces; /* list of namespaces as ResTarget */
+ List *columns; /* list of RangeTableFuncCol */
+ Alias *alias; /* table alias & optional column aliases */
+ int location; /* token location, or -1 if unknown */
+} RangeTableFunc;
+
+/*
+ * RangeTableFuncCol - one column in a RangeTableFunc->columns
+ *
+ * If for_ordinality is true (FOR ORDINALITY), then the column is an int4
+ * column and the rest of the fields are ignored.
+ */
+typedef struct RangeTableFuncCol
+{
+ NodeTag type;
+ char *colname; /* name of generated column */
+ TypeName *typeName; /* type of generated column */
+ bool for_ordinality; /* does it have FOR ORDINALITY? */
+ bool is_not_null; /* does it have NOT NULL? */
+ Node *colexpr; /* column filter expression */
+ Node *coldefexpr; /* column default value expression */
+ int location; /* token location, or -1 if unknown */
+} RangeTableFuncCol;
+
+/*
+ * RangeTableSample - TABLESAMPLE appearing in a raw FROM clause
+ *
+ * This node, appearing only in raw parse trees, represents
+ * <relation> TABLESAMPLE <method> (<params>) REPEATABLE (<num>)
+ * Currently, the <relation> can only be a RangeVar, but we might in future
+ * allow RangeSubselect and other options. Note that the RangeTableSample
+ * is wrapped around the node representing the <relation>, rather than being
+ * a subfield of it.
+ */
+typedef struct RangeTableSample
+{
+ NodeTag type;
+ Node *relation; /* relation to be sampled */
+ List *method; /* sampling method name (possibly qualified) */
+ List *args; /* argument(s) for sampling method */
+ Node *repeatable; /* REPEATABLE expression, or NULL if none */
+ int location; /* method name location, or -1 if unknown */
+} RangeTableSample;
+
+/*
+ * ColumnDef - column definition (used in various creates)
+ *
+ * If the column has a default value, we may have the value expression
+ * in either "raw" form (an untransformed parse tree) or "cooked" form
+ * (a post-parse-analysis, executable expression tree), depending on
+ * how this ColumnDef node was created (by parsing, or by inheritance
+ * from an existing relation). We should never have both in the same node!
+ *
+ * Similarly, we may have a COLLATE specification in either raw form
+ * (represented as a CollateClause with arg==NULL) or cooked form
+ * (the collation's OID).
+ *
+ * The constraints list may contain a CONSTR_DEFAULT item in a raw
+ * parsetree produced by gram.y, but transformCreateStmt will remove
+ * the item and set raw_default instead. CONSTR_DEFAULT items
+ * should not appear in any subsequent processing.
+ */
+typedef struct ColumnDef
+{
+ NodeTag type;
+ char *colname; /* name of column */
+ TypeName *typeName; /* type of column */
+ char *compression; /* compression method for column */
+ int inhcount; /* number of times column is inherited */
+ bool is_local; /* column has local (non-inherited) def'n */
+ bool is_not_null; /* NOT NULL constraint specified? */
+ bool is_from_type; /* column definition came from table type */
+ char storage; /* attstorage setting, or 0 for default */
+ char *storage_name; /* attstorage setting name or NULL for default */
+ Node *raw_default; /* default value (untransformed parse tree) */
+ Node *cooked_default; /* default value (transformed expr tree) */
+ char identity; /* attidentity setting */
+ RangeVar *identitySequence; /* to store identity sequence name for
+ * ALTER TABLE ... ADD COLUMN */
+ char generated; /* attgenerated setting */
+ CollateClause *collClause; /* untransformed COLLATE spec, if any */
+ Oid collOid; /* collation OID (InvalidOid if not set) */
+ List *constraints; /* other constraints on column */
+ List *fdwoptions; /* per-column FDW options */
+ int location; /* parse location, or -1 if none/unknown */
+} ColumnDef;
+
+/*
+ * TableLikeClause - CREATE TABLE ( ... LIKE ... ) clause
+ */
+typedef struct TableLikeClause
+{
+ NodeTag type;
+ RangeVar *relation;
+ bits32 options; /* OR of TableLikeOption flags */
+ Oid relationOid; /* If table has been looked up, its OID */
+} TableLikeClause;
+
+typedef enum TableLikeOption
+{
+ CREATE_TABLE_LIKE_COMMENTS = 1 << 0,
+ CREATE_TABLE_LIKE_COMPRESSION = 1 << 1,
+ CREATE_TABLE_LIKE_CONSTRAINTS = 1 << 2,
+ CREATE_TABLE_LIKE_DEFAULTS = 1 << 3,
+ CREATE_TABLE_LIKE_GENERATED = 1 << 4,
+ CREATE_TABLE_LIKE_IDENTITY = 1 << 5,
+ CREATE_TABLE_LIKE_INDEXES = 1 << 6,
+ CREATE_TABLE_LIKE_STATISTICS = 1 << 7,
+ CREATE_TABLE_LIKE_STORAGE = 1 << 8,
+ CREATE_TABLE_LIKE_ALL = PG_INT32_MAX
+} TableLikeOption;
+
+/*
+ * IndexElem - index parameters (used in CREATE INDEX, and in ON CONFLICT)
+ *
+ * For a plain index attribute, 'name' is the name of the table column to
+ * index, and 'expr' is NULL. For an index expression, 'name' is NULL and
+ * 'expr' is the expression tree.
+ */
+typedef struct IndexElem
+{
+ NodeTag type;
+ char *name; /* name of attribute to index, or NULL */
+ Node *expr; /* expression to index, or NULL */
+ char *indexcolname; /* name for index column; NULL = default */
+ List *collation; /* name of collation; NIL = default */
+ List *opclass; /* name of desired opclass; NIL = default */
+ List *opclassopts; /* opclass-specific options, or NIL */
+ SortByDir ordering; /* ASC/DESC/default */
+ SortByNulls nulls_ordering; /* FIRST/LAST/default */
+} IndexElem;
+
+/*
+ * DefElem - a generic "name = value" option definition
+ *
+ * In some contexts the name can be qualified. Also, certain SQL commands
+ * allow a SET/ADD/DROP action to be attached to option settings, so it's
+ * convenient to carry a field for that too. (Note: currently, it is our
+ * practice that the grammar allows namespace and action only in statements
+ * where they are relevant; C code can just ignore those fields in other
+ * statements.)
+ */
+typedef enum DefElemAction
+{
+ DEFELEM_UNSPEC, /* no action given */
+ DEFELEM_SET,
+ DEFELEM_ADD,
+ DEFELEM_DROP
+} DefElemAction;
+
+typedef struct DefElem
+{
+ NodeTag type;
+ char *defnamespace; /* NULL if unqualified name */
+ char *defname;
+ Node *arg; /* typically Integer, Float, String, or
+ * TypeName */
+ DefElemAction defaction; /* unspecified action, or SET/ADD/DROP */
+ int location; /* token location, or -1 if unknown */
+} DefElem;
+
+/*
+ * LockingClause - raw representation of FOR [NO KEY] UPDATE/[KEY] SHARE
+ * options
+ *
+ * Note: lockedRels == NIL means "all relations in query". Otherwise it
+ * is a list of RangeVar nodes. (We use RangeVar mainly because it carries
+ * a location field --- currently, parse analysis insists on unqualified
+ * names in LockingClause.)
+ */
+typedef struct LockingClause
+{
+ NodeTag type;
+ List *lockedRels; /* FOR [KEY] UPDATE/SHARE relations */
+ LockClauseStrength strength;
+ LockWaitPolicy waitPolicy; /* NOWAIT and SKIP LOCKED */
+} LockingClause;
+
+/*
+ * XMLSERIALIZE (in raw parse tree only)
+ */
+typedef struct XmlSerialize
+{
+ NodeTag type;
+ XmlOptionType xmloption; /* DOCUMENT or CONTENT */
+ Node *expr;
+ TypeName *typeName;
+ bool indent; /* [NO] INDENT */
+ int location; /* token location, or -1 if unknown */
+} XmlSerialize;
+
+/* Partitioning related definitions */
+
+/*
+ * PartitionElem - parse-time representation of a single partition key
+ *
+ * expr can be either a raw expression tree or a parse-analyzed expression.
+ * We don't store these on-disk, though.
+ */
+typedef struct PartitionElem
+{
+ NodeTag type;
+ char *name; /* name of column to partition on, or NULL */
+ Node *expr; /* expression to partition on, or NULL */
+ List *collation; /* name of collation; NIL = default */
+ List *opclass; /* name of desired opclass; NIL = default */
+ int location; /* token location, or -1 if unknown */
+} PartitionElem;
+
+typedef enum PartitionStrategy
+{
+ PARTITION_STRATEGY_LIST = 'l',
+ PARTITION_STRATEGY_RANGE = 'r',
+ PARTITION_STRATEGY_HASH = 'h'
+} PartitionStrategy;
+
+/*
+ * PartitionSpec - parse-time representation of a partition key specification
+ *
+ * This represents the key space we will be partitioning on.
+ */
+typedef struct PartitionSpec
+{
+ NodeTag type;
+ PartitionStrategy strategy;
+ List *partParams; /* List of PartitionElems */
+ int location; /* token location, or -1 if unknown */
+} PartitionSpec;
+
+/*
+ * PartitionBoundSpec - a partition bound specification
+ *
+ * This represents the portion of the partition key space assigned to a
+ * particular partition. These are stored on disk in pg_class.relpartbound.
+ */
+struct PartitionBoundSpec
+{
+ NodeTag type;
+
+ char strategy; /* see PARTITION_STRATEGY codes above */
+ bool is_default; /* is it a default partition bound? */
+
+ /* Partitioning info for HASH strategy: */
+ int modulus;
+ int remainder;
+
+ /* Partitioning info for LIST strategy: */
+ List *listdatums; /* List of Consts (or A_Consts in raw tree) */
+
+ /* Partitioning info for RANGE strategy: */
+ List *lowerdatums; /* List of PartitionRangeDatums */
+ List *upperdatums; /* List of PartitionRangeDatums */
+
+ int location; /* token location, or -1 if unknown */
+};
+
+/*
+ * PartitionRangeDatum - one of the values in a range partition bound
+ *
+ * This can be MINVALUE, MAXVALUE or a specific bounded value.
+ */
+typedef enum PartitionRangeDatumKind
+{
+ PARTITION_RANGE_DATUM_MINVALUE = -1, /* less than any other value */
+ PARTITION_RANGE_DATUM_VALUE = 0, /* a specific (bounded) value */
+ PARTITION_RANGE_DATUM_MAXVALUE = 1 /* greater than any other value */
+} PartitionRangeDatumKind;
+
+typedef struct PartitionRangeDatum
+{
+ NodeTag type;
+
+ PartitionRangeDatumKind kind;
+ Node *value; /* Const (or A_Const in raw tree), if kind is
+ * PARTITION_RANGE_DATUM_VALUE, else NULL */
+
+ int location; /* token location, or -1 if unknown */
+} PartitionRangeDatum;
+
+/*
+ * PartitionCmd - info for ALTER TABLE/INDEX ATTACH/DETACH PARTITION commands
+ */
+typedef struct PartitionCmd
+{
+ NodeTag type;
+ RangeVar *name; /* name of partition to attach/detach */
+ PartitionBoundSpec *bound; /* FOR VALUES, if attaching */
+ bool concurrent;
+} PartitionCmd;
+
+/****************************************************************************
+ * Nodes for a Query tree
+ ****************************************************************************/
+
+/*--------------------
+ * RangeTblEntry -
+ * A range table is a List of RangeTblEntry nodes.
+ *
+ * A range table entry may represent a plain relation, a sub-select in
+ * FROM, or the result of a JOIN clause. (Only explicit JOIN syntax
+ * produces an RTE, not the implicit join resulting from multiple FROM
+ * items. This is because we only need the RTE to deal with SQL features
+ * like outer joins and join-output-column aliasing.) Other special
+ * RTE types also exist, as indicated by RTEKind.
+ *
+ * Note that we consider RTE_RELATION to cover anything that has a pg_class
+ * entry. relkind distinguishes the sub-cases.
+ *
+ * alias is an Alias node representing the AS alias-clause attached to the
+ * FROM expression, or NULL if no clause.
+ *
+ * eref is the table reference name and column reference names (either
+ * real or aliases). Note that system columns (OID etc) are not included
+ * in the column list.
+ * eref->aliasname is required to be present, and should generally be used
+ * to identify the RTE for error messages etc.
+ *
+ * In RELATION RTEs, the colnames in both alias and eref are indexed by
+ * physical attribute number; this means there must be colname entries for
+ * dropped columns. When building an RTE we insert empty strings ("") for
+ * dropped columns. Note however that a stored rule may have nonempty
+ * colnames for columns dropped since the rule was created (and for that
+ * matter the colnames might be out of date due to column renamings).
+ * The same comments apply to FUNCTION RTEs when a function's return type
+ * is a named composite type.
+ *
+ * In JOIN RTEs, the colnames in both alias and eref are one-to-one with
+ * joinaliasvars entries. A JOIN RTE will omit columns of its inputs when
+ * those columns are known to be dropped at parse time. Again, however,
+ * a stored rule might contain entries for columns dropped since the rule
+ * was created. (This is only possible for columns not actually referenced
+ * in the rule.) When loading a stored rule, we replace the joinaliasvars
+ * items for any such columns with null pointers. (We can't simply delete
+ * them from the joinaliasvars list, because that would affect the attnums
+ * of Vars referencing the rest of the list.)
+ *
+ * inh is true for relation references that should be expanded to include
+ * inheritance children, if the rel has any. This *must* be false for
+ * RTEs other than RTE_RELATION entries.
+ *
+ * inFromCl marks those range variables that are listed in the FROM clause.
+ * It's false for RTEs that are added to a query behind the scenes, such
+ * as the NEW and OLD variables for a rule, or the subqueries of a UNION.
+ * This flag is not used during parsing (except in transformLockingClause,
+ * q.v.); the parser now uses a separate "namespace" data structure to
+ * control visibility. But it is needed by ruleutils.c to determine
+ * whether RTEs should be shown in decompiled queries.
+ *
+ * securityQuals is a list of security barrier quals (boolean expressions),
+ * to be tested in the listed order before returning a row from the
+ * relation. It is always NIL in parser output. Entries are added by the
+ * rewriter to implement security-barrier views and/or row-level security.
+ * Note that the planner turns each boolean expression into an implicitly
+ * AND'ed sublist, as is its usual habit with qualification expressions.
+ *--------------------
+ */
+typedef enum RTEKind
+{
+ RTE_RELATION, /* ordinary relation reference */
+ RTE_SUBQUERY, /* subquery in FROM */
+ RTE_JOIN, /* join */
+ RTE_FUNCTION, /* function in FROM */
+ RTE_TABLEFUNC, /* TableFunc(.., column list) */
+ RTE_VALUES, /* VALUES (<exprlist>), (<exprlist>), ... */
+ RTE_CTE, /* common table expr (WITH list element) */
+ RTE_NAMEDTUPLESTORE, /* tuplestore, e.g. for AFTER triggers */
+ RTE_RESULT /* RTE represents an empty FROM clause; such
+ * RTEs are added by the planner, they're not
+ * present during parsing or rewriting */
+} RTEKind;
+
+typedef struct RangeTblEntry
+{
+ pg_node_attr(custom_read_write, custom_query_jumble)
+
+ NodeTag type;
+
+ RTEKind rtekind; /* see above */
+
+ /*
+ * XXX the fields applicable to only some rte kinds should be merged into
+ * a union. I didn't do this yet because the diffs would impact a lot of
+ * code that is being actively worked on. FIXME someday.
+ */
+
+ /*
+ * Fields valid for a plain relation RTE (else zero):
+ *
+ * rellockmode is really LOCKMODE, but it's declared int to avoid having
+ * to include lock-related headers here. It must be RowExclusiveLock if
+ * the RTE is an INSERT/UPDATE/DELETE/MERGE target, else RowShareLock if
+ * the RTE is a SELECT FOR UPDATE/FOR SHARE target, else AccessShareLock.
+ *
+ * Note: in some cases, rule expansion may result in RTEs that are marked
+ * with RowExclusiveLock even though they are not the target of the
+ * current query; this happens if a DO ALSO rule simply scans the original
+ * target table. We leave such RTEs with their original lockmode so as to
+ * avoid getting an additional, lesser lock.
+ *
+ * perminfoindex is 1-based index of the RTEPermissionInfo belonging to
+ * this RTE in the containing struct's list of same; 0 if permissions need
+ * not be checked for this RTE.
+ *
+ * As a special case, relid, relkind, rellockmode, and perminfoindex can
+ * also be set (nonzero) in an RTE_SUBQUERY RTE. This occurs when we
+ * convert an RTE_RELATION RTE naming a view into an RTE_SUBQUERY
+ * containing the view's query. We still need to perform run-time locking
+ * and permission checks on the view, even though it's not directly used
+ * in the query anymore, and the most expedient way to do that is to
+ * retain these fields from the old state of the RTE.
+ *
+ * As a special case, RTE_NAMEDTUPLESTORE can also set relid to indicate
+ * that the tuple format of the tuplestore is the same as the referenced
+ * relation. This allows plans referencing AFTER trigger transition
+ * tables to be invalidated if the underlying table is altered.
+ */
+ Oid relid; /* OID of the relation */
+ char relkind; /* relation kind (see pg_class.relkind) */
+ int rellockmode; /* lock level that query requires on the rel */
+ struct TableSampleClause *tablesample; /* sampling info, or NULL */
+ Index perminfoindex;
+
+ /*
+ * Fields valid for a subquery RTE (else NULL):
+ */
+ Query *subquery; /* the sub-query */
+ bool security_barrier; /* is from security_barrier view? */
+
+ /*
+ * Fields valid for a join RTE (else NULL/zero):
+ *
+ * joinaliasvars is a list of (usually) Vars corresponding to the columns
+ * of the join result. An alias Var referencing column K of the join
+ * result can be replaced by the K'th element of joinaliasvars --- but to
+ * simplify the task of reverse-listing aliases correctly, we do not do
+ * that until planning time. In detail: an element of joinaliasvars can
+ * be a Var of one of the join's input relations, or such a Var with an
+ * implicit coercion to the join's output column type, or a COALESCE
+ * expression containing the two input column Vars (possibly coerced).
+ * Elements beyond the first joinmergedcols entries are always just Vars,
+ * and are never referenced from elsewhere in the query (that is, join
+ * alias Vars are generated only for merged columns). We keep these
+ * entries only because they're needed in expandRTE() and similar code.
+ *
+ * Vars appearing within joinaliasvars are marked with varnullingrels sets
+ * that describe the nulling effects of this join and lower ones. This is
+ * essential for FULL JOIN cases, because the COALESCE expression only
+ * describes the semantics correctly if its inputs have been nulled by the
+ * join. For other cases, it allows expandRTE() to generate a valid
+ * representation of the join's output without consulting additional
+ * parser state.
+ *
+ * Within a Query loaded from a stored rule, it is possible for non-merged
+ * joinaliasvars items to be null pointers, which are placeholders for
+ * (necessarily unreferenced) columns dropped since the rule was made.
+ * Also, once planning begins, joinaliasvars items can be almost anything,
+ * as a result of subquery-flattening substitutions.
+ *
+ * joinleftcols is an integer list of physical column numbers of the left
+ * join input rel that are included in the join; likewise joinrighttcols
+ * for the right join input rel. (Which rels those are can be determined
+ * from the associated JoinExpr.) If the join is USING/NATURAL, then the
+ * first joinmergedcols entries in each list identify the merged columns.
+ * The merged columns come first in the join output, then remaining
+ * columns of the left input, then remaining columns of the right.
+ *
+ * Note that input columns could have been dropped after creation of a
+ * stored rule, if they are not referenced in the query (in particular,
+ * merged columns could not be dropped); this is not accounted for in
+ * joinleftcols/joinrighttcols.
+ */
+ JoinType jointype; /* type of join */
+ int joinmergedcols; /* number of merged (JOIN USING) columns */
+ List *joinaliasvars; /* list of alias-var expansions */
+ List *joinleftcols; /* left-side input column numbers */
+ List *joinrightcols; /* right-side input column numbers */
+
+ /*
+ * join_using_alias is an alias clause attached directly to JOIN/USING. It
+ * is different from the alias field (below) in that it does not hide the
+ * range variables of the tables being joined.
+ */
+ Alias *join_using_alias;
+
+ /*
+ * Fields valid for a function RTE (else NIL/zero):
+ *
+ * When funcordinality is true, the eref->colnames list includes an alias
+ * for the ordinality column. The ordinality column is otherwise
+ * implicit, and must be accounted for "by hand" in places such as
+ * expandRTE().
+ */
+ List *functions; /* list of RangeTblFunction nodes */
+ bool funcordinality; /* is this called WITH ORDINALITY? */
+
+ /*
+ * Fields valid for a TableFunc RTE (else NULL):
+ */
+ TableFunc *tablefunc;
+
+ /*
+ * Fields valid for a values RTE (else NIL):
+ */
+ List *values_lists; /* list of expression lists */
+
+ /*
+ * Fields valid for a CTE RTE (else NULL/zero):
+ */
+ char *ctename; /* name of the WITH list item */
+ Index ctelevelsup; /* number of query levels up */
+ bool self_reference; /* is this a recursive self-reference? */
+
+ /*
+ * Fields valid for CTE, VALUES, ENR, and TableFunc RTEs (else NIL):
+ *
+ * We need these for CTE RTEs so that the types of self-referential
+ * columns are well-defined. For VALUES RTEs, storing these explicitly
+ * saves having to re-determine the info by scanning the values_lists. For
+ * ENRs, we store the types explicitly here (we could get the information
+ * from the catalogs if 'relid' was supplied, but we'd still need these
+ * for TupleDesc-based ENRs, so we might as well always store the type
+ * info here). For TableFuncs, these fields are redundant with data in
+ * the TableFunc node, but keeping them here allows some code sharing with
+ * the other cases.
+ *
+ * For ENRs only, we have to consider the possibility of dropped columns.
+ * A dropped column is included in these lists, but it will have zeroes in
+ * all three lists (as well as an empty-string entry in eref). Testing
+ * for zero coltype is the standard way to detect a dropped column.
+ */
+ List *coltypes; /* OID list of column type OIDs */
+ List *coltypmods; /* integer list of column typmods */
+ List *colcollations; /* OID list of column collation OIDs */
+
+ /*
+ * Fields valid for ENR RTEs (else NULL/zero):
+ */
+ char *enrname; /* name of ephemeral named relation */
+ Cardinality enrtuples; /* estimated or actual from caller */
+
+ /*
+ * Fields valid in all RTEs:
+ */
+ Alias *alias; /* user-written alias clause, if any */
+ Alias *eref; /* expanded reference names */
+ bool lateral; /* subquery, function, or values is LATERAL? */
+ bool inh; /* inheritance requested? */
+ bool inFromCl; /* present in FROM clause? */
+ List *securityQuals; /* security barrier quals to apply, if any */
+} RangeTblEntry;
+
+/*
+ * RTEPermissionInfo
+ * Per-relation information for permission checking. Added to the Query
+ * node by the parser when adding the corresponding RTE to the query
+ * range table and subsequently editorialized on by the rewriter if
+ * needed after rule expansion.
+ *
+ * Only the relations directly mentioned in the query are checked for
+ * access permissions by the core executor, so only their RTEPermissionInfos
+ * are present in the Query. However, extensions may want to check inheritance
+ * children too, depending on the value of rte->inh, so it's copied in 'inh'
+ * for their perusal.
+ *
+ * requiredPerms and checkAsUser specify run-time access permissions checks
+ * to be performed at query startup. The user must have *all* of the
+ * permissions that are OR'd together in requiredPerms (never 0!). If
+ * checkAsUser is not zero, then do the permissions checks using the access
+ * rights of that user, not the current effective user ID. (This allows rules
+ * to act as setuid gateways.)
+ *
+ * For SELECT/INSERT/UPDATE permissions, if the user doesn't have table-wide
+ * permissions then it is sufficient to have the permissions on all columns
+ * identified in selectedCols (for SELECT) and/or insertedCols and/or
+ * updatedCols (INSERT with ON CONFLICT DO UPDATE may have all 3).
+ * selectedCols, insertedCols and updatedCols are bitmapsets, which cannot have
+ * negative integer members, so we subtract FirstLowInvalidHeapAttributeNumber
+ * from column numbers before storing them in these fields. A whole-row Var
+ * reference is represented by setting the bit for InvalidAttrNumber.
+ *
+ * updatedCols is also used in some other places, for example, to determine
+ * which triggers to fire and in FDWs to know which changed columns they need
+ * to ship off.
+ */
+typedef struct RTEPermissionInfo
+{
+ NodeTag type;
+
+ Oid relid; /* relation OID */
+ bool inh; /* separately check inheritance children? */
+ AclMode requiredPerms; /* bitmask of required access permissions */
+ Oid checkAsUser; /* if valid, check access as this role */
+ Bitmapset *selectedCols; /* columns needing SELECT permission */
+ Bitmapset *insertedCols; /* columns needing INSERT permission */
+ Bitmapset *updatedCols; /* columns needing UPDATE permission */
+} RTEPermissionInfo;
+
+/*
+ * RangeTblFunction -
+ * RangeTblEntry subsidiary data for one function in a FUNCTION RTE.
+ *
+ * If the function had a column definition list (required for an
+ * otherwise-unspecified RECORD result), funccolnames lists the names given
+ * in the definition list, funccoltypes lists their declared column types,
+ * funccoltypmods lists their typmods, funccolcollations their collations.
+ * Otherwise, those fields are NIL.
+ *
+ * Notice we don't attempt to store info about the results of functions
+ * returning named composite types, because those can change from time to
+ * time. We do however remember how many columns we thought the type had
+ * (including dropped columns!), so that we can successfully ignore any
+ * columns added after the query was parsed.
+ *
+ * The query jumbling only needs to track the function expression.
+ */
+typedef struct RangeTblFunction
+{
+ NodeTag type;
+
+ Node *funcexpr; /* expression tree for func call */
+ /* number of columns it contributes to RTE */
+ int funccolcount pg_node_attr(query_jumble_ignore);
+ /* These fields record the contents of a column definition list, if any: */
+ /* column names (list of String) */
+ List *funccolnames pg_node_attr(query_jumble_ignore);
+ /* OID list of column type OIDs */
+ List *funccoltypes pg_node_attr(query_jumble_ignore);
+ /* integer list of column typmods */
+ List *funccoltypmods pg_node_attr(query_jumble_ignore);
+ /* OID list of column collation OIDs */
+ List *funccolcollations pg_node_attr(query_jumble_ignore);
+
+ /* This is set during planning for use by the executor: */
+ /* PARAM_EXEC Param IDs affecting this func */
+ Bitmapset *funcparams pg_node_attr(query_jumble_ignore);
+} RangeTblFunction;
+
+/*
+ * TableSampleClause - TABLESAMPLE appearing in a transformed FROM clause
+ *
+ * Unlike RangeTableSample, this is a subnode of the relevant RangeTblEntry.
+ */
+typedef struct TableSampleClause
+{
+ NodeTag type;
+ Oid tsmhandler; /* OID of the tablesample handler function */
+ List *args; /* tablesample argument expression(s) */
+ Expr *repeatable; /* REPEATABLE expression, or NULL if none */
+} TableSampleClause;
+
+/*
+ * WithCheckOption -
+ * representation of WITH CHECK OPTION checks to be applied to new tuples
+ * when inserting/updating an auto-updatable view, or RLS WITH CHECK
+ * policies to be applied when inserting/updating a relation with RLS.
+ */
+typedef enum WCOKind
+{
+ WCO_VIEW_CHECK, /* WCO on an auto-updatable view */
+ WCO_RLS_INSERT_CHECK, /* RLS INSERT WITH CHECK policy */
+ WCO_RLS_UPDATE_CHECK, /* RLS UPDATE WITH CHECK policy */
+ WCO_RLS_CONFLICT_CHECK, /* RLS ON CONFLICT DO UPDATE USING policy */
+ WCO_RLS_MERGE_UPDATE_CHECK, /* RLS MERGE UPDATE USING policy */
+ WCO_RLS_MERGE_DELETE_CHECK /* RLS MERGE DELETE USING policy */
+} WCOKind;
+
+typedef struct WithCheckOption
+{
+ NodeTag type;
+ WCOKind kind; /* kind of WCO */
+ char *relname; /* name of relation that specified the WCO */
+ char *polname; /* name of RLS policy being checked */
+ Node *qual; /* constraint qual to check */
+ bool cascaded; /* true for a cascaded WCO on a view */
+} WithCheckOption;
+
+/*
+ * SortGroupClause -
+ * representation of ORDER BY, GROUP BY, PARTITION BY,
+ * DISTINCT, DISTINCT ON items
+ *
+ * You might think that ORDER BY is only interested in defining ordering,
+ * and GROUP/DISTINCT are only interested in defining equality. However,
+ * one way to implement grouping is to sort and then apply a "uniq"-like
+ * filter. So it's also interesting to keep track of possible sort operators
+ * for GROUP/DISTINCT, and in particular to try to sort for the grouping
+ * in a way that will also yield a requested ORDER BY ordering. So we need
+ * to be able to compare ORDER BY and GROUP/DISTINCT lists, which motivates
+ * the decision to give them the same representation.
+ *
+ * tleSortGroupRef must match ressortgroupref of exactly one entry of the
+ * query's targetlist; that is the expression to be sorted or grouped by.
+ * eqop is the OID of the equality operator.
+ * sortop is the OID of the ordering operator (a "<" or ">" operator),
+ * or InvalidOid if not available.
+ * nulls_first means about what you'd expect. If sortop is InvalidOid
+ * then nulls_first is meaningless and should be set to false.
+ * hashable is true if eqop is hashable (note this condition also depends
+ * on the datatype of the input expression).
+ *
+ * In an ORDER BY item, all fields must be valid. (The eqop isn't essential
+ * here, but it's cheap to get it along with the sortop, and requiring it
+ * to be valid eases comparisons to grouping items.) Note that this isn't
+ * actually enough information to determine an ordering: if the sortop is
+ * collation-sensitive, a collation OID is needed too. We don't store the
+ * collation in SortGroupClause because it's not available at the time the
+ * parser builds the SortGroupClause; instead, consult the exposed collation
+ * of the referenced targetlist expression to find out what it is.
+ *
+ * In a grouping item, eqop must be valid. If the eqop is a btree equality
+ * operator, then sortop should be set to a compatible ordering operator.
+ * We prefer to set eqop/sortop/nulls_first to match any ORDER BY item that
+ * the query presents for the same tlist item. If there is none, we just
+ * use the default ordering op for the datatype.
+ *
+ * If the tlist item's type has a hash opclass but no btree opclass, then
+ * we will set eqop to the hash equality operator, sortop to InvalidOid,
+ * and nulls_first to false. A grouping item of this kind can only be
+ * implemented by hashing, and of course it'll never match an ORDER BY item.
+ *
+ * The hashable flag is provided since we generally have the requisite
+ * information readily available when the SortGroupClause is constructed,
+ * and it's relatively expensive to get it again later. Note there is no
+ * need for a "sortable" flag since OidIsValid(sortop) serves the purpose.
+ *
+ * A query might have both ORDER BY and DISTINCT (or DISTINCT ON) clauses.
+ * In SELECT DISTINCT, the distinctClause list is as long or longer than the
+ * sortClause list, while in SELECT DISTINCT ON it's typically shorter.
+ * The two lists must match up to the end of the shorter one --- the parser
+ * rearranges the distinctClause if necessary to make this true. (This
+ * restriction ensures that only one sort step is needed to both satisfy the
+ * ORDER BY and set up for the Unique step. This is semantically necessary
+ * for DISTINCT ON, and presents no real drawback for DISTINCT.)
+ */
+typedef struct SortGroupClause
+{
+ NodeTag type;
+ Index tleSortGroupRef; /* reference into targetlist */
+ Oid eqop; /* the equality operator ('=' op) */
+ Oid sortop; /* the ordering operator ('<' op), or 0 */
+ bool nulls_first; /* do NULLs come before normal values? */
+ /* can eqop be implemented by hashing? */
+ bool hashable pg_node_attr(query_jumble_ignore);
+} SortGroupClause;
+
+/*
+ * GroupingSet -
+ * representation of CUBE, ROLLUP and GROUPING SETS clauses
+ *
+ * In a Query with grouping sets, the groupClause contains a flat list of
+ * SortGroupClause nodes for each distinct expression used. The actual
+ * structure of the GROUP BY clause is given by the groupingSets tree.
+ *
+ * In the raw parser output, GroupingSet nodes (of all types except SIMPLE
+ * which is not used) are potentially mixed in with the expressions in the
+ * groupClause of the SelectStmt. (An expression can't contain a GroupingSet,
+ * but a list may mix GroupingSet and expression nodes.) At this stage, the
+ * content of each node is a list of expressions, some of which may be RowExprs
+ * which represent sublists rather than actual row constructors, and nested
+ * GroupingSet nodes where legal in the grammar. The structure directly
+ * reflects the query syntax.
+ *
+ * In parse analysis, the transformed expressions are used to build the tlist
+ * and groupClause list (of SortGroupClause nodes), and the groupingSets tree
+ * is eventually reduced to a fixed format:
+ *
+ * EMPTY nodes represent (), and obviously have no content
+ *
+ * SIMPLE nodes represent a list of one or more expressions to be treated as an
+ * atom by the enclosing structure; the content is an integer list of
+ * ressortgroupref values (see SortGroupClause)
+ *
+ * CUBE and ROLLUP nodes contain a list of one or more SIMPLE nodes.
+ *
+ * SETS nodes contain a list of EMPTY, SIMPLE, CUBE or ROLLUP nodes, but after
+ * parse analysis they cannot contain more SETS nodes; enough of the syntactic
+ * transforms of the spec have been applied that we no longer have arbitrarily
+ * deep nesting (though we still preserve the use of cube/rollup).
+ *
+ * Note that if the groupingSets tree contains no SIMPLE nodes (only EMPTY
+ * nodes at the leaves), then the groupClause will be empty, but this is still
+ * an aggregation query (similar to using aggs or HAVING without GROUP BY).
+ *
+ * As an example, the following clause:
+ *
+ * GROUP BY GROUPING SETS ((a,b), CUBE(c,(d,e)))
+ *
+ * looks like this after raw parsing:
+ *
+ * SETS( RowExpr(a,b) , CUBE( c, RowExpr(d,e) ) )
+ *
+ * and parse analysis converts it to:
+ *
+ * SETS( SIMPLE(1,2), CUBE( SIMPLE(3), SIMPLE(4,5) ) )
+ */
+typedef enum GroupingSetKind
+{
+ GROUPING_SET_EMPTY,
+ GROUPING_SET_SIMPLE,
+ GROUPING_SET_ROLLUP,
+ GROUPING_SET_CUBE,
+ GROUPING_SET_SETS
+} GroupingSetKind;
+
+typedef struct GroupingSet
+{
+ NodeTag type;
+ GroupingSetKind kind pg_node_attr(query_jumble_ignore);
+ List *content;
+ int location;
+} GroupingSet;
+
+/*
+ * WindowClause -
+ * transformed representation of WINDOW and OVER clauses
+ *
+ * A parsed Query's windowClause list contains these structs. "name" is set
+ * if the clause originally came from WINDOW, and is NULL if it originally
+ * was an OVER clause (but note that we collapse out duplicate OVERs).
+ * partitionClause and orderClause are lists of SortGroupClause structs.
+ * If we have RANGE with offset PRECEDING/FOLLOWING, the semantics of that are
+ * specified by startInRangeFunc/inRangeColl/inRangeAsc/inRangeNullsFirst
+ * for the start offset, or endInRangeFunc/inRange* for the end offset.
+ * winref is an ID number referenced by WindowFunc nodes; it must be unique
+ * among the members of a Query's windowClause list.
+ * When refname isn't null, the partitionClause is always copied from there;
+ * the orderClause might or might not be copied (see copiedOrder); the framing
+ * options are never copied, per spec.
+ *
+ * The information relevant for the query jumbling is the partition clause
+ * type and its bounds.
+ */
+typedef struct WindowClause
+{
+ NodeTag type;
+ /* window name (NULL in an OVER clause) */
+ char *name pg_node_attr(query_jumble_ignore);
+ /* referenced window name, if any */
+ char *refname pg_node_attr(query_jumble_ignore);
+ List *partitionClause; /* PARTITION BY list */
+ /* ORDER BY list */
+ List *orderClause;
+ int frameOptions; /* frame_clause options, see WindowDef */
+ Node *startOffset; /* expression for starting bound, if any */
+ Node *endOffset; /* expression for ending bound, if any */
+ /* qual to help short-circuit execution */
+ List *runCondition pg_node_attr(query_jumble_ignore);
+ /* in_range function for startOffset */
+ Oid startInRangeFunc pg_node_attr(query_jumble_ignore);
+ /* in_range function for endOffset */
+ Oid endInRangeFunc pg_node_attr(query_jumble_ignore);
+ /* collation for in_range tests */
+ Oid inRangeColl pg_node_attr(query_jumble_ignore);
+ /* use ASC sort order for in_range tests? */
+ bool inRangeAsc pg_node_attr(query_jumble_ignore);
+ /* nulls sort first for in_range tests? */
+ bool inRangeNullsFirst pg_node_attr(query_jumble_ignore);
+ Index winref; /* ID referenced by window functions */
+ /* did we copy orderClause from refname? */
+ bool copiedOrder pg_node_attr(query_jumble_ignore);
+} WindowClause;
+
+/*
+ * RowMarkClause -
+ * parser output representation of FOR [KEY] UPDATE/SHARE clauses
+ *
+ * Query.rowMarks contains a separate RowMarkClause node for each relation
+ * identified as a FOR [KEY] UPDATE/SHARE target. If one of these clauses
+ * is applied to a subquery, we generate RowMarkClauses for all normal and
+ * subquery rels in the subquery, but they are marked pushedDown = true to
+ * distinguish them from clauses that were explicitly written at this query
+ * level. Also, Query.hasForUpdate tells whether there were explicit FOR
+ * UPDATE/SHARE/KEY SHARE clauses in the current query level.
+ */
+typedef struct RowMarkClause
+{
+ NodeTag type;
+ Index rti; /* range table index of target relation */
+ LockClauseStrength strength;
+ LockWaitPolicy waitPolicy; /* NOWAIT and SKIP LOCKED */
+ bool pushedDown; /* pushed down from higher query level? */
+} RowMarkClause;
+
+/*
+ * WithClause -
+ * representation of WITH clause
+ *
+ * Note: WithClause does not propagate into the Query representation;
+ * but CommonTableExpr does.
+ */
+typedef struct WithClause
+{
+ NodeTag type;
+ List *ctes; /* list of CommonTableExprs */
+ bool recursive; /* true = WITH RECURSIVE */
+ int location; /* token location, or -1 if unknown */
+} WithClause;
+
+/*
+ * InferClause -
+ * ON CONFLICT unique index inference clause
+ *
+ * Note: InferClause does not propagate into the Query representation.
+ */
+typedef struct InferClause
+{
+ NodeTag type;
+ List *indexElems; /* IndexElems to infer unique index */
+ Node *whereClause; /* qualification (partial-index predicate) */
+ char *conname; /* Constraint name, or NULL if unnamed */
+ int location; /* token location, or -1 if unknown */
+} InferClause;
+
+/*
+ * OnConflictClause -
+ * representation of ON CONFLICT clause
+ *
+ * Note: OnConflictClause does not propagate into the Query representation.
+ */
+typedef struct OnConflictClause
+{
+ NodeTag type;
+ OnConflictAction action; /* DO NOTHING or UPDATE? */
+ InferClause *infer; /* Optional index inference clause */
+ List *targetList; /* the target list (of ResTarget) */
+ Node *whereClause; /* qualifications */
+ int location; /* token location, or -1 if unknown */
+} OnConflictClause;
+
+/*
+ * CommonTableExpr -
+ * representation of WITH list element
+ */
+
+typedef enum CTEMaterialize
+{
+ CTEMaterializeDefault, /* no option specified */
+ CTEMaterializeAlways, /* MATERIALIZED */
+ CTEMaterializeNever /* NOT MATERIALIZED */
+} CTEMaterialize;
+
+typedef struct CTESearchClause
+{
+ NodeTag type;
+ List *search_col_list;
+ bool search_breadth_first;
+ char *search_seq_column;
+ int location;
+} CTESearchClause;
+
+typedef struct CTECycleClause
+{
+ NodeTag type;
+ List *cycle_col_list;
+ char *cycle_mark_column;
+ Node *cycle_mark_value;
+ Node *cycle_mark_default;
+ char *cycle_path_column;
+ int location;
+ /* These fields are set during parse analysis: */
+ Oid cycle_mark_type; /* common type of _value and _default */
+ int cycle_mark_typmod;
+ Oid cycle_mark_collation;
+ Oid cycle_mark_neop; /* <> operator for type */
+} CTECycleClause;
+
+typedef struct CommonTableExpr
+{
+ NodeTag type;
+
+ /*
+ * Query name (never qualified). The string name is included in the query
+ * jumbling because RTE_CTE RTEs need it.
+ */
+ char *ctename;
+ /* optional list of column names */
+ List *aliascolnames pg_node_attr(query_jumble_ignore);
+ CTEMaterialize ctematerialized; /* is this an optimization fence? */
+ /* SelectStmt/InsertStmt/etc before parse analysis, Query afterwards: */
+ Node *ctequery; /* the CTE's subquery */
+ CTESearchClause *search_clause pg_node_attr(query_jumble_ignore);
+ CTECycleClause *cycle_clause pg_node_attr(query_jumble_ignore);
+ int location; /* token location, or -1 if unknown */
+ /* These fields are set during parse analysis: */
+ /* is this CTE actually recursive? */
+ bool cterecursive pg_node_attr(query_jumble_ignore);
+
+ /*
+ * Number of RTEs referencing this CTE (excluding internal
+ * self-references), irrelevant for query jumbling.
+ */
+ int cterefcount pg_node_attr(query_jumble_ignore);
+ /* list of output column names */
+ List *ctecolnames pg_node_attr(query_jumble_ignore);
+ /* OID list of output column type OIDs */
+ List *ctecoltypes pg_node_attr(query_jumble_ignore);
+ /* integer list of output column typmods */
+ List *ctecoltypmods pg_node_attr(query_jumble_ignore);
+ /* OID list of column collation OIDs */
+ List *ctecolcollations pg_node_attr(query_jumble_ignore);
+} CommonTableExpr;
+
+/* Convenience macro to get the output tlist of a CTE's query */
+#define GetCTETargetList(cte) \
+ (AssertMacro(IsA((cte)->ctequery, Query)), \
+ ((Query *) (cte)->ctequery)->commandType == CMD_SELECT ? \
+ ((Query *) (cte)->ctequery)->targetList : \
+ ((Query *) (cte)->ctequery)->returningList)
+
+/*
+ * MergeWhenClause -
+ * raw parser representation of a WHEN clause in a MERGE statement
+ *
+ * This is transformed into MergeAction by parse analysis
+ */
+typedef struct MergeWhenClause
+{
+ NodeTag type;
+ bool matched; /* true=MATCHED, false=NOT MATCHED */
+ CmdType commandType; /* INSERT/UPDATE/DELETE/DO NOTHING */
+ OverridingKind override; /* OVERRIDING clause */
+ Node *condition; /* WHEN conditions (raw parser) */
+ List *targetList; /* INSERT/UPDATE targetlist */
+ /* the following members are only used in INSERT actions */
+ List *values; /* VALUES to INSERT, or NULL */
+} MergeWhenClause;
+
+/*
+ * MergeAction -
+ * Transformed representation of a WHEN clause in a MERGE statement
+ */
+typedef struct MergeAction
+{
+ NodeTag type;
+ bool matched; /* true=MATCHED, false=NOT MATCHED */
+ CmdType commandType; /* INSERT/UPDATE/DELETE/DO NOTHING */
+ /* OVERRIDING clause */
+ OverridingKind override pg_node_attr(query_jumble_ignore);
+ Node *qual; /* transformed WHEN conditions */
+ List *targetList; /* the target list (of TargetEntry) */
+ /* target attribute numbers of an UPDATE */
+ List *updateColnos pg_node_attr(query_jumble_ignore);
+} MergeAction;
+
+/*
+ * TriggerTransition -
+ * representation of transition row or table naming clause
+ *
+ * Only transition tables are initially supported in the syntax, and only for
+ * AFTER triggers, but other permutations are accepted by the parser so we can
+ * give a meaningful message from C code.
+ */
+typedef struct TriggerTransition
+{
+ NodeTag type;
+ char *name;
+ bool isNew;
+ bool isTable;
+} TriggerTransition;
+
+/* Nodes for SQL/JSON support */
+
+/*
+ * JsonOutput -
+ * representation of JSON output clause (RETURNING type [FORMAT format])
+ */
+typedef struct JsonOutput
+{
+ NodeTag type;
+ TypeName *typeName; /* RETURNING type name, if specified */
+ JsonReturning *returning; /* RETURNING FORMAT clause and type Oids */
+} JsonOutput;
+
+/*
+ * JsonKeyValue -
+ * untransformed representation of JSON object key-value pair for
+ * JSON_OBJECT() and JSON_OBJECTAGG()
+ */
+typedef struct JsonKeyValue
+{
+ NodeTag type;
+ Expr *key; /* key expression */
+ JsonValueExpr *value; /* JSON value expression */
+} JsonKeyValue;
+
+/*
+ * JsonObjectConstructor -
+ * untransformed representation of JSON_OBJECT() constructor
+ */
+typedef struct JsonObjectConstructor
+{
+ NodeTag type;
+ List *exprs; /* list of JsonKeyValue pairs */
+ JsonOutput *output; /* RETURNING clause, if specified */
+ bool absent_on_null; /* skip NULL values? */
+ bool unique; /* check key uniqueness? */
+ int location; /* token location, or -1 if unknown */
+} JsonObjectConstructor;
+
+/*
+ * JsonArrayConstructor -
+ * untransformed representation of JSON_ARRAY(element,...) constructor
+ */
+typedef struct JsonArrayConstructor
+{
+ NodeTag type;
+ List *exprs; /* list of JsonValueExpr elements */
+ JsonOutput *output; /* RETURNING clause, if specified */
+ bool absent_on_null; /* skip NULL elements? */
+ int location; /* token location, or -1 if unknown */
+} JsonArrayConstructor;
+
+/*
+ * JsonArrayQueryConstructor -
+ * untransformed representation of JSON_ARRAY(subquery) constructor
+ */
+typedef struct JsonArrayQueryConstructor
+{
+ NodeTag type;
+ Node *query; /* subquery */
+ JsonOutput *output; /* RETURNING clause, if specified */
+ JsonFormat *format; /* FORMAT clause for subquery, if specified */
+ bool absent_on_null; /* skip NULL elements? */
+ int location; /* token location, or -1 if unknown */
+} JsonArrayQueryConstructor;
+
+/*
+ * JsonAggConstructor -
+ * common fields of untransformed representation of
+ * JSON_ARRAYAGG() and JSON_OBJECTAGG()
+ */
+typedef struct JsonAggConstructor
+{
+ NodeTag type;
+ JsonOutput *output; /* RETURNING clause, if any */
+ Node *agg_filter; /* FILTER clause, if any */
+ List *agg_order; /* ORDER BY clause, if any */
+ struct WindowDef *over; /* OVER clause, if any */
+ int location; /* token location, or -1 if unknown */
+} JsonAggConstructor;
+
+/*
+ * JsonObjectAgg -
+ * untransformed representation of JSON_OBJECTAGG()
+ */
+typedef struct JsonObjectAgg
+{
+ NodeTag type;
+ JsonAggConstructor *constructor; /* common fields */
+ JsonKeyValue *arg; /* object key-value pair */
+ bool absent_on_null; /* skip NULL values? */
+ bool unique; /* check key uniqueness? */
+} JsonObjectAgg;
+
+/*
+ * JsonArrayAgg -
+ * untransformed representation of JSON_ARRAYAGG()
+ */
+typedef struct JsonArrayAgg
+{
+ NodeTag type;
+ JsonAggConstructor *constructor; /* common fields */
+ JsonValueExpr *arg; /* array element expression */
+ bool absent_on_null; /* skip NULL elements? */
+} JsonArrayAgg;
+
+
+/*****************************************************************************
+ * Raw Grammar Output Statements
+ *****************************************************************************/
+
+/*
+ * RawStmt --- container for any one statement's raw parse tree
+ *
+ * Parse analysis converts a raw parse tree headed by a RawStmt node into
+ * an analyzed statement headed by a Query node. For optimizable statements,
+ * the conversion is complex. For utility statements, the parser usually just
+ * transfers the raw parse tree (sans RawStmt) into the utilityStmt field of
+ * the Query node, and all the useful work happens at execution time.
+ *
+ * stmt_location/stmt_len identify the portion of the source text string
+ * containing this raw statement (useful for multi-statement strings).
+ *
+ * This is irrelevant for query jumbling, as this is not used in parsed
+ * queries.
+ */
+typedef struct RawStmt
+{
+ pg_node_attr(no_query_jumble)
+
+ NodeTag type;
+ Node *stmt; /* raw parse tree */
+ int stmt_location; /* start location, or -1 if unknown */
+ int stmt_len; /* length in bytes; 0 means "rest of string" */
+} RawStmt;
+
+/*****************************************************************************
+ * Optimizable Statements
+ *****************************************************************************/
+
+/* ----------------------
+ * Insert Statement
+ *
+ * The source expression is represented by SelectStmt for both the
+ * SELECT and VALUES cases. If selectStmt is NULL, then the query
+ * is INSERT ... DEFAULT VALUES.
+ * ----------------------
+ */
+typedef struct InsertStmt
+{
+ NodeTag type;
+ RangeVar *relation; /* relation to insert into */
+ List *cols; /* optional: names of the target columns */
+ Node *selectStmt; /* the source SELECT/VALUES, or NULL */
+ OnConflictClause *onConflictClause; /* ON CONFLICT clause */
+ List *returningList; /* list of expressions to return */
+ WithClause *withClause; /* WITH clause */
+ OverridingKind override; /* OVERRIDING clause */
+} InsertStmt;
+
+/* ----------------------
+ * Delete Statement
+ * ----------------------
+ */
+typedef struct DeleteStmt
+{
+ NodeTag type;
+ RangeVar *relation; /* relation to delete from */
+ List *usingClause; /* optional using clause for more tables */
+ Node *whereClause; /* qualifications */
+ List *returningList; /* list of expressions to return */
+ WithClause *withClause; /* WITH clause */
+} DeleteStmt;
+
+/* ----------------------
+ * Update Statement
+ * ----------------------
+ */
+typedef struct UpdateStmt
+{
+ NodeTag type;
+ RangeVar *relation; /* relation to update */
+ List *targetList; /* the target list (of ResTarget) */
+ Node *whereClause; /* qualifications */
+ List *fromClause; /* optional from clause for more tables */
+ List *returningList; /* list of expressions to return */
+ WithClause *withClause; /* WITH clause */
+} UpdateStmt;
+
+/* ----------------------
+ * Merge Statement
+ * ----------------------
+ */
+typedef struct MergeStmt
+{
+ NodeTag type;
+ RangeVar *relation; /* target relation to merge into */
+ Node *sourceRelation; /* source relation */
+ Node *joinCondition; /* join condition between source and target */
+ List *mergeWhenClauses; /* list of MergeWhenClause(es) */
+ WithClause *withClause; /* WITH clause */
+} MergeStmt;
+
+/* ----------------------
+ * Select Statement
+ *
+ * A "simple" SELECT is represented in the output of gram.y by a single
+ * SelectStmt node; so is a VALUES construct. A query containing set
+ * operators (UNION, INTERSECT, EXCEPT) is represented by a tree of SelectStmt
+ * nodes, in which the leaf nodes are component SELECTs and the internal nodes
+ * represent UNION, INTERSECT, or EXCEPT operators. Using the same node
+ * type for both leaf and internal nodes allows gram.y to stick ORDER BY,
+ * LIMIT, etc, clause values into a SELECT statement without worrying
+ * whether it is a simple or compound SELECT.
+ * ----------------------
+ */
+typedef enum SetOperation
+{
+ SETOP_NONE = 0,
+ SETOP_UNION,
+ SETOP_INTERSECT,
+ SETOP_EXCEPT
+} SetOperation;
+
+typedef struct SelectStmt
+{
+ NodeTag type;
+
+ /*
+ * These fields are used only in "leaf" SelectStmts.
+ */
+ List *distinctClause; /* NULL, list of DISTINCT ON exprs, or
+ * lcons(NIL,NIL) for all (SELECT DISTINCT) */
+ IntoClause *intoClause; /* target for SELECT INTO */
+ List *targetList; /* the target list (of ResTarget) */
+ List *fromClause; /* the FROM clause */
+ Node *whereClause; /* WHERE qualification */
+ List *groupClause; /* GROUP BY clauses */
+ bool groupDistinct; /* Is this GROUP BY DISTINCT? */
+ Node *havingClause; /* HAVING conditional-expression */
+ List *windowClause; /* WINDOW window_name AS (...), ... */
+
+ /*
+ * In a "leaf" node representing a VALUES list, the above fields are all
+ * null, and instead this field is set. Note that the elements of the
+ * sublists are just expressions, without ResTarget decoration. Also note
+ * that a list element can be DEFAULT (represented as a SetToDefault
+ * node), regardless of the context of the VALUES list. It's up to parse
+ * analysis to reject that where not valid.
+ */
+ List *valuesLists; /* untransformed list of expression lists */
+
+ /*
+ * These fields are used in both "leaf" SelectStmts and upper-level
+ * SelectStmts.
+ */
+ List *sortClause; /* sort clause (a list of SortBy's) */
+ Node *limitOffset; /* # of result tuples to skip */
+ Node *limitCount; /* # of result tuples to return */
+ LimitOption limitOption; /* limit type */
+ List *lockingClause; /* FOR UPDATE (list of LockingClause's) */
+ WithClause *withClause; /* WITH clause */
+
+ /*
+ * These fields are used only in upper-level SelectStmts.
+ */
+ SetOperation op; /* type of set op */
+ bool all; /* ALL specified? */
+ struct SelectStmt *larg; /* left child */
+ struct SelectStmt *rarg; /* right child */
+ /* Eventually add fields for CORRESPONDING spec here */
+} SelectStmt;
+
+
+/* ----------------------
+ * Set Operation node for post-analysis query trees
+ *
+ * After parse analysis, a SELECT with set operations is represented by a
+ * top-level Query node containing the leaf SELECTs as subqueries in its
+ * range table. Its setOperations field shows the tree of set operations,
+ * with leaf SelectStmt nodes replaced by RangeTblRef nodes, and internal
+ * nodes replaced by SetOperationStmt nodes. Information about the output
+ * column types is added, too. (Note that the child nodes do not necessarily
+ * produce these types directly, but we've checked that their output types
+ * can be coerced to the output column type.) Also, if it's not UNION ALL,
+ * information about the types' sort/group semantics is provided in the form
+ * of a SortGroupClause list (same representation as, eg, DISTINCT).
+ * The resolved common column collations are provided too; but note that if
+ * it's not UNION ALL, it's okay for a column to not have a common collation,
+ * so a member of the colCollations list could be InvalidOid even though the
+ * column has a collatable type.
+ * ----------------------
+ */
+typedef struct SetOperationStmt
+{
+ NodeTag type;
+ SetOperation op; /* type of set op */
+ bool all; /* ALL specified? */
+ Node *larg; /* left child */
+ Node *rarg; /* right child */
+ /* Eventually add fields for CORRESPONDING spec here */
+
+ /* Fields derived during parse analysis (irrelevant for query jumbling): */
+ /* OID list of output column type OIDs */
+ List *colTypes pg_node_attr(query_jumble_ignore);
+ /* integer list of output column typmods */
+ List *colTypmods pg_node_attr(query_jumble_ignore);
+ /* OID list of output column collation OIDs */
+ List *colCollations pg_node_attr(query_jumble_ignore);
+ /* a list of SortGroupClause's */
+ List *groupClauses pg_node_attr(query_jumble_ignore);
+ /* groupClauses is NIL if UNION ALL, but must be set otherwise */
+} SetOperationStmt;
+
+
+/*
+ * RETURN statement (inside SQL function body)
+ */
+typedef struct ReturnStmt
+{
+ NodeTag type;
+ Node *returnval;
+} ReturnStmt;
+
+
+/* ----------------------
+ * PL/pgSQL Assignment Statement
+ *
+ * Like SelectStmt, this is transformed into a SELECT Query.
+ * However, the targetlist of the result looks more like an UPDATE.
+ * ----------------------
+ */
+typedef struct PLAssignStmt
+{
+ NodeTag type;
+
+ char *name; /* initial column name */
+ List *indirection; /* subscripts and field names, if any */
+ int nnames; /* number of names to use in ColumnRef */
+ SelectStmt *val; /* the PL/pgSQL expression to assign */
+ int location; /* name's token location, or -1 if unknown */
+} PLAssignStmt;
+
+
+/*****************************************************************************
+ * Other Statements (no optimizations required)
+ *
+ * These are not touched by parser/analyze.c except to put them into
+ * the utilityStmt field of a Query. This is eventually passed to
+ * ProcessUtility (by-passing rewriting and planning). Some of the
+ * statements do need attention from parse analysis, and this is
+ * done by routines in parser/parse_utilcmd.c after ProcessUtility
+ * receives the command for execution.
+ * DECLARE CURSOR, EXPLAIN, and CREATE TABLE AS are special cases:
+ * they contain optimizable statements, which get processed normally
+ * by parser/analyze.c.
+ *****************************************************************************/
+
+/*
+ * When a command can act on several kinds of objects with only one
+ * parse structure required, use these constants to designate the
+ * object type. Note that commands typically don't support all the types.
+ */
+
+typedef enum ObjectType
+{
+ OBJECT_ACCESS_METHOD,
+ OBJECT_AGGREGATE,
+ OBJECT_AMOP,
+ OBJECT_AMPROC,
+ OBJECT_ATTRIBUTE, /* type's attribute, when distinct from column */
+ OBJECT_CAST,
+ OBJECT_COLUMN,
+ OBJECT_COLLATION,
+ OBJECT_CONVERSION,
+ OBJECT_DATABASE,
+ OBJECT_DEFAULT,
+ OBJECT_DEFACL,
+ OBJECT_DOMAIN,
+ OBJECT_DOMCONSTRAINT,
+ OBJECT_EVENT_TRIGGER,
+ OBJECT_EXTENSION,
+ OBJECT_FDW,
+ OBJECT_FOREIGN_SERVER,
+ OBJECT_FOREIGN_TABLE,
+ OBJECT_FUNCTION,
+ OBJECT_INDEX,
+ OBJECT_LANGUAGE,
+ OBJECT_LARGEOBJECT,
+ OBJECT_MATVIEW,
+ OBJECT_OPCLASS,
+ OBJECT_OPERATOR,
+ OBJECT_OPFAMILY,
+ OBJECT_PARAMETER_ACL,
+ OBJECT_POLICY,
+ OBJECT_PROCEDURE,
+ OBJECT_PUBLICATION,
+ OBJECT_PUBLICATION_NAMESPACE,
+ OBJECT_PUBLICATION_REL,
+ OBJECT_ROLE,
+ OBJECT_ROUTINE,
+ OBJECT_RULE,
+ OBJECT_SCHEMA,
+ OBJECT_SEQUENCE,
+ OBJECT_SUBSCRIPTION,
+ OBJECT_STATISTIC_EXT,
+ OBJECT_TABCONSTRAINT,
+ OBJECT_TABLE,
+ OBJECT_TABLESPACE,
+ OBJECT_TRANSFORM,
+ OBJECT_TRIGGER,
+ OBJECT_TSCONFIGURATION,
+ OBJECT_TSDICTIONARY,
+ OBJECT_TSPARSER,
+ OBJECT_TSTEMPLATE,
+ OBJECT_TYPE,
+ OBJECT_USER_MAPPING,
+ OBJECT_VIEW
+} ObjectType;
+
+/* ----------------------
+ * Create Schema Statement
+ *
+ * NOTE: the schemaElts list contains raw parsetrees for component statements
+ * of the schema, such as CREATE TABLE, GRANT, etc. These are analyzed and
+ * executed after the schema itself is created.
+ * ----------------------
+ */
+typedef struct CreateSchemaStmt
+{
+ NodeTag type;
+ char *schemaname; /* the name of the schema to create */
+ RoleSpec *authrole; /* the owner of the created schema */
+ List *schemaElts; /* schema components (list of parsenodes) */
+ bool if_not_exists; /* just do nothing if schema already exists? */
+} CreateSchemaStmt;
+
+typedef enum DropBehavior
+{
+ DROP_RESTRICT, /* drop fails if any dependent objects */
+ DROP_CASCADE /* remove dependent objects too */
+} DropBehavior;
+
+/* ----------------------
+ * Alter Table
+ * ----------------------
+ */
+typedef struct AlterTableStmt
+{
+ NodeTag type;
+ RangeVar *relation; /* table to work on */
+ List *cmds; /* list of subcommands */
+ ObjectType objtype; /* type of object */
+ bool missing_ok; /* skip error if table missing */
+} AlterTableStmt;
+
+typedef enum AlterTableType
+{
+ AT_AddColumn, /* add column */
+ AT_AddColumnToView, /* implicitly via CREATE OR REPLACE VIEW */
+ AT_ColumnDefault, /* alter column default */
+ AT_CookedColumnDefault, /* add a pre-cooked column default */
+ AT_DropNotNull, /* alter column drop not null */
+ AT_SetNotNull, /* alter column set not null */
+ AT_DropExpression, /* alter column drop expression */
+ AT_CheckNotNull, /* check column is already marked not null */
+ AT_SetStatistics, /* alter column set statistics */
+ AT_SetOptions, /* alter column set ( options ) */
+ AT_ResetOptions, /* alter column reset ( options ) */
+ AT_SetStorage, /* alter column set storage */
+ AT_SetCompression, /* alter column set compression */
+ AT_DropColumn, /* drop column */
+ AT_AddIndex, /* add index */
+ AT_ReAddIndex, /* internal to commands/tablecmds.c */
+ AT_AddConstraint, /* add constraint */
+ AT_ReAddConstraint, /* internal to commands/tablecmds.c */
+ AT_ReAddDomainConstraint, /* internal to commands/tablecmds.c */
+ AT_AlterConstraint, /* alter constraint */
+ AT_ValidateConstraint, /* validate constraint */
+ AT_AddIndexConstraint, /* add constraint using existing index */
+ AT_DropConstraint, /* drop constraint */
+ AT_ReAddComment, /* internal to commands/tablecmds.c */
+ AT_AlterColumnType, /* alter column type */
+ AT_AlterColumnGenericOptions, /* alter column OPTIONS (...) */
+ AT_ChangeOwner, /* change owner */
+ AT_ClusterOn, /* CLUSTER ON */
+ AT_DropCluster, /* SET WITHOUT CLUSTER */
+ AT_SetLogged, /* SET LOGGED */
+ AT_SetUnLogged, /* SET UNLOGGED */
+ AT_DropOids, /* SET WITHOUT OIDS */
+ AT_SetAccessMethod, /* SET ACCESS METHOD */
+ AT_SetTableSpace, /* SET TABLESPACE */
+ AT_SetRelOptions, /* SET (...) -- AM specific parameters */
+ AT_ResetRelOptions, /* RESET (...) -- AM specific parameters */
+ AT_ReplaceRelOptions, /* replace reloption list in its entirety */
+ AT_EnableTrig, /* ENABLE TRIGGER name */
+ AT_EnableAlwaysTrig, /* ENABLE ALWAYS TRIGGER name */
+ AT_EnableReplicaTrig, /* ENABLE REPLICA TRIGGER name */
+ AT_DisableTrig, /* DISABLE TRIGGER name */
+ AT_EnableTrigAll, /* ENABLE TRIGGER ALL */
+ AT_DisableTrigAll, /* DISABLE TRIGGER ALL */
+ AT_EnableTrigUser, /* ENABLE TRIGGER USER */
+ AT_DisableTrigUser, /* DISABLE TRIGGER USER */
+ AT_EnableRule, /* ENABLE RULE name */
+ AT_EnableAlwaysRule, /* ENABLE ALWAYS RULE name */
+ AT_EnableReplicaRule, /* ENABLE REPLICA RULE name */
+ AT_DisableRule, /* DISABLE RULE name */
+ AT_AddInherit, /* INHERIT parent */
+ AT_DropInherit, /* NO INHERIT parent */
+ AT_AddOf, /* OF <type_name> */
+ AT_DropOf, /* NOT OF */
+ AT_ReplicaIdentity, /* REPLICA IDENTITY */
+ AT_EnableRowSecurity, /* ENABLE ROW SECURITY */
+ AT_DisableRowSecurity, /* DISABLE ROW SECURITY */
+ AT_ForceRowSecurity, /* FORCE ROW SECURITY */
+ AT_NoForceRowSecurity, /* NO FORCE ROW SECURITY */
+ AT_GenericOptions, /* OPTIONS (...) */
+ AT_AttachPartition, /* ATTACH PARTITION */
+ AT_DetachPartition, /* DETACH PARTITION */
+ AT_DetachPartitionFinalize, /* DETACH PARTITION FINALIZE */
+ AT_AddIdentity, /* ADD IDENTITY */
+ AT_SetIdentity, /* SET identity column options */
+ AT_DropIdentity, /* DROP IDENTITY */
+ AT_ReAddStatistics /* internal to commands/tablecmds.c */
+} AlterTableType;
+
+typedef struct ReplicaIdentityStmt
+{
+ NodeTag type;
+ char identity_type;
+ char *name;
+} ReplicaIdentityStmt;
+
+typedef struct AlterTableCmd /* one subcommand of an ALTER TABLE */
+{
+ NodeTag type;
+ AlterTableType subtype; /* Type of table alteration to apply */
+ char *name; /* column, constraint, or trigger to act on,
+ * or tablespace */
+ int16 num; /* attribute number for columns referenced by
+ * number */
+ RoleSpec *newowner;
+ Node *def; /* definition of new column, index,
+ * constraint, or parent table */
+ DropBehavior behavior; /* RESTRICT or CASCADE for DROP cases */
+ bool missing_ok; /* skip error if missing? */
+ bool recurse; /* exec-time recursion */
+} AlterTableCmd;
+
+
+/* ----------------------
+ * Alter Collation
+ * ----------------------
+ */
+typedef struct AlterCollationStmt
+{
+ NodeTag type;
+ List *collname;
+} AlterCollationStmt;
+
+
+/* ----------------------
+ * Alter Domain
+ *
+ * The fields are used in different ways by the different variants of
+ * this command.
+ * ----------------------
+ */
+typedef struct AlterDomainStmt
+{
+ NodeTag type;
+ char subtype; /*------------
+ * T = alter column default
+ * N = alter column drop not null
+ * O = alter column set not null
+ * C = add constraint
+ * X = drop constraint
+ *------------
+ */
+ List *typeName; /* domain to work on */
+ char *name; /* column or constraint name to act on */
+ Node *def; /* definition of default or constraint */
+ DropBehavior behavior; /* RESTRICT or CASCADE for DROP cases */
+ bool missing_ok; /* skip error if missing? */
+} AlterDomainStmt;
+
+
+/* ----------------------
+ * Grant|Revoke Statement
+ * ----------------------
+ */
+typedef enum GrantTargetType
+{
+ ACL_TARGET_OBJECT, /* grant on specific named object(s) */
+ ACL_TARGET_ALL_IN_SCHEMA, /* grant on all objects in given schema(s) */
+ ACL_TARGET_DEFAULTS /* ALTER DEFAULT PRIVILEGES */
+} GrantTargetType;
+
+typedef struct GrantStmt
+{
+ NodeTag type;
+ bool is_grant; /* true = GRANT, false = REVOKE */
+ GrantTargetType targtype; /* type of the grant target */
+ ObjectType objtype; /* kind of object being operated on */
+ List *objects; /* list of RangeVar nodes, ObjectWithArgs
+ * nodes, or plain names (as String values) */
+ List *privileges; /* list of AccessPriv nodes */
+ /* privileges == NIL denotes ALL PRIVILEGES */
+ List *grantees; /* list of RoleSpec nodes */
+ bool grant_option; /* grant or revoke grant option */
+ RoleSpec *grantor;
+ DropBehavior behavior; /* drop behavior (for REVOKE) */
+} GrantStmt;
+
+/*
+ * ObjectWithArgs represents a function/procedure/operator name plus parameter
+ * identification.
+ *
+ * objargs includes only the types of the input parameters of the object.
+ * In some contexts, that will be all we have, and it's enough to look up
+ * objects according to the traditional Postgres rules (i.e., when only input
+ * arguments matter).
+ *
+ * objfuncargs, if not NIL, carries the full specification of the parameter
+ * list, including parameter mode annotations.
+ *
+ * Some grammar productions can set args_unspecified = true instead of
+ * providing parameter info. In this case, lookup will succeed only if
+ * the object name is unique. Note that otherwise, NIL parameter lists
+ * mean zero arguments.
+ */
+typedef struct ObjectWithArgs
+{
+ NodeTag type;
+ List *objname; /* qualified name of function/operator */
+ List *objargs; /* list of Typename nodes (input args only) */
+ List *objfuncargs; /* list of FunctionParameter nodes */
+ bool args_unspecified; /* argument list was omitted? */
+} ObjectWithArgs;
+
+/*
+ * An access privilege, with optional list of column names
+ * priv_name == NULL denotes ALL PRIVILEGES (only used with a column list)
+ * cols == NIL denotes "all columns"
+ * Note that simple "ALL PRIVILEGES" is represented as a NIL list, not
+ * an AccessPriv with both fields null.
+ */
+typedef struct AccessPriv
+{
+ NodeTag type;
+ char *priv_name; /* string name of privilege */
+ List *cols; /* list of String */
+} AccessPriv;
+
+/* ----------------------
+ * Grant/Revoke Role Statement
+ *
+ * Note: because of the parsing ambiguity with the GRANT <privileges>
+ * statement, granted_roles is a list of AccessPriv; the execution code
+ * should complain if any column lists appear. grantee_roles is a list
+ * of role names, as String values.
+ * ----------------------
+ */
+typedef struct GrantRoleStmt
+{
+ NodeTag type;
+ List *granted_roles; /* list of roles to be granted/revoked */
+ List *grantee_roles; /* list of member roles to add/delete */
+ bool is_grant; /* true = GRANT, false = REVOKE */
+ List *opt; /* options e.g. WITH GRANT OPTION */
+ RoleSpec *grantor; /* set grantor to other than current role */
+ DropBehavior behavior; /* drop behavior (for REVOKE) */
+} GrantRoleStmt;
+
+/* ----------------------
+ * Alter Default Privileges Statement
+ * ----------------------
+ */
+typedef struct AlterDefaultPrivilegesStmt
+{
+ NodeTag type;
+ List *options; /* list of DefElem */
+ GrantStmt *action; /* GRANT/REVOKE action (with objects=NIL) */
+} AlterDefaultPrivilegesStmt;
+
+/* ----------------------
+ * Copy Statement
+ *
+ * We support "COPY relation FROM file", "COPY relation TO file", and
+ * "COPY (query) TO file". In any given CopyStmt, exactly one of "relation"
+ * and "query" must be non-NULL.
+ * ----------------------
+ */
+typedef struct CopyStmt
+{
+ NodeTag type;
+ RangeVar *relation; /* the relation to copy */
+ Node *query; /* the query (SELECT or DML statement with
+ * RETURNING) to copy, as a raw parse tree */
+ List *attlist; /* List of column names (as Strings), or NIL
+ * for all columns */
+ bool is_from; /* TO or FROM */
+ bool is_program; /* is 'filename' a program to popen? */
+ char *filename; /* filename, or NULL for STDIN/STDOUT */
+ List *options; /* List of DefElem nodes */
+ Node *whereClause; /* WHERE condition (or NULL) */
+} CopyStmt;
+
+/* ----------------------
+ * SET Statement (includes RESET)
+ *
+ * "SET var TO DEFAULT" and "RESET var" are semantically equivalent, but we
+ * preserve the distinction in VariableSetKind for CreateCommandTag().
+ * ----------------------
+ */
+typedef enum VariableSetKind
+{
+ VAR_SET_VALUE, /* SET var = value */
+ VAR_SET_DEFAULT, /* SET var TO DEFAULT */
+ VAR_SET_CURRENT, /* SET var FROM CURRENT */
+ VAR_SET_MULTI, /* special case for SET TRANSACTION ... */
+ VAR_RESET, /* RESET var */
+ VAR_RESET_ALL /* RESET ALL */
+} VariableSetKind;
+
+typedef struct VariableSetStmt
+{
+ NodeTag type;
+ VariableSetKind kind;
+ char *name; /* variable to be set */
+ List *args; /* List of A_Const nodes */
+ bool is_local; /* SET LOCAL? */
+} VariableSetStmt;
+
+/* ----------------------
+ * Show Statement
+ * ----------------------
+ */
+typedef struct VariableShowStmt
+{
+ NodeTag type;
+ char *name;
+} VariableShowStmt;
+
+/* ----------------------
+ * Create Table Statement
+ *
+ * NOTE: in the raw gram.y output, ColumnDef and Constraint nodes are
+ * intermixed in tableElts, and constraints is NIL. After parse analysis,
+ * tableElts contains just ColumnDefs, and constraints contains just
+ * Constraint nodes (in fact, only CONSTR_CHECK nodes, in the present
+ * implementation).
+ * ----------------------
+ */
+
+typedef struct CreateStmt
+{
+ NodeTag type;
+ RangeVar *relation; /* relation to create */
+ List *tableElts; /* column definitions (list of ColumnDef) */
+ List *inhRelations; /* relations to inherit from (list of
+ * RangeVar) */
+ PartitionBoundSpec *partbound; /* FOR VALUES clause */
+ PartitionSpec *partspec; /* PARTITION BY clause */
+ TypeName *ofTypename; /* OF typename */
+ List *constraints; /* constraints (list of Constraint nodes) */
+ List *options; /* options from WITH clause */
+ OnCommitAction oncommit; /* what do we do at COMMIT? */
+ char *tablespacename; /* table space to use, or NULL */
+ char *accessMethod; /* table access method */
+ bool if_not_exists; /* just do nothing if it already exists? */
+} CreateStmt;
+
+/* ----------
+ * Definitions for constraints in CreateStmt
+ *
+ * Note that column defaults are treated as a type of constraint,
+ * even though that's a bit odd semantically.
+ *
+ * For constraints that use expressions (CONSTR_CHECK, CONSTR_DEFAULT)
+ * we may have the expression in either "raw" form (an untransformed
+ * parse tree) or "cooked" form (the nodeToString representation of
+ * an executable expression tree), depending on how this Constraint
+ * node was created (by parsing, or by inheritance from an existing
+ * relation). We should never have both in the same node!
+ *
+ * FKCONSTR_ACTION_xxx values are stored into pg_constraint.confupdtype
+ * and pg_constraint.confdeltype columns; FKCONSTR_MATCH_xxx values are
+ * stored into pg_constraint.confmatchtype. Changing the code values may
+ * require an initdb!
+ *
+ * If skip_validation is true then we skip checking that the existing rows
+ * in the table satisfy the constraint, and just install the catalog entries
+ * for the constraint. A new FK constraint is marked as valid iff
+ * initially_valid is true. (Usually skip_validation and initially_valid
+ * are inverses, but we can set both true if the table is known empty.)
+ *
+ * Constraint attributes (DEFERRABLE etc) are initially represented as
+ * separate Constraint nodes for simplicity of parsing. parse_utilcmd.c makes
+ * a pass through the constraints list to insert the info into the appropriate
+ * Constraint node.
+ * ----------
+ */
+
+typedef enum ConstrType /* types of constraints */
+{
+ CONSTR_NULL, /* not standard SQL, but a lot of people
+ * expect it */
+ CONSTR_NOTNULL,
+ CONSTR_DEFAULT,
+ CONSTR_IDENTITY,
+ CONSTR_GENERATED,
+ CONSTR_CHECK,
+ CONSTR_PRIMARY,
+ CONSTR_UNIQUE,
+ CONSTR_EXCLUSION,
+ CONSTR_FOREIGN,
+ CONSTR_ATTR_DEFERRABLE, /* attributes for previous constraint node */
+ CONSTR_ATTR_NOT_DEFERRABLE,
+ CONSTR_ATTR_DEFERRED,
+ CONSTR_ATTR_IMMEDIATE
+} ConstrType;
+
+/* Foreign key action codes */
+#define FKCONSTR_ACTION_NOACTION 'a'
+#define FKCONSTR_ACTION_RESTRICT 'r'
+#define FKCONSTR_ACTION_CASCADE 'c'
+#define FKCONSTR_ACTION_SETNULL 'n'
+#define FKCONSTR_ACTION_SETDEFAULT 'd'
+
+/* Foreign key matchtype codes */
+#define FKCONSTR_MATCH_FULL 'f'
+#define FKCONSTR_MATCH_PARTIAL 'p'
+#define FKCONSTR_MATCH_SIMPLE 's'
+
+typedef struct Constraint
+{
+ pg_node_attr(custom_read_write)
+
+ NodeTag type;
+ ConstrType contype; /* see above */
+
+ /* Fields used for most/all constraint types: */
+ char *conname; /* Constraint name, or NULL if unnamed */
+ bool deferrable; /* DEFERRABLE? */
+ bool initdeferred; /* INITIALLY DEFERRED? */
+ int location; /* token location, or -1 if unknown */
+
+ /* Fields used for constraints with expressions (CHECK and DEFAULT): */
+ bool is_no_inherit; /* is constraint non-inheritable? */
+ Node *raw_expr; /* expr, as untransformed parse tree */
+ char *cooked_expr; /* expr, as nodeToString representation */
+ char generated_when; /* ALWAYS or BY DEFAULT */
+
+ /* Fields used for unique constraints (UNIQUE and PRIMARY KEY): */
+ bool nulls_not_distinct; /* null treatment for UNIQUE constraints */
+ List *keys; /* String nodes naming referenced key
+ * column(s) */
+ List *including; /* String nodes naming referenced nonkey
+ * column(s) */
+
+ /* Fields used for EXCLUSION constraints: */
+ List *exclusions; /* list of (IndexElem, operator name) pairs */
+
+ /* Fields used for index constraints (UNIQUE, PRIMARY KEY, EXCLUSION): */
+ List *options; /* options from WITH clause */
+ char *indexname; /* existing index to use; otherwise NULL */
+ char *indexspace; /* index tablespace; NULL for default */
+ bool reset_default_tblspc; /* reset default_tablespace prior to
+ * creating the index */
+ /* These could be, but currently are not, used for UNIQUE/PKEY: */
+ char *access_method; /* index access method; NULL for default */
+ Node *where_clause; /* partial index predicate */
+
+ /* Fields used for FOREIGN KEY constraints: */
+ RangeVar *pktable; /* Primary key table */
+ List *fk_attrs; /* Attributes of foreign key */
+ List *pk_attrs; /* Corresponding attrs in PK table */
+ char fk_matchtype; /* FULL, PARTIAL, SIMPLE */
+ char fk_upd_action; /* ON UPDATE action */
+ char fk_del_action; /* ON DELETE action */
+ List *fk_del_set_cols; /* ON DELETE SET NULL/DEFAULT (col1, col2) */
+ List *old_conpfeqop; /* pg_constraint.conpfeqop of my former self */
+ Oid old_pktable_oid; /* pg_constraint.confrelid of my former
+ * self */
+
+ /* Fields used for constraints that allow a NOT VALID specification */
+ bool skip_validation; /* skip validation of existing rows? */
+ bool initially_valid; /* mark the new constraint as valid? */
+} Constraint;
+
+/* ----------------------
+ * Create/Drop Table Space Statements
+ * ----------------------
+ */
+
+typedef struct CreateTableSpaceStmt
+{
+ NodeTag type;
+ char *tablespacename;
+ RoleSpec *owner;
+ char *location;
+ List *options;
+} CreateTableSpaceStmt;
+
+typedef struct DropTableSpaceStmt
+{
+ NodeTag type;
+ char *tablespacename;
+ bool missing_ok; /* skip error if missing? */
+} DropTableSpaceStmt;
+
+typedef struct AlterTableSpaceOptionsStmt
+{
+ NodeTag type;
+ char *tablespacename;
+ List *options;
+ bool isReset;
+} AlterTableSpaceOptionsStmt;
+
+typedef struct AlterTableMoveAllStmt
+{
+ NodeTag type;
+ char *orig_tablespacename;
+ ObjectType objtype; /* Object type to move */
+ List *roles; /* List of roles to move objects of */
+ char *new_tablespacename;
+ bool nowait;
+} AlterTableMoveAllStmt;
+
+/* ----------------------
+ * Create/Alter Extension Statements
+ * ----------------------
+ */
+
+typedef struct CreateExtensionStmt
+{
+ NodeTag type;
+ char *extname;
+ bool if_not_exists; /* just do nothing if it already exists? */
+ List *options; /* List of DefElem nodes */
+} CreateExtensionStmt;
+
+/* Only used for ALTER EXTENSION UPDATE; later might need an action field */
+typedef struct AlterExtensionStmt
+{
+ NodeTag type;
+ char *extname;
+ List *options; /* List of DefElem nodes */
+} AlterExtensionStmt;
+
+typedef struct AlterExtensionContentsStmt
+{
+ NodeTag type;
+ char *extname; /* Extension's name */
+ int action; /* +1 = add object, -1 = drop object */
+ ObjectType objtype; /* Object's type */
+ Node *object; /* Qualified name of the object */
+} AlterExtensionContentsStmt;
+
+/* ----------------------
+ * Create/Alter FOREIGN DATA WRAPPER Statements
+ * ----------------------
+ */
+
+typedef struct CreateFdwStmt
+{
+ NodeTag type;
+ char *fdwname; /* foreign-data wrapper name */
+ List *func_options; /* HANDLER/VALIDATOR options */
+ List *options; /* generic options to FDW */
+} CreateFdwStmt;
+
+typedef struct AlterFdwStmt
+{
+ NodeTag type;
+ char *fdwname; /* foreign-data wrapper name */
+ List *func_options; /* HANDLER/VALIDATOR options */
+ List *options; /* generic options to FDW */
+} AlterFdwStmt;
+
+/* ----------------------
+ * Create/Alter FOREIGN SERVER Statements
+ * ----------------------
+ */
+
+typedef struct CreateForeignServerStmt
+{
+ NodeTag type;
+ char *servername; /* server name */
+ char *servertype; /* optional server type */
+ char *version; /* optional server version */
+ char *fdwname; /* FDW name */
+ bool if_not_exists; /* just do nothing if it already exists? */
+ List *options; /* generic options to server */
+} CreateForeignServerStmt;
+
+typedef struct AlterForeignServerStmt
+{
+ NodeTag type;
+ char *servername; /* server name */
+ char *version; /* optional server version */
+ List *options; /* generic options to server */
+ bool has_version; /* version specified */
+} AlterForeignServerStmt;
+
+/* ----------------------
+ * Create FOREIGN TABLE Statement
+ * ----------------------
+ */
+
+typedef struct CreateForeignTableStmt
+{
+ CreateStmt base;
+ char *servername;
+ List *options;
+} CreateForeignTableStmt;
+
+/* ----------------------
+ * Create/Drop USER MAPPING Statements
+ * ----------------------
+ */
+
+typedef struct CreateUserMappingStmt
+{
+ NodeTag type;
+ RoleSpec *user; /* user role */
+ char *servername; /* server name */
+ bool if_not_exists; /* just do nothing if it already exists? */
+ List *options; /* generic options to server */
+} CreateUserMappingStmt;
+
+typedef struct AlterUserMappingStmt
+{
+ NodeTag type;
+ RoleSpec *user; /* user role */
+ char *servername; /* server name */
+ List *options; /* generic options to server */
+} AlterUserMappingStmt;
+
+typedef struct DropUserMappingStmt
+{
+ NodeTag type;
+ RoleSpec *user; /* user role */
+ char *servername; /* server name */
+ bool missing_ok; /* ignore missing mappings */
+} DropUserMappingStmt;
+
+/* ----------------------
+ * Import Foreign Schema Statement
+ * ----------------------
+ */
+
+typedef enum ImportForeignSchemaType
+{
+ FDW_IMPORT_SCHEMA_ALL, /* all relations wanted */
+ FDW_IMPORT_SCHEMA_LIMIT_TO, /* include only listed tables in import */
+ FDW_IMPORT_SCHEMA_EXCEPT /* exclude listed tables from import */
+} ImportForeignSchemaType;
+
+typedef struct ImportForeignSchemaStmt
+{
+ NodeTag type;
+ char *server_name; /* FDW server name */
+ char *remote_schema; /* remote schema name to query */
+ char *local_schema; /* local schema to create objects in */
+ ImportForeignSchemaType list_type; /* type of table list */
+ List *table_list; /* List of RangeVar */
+ List *options; /* list of options to pass to FDW */
+} ImportForeignSchemaStmt;
+
+/*----------------------
+ * Create POLICY Statement
+ *----------------------
+ */
+typedef struct CreatePolicyStmt
+{
+ NodeTag type;
+ char *policy_name; /* Policy's name */
+ RangeVar *table; /* the table name the policy applies to */
+ char *cmd_name; /* the command name the policy applies to */
+ bool permissive; /* restrictive or permissive policy */
+ List *roles; /* the roles associated with the policy */
+ Node *qual; /* the policy's condition */
+ Node *with_check; /* the policy's WITH CHECK condition. */
+} CreatePolicyStmt;
+
+/*----------------------
+ * Alter POLICY Statement
+ *----------------------
+ */
+typedef struct AlterPolicyStmt
+{
+ NodeTag type;
+ char *policy_name; /* Policy's name */
+ RangeVar *table; /* the table name the policy applies to */
+ List *roles; /* the roles associated with the policy */
+ Node *qual; /* the policy's condition */
+ Node *with_check; /* the policy's WITH CHECK condition. */
+} AlterPolicyStmt;
+
+/*----------------------
+ * Create ACCESS METHOD Statement
+ *----------------------
+ */
+typedef struct CreateAmStmt
+{
+ NodeTag type;
+ char *amname; /* access method name */
+ List *handler_name; /* handler function name */
+ char amtype; /* type of access method */
+} CreateAmStmt;
+
+/* ----------------------
+ * Create TRIGGER Statement
+ * ----------------------
+ */
+typedef struct CreateTrigStmt
+{
+ NodeTag type;
+ bool replace; /* replace trigger if already exists */
+ bool isconstraint; /* This is a constraint trigger */
+ char *trigname; /* TRIGGER's name */
+ RangeVar *relation; /* relation trigger is on */
+ List *funcname; /* qual. name of function to call */
+ List *args; /* list of String or NIL */
+ bool row; /* ROW/STATEMENT */
+ /* timing uses the TRIGGER_TYPE bits defined in catalog/pg_trigger.h */
+ int16 timing; /* BEFORE, AFTER, or INSTEAD */
+ /* events uses the TRIGGER_TYPE bits defined in catalog/pg_trigger.h */
+ int16 events; /* "OR" of INSERT/UPDATE/DELETE/TRUNCATE */
+ List *columns; /* column names, or NIL for all columns */
+ Node *whenClause; /* qual expression, or NULL if none */
+ /* explicitly named transition data */
+ List *transitionRels; /* TriggerTransition nodes, or NIL if none */
+ /* The remaining fields are only used for constraint triggers */
+ bool deferrable; /* [NOT] DEFERRABLE */
+ bool initdeferred; /* INITIALLY {DEFERRED|IMMEDIATE} */
+ RangeVar *constrrel; /* opposite relation, if RI trigger */
+} CreateTrigStmt;
+
+/* ----------------------
+ * Create EVENT TRIGGER Statement
+ * ----------------------
+ */
+typedef struct CreateEventTrigStmt
+{
+ NodeTag type;
+ char *trigname; /* TRIGGER's name */
+ char *eventname; /* event's identifier */
+ List *whenclause; /* list of DefElems indicating filtering */
+ List *funcname; /* qual. name of function to call */
+} CreateEventTrigStmt;
+
+/* ----------------------
+ * Alter EVENT TRIGGER Statement
+ * ----------------------
+ */
+typedef struct AlterEventTrigStmt
+{
+ NodeTag type;
+ char *trigname; /* TRIGGER's name */
+ char tgenabled; /* trigger's firing configuration WRT
+ * session_replication_role */
+} AlterEventTrigStmt;
+
+/* ----------------------
+ * Create LANGUAGE Statements
+ * ----------------------
+ */
+typedef struct CreatePLangStmt
+{
+ NodeTag type;
+ bool replace; /* T => replace if already exists */
+ char *plname; /* PL name */
+ List *plhandler; /* PL call handler function (qual. name) */
+ List *plinline; /* optional inline function (qual. name) */
+ List *plvalidator; /* optional validator function (qual. name) */
+ bool pltrusted; /* PL is trusted */
+} CreatePLangStmt;
+
+/* ----------------------
+ * Create/Alter/Drop Role Statements
+ *
+ * Note: these node types are also used for the backwards-compatible
+ * Create/Alter/Drop User/Group statements. In the ALTER and DROP cases
+ * there's really no need to distinguish what the original spelling was,
+ * but for CREATE we mark the type because the defaults vary.
+ * ----------------------
+ */
+typedef enum RoleStmtType
+{
+ ROLESTMT_ROLE,
+ ROLESTMT_USER,
+ ROLESTMT_GROUP
+} RoleStmtType;
+
+typedef struct CreateRoleStmt
+{
+ NodeTag type;
+ RoleStmtType stmt_type; /* ROLE/USER/GROUP */
+ char *role; /* role name */
+ List *options; /* List of DefElem nodes */
+} CreateRoleStmt;
+
+typedef struct AlterRoleStmt
+{
+ NodeTag type;
+ RoleSpec *role; /* role */
+ List *options; /* List of DefElem nodes */
+ int action; /* +1 = add members, -1 = drop members */
+} AlterRoleStmt;
+
+typedef struct AlterRoleSetStmt
+{
+ NodeTag type;
+ RoleSpec *role; /* role */
+ char *database; /* database name, or NULL */
+ VariableSetStmt *setstmt; /* SET or RESET subcommand */
+} AlterRoleSetStmt;
+
+typedef struct DropRoleStmt
+{
+ NodeTag type;
+ List *roles; /* List of roles to remove */
+ bool missing_ok; /* skip error if a role is missing? */
+} DropRoleStmt;
+
+/* ----------------------
+ * {Create|Alter} SEQUENCE Statement
+ * ----------------------
+ */
+
+typedef struct CreateSeqStmt
+{
+ NodeTag type;
+ RangeVar *sequence; /* the sequence to create */
+ List *options;
+ Oid ownerId; /* ID of owner, or InvalidOid for default */
+ bool for_identity;
+ bool if_not_exists; /* just do nothing if it already exists? */
+} CreateSeqStmt;
+
+typedef struct AlterSeqStmt
+{
+ NodeTag type;
+ RangeVar *sequence; /* the sequence to alter */
+ List *options;
+ bool for_identity;
+ bool missing_ok; /* skip error if a role is missing? */
+} AlterSeqStmt;
+
+/* ----------------------
+ * Create {Aggregate|Operator|Type} Statement
+ * ----------------------
+ */
+typedef struct DefineStmt
+{
+ NodeTag type;
+ ObjectType kind; /* aggregate, operator, type */
+ bool oldstyle; /* hack to signal old CREATE AGG syntax */
+ List *defnames; /* qualified name (list of String) */
+ List *args; /* a list of TypeName (if needed) */
+ List *definition; /* a list of DefElem */
+ bool if_not_exists; /* just do nothing if it already exists? */
+ bool replace; /* replace if already exists? */
+} DefineStmt;
+
+/* ----------------------
+ * Create Domain Statement
+ * ----------------------
+ */
+typedef struct CreateDomainStmt
+{
+ NodeTag type;
+ List *domainname; /* qualified name (list of String) */
+ TypeName *typeName; /* the base type */
+ CollateClause *collClause; /* untransformed COLLATE spec, if any */
+ List *constraints; /* constraints (list of Constraint nodes) */
+} CreateDomainStmt;
+
+/* ----------------------
+ * Create Operator Class Statement
+ * ----------------------
+ */
+typedef struct CreateOpClassStmt
+{
+ NodeTag type;
+ List *opclassname; /* qualified name (list of String) */
+ List *opfamilyname; /* qualified name (ditto); NIL if omitted */
+ char *amname; /* name of index AM opclass is for */
+ TypeName *datatype; /* datatype of indexed column */
+ List *items; /* List of CreateOpClassItem nodes */
+ bool isDefault; /* Should be marked as default for type? */
+} CreateOpClassStmt;
+
+#define OPCLASS_ITEM_OPERATOR 1
+#define OPCLASS_ITEM_FUNCTION 2
+#define OPCLASS_ITEM_STORAGETYPE 3
+
+typedef struct CreateOpClassItem
+{
+ NodeTag type;
+ int itemtype; /* see codes above */
+ ObjectWithArgs *name; /* operator or function name and args */
+ int number; /* strategy num or support proc num */
+ List *order_family; /* only used for ordering operators */
+ List *class_args; /* amproclefttype/amprocrighttype or
+ * amoplefttype/amoprighttype */
+ /* fields used for a storagetype item: */
+ TypeName *storedtype; /* datatype stored in index */
+} CreateOpClassItem;
+
+/* ----------------------
+ * Create Operator Family Statement
+ * ----------------------
+ */
+typedef struct CreateOpFamilyStmt
+{
+ NodeTag type;
+ List *opfamilyname; /* qualified name (list of String) */
+ char *amname; /* name of index AM opfamily is for */
+} CreateOpFamilyStmt;
+
+/* ----------------------
+ * Alter Operator Family Statement
+ * ----------------------
+ */
+typedef struct AlterOpFamilyStmt
+{
+ NodeTag type;
+ List *opfamilyname; /* qualified name (list of String) */
+ char *amname; /* name of index AM opfamily is for */
+ bool isDrop; /* ADD or DROP the items? */
+ List *items; /* List of CreateOpClassItem nodes */
+} AlterOpFamilyStmt;
+
+/* ----------------------
+ * Drop Table|Sequence|View|Index|Type|Domain|Conversion|Schema Statement
+ * ----------------------
+ */
+
+typedef struct DropStmt
+{
+ NodeTag type;
+ List *objects; /* list of names */
+ ObjectType removeType; /* object type */
+ DropBehavior behavior; /* RESTRICT or CASCADE behavior */
+ bool missing_ok; /* skip error if object is missing? */
+ bool concurrent; /* drop index concurrently? */
+} DropStmt;
+
+/* ----------------------
+ * Truncate Table Statement
+ * ----------------------
+ */
+typedef struct TruncateStmt
+{
+ NodeTag type;
+ List *relations; /* relations (RangeVars) to be truncated */
+ bool restart_seqs; /* restart owned sequences? */
+ DropBehavior behavior; /* RESTRICT or CASCADE behavior */
+} TruncateStmt;
+
+/* ----------------------
+ * Comment On Statement
+ * ----------------------
+ */
+typedef struct CommentStmt
+{
+ NodeTag type;
+ ObjectType objtype; /* Object's type */
+ Node *object; /* Qualified name of the object */
+ char *comment; /* Comment to insert, or NULL to remove */
+} CommentStmt;
+
+/* ----------------------
+ * SECURITY LABEL Statement
+ * ----------------------
+ */
+typedef struct SecLabelStmt
+{
+ NodeTag type;
+ ObjectType objtype; /* Object's type */
+ Node *object; /* Qualified name of the object */
+ char *provider; /* Label provider (or NULL) */
+ char *label; /* New security label to be assigned */
+} SecLabelStmt;
+
+/* ----------------------
+ * Declare Cursor Statement
+ *
+ * The "query" field is initially a raw parse tree, and is converted to a
+ * Query node during parse analysis. Note that rewriting and planning
+ * of the query are always postponed until execution.
+ * ----------------------
+ */
+#define CURSOR_OPT_BINARY 0x0001 /* BINARY */
+#define CURSOR_OPT_SCROLL 0x0002 /* SCROLL explicitly given */
+#define CURSOR_OPT_NO_SCROLL 0x0004 /* NO SCROLL explicitly given */
+#define CURSOR_OPT_INSENSITIVE 0x0008 /* INSENSITIVE */
+#define CURSOR_OPT_ASENSITIVE 0x0010 /* ASENSITIVE */
+#define CURSOR_OPT_HOLD 0x0020 /* WITH HOLD */
+/* these planner-control flags do not correspond to any SQL grammar: */
+#define CURSOR_OPT_FAST_PLAN 0x0100 /* prefer fast-start plan */
+#define CURSOR_OPT_GENERIC_PLAN 0x0200 /* force use of generic plan */
+#define CURSOR_OPT_CUSTOM_PLAN 0x0400 /* force use of custom plan */
+#define CURSOR_OPT_PARALLEL_OK 0x0800 /* parallel mode OK */
+
+typedef struct DeclareCursorStmt
+{
+ NodeTag type;
+ char *portalname; /* name of the portal (cursor) */
+ int options; /* bitmask of options (see above) */
+ Node *query; /* the query (see comments above) */
+} DeclareCursorStmt;
+
+/* ----------------------
+ * Close Portal Statement
+ * ----------------------
+ */
+typedef struct ClosePortalStmt
+{
+ NodeTag type;
+ char *portalname; /* name of the portal (cursor) */
+ /* NULL means CLOSE ALL */
+} ClosePortalStmt;
+
+/* ----------------------
+ * Fetch Statement (also Move)
+ * ----------------------
+ */
+typedef enum FetchDirection
+{
+ /* for these, howMany is how many rows to fetch; FETCH_ALL means ALL */
+ FETCH_FORWARD,
+ FETCH_BACKWARD,
+ /* for these, howMany indicates a position; only one row is fetched */
+ FETCH_ABSOLUTE,
+ FETCH_RELATIVE
+} FetchDirection;
+
+#define FETCH_ALL LONG_MAX
+
+typedef struct FetchStmt
+{
+ NodeTag type;
+ FetchDirection direction; /* see above */
+ long howMany; /* number of rows, or position argument */
+ char *portalname; /* name of portal (cursor) */
+ bool ismove; /* true if MOVE */
+} FetchStmt;
+
+/* ----------------------
+ * Create Index Statement
+ *
+ * This represents creation of an index and/or an associated constraint.
+ * If isconstraint is true, we should create a pg_constraint entry along
+ * with the index. But if indexOid isn't InvalidOid, we are not creating an
+ * index, just a UNIQUE/PKEY constraint using an existing index. isconstraint
+ * must always be true in this case, and the fields describing the index
+ * properties are empty.
+ * ----------------------
+ */
+typedef struct IndexStmt
+{
+ NodeTag type;
+ char *idxname; /* name of new index, or NULL for default */
+ RangeVar *relation; /* relation to build index on */
+ char *accessMethod; /* name of access method (eg. btree) */
+ char *tableSpace; /* tablespace, or NULL for default */
+ List *indexParams; /* columns to index: a list of IndexElem */
+ List *indexIncludingParams; /* additional columns to index: a list
+ * of IndexElem */
+ List *options; /* WITH clause options: a list of DefElem */
+ Node *whereClause; /* qualification (partial-index predicate) */
+ List *excludeOpNames; /* exclusion operator names, or NIL if none */
+ char *idxcomment; /* comment to apply to index, or NULL */
+ Oid indexOid; /* OID of an existing index, if any */
+ RelFileNumber oldNumber; /* relfilenumber of existing storage, if any */
+ SubTransactionId oldCreateSubid; /* rd_createSubid of oldNumber */
+ SubTransactionId oldFirstRelfilelocatorSubid; /* rd_firstRelfilelocatorSubid
+ * of oldNumber */
+ bool unique; /* is index unique? */
+ bool nulls_not_distinct; /* null treatment for UNIQUE constraints */
+ bool primary; /* is index a primary key? */
+ bool isconstraint; /* is it for a pkey/unique constraint? */
+ bool deferrable; /* is the constraint DEFERRABLE? */
+ bool initdeferred; /* is the constraint INITIALLY DEFERRED? */
+ bool transformed; /* true when transformIndexStmt is finished */
+ bool concurrent; /* should this be a concurrent index build? */
+ bool if_not_exists; /* just do nothing if index already exists? */
+ bool reset_default_tblspc; /* reset default_tablespace prior to
+ * executing */
+} IndexStmt;
+
+/* ----------------------
+ * Create Statistics Statement
+ * ----------------------
+ */
+typedef struct CreateStatsStmt
+{
+ NodeTag type;
+ List *defnames; /* qualified name (list of String) */
+ List *stat_types; /* stat types (list of String) */
+ List *exprs; /* expressions to build statistics on */
+ List *relations; /* rels to build stats on (list of RangeVar) */
+ char *stxcomment; /* comment to apply to stats, or NULL */
+ bool transformed; /* true when transformStatsStmt is finished */
+ bool if_not_exists; /* do nothing if stats name already exists */
+} CreateStatsStmt;
+
+/*
+ * StatsElem - statistics parameters (used in CREATE STATISTICS)
+ *
+ * For a plain attribute, 'name' is the name of the referenced table column
+ * and 'expr' is NULL. For an expression, 'name' is NULL and 'expr' is the
+ * expression tree.
+ */
+typedef struct StatsElem
+{
+ NodeTag type;
+ char *name; /* name of attribute to index, or NULL */
+ Node *expr; /* expression to index, or NULL */
+} StatsElem;
+
+
+/* ----------------------
+ * Alter Statistics Statement
+ * ----------------------
+ */
+typedef struct AlterStatsStmt
+{
+ NodeTag type;
+ List *defnames; /* qualified name (list of String) */
+ int stxstattarget; /* statistics target */
+ bool missing_ok; /* skip error if statistics object is missing */
+} AlterStatsStmt;
+
+/* ----------------------
+ * Create Function Statement
+ * ----------------------
+ */
+typedef struct CreateFunctionStmt
+{
+ NodeTag type;
+ bool is_procedure; /* it's really CREATE PROCEDURE */
+ bool replace; /* T => replace if already exists */
+ List *funcname; /* qualified name of function to create */
+ List *parameters; /* a list of FunctionParameter */
+ TypeName *returnType; /* the return type */
+ List *options; /* a list of DefElem */
+ Node *sql_body;
+} CreateFunctionStmt;
+
+typedef enum FunctionParameterMode
+{
+ /* the assigned enum values appear in pg_proc, don't change 'em! */
+ FUNC_PARAM_IN = 'i', /* input only */
+ FUNC_PARAM_OUT = 'o', /* output only */
+ FUNC_PARAM_INOUT = 'b', /* both */
+ FUNC_PARAM_VARIADIC = 'v', /* variadic (always input) */
+ FUNC_PARAM_TABLE = 't', /* table function output column */
+ /* this is not used in pg_proc: */
+ FUNC_PARAM_DEFAULT = 'd' /* default; effectively same as IN */
+} FunctionParameterMode;
+
+typedef struct FunctionParameter
+{
+ NodeTag type;
+ char *name; /* parameter name, or NULL if not given */
+ TypeName *argType; /* TypeName for parameter type */
+ FunctionParameterMode mode; /* IN/OUT/etc */
+ Node *defexpr; /* raw default expr, or NULL if not given */
+} FunctionParameter;
+
+typedef struct AlterFunctionStmt
+{
+ NodeTag type;
+ ObjectType objtype;
+ ObjectWithArgs *func; /* name and args of function */
+ List *actions; /* list of DefElem */
+} AlterFunctionStmt;
+
+/* ----------------------
+ * DO Statement
+ *
+ * DoStmt is the raw parser output, InlineCodeBlock is the execution-time API
+ * ----------------------
+ */
+typedef struct DoStmt
+{
+ NodeTag type;
+ List *args; /* List of DefElem nodes */
+} DoStmt;
+
+typedef struct InlineCodeBlock
+{
+ pg_node_attr(nodetag_only) /* this is not a member of parse trees */
+
+ NodeTag type;
+ char *source_text; /* source text of anonymous code block */
+ Oid langOid; /* OID of selected language */
+ bool langIsTrusted; /* trusted property of the language */
+ bool atomic; /* atomic execution context */
+} InlineCodeBlock;
+
+/* ----------------------
+ * CALL statement
+ *
+ * OUT-mode arguments are removed from the transformed funcexpr. The outargs
+ * list contains copies of the expressions for all output arguments, in the
+ * order of the procedure's declared arguments. (outargs is never evaluated,
+ * but is useful to the caller as a reference for what to assign to.)
+ * The transformed call state is not relevant in the query jumbling, only the
+ * function call is.
+ * ----------------------
+ */
+typedef struct CallStmt
+{
+ NodeTag type;
+ FuncCall *funccall; /* from the parser */
+ /* transformed call, with only input args */
+ FuncExpr *funcexpr pg_node_attr(query_jumble_ignore);
+ /* transformed output-argument expressions */
+ List *outargs pg_node_attr(query_jumble_ignore);
+} CallStmt;
+
+typedef struct CallContext
+{
+ pg_node_attr(nodetag_only) /* this is not a member of parse trees */
+
+ NodeTag type;
+ bool atomic;
+} CallContext;
+
+/* ----------------------
+ * Alter Object Rename Statement
+ * ----------------------
+ */
+typedef struct RenameStmt
+{
+ NodeTag type;
+ ObjectType renameType; /* OBJECT_TABLE, OBJECT_COLUMN, etc */
+ ObjectType relationType; /* if column name, associated relation type */
+ RangeVar *relation; /* in case it's a table */
+ Node *object; /* in case it's some other object */
+ char *subname; /* name of contained object (column, rule,
+ * trigger, etc) */
+ char *newname; /* the new name */
+ DropBehavior behavior; /* RESTRICT or CASCADE behavior */
+ bool missing_ok; /* skip error if missing? */
+} RenameStmt;
+
+/* ----------------------
+ * ALTER object DEPENDS ON EXTENSION extname
+ * ----------------------
+ */
+typedef struct AlterObjectDependsStmt
+{
+ NodeTag type;
+ ObjectType objectType; /* OBJECT_FUNCTION, OBJECT_TRIGGER, etc */
+ RangeVar *relation; /* in case a table is involved */
+ Node *object; /* name of the object */
+ String *extname; /* extension name */
+ bool remove; /* set true to remove dep rather than add */
+} AlterObjectDependsStmt;
+
+/* ----------------------
+ * ALTER object SET SCHEMA Statement
+ * ----------------------
+ */
+typedef struct AlterObjectSchemaStmt
+{
+ NodeTag type;
+ ObjectType objectType; /* OBJECT_TABLE, OBJECT_TYPE, etc */
+ RangeVar *relation; /* in case it's a table */
+ Node *object; /* in case it's some other object */
+ char *newschema; /* the new schema */
+ bool missing_ok; /* skip error if missing? */
+} AlterObjectSchemaStmt;
+
+/* ----------------------
+ * Alter Object Owner Statement
+ * ----------------------
+ */
+typedef struct AlterOwnerStmt
+{
+ NodeTag type;
+ ObjectType objectType; /* OBJECT_TABLE, OBJECT_TYPE, etc */
+ RangeVar *relation; /* in case it's a table */
+ Node *object; /* in case it's some other object */
+ RoleSpec *newowner; /* the new owner */
+} AlterOwnerStmt;
+
+/* ----------------------
+ * Alter Operator Set ( this-n-that )
+ * ----------------------
+ */
+typedef struct AlterOperatorStmt
+{
+ NodeTag type;
+ ObjectWithArgs *opername; /* operator name and argument types */
+ List *options; /* List of DefElem nodes */
+} AlterOperatorStmt;
+
+/* ------------------------
+ * Alter Type Set ( this-n-that )
+ * ------------------------
+ */
+typedef struct AlterTypeStmt
+{
+ NodeTag type;
+ List *typeName; /* type name (possibly qualified) */
+ List *options; /* List of DefElem nodes */
+} AlterTypeStmt;
+
+/* ----------------------
+ * Create Rule Statement
+ * ----------------------
+ */
+typedef struct RuleStmt
+{
+ NodeTag type;
+ RangeVar *relation; /* relation the rule is for */
+ char *rulename; /* name of the rule */
+ Node *whereClause; /* qualifications */
+ CmdType event; /* SELECT, INSERT, etc */
+ bool instead; /* is a 'do instead'? */
+ List *actions; /* the action statements */
+ bool replace; /* OR REPLACE */
+} RuleStmt;
+
+/* ----------------------
+ * Notify Statement
+ * ----------------------
+ */
+typedef struct NotifyStmt
+{
+ NodeTag type;
+ char *conditionname; /* condition name to notify */
+ char *payload; /* the payload string, or NULL if none */
+} NotifyStmt;
+
+/* ----------------------
+ * Listen Statement
+ * ----------------------
+ */
+typedef struct ListenStmt
+{
+ NodeTag type;
+ char *conditionname; /* condition name to listen on */
+} ListenStmt;
+
+/* ----------------------
+ * Unlisten Statement
+ * ----------------------
+ */
+typedef struct UnlistenStmt
+{
+ NodeTag type;
+ char *conditionname; /* name to unlisten on, or NULL for all */
+} UnlistenStmt;
+
+/* ----------------------
+ * {Begin|Commit|Rollback} Transaction Statement
+ * ----------------------
+ */
+typedef enum TransactionStmtKind
+{
+ TRANS_STMT_BEGIN,
+ TRANS_STMT_START, /* semantically identical to BEGIN */
+ TRANS_STMT_COMMIT,
+ TRANS_STMT_ROLLBACK,
+ TRANS_STMT_SAVEPOINT,
+ TRANS_STMT_RELEASE,
+ TRANS_STMT_ROLLBACK_TO,
+ TRANS_STMT_PREPARE,
+ TRANS_STMT_COMMIT_PREPARED,
+ TRANS_STMT_ROLLBACK_PREPARED
+} TransactionStmtKind;
+
+typedef struct TransactionStmt
+{
+ NodeTag type;
+ TransactionStmtKind kind; /* see above */
+ List *options; /* for BEGIN/START commands */
+ char *savepoint_name; /* for savepoint commands */
+ char *gid; /* for two-phase-commit related commands */
+ bool chain; /* AND CHAIN option */
+} TransactionStmt;
+
+/* ----------------------
+ * Create Type Statement, composite types
+ * ----------------------
+ */
+typedef struct CompositeTypeStmt
+{
+ NodeTag type;
+ RangeVar *typevar; /* the composite type to be created */
+ List *coldeflist; /* list of ColumnDef nodes */
+} CompositeTypeStmt;
+
+/* ----------------------
+ * Create Type Statement, enum types
+ * ----------------------
+ */
+typedef struct CreateEnumStmt
+{
+ NodeTag type;
+ List *typeName; /* qualified name (list of String) */
+ List *vals; /* enum values (list of String) */
+} CreateEnumStmt;
+
+/* ----------------------
+ * Create Type Statement, range types
+ * ----------------------
+ */
+typedef struct CreateRangeStmt
+{
+ NodeTag type;
+ List *typeName; /* qualified name (list of String) */
+ List *params; /* range parameters (list of DefElem) */
+} CreateRangeStmt;
+
+/* ----------------------
+ * Alter Type Statement, enum types
+ * ----------------------
+ */
+typedef struct AlterEnumStmt
+{
+ NodeTag type;
+ List *typeName; /* qualified name (list of String) */
+ char *oldVal; /* old enum value's name, if renaming */
+ char *newVal; /* new enum value's name */
+ char *newValNeighbor; /* neighboring enum value, if specified */
+ bool newValIsAfter; /* place new enum value after neighbor? */
+ bool skipIfNewValExists; /* no error if new already exists? */
+} AlterEnumStmt;
+
+/* ----------------------
+ * Create View Statement
+ * ----------------------
+ */
+typedef enum ViewCheckOption
+{
+ NO_CHECK_OPTION,
+ LOCAL_CHECK_OPTION,
+ CASCADED_CHECK_OPTION
+} ViewCheckOption;
+
+typedef struct ViewStmt
+{
+ NodeTag type;
+ RangeVar *view; /* the view to be created */
+ List *aliases; /* target column names */
+ Node *query; /* the SELECT query (as a raw parse tree) */
+ bool replace; /* replace an existing view? */
+ List *options; /* options from WITH clause */
+ ViewCheckOption withCheckOption; /* WITH CHECK OPTION */
+} ViewStmt;
+
+/* ----------------------
+ * Load Statement
+ * ----------------------
+ */
+typedef struct LoadStmt
+{
+ NodeTag type;
+ char *filename; /* file to load */
+} LoadStmt;
+
+/* ----------------------
+ * Createdb Statement
+ * ----------------------
+ */
+typedef struct CreatedbStmt
+{
+ NodeTag type;
+ char *dbname; /* name of database to create */
+ List *options; /* List of DefElem nodes */
+} CreatedbStmt;
+
+/* ----------------------
+ * Alter Database
+ * ----------------------
+ */
+typedef struct AlterDatabaseStmt
+{
+ NodeTag type;
+ char *dbname; /* name of database to alter */
+ List *options; /* List of DefElem nodes */
+} AlterDatabaseStmt;
+
+typedef struct AlterDatabaseRefreshCollStmt
+{
+ NodeTag type;
+ char *dbname;
+} AlterDatabaseRefreshCollStmt;
+
+typedef struct AlterDatabaseSetStmt
+{
+ NodeTag type;
+ char *dbname; /* database name */
+ VariableSetStmt *setstmt; /* SET or RESET subcommand */
+} AlterDatabaseSetStmt;
+
+/* ----------------------
+ * Dropdb Statement
+ * ----------------------
+ */
+typedef struct DropdbStmt
+{
+ NodeTag type;
+ char *dbname; /* database to drop */
+ bool missing_ok; /* skip error if db is missing? */
+ List *options; /* currently only FORCE is supported */
+} DropdbStmt;
+
+/* ----------------------
+ * Alter System Statement
+ * ----------------------
+ */
+typedef struct AlterSystemStmt
+{
+ NodeTag type;
+ VariableSetStmt *setstmt; /* SET subcommand */
+} AlterSystemStmt;
+
+/* ----------------------
+ * Cluster Statement (support pbrown's cluster index implementation)
+ * ----------------------
+ */
+typedef struct ClusterStmt
+{
+ NodeTag type;
+ RangeVar *relation; /* relation being indexed, or NULL if all */
+ char *indexname; /* original index defined */
+ List *params; /* list of DefElem nodes */
+} ClusterStmt;
+
+/* ----------------------
+ * Vacuum and Analyze Statements
+ *
+ * Even though these are nominally two statements, it's convenient to use
+ * just one node type for both.
+ * ----------------------
+ */
+typedef struct VacuumStmt
+{
+ NodeTag type;
+ List *options; /* list of DefElem nodes */
+ List *rels; /* list of VacuumRelation, or NIL for all */
+ bool is_vacuumcmd; /* true for VACUUM, false for ANALYZE */
+} VacuumStmt;
+
+/*
+ * Info about a single target table of VACUUM/ANALYZE.
+ *
+ * If the OID field is set, it always identifies the table to process.
+ * Then the relation field can be NULL; if it isn't, it's used only to report
+ * failure to open/lock the relation.
+ */
+typedef struct VacuumRelation
+{
+ NodeTag type;
+ RangeVar *relation; /* table name to process, or NULL */
+ Oid oid; /* table's OID; InvalidOid if not looked up */
+ List *va_cols; /* list of column names, or NIL for all */
+} VacuumRelation;
+
+/* ----------------------
+ * Explain Statement
+ *
+ * The "query" field is initially a raw parse tree, and is converted to a
+ * Query node during parse analysis. Note that rewriting and planning
+ * of the query are always postponed until execution.
+ * ----------------------
+ */
+typedef struct ExplainStmt
+{
+ NodeTag type;
+ Node *query; /* the query (see comments above) */
+ List *options; /* list of DefElem nodes */
+} ExplainStmt;
+
+/* ----------------------
+ * CREATE TABLE AS Statement (a/k/a SELECT INTO)
+ *
+ * A query written as CREATE TABLE AS will produce this node type natively.
+ * A query written as SELECT ... INTO will be transformed to this form during
+ * parse analysis.
+ * A query written as CREATE MATERIALIZED view will produce this node type,
+ * during parse analysis, since it needs all the same data.
+ *
+ * The "query" field is handled similarly to EXPLAIN, though note that it
+ * can be a SELECT or an EXECUTE, but not other DML statements.
+ * ----------------------
+ */
+typedef struct CreateTableAsStmt
+{
+ NodeTag type;
+ Node *query; /* the query (see comments above) */
+ IntoClause *into; /* destination table */
+ ObjectType objtype; /* OBJECT_TABLE or OBJECT_MATVIEW */
+ bool is_select_into; /* it was written as SELECT INTO */
+ bool if_not_exists; /* just do nothing if it already exists? */
+} CreateTableAsStmt;
+
+/* ----------------------
+ * REFRESH MATERIALIZED VIEW Statement
+ * ----------------------
+ */
+typedef struct RefreshMatViewStmt
+{
+ NodeTag type;
+ bool concurrent; /* allow concurrent access? */
+ bool skipData; /* true for WITH NO DATA */
+ RangeVar *relation; /* relation to insert into */
+} RefreshMatViewStmt;
+
+/* ----------------------
+ * Checkpoint Statement
+ * ----------------------
+ */
+typedef struct CheckPointStmt
+{
+ NodeTag type;
+} CheckPointStmt;
+
+/* ----------------------
+ * Discard Statement
+ * ----------------------
+ */
+
+typedef enum DiscardMode
+{
+ DISCARD_ALL,
+ DISCARD_PLANS,
+ DISCARD_SEQUENCES,
+ DISCARD_TEMP
+} DiscardMode;
+
+typedef struct DiscardStmt
+{
+ NodeTag type;
+ DiscardMode target;
+} DiscardStmt;
+
+/* ----------------------
+ * LOCK Statement
+ * ----------------------
+ */
+typedef struct LockStmt
+{
+ NodeTag type;
+ List *relations; /* relations to lock */
+ int mode; /* lock mode */
+ bool nowait; /* no wait mode */
+} LockStmt;
+
+/* ----------------------
+ * SET CONSTRAINTS Statement
+ * ----------------------
+ */
+typedef struct ConstraintsSetStmt
+{
+ NodeTag type;
+ List *constraints; /* List of names as RangeVars */
+ bool deferred;
+} ConstraintsSetStmt;
+
+/* ----------------------
+ * REINDEX Statement
+ * ----------------------
+ */
+typedef enum ReindexObjectType
+{
+ REINDEX_OBJECT_INDEX, /* index */
+ REINDEX_OBJECT_TABLE, /* table or materialized view */
+ REINDEX_OBJECT_SCHEMA, /* schema */
+ REINDEX_OBJECT_SYSTEM, /* system catalogs */
+ REINDEX_OBJECT_DATABASE /* database */
+} ReindexObjectType;
+
+typedef struct ReindexStmt
+{
+ NodeTag type;
+ ReindexObjectType kind; /* REINDEX_OBJECT_INDEX, REINDEX_OBJECT_TABLE,
+ * etc. */
+ RangeVar *relation; /* Table or index to reindex */
+ const char *name; /* name of database to reindex */
+ List *params; /* list of DefElem nodes */
+} ReindexStmt;
+
+/* ----------------------
+ * CREATE CONVERSION Statement
+ * ----------------------
+ */
+typedef struct CreateConversionStmt
+{
+ NodeTag type;
+ List *conversion_name; /* Name of the conversion */
+ char *for_encoding_name; /* source encoding name */
+ char *to_encoding_name; /* destination encoding name */
+ List *func_name; /* qualified conversion function name */
+ bool def; /* is this a default conversion? */
+} CreateConversionStmt;
+
+/* ----------------------
+ * CREATE CAST Statement
+ * ----------------------
+ */
+typedef struct CreateCastStmt
+{
+ NodeTag type;
+ TypeName *sourcetype;
+ TypeName *targettype;
+ ObjectWithArgs *func;
+ CoercionContext context;
+ bool inout;
+} CreateCastStmt;
+
+/* ----------------------
+ * CREATE TRANSFORM Statement
+ * ----------------------
+ */
+typedef struct CreateTransformStmt
+{
+ NodeTag type;
+ bool replace;
+ TypeName *type_name;
+ char *lang;
+ ObjectWithArgs *fromsql;
+ ObjectWithArgs *tosql;
+} CreateTransformStmt;
+
+/* ----------------------
+ * PREPARE Statement
+ * ----------------------
+ */
+typedef struct PrepareStmt
+{
+ NodeTag type;
+ char *name; /* Name of plan, arbitrary */
+ List *argtypes; /* Types of parameters (List of TypeName) */
+ Node *query; /* The query itself (as a raw parsetree) */
+} PrepareStmt;
+
+
+/* ----------------------
+ * EXECUTE Statement
+ * ----------------------
+ */
+
+typedef struct ExecuteStmt
+{
+ NodeTag type;
+ char *name; /* The name of the plan to execute */
+ List *params; /* Values to assign to parameters */
+} ExecuteStmt;
+
+
+/* ----------------------
+ * DEALLOCATE Statement
+ * ----------------------
+ */
+typedef struct DeallocateStmt
+{
+ NodeTag type;
+ char *name; /* The name of the plan to remove */
+ /* NULL means DEALLOCATE ALL */
+} DeallocateStmt;
+
+/*
+ * DROP OWNED statement
+ */
+typedef struct DropOwnedStmt
+{
+ NodeTag type;
+ List *roles;
+ DropBehavior behavior;
+} DropOwnedStmt;
+
+/*
+ * REASSIGN OWNED statement
+ */
+typedef struct ReassignOwnedStmt
+{
+ NodeTag type;
+ List *roles;
+ RoleSpec *newrole;
+} ReassignOwnedStmt;
+
+/*
+ * TS Dictionary stmts: DefineStmt, RenameStmt and DropStmt are default
+ */
+typedef struct AlterTSDictionaryStmt
+{
+ NodeTag type;
+ List *dictname; /* qualified name (list of String) */
+ List *options; /* List of DefElem nodes */
+} AlterTSDictionaryStmt;
+
+/*
+ * TS Configuration stmts: DefineStmt, RenameStmt and DropStmt are default
+ */
+typedef enum AlterTSConfigType
+{
+ ALTER_TSCONFIG_ADD_MAPPING,
+ ALTER_TSCONFIG_ALTER_MAPPING_FOR_TOKEN,
+ ALTER_TSCONFIG_REPLACE_DICT,
+ ALTER_TSCONFIG_REPLACE_DICT_FOR_TOKEN,
+ ALTER_TSCONFIG_DROP_MAPPING
+} AlterTSConfigType;
+
+typedef struct AlterTSConfigurationStmt
+{
+ NodeTag type;
+ AlterTSConfigType kind; /* ALTER_TSCONFIG_ADD_MAPPING, etc */
+ List *cfgname; /* qualified name (list of String) */
+
+ /*
+ * dicts will be non-NIL if ADD/ALTER MAPPING was specified. If dicts is
+ * NIL, but tokentype isn't, DROP MAPPING was specified.
+ */
+ List *tokentype; /* list of String */
+ List *dicts; /* list of list of String */
+ bool override; /* if true - remove old variant */
+ bool replace; /* if true - replace dictionary by another */
+ bool missing_ok; /* for DROP - skip error if missing? */
+} AlterTSConfigurationStmt;
+
+typedef struct PublicationTable
+{
+ NodeTag type;
+ RangeVar *relation; /* relation to be published */
+ Node *whereClause; /* qualifications */
+ List *columns; /* List of columns in a publication table */
+} PublicationTable;
+
+/*
+ * Publication object type
+ */
+typedef enum PublicationObjSpecType
+{
+ PUBLICATIONOBJ_TABLE, /* A table */
+ PUBLICATIONOBJ_TABLES_IN_SCHEMA, /* All tables in schema */
+ PUBLICATIONOBJ_TABLES_IN_CUR_SCHEMA, /* All tables in first element of
+ * search_path */
+ PUBLICATIONOBJ_CONTINUATION /* Continuation of previous type */
+} PublicationObjSpecType;
+
+typedef struct PublicationObjSpec
+{
+ NodeTag type;
+ PublicationObjSpecType pubobjtype; /* type of this publication object */
+ char *name;
+ PublicationTable *pubtable;
+ int location; /* token location, or -1 if unknown */
+} PublicationObjSpec;
+
+typedef struct CreatePublicationStmt
+{
+ NodeTag type;
+ char *pubname; /* Name of the publication */
+ List *options; /* List of DefElem nodes */
+ List *pubobjects; /* Optional list of publication objects */
+ bool for_all_tables; /* Special publication for all tables in db */
+} CreatePublicationStmt;
+
+typedef enum AlterPublicationAction
+{
+ AP_AddObjects, /* add objects to publication */
+ AP_DropObjects, /* remove objects from publication */
+ AP_SetObjects /* set list of objects */
+} AlterPublicationAction;
+
+typedef struct AlterPublicationStmt
+{
+ NodeTag type;
+ char *pubname; /* Name of the publication */
+
+ /* parameters used for ALTER PUBLICATION ... WITH */
+ List *options; /* List of DefElem nodes */
+
+ /*
+ * Parameters used for ALTER PUBLICATION ... ADD/DROP/SET publication
+ * objects.
+ */
+ List *pubobjects; /* Optional list of publication objects */
+ bool for_all_tables; /* Special publication for all tables in db */
+ AlterPublicationAction action; /* What action to perform with the given
+ * objects */
+} AlterPublicationStmt;
+
+typedef struct CreateSubscriptionStmt
+{
+ NodeTag type;
+ char *subname; /* Name of the subscription */
+ char *conninfo; /* Connection string to publisher */
+ List *publication; /* One or more publication to subscribe to */
+ List *options; /* List of DefElem nodes */
+} CreateSubscriptionStmt;
+
+typedef enum AlterSubscriptionType
+{
+ ALTER_SUBSCRIPTION_OPTIONS,
+ ALTER_SUBSCRIPTION_CONNECTION,
+ ALTER_SUBSCRIPTION_SET_PUBLICATION,
+ ALTER_SUBSCRIPTION_ADD_PUBLICATION,
+ ALTER_SUBSCRIPTION_DROP_PUBLICATION,
+ ALTER_SUBSCRIPTION_REFRESH,
+ ALTER_SUBSCRIPTION_ENABLED,
+ ALTER_SUBSCRIPTION_SKIP
+} AlterSubscriptionType;
+
+typedef struct AlterSubscriptionStmt
+{
+ NodeTag type;
+ AlterSubscriptionType kind; /* ALTER_SUBSCRIPTION_OPTIONS, etc */
+ char *subname; /* Name of the subscription */
+ char *conninfo; /* Connection string to publisher */
+ List *publication; /* One or more publication to subscribe to */
+ List *options; /* List of DefElem nodes */
+} AlterSubscriptionStmt;
+
+typedef struct DropSubscriptionStmt
+{
+ NodeTag type;
+ char *subname; /* Name of the subscription */
+ bool missing_ok; /* Skip error if missing? */
+ DropBehavior behavior; /* RESTRICT or CASCADE behavior */
+} DropSubscriptionStmt;
+
+#endif /* PARSENODES_H */
diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h
new file mode 100644
index 0000000..94aebad
--- /dev/null
+++ b/src/include/nodes/pathnodes.h
@@ -0,0 +1,3384 @@
+/*-------------------------------------------------------------------------
+ *
+ * pathnodes.h
+ * Definitions for planner's internal data structures, especially Paths.
+ *
+ * We don't support copying RelOptInfo, IndexOptInfo, or Path nodes.
+ * There are some subsidiary structs that are useful to copy, though.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/nodes/pathnodes.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PATHNODES_H
+#define PATHNODES_H
+
+#include "access/sdir.h"
+#include "lib/stringinfo.h"
+#include "nodes/params.h"
+#include "nodes/parsenodes.h"
+#include "storage/block.h"
+
+
+/*
+ * Relids
+ * Set of relation identifiers (indexes into the rangetable).
+ */
+typedef Bitmapset *Relids;
+
+/*
+ * When looking for a "cheapest path", this enum specifies whether we want
+ * cheapest startup cost or cheapest total cost.
+ */
+typedef enum CostSelector
+{
+ STARTUP_COST, TOTAL_COST
+} CostSelector;
+
+/*
+ * The cost estimate produced by cost_qual_eval() includes both a one-time
+ * (startup) cost, and a per-tuple cost.
+ */
+typedef struct QualCost
+{
+ Cost startup; /* one-time cost */
+ Cost per_tuple; /* per-evaluation cost */
+} QualCost;
+
+/*
+ * Costing aggregate function execution requires these statistics about
+ * the aggregates to be executed by a given Agg node. Note that the costs
+ * include the execution costs of the aggregates' argument expressions as
+ * well as the aggregate functions themselves. Also, the fields must be
+ * defined so that initializing the struct to zeroes with memset is correct.
+ */
+typedef struct AggClauseCosts
+{
+ QualCost transCost; /* total per-input-row execution costs */
+ QualCost finalCost; /* total per-aggregated-row costs */
+ Size transitionSpace; /* space for pass-by-ref transition data */
+} AggClauseCosts;
+
+/*
+ * This enum identifies the different types of "upper" (post-scan/join)
+ * relations that we might deal with during planning.
+ */
+typedef enum UpperRelationKind
+{
+ UPPERREL_SETOP, /* result of UNION/INTERSECT/EXCEPT, if any */
+ UPPERREL_PARTIAL_GROUP_AGG, /* result of partial grouping/aggregation, if
+ * any */
+ UPPERREL_GROUP_AGG, /* result of grouping/aggregation, if any */
+ UPPERREL_WINDOW, /* result of window functions, if any */
+ UPPERREL_PARTIAL_DISTINCT, /* result of partial "SELECT DISTINCT", if any */
+ UPPERREL_DISTINCT, /* result of "SELECT DISTINCT", if any */
+ UPPERREL_ORDERED, /* result of ORDER BY, if any */
+ UPPERREL_FINAL /* result of any remaining top-level actions */
+ /* NB: UPPERREL_FINAL must be last enum entry; it's used to size arrays */
+} UpperRelationKind;
+
+/*----------
+ * PlannerGlobal
+ * Global information for planning/optimization
+ *
+ * PlannerGlobal holds state for an entire planner invocation; this state
+ * is shared across all levels of sub-Queries that exist in the command being
+ * planned.
+ *
+ * Not all fields are printed. (In some cases, there is no print support for
+ * the field type; in others, doing so would lead to infinite recursion.)
+ *----------
+ */
+typedef struct PlannerGlobal
+{
+ pg_node_attr(no_copy_equal, no_read, no_query_jumble)
+
+ NodeTag type;
+
+ /* Param values provided to planner() */
+ ParamListInfo boundParams pg_node_attr(read_write_ignore);
+
+ /* Plans for SubPlan nodes */
+ List *subplans;
+
+ /* PlannerInfos for SubPlan nodes */
+ List *subroots pg_node_attr(read_write_ignore);
+
+ /* indices of subplans that require REWIND */
+ Bitmapset *rewindPlanIDs;
+
+ /* "flat" rangetable for executor */
+ List *finalrtable;
+
+ /* "flat" list of RTEPermissionInfos */
+ List *finalrteperminfos;
+
+ /* "flat" list of PlanRowMarks */
+ List *finalrowmarks;
+
+ /* "flat" list of integer RT indexes */
+ List *resultRelations;
+
+ /* "flat" list of AppendRelInfos */
+ List *appendRelations;
+
+ /* OIDs of relations the plan depends on */
+ List *relationOids;
+
+ /* other dependencies, as PlanInvalItems */
+ List *invalItems;
+
+ /* type OIDs for PARAM_EXEC Params */
+ List *paramExecTypes;
+
+ /* highest PlaceHolderVar ID assigned */
+ Index lastPHId;
+
+ /* highest PlanRowMark ID assigned */
+ Index lastRowMarkId;
+
+ /* highest plan node ID assigned */
+ int lastPlanNodeId;
+
+ /* redo plan when TransactionXmin changes? */
+ bool transientPlan;
+
+ /* is plan specific to current role? */
+ bool dependsOnRole;
+
+ /* parallel mode potentially OK? */
+ bool parallelModeOK;
+
+ /* parallel mode actually required? */
+ bool parallelModeNeeded;
+
+ /* worst PROPARALLEL hazard level */
+ char maxParallelHazard;
+
+ /* partition descriptors */
+ PartitionDirectory partition_directory pg_node_attr(read_write_ignore);
+} PlannerGlobal;
+
+/* macro for fetching the Plan associated with a SubPlan node */
+#define planner_subplan_get_plan(root, subplan) \
+ ((Plan *) list_nth((root)->glob->subplans, (subplan)->plan_id - 1))
+
+
+/*----------
+ * PlannerInfo
+ * Per-query information for planning/optimization
+ *
+ * This struct is conventionally called "root" in all the planner routines.
+ * It holds links to all of the planner's working state, in addition to the
+ * original Query. Note that at present the planner extensively modifies
+ * the passed-in Query data structure; someday that should stop.
+ *
+ * For reasons explained in optimizer/optimizer.h, we define the typedef
+ * either here or in that header, whichever is read first.
+ *
+ * Not all fields are printed. (In some cases, there is no print support for
+ * the field type; in others, doing so would lead to infinite recursion or
+ * bloat dump output more than seems useful.)
+ *----------
+ */
+#ifndef HAVE_PLANNERINFO_TYPEDEF
+typedef struct PlannerInfo PlannerInfo;
+#define HAVE_PLANNERINFO_TYPEDEF 1
+#endif
+
+struct PlannerInfo
+{
+ pg_node_attr(no_copy_equal, no_read, no_query_jumble)
+
+ NodeTag type;
+
+ /* the Query being planned */
+ Query *parse;
+
+ /* global info for current planner run */
+ PlannerGlobal *glob;
+
+ /* 1 at the outermost Query */
+ Index query_level;
+
+ /* NULL at outermost Query */
+ PlannerInfo *parent_root pg_node_attr(read_write_ignore);
+
+ /*
+ * plan_params contains the expressions that this query level needs to
+ * make available to a lower query level that is currently being planned.
+ * outer_params contains the paramIds of PARAM_EXEC Params that outer
+ * query levels will make available to this query level.
+ */
+ /* list of PlannerParamItems, see below */
+ List *plan_params;
+ Bitmapset *outer_params;
+
+ /*
+ * simple_rel_array holds pointers to "base rels" and "other rels" (see
+ * comments for RelOptInfo for more info). It is indexed by rangetable
+ * index (so entry 0 is always wasted). Entries can be NULL when an RTE
+ * does not correspond to a base relation, such as a join RTE or an
+ * unreferenced view RTE; or if the RelOptInfo hasn't been made yet.
+ */
+ struct RelOptInfo **simple_rel_array pg_node_attr(array_size(simple_rel_array_size));
+ /* allocated size of array */
+ int simple_rel_array_size;
+
+ /*
+ * simple_rte_array is the same length as simple_rel_array and holds
+ * pointers to the associated rangetable entries. Using this is a shade
+ * faster than using rt_fetch(), mostly due to fewer indirections. (Not
+ * printed because it'd be redundant with parse->rtable.)
+ */
+ RangeTblEntry **simple_rte_array pg_node_attr(read_write_ignore);
+
+ /*
+ * append_rel_array is the same length as the above arrays, and holds
+ * pointers to the corresponding AppendRelInfo entry indexed by
+ * child_relid, or NULL if the rel is not an appendrel child. The array
+ * itself is not allocated if append_rel_list is empty. (Not printed
+ * because it'd be redundant with append_rel_list.)
+ */
+ struct AppendRelInfo **append_rel_array pg_node_attr(read_write_ignore);
+
+ /*
+ * all_baserels is a Relids set of all base relids (but not joins or
+ * "other" rels) in the query. This is computed in deconstruct_jointree.
+ */
+ Relids all_baserels;
+
+ /*
+ * outer_join_rels is a Relids set of all outer-join relids in the query.
+ * This is computed in deconstruct_jointree.
+ */
+ Relids outer_join_rels;
+
+ /*
+ * all_query_rels is a Relids set of all base relids and outer join relids
+ * (but not "other" relids) in the query. This is the Relids identifier
+ * of the final join we need to form. This is computed in
+ * deconstruct_jointree.
+ */
+ Relids all_query_rels;
+
+ /*
+ * join_rel_list is a list of all join-relation RelOptInfos we have
+ * considered in this planning run. For small problems we just scan the
+ * list to do lookups, but when there are many join relations we build a
+ * hash table for faster lookups. The hash table is present and valid
+ * when join_rel_hash is not NULL. Note that we still maintain the list
+ * even when using the hash table for lookups; this simplifies life for
+ * GEQO.
+ */
+ List *join_rel_list;
+ struct HTAB *join_rel_hash pg_node_attr(read_write_ignore);
+
+ /*
+ * When doing a dynamic-programming-style join search, join_rel_level[k]
+ * is a list of all join-relation RelOptInfos of level k, and
+ * join_cur_level is the current level. New join-relation RelOptInfos are
+ * automatically added to the join_rel_level[join_cur_level] list.
+ * join_rel_level is NULL if not in use.
+ *
+ * Note: we've already printed all baserel and joinrel RelOptInfos above,
+ * so we don't dump join_rel_level or other lists of RelOptInfos.
+ */
+ /* lists of join-relation RelOptInfos */
+ List **join_rel_level pg_node_attr(read_write_ignore);
+ /* index of list being extended */
+ int join_cur_level;
+
+ /* init SubPlans for query */
+ List *init_plans;
+
+ /*
+ * per-CTE-item list of subplan IDs (or -1 if no subplan was made for that
+ * CTE)
+ */
+ List *cte_plan_ids;
+
+ /* List of Lists of Params for MULTIEXPR subquery outputs */
+ List *multiexpr_params;
+
+ /* list of JoinDomains used in the query (higher ones first) */
+ List *join_domains;
+
+ /* list of active EquivalenceClasses */
+ List *eq_classes;
+
+ /* set true once ECs are canonical */
+ bool ec_merging_done;
+
+ /* list of "canonical" PathKeys */
+ List *canon_pathkeys;
+
+ /*
+ * list of OuterJoinClauseInfos for mergejoinable outer join clauses
+ * w/nonnullable var on left
+ */
+ List *left_join_clauses;
+
+ /*
+ * list of OuterJoinClauseInfos for mergejoinable outer join clauses
+ * w/nonnullable var on right
+ */
+ List *right_join_clauses;
+
+ /*
+ * list of OuterJoinClauseInfos for mergejoinable full join clauses
+ */
+ List *full_join_clauses;
+
+ /* list of SpecialJoinInfos */
+ List *join_info_list;
+
+ /* counter for assigning RestrictInfo serial numbers */
+ int last_rinfo_serial;
+
+ /*
+ * all_result_relids is empty for SELECT, otherwise it contains at least
+ * parse->resultRelation. For UPDATE/DELETE/MERGE across an inheritance
+ * or partitioning tree, the result rel's child relids are added. When
+ * using multi-level partitioning, intermediate partitioned rels are
+ * included. leaf_result_relids is similar except that only actual result
+ * tables, not partitioned tables, are included in it.
+ */
+ /* set of all result relids */
+ Relids all_result_relids;
+ /* set of all leaf relids */
+ Relids leaf_result_relids;
+
+ /*
+ * list of AppendRelInfos
+ *
+ * Note: for AppendRelInfos describing partitions of a partitioned table,
+ * we guarantee that partitions that come earlier in the partitioned
+ * table's PartitionDesc will appear earlier in append_rel_list.
+ */
+ List *append_rel_list;
+
+ /* list of RowIdentityVarInfos */
+ List *row_identity_vars;
+
+ /* list of PlanRowMarks */
+ List *rowMarks;
+
+ /* list of PlaceHolderInfos */
+ List *placeholder_list;
+
+ /* array of PlaceHolderInfos indexed by phid */
+ struct PlaceHolderInfo **placeholder_array pg_node_attr(read_write_ignore, array_size(placeholder_array_size));
+ /* allocated size of array */
+ int placeholder_array_size pg_node_attr(read_write_ignore);
+
+ /* list of ForeignKeyOptInfos */
+ List *fkey_list;
+
+ /* desired pathkeys for query_planner() */
+ List *query_pathkeys;
+
+ /* groupClause pathkeys, if any */
+ List *group_pathkeys;
+
+ /*
+ * The number of elements in the group_pathkeys list which belong to the
+ * GROUP BY clause. Additional ones belong to ORDER BY / DISTINCT
+ * aggregates.
+ */
+ int num_groupby_pathkeys;
+
+ /* pathkeys of bottom window, if any */
+ List *window_pathkeys;
+ /* distinctClause pathkeys, if any */
+ List *distinct_pathkeys;
+ /* sortClause pathkeys, if any */
+ List *sort_pathkeys;
+
+ /* Canonicalised partition schemes used in the query. */
+ List *part_schemes pg_node_attr(read_write_ignore);
+
+ /* RelOptInfos we are now trying to join */
+ List *initial_rels pg_node_attr(read_write_ignore);
+
+ /*
+ * Upper-rel RelOptInfos. Use fetch_upper_rel() to get any particular
+ * upper rel.
+ */
+ List *upper_rels[UPPERREL_FINAL + 1] pg_node_attr(read_write_ignore);
+
+ /* Result tlists chosen by grouping_planner for upper-stage processing */
+ struct PathTarget *upper_targets[UPPERREL_FINAL + 1] pg_node_attr(read_write_ignore);
+
+ /*
+ * The fully-processed groupClause is kept here. It differs from
+ * parse->groupClause in that we remove any items that we can prove
+ * redundant, so that only the columns named here actually need to be
+ * compared to determine grouping. Note that it's possible for *all* the
+ * items to be proven redundant, implying that there is only one group
+ * containing all the query's rows. Hence, if you want to check whether
+ * GROUP BY was specified, test for nonempty parse->groupClause, not for
+ * nonempty processed_groupClause.
+ *
+ * Currently, when grouping sets are specified we do not attempt to
+ * optimize the groupClause, so that processed_groupClause will be
+ * identical to parse->groupClause.
+ */
+ List *processed_groupClause;
+
+ /*
+ * The fully-processed distinctClause is kept here. It differs from
+ * parse->distinctClause in that we remove any items that we can prove
+ * redundant, so that only the columns named here actually need to be
+ * compared to determine uniqueness. Note that it's possible for *all*
+ * the items to be proven redundant, implying that there should be only
+ * one output row. Hence, if you want to check whether DISTINCT was
+ * specified, test for nonempty parse->distinctClause, not for nonempty
+ * processed_distinctClause.
+ */
+ List *processed_distinctClause;
+
+ /*
+ * The fully-processed targetlist is kept here. It differs from
+ * parse->targetList in that (for INSERT) it's been reordered to match the
+ * target table, and defaults have been filled in. Also, additional
+ * resjunk targets may be present. preprocess_targetlist() does most of
+ * that work, but note that more resjunk targets can get added during
+ * appendrel expansion. (Hence, upper_targets mustn't get set up till
+ * after that.)
+ */
+ List *processed_tlist;
+
+ /*
+ * For UPDATE, this list contains the target table's attribute numbers to
+ * which the first N entries of processed_tlist are to be assigned. (Any
+ * additional entries in processed_tlist must be resjunk.) DO NOT use the
+ * resnos in processed_tlist to identify the UPDATE target columns.
+ */
+ List *update_colnos;
+
+ /*
+ * Fields filled during create_plan() for use in setrefs.c
+ */
+ /* for GroupingFunc fixup (can't print: array length not known here) */
+ AttrNumber *grouping_map pg_node_attr(read_write_ignore);
+ /* List of MinMaxAggInfos */
+ List *minmax_aggs;
+
+ /* context holding PlannerInfo */
+ MemoryContext planner_cxt pg_node_attr(read_write_ignore);
+
+ /* # of pages in all non-dummy tables of query */
+ Cardinality total_table_pages;
+
+ /* tuple_fraction passed to query_planner */
+ Selectivity tuple_fraction;
+ /* limit_tuples passed to query_planner */
+ Cardinality limit_tuples;
+
+ /*
+ * Minimum security_level for quals. Note: qual_security_level is zero if
+ * there are no securityQuals.
+ */
+ Index qual_security_level;
+
+ /* true if any RTEs are RTE_JOIN kind */
+ bool hasJoinRTEs;
+ /* true if any RTEs are marked LATERAL */
+ bool hasLateralRTEs;
+ /* true if havingQual was non-null */
+ bool hasHavingQual;
+ /* true if any RestrictInfo has pseudoconstant = true */
+ bool hasPseudoConstantQuals;
+ /* true if we've made any of those */
+ bool hasAlternativeSubPlans;
+ /* true once we're no longer allowed to add PlaceHolderInfos */
+ bool placeholdersFrozen;
+ /* true if planning a recursive WITH item */
+ bool hasRecursion;
+
+ /*
+ * Information about aggregates. Filled by preprocess_aggrefs().
+ */
+ /* AggInfo structs */
+ List *agginfos;
+ /* AggTransInfo structs */
+ List *aggtransinfos;
+ /* number of aggs with DISTINCT/ORDER BY/WITHIN GROUP */
+ int numOrderedAggs;
+ /* does any agg not support partial mode? */
+ bool hasNonPartialAggs;
+ /* is any partial agg non-serializable? */
+ bool hasNonSerialAggs;
+
+ /*
+ * These fields are used only when hasRecursion is true:
+ */
+ /* PARAM_EXEC ID for the work table */
+ int wt_param_id;
+ /* a path for non-recursive term */
+ struct Path *non_recursive_path;
+
+ /*
+ * These fields are workspace for createplan.c
+ */
+ /* outer rels above current node */
+ Relids curOuterRels;
+ /* not-yet-assigned NestLoopParams */
+ List *curOuterParams;
+
+ /*
+ * These fields are workspace for setrefs.c. Each is an array
+ * corresponding to glob->subplans. (We could probably teach
+ * gen_node_support.pl how to determine the array length, but it doesn't
+ * seem worth the trouble, so just mark them read_write_ignore.)
+ */
+ bool *isAltSubplan pg_node_attr(read_write_ignore);
+ bool *isUsedSubplan pg_node_attr(read_write_ignore);
+
+ /* optional private data for join_search_hook, e.g., GEQO */
+ void *join_search_private pg_node_attr(read_write_ignore);
+
+ /* Does this query modify any partition key columns? */
+ bool partColsUpdated;
+};
+
+
+/*
+ * In places where it's known that simple_rte_array[] must have been prepared
+ * already, we just index into it to fetch RTEs. In code that might be
+ * executed before or after entering query_planner(), use this macro.
+ */
+#define planner_rt_fetch(rti, root) \
+ ((root)->simple_rte_array ? (root)->simple_rte_array[rti] : \
+ rt_fetch(rti, (root)->parse->rtable))
+
+/*
+ * If multiple relations are partitioned the same way, all such partitions
+ * will have a pointer to the same PartitionScheme. A list of PartitionScheme
+ * objects is attached to the PlannerInfo. By design, the partition scheme
+ * incorporates only the general properties of the partition method (LIST vs.
+ * RANGE, number of partitioning columns and the type information for each)
+ * and not the specific bounds.
+ *
+ * We store the opclass-declared input data types instead of the partition key
+ * datatypes since the former rather than the latter are used to compare
+ * partition bounds. Since partition key data types and the opclass declared
+ * input data types are expected to be binary compatible (per ResolveOpClass),
+ * both of those should have same byval and length properties.
+ */
+typedef struct PartitionSchemeData
+{
+ char strategy; /* partition strategy */
+ int16 partnatts; /* number of partition attributes */
+ Oid *partopfamily; /* OIDs of operator families */
+ Oid *partopcintype; /* OIDs of opclass declared input data types */
+ Oid *partcollation; /* OIDs of partitioning collations */
+
+ /* Cached information about partition key data types. */
+ int16 *parttyplen;
+ bool *parttypbyval;
+
+ /* Cached information about partition comparison functions. */
+ struct FmgrInfo *partsupfunc;
+} PartitionSchemeData;
+
+typedef struct PartitionSchemeData *PartitionScheme;
+
+/*----------
+ * RelOptInfo
+ * Per-relation information for planning/optimization
+ *
+ * For planning purposes, a "base rel" is either a plain relation (a table)
+ * or the output of a sub-SELECT or function that appears in the range table.
+ * In either case it is uniquely identified by an RT index. A "joinrel"
+ * is the joining of two or more base rels. A joinrel is identified by
+ * the set of RT indexes for its component baserels, along with RT indexes
+ * for any outer joins it has computed. We create RelOptInfo nodes for each
+ * baserel and joinrel, and store them in the PlannerInfo's simple_rel_array
+ * and join_rel_list respectively.
+ *
+ * Note that there is only one joinrel for any given set of component
+ * baserels, no matter what order we assemble them in; so an unordered
+ * set is the right datatype to identify it with.
+ *
+ * We also have "other rels", which are like base rels in that they refer to
+ * single RT indexes; but they are not part of the join tree, and are given
+ * a different RelOptKind to identify them.
+ * Currently the only kind of otherrels are those made for member relations
+ * of an "append relation", that is an inheritance set or UNION ALL subquery.
+ * An append relation has a parent RTE that is a base rel, which represents
+ * the entire append relation. The member RTEs are otherrels. The parent
+ * is present in the query join tree but the members are not. The member
+ * RTEs and otherrels are used to plan the scans of the individual tables or
+ * subqueries of the append set; then the parent baserel is given Append
+ * and/or MergeAppend paths comprising the best paths for the individual
+ * member rels. (See comments for AppendRelInfo for more information.)
+ *
+ * At one time we also made otherrels to represent join RTEs, for use in
+ * handling join alias Vars. Currently this is not needed because all join
+ * alias Vars are expanded to non-aliased form during preprocess_expression.
+ *
+ * We also have relations representing joins between child relations of
+ * different partitioned tables. These relations are not added to
+ * join_rel_level lists as they are not joined directly by the dynamic
+ * programming algorithm.
+ *
+ * There is also a RelOptKind for "upper" relations, which are RelOptInfos
+ * that describe post-scan/join processing steps, such as aggregation.
+ * Many of the fields in these RelOptInfos are meaningless, but their Path
+ * fields always hold Paths showing ways to do that processing step.
+ *
+ * Parts of this data structure are specific to various scan and join
+ * mechanisms. It didn't seem worth creating new node types for them.
+ *
+ * relids - Set of relation identifiers (RT indexes). This is a base
+ * relation if there is just one, a join relation if more;
+ * in the join case, RT indexes of any outer joins formed
+ * at or below this join are included along with baserels
+ * rows - estimated number of tuples in the relation after restriction
+ * clauses have been applied (ie, output rows of a plan for it)
+ * consider_startup - true if there is any value in keeping plain paths for
+ * this rel on the basis of having cheap startup cost
+ * consider_param_startup - the same for parameterized paths
+ * reltarget - Default Path output tlist for this rel; normally contains
+ * Var and PlaceHolderVar nodes for the values we need to
+ * output from this relation.
+ * List is in no particular order, but all rels of an
+ * appendrel set must use corresponding orders.
+ * NOTE: in an appendrel child relation, may contain
+ * arbitrary expressions pulled up from a subquery!
+ * pathlist - List of Path nodes, one for each potentially useful
+ * method of generating the relation
+ * ppilist - ParamPathInfo nodes for parameterized Paths, if any
+ * cheapest_startup_path - the pathlist member with lowest startup cost
+ * (regardless of ordering) among the unparameterized paths;
+ * or NULL if there is no unparameterized path
+ * cheapest_total_path - the pathlist member with lowest total cost
+ * (regardless of ordering) among the unparameterized paths;
+ * or if there is no unparameterized path, the path with lowest
+ * total cost among the paths with minimum parameterization
+ * cheapest_unique_path - for caching cheapest path to produce unique
+ * (no duplicates) output from relation; NULL if not yet requested
+ * cheapest_parameterized_paths - best paths for their parameterizations;
+ * always includes cheapest_total_path, even if that's unparameterized
+ * direct_lateral_relids - rels this rel has direct LATERAL references to
+ * lateral_relids - required outer rels for LATERAL, as a Relids set
+ * (includes both direct and indirect lateral references)
+ *
+ * If the relation is a base relation it will have these fields set:
+ *
+ * relid - RTE index (this is redundant with the relids field, but
+ * is provided for convenience of access)
+ * rtekind - copy of RTE's rtekind field
+ * min_attr, max_attr - range of valid AttrNumbers for rel
+ * attr_needed - array of bitmapsets indicating the highest joinrel
+ * in which each attribute is needed; if bit 0 is set then
+ * the attribute is needed as part of final targetlist
+ * attr_widths - cache space for per-attribute width estimates;
+ * zero means not computed yet
+ * nulling_relids - relids of outer joins that can null this rel
+ * lateral_vars - lateral cross-references of rel, if any (list of
+ * Vars and PlaceHolderVars)
+ * lateral_referencers - relids of rels that reference this one laterally
+ * (includes both direct and indirect lateral references)
+ * indexlist - list of IndexOptInfo nodes for relation's indexes
+ * (always NIL if it's not a table or partitioned table)
+ * pages - number of disk pages in relation (zero if not a table)
+ * tuples - number of tuples in relation (not considering restrictions)
+ * allvisfrac - fraction of disk pages that are marked all-visible
+ * eclass_indexes - EquivalenceClasses that mention this rel (filled
+ * only after EC merging is complete)
+ * subroot - PlannerInfo for subquery (NULL if it's not a subquery)
+ * subplan_params - list of PlannerParamItems to be passed to subquery
+ *
+ * Note: for a subquery, tuples and subroot are not set immediately
+ * upon creation of the RelOptInfo object; they are filled in when
+ * set_subquery_pathlist processes the object.
+ *
+ * For otherrels that are appendrel members, these fields are filled
+ * in just as for a baserel, except we don't bother with lateral_vars.
+ *
+ * If the relation is either a foreign table or a join of foreign tables that
+ * all belong to the same foreign server and are assigned to the same user to
+ * check access permissions as (cf checkAsUser), these fields will be set:
+ *
+ * serverid - OID of foreign server, if foreign table (else InvalidOid)
+ * userid - OID of user to check access as (InvalidOid means current user)
+ * useridiscurrent - we've assumed that userid equals current user
+ * fdwroutine - function hooks for FDW, if foreign table (else NULL)
+ * fdw_private - private state for FDW, if foreign table (else NULL)
+ *
+ * Two fields are used to cache knowledge acquired during the join search
+ * about whether this rel is provably unique when being joined to given other
+ * relation(s), ie, it can have at most one row matching any given row from
+ * that join relation. Currently we only attempt such proofs, and thus only
+ * populate these fields, for base rels; but someday they might be used for
+ * join rels too:
+ *
+ * unique_for_rels - list of Relid sets, each one being a set of other
+ * rels for which this one has been proven unique
+ * non_unique_for_rels - list of Relid sets, each one being a set of
+ * other rels for which we have tried and failed to prove
+ * this one unique
+ *
+ * The presence of the following fields depends on the restrictions
+ * and joins that the relation participates in:
+ *
+ * baserestrictinfo - List of RestrictInfo nodes, containing info about
+ * each non-join qualification clause in which this relation
+ * participates (only used for base rels)
+ * baserestrictcost - Estimated cost of evaluating the baserestrictinfo
+ * clauses at a single tuple (only used for base rels)
+ * baserestrict_min_security - Smallest security_level found among
+ * clauses in baserestrictinfo
+ * joininfo - List of RestrictInfo nodes, containing info about each
+ * join clause in which this relation participates (but
+ * note this excludes clauses that might be derivable from
+ * EquivalenceClasses)
+ * has_eclass_joins - flag that EquivalenceClass joins are possible
+ *
+ * Note: Keeping a restrictinfo list in the RelOptInfo is useful only for
+ * base rels, because for a join rel the set of clauses that are treated as
+ * restrict clauses varies depending on which sub-relations we choose to join.
+ * (For example, in a 3-base-rel join, a clause relating rels 1 and 2 must be
+ * treated as a restrictclause if we join {1} and {2 3} to make {1 2 3}; but
+ * if we join {1 2} and {3} then that clause will be a restrictclause in {1 2}
+ * and should not be processed again at the level of {1 2 3}.) Therefore,
+ * the restrictinfo list in the join case appears in individual JoinPaths
+ * (field joinrestrictinfo), not in the parent relation. But it's OK for
+ * the RelOptInfo to store the joininfo list, because that is the same
+ * for a given rel no matter how we form it.
+ *
+ * We store baserestrictcost in the RelOptInfo (for base relations) because
+ * we know we will need it at least once (to price the sequential scan)
+ * and may need it multiple times to price index scans.
+ *
+ * A join relation is considered to be partitioned if it is formed from a
+ * join of two relations that are partitioned, have matching partitioning
+ * schemes, and are joined on an equijoin of the partitioning columns.
+ * Under those conditions we can consider the join relation to be partitioned
+ * by either relation's partitioning keys, though some care is needed if
+ * either relation can be forced to null by outer-joining. For example, an
+ * outer join like (A LEFT JOIN B ON A.a = B.b) may produce rows with B.b
+ * NULL. These rows may not fit the partitioning conditions imposed on B.
+ * Hence, strictly speaking, the join is not partitioned by B.b and thus
+ * partition keys of an outer join should include partition key expressions
+ * from the non-nullable side only. However, if a subsequent join uses
+ * strict comparison operators (and all commonly-used equijoin operators are
+ * strict), the presence of nulls doesn't cause a problem: such rows couldn't
+ * match anything on the other side and thus they don't create a need to do
+ * any cross-partition sub-joins. Hence we can treat such values as still
+ * partitioning the join output for the purpose of additional partitionwise
+ * joining, so long as a strict join operator is used by the next join.
+ *
+ * If the relation is partitioned, these fields will be set:
+ *
+ * part_scheme - Partitioning scheme of the relation
+ * nparts - Number of partitions
+ * boundinfo - Partition bounds
+ * partbounds_merged - true if partition bounds are merged ones
+ * partition_qual - Partition constraint if not the root
+ * part_rels - RelOptInfos for each partition
+ * all_partrels - Relids set of all partition relids
+ * partexprs, nullable_partexprs - Partition key expressions
+ *
+ * The partexprs and nullable_partexprs arrays each contain
+ * part_scheme->partnatts elements. Each of the elements is a list of
+ * partition key expressions. For partitioned base relations, there is one
+ * expression in each partexprs element, and nullable_partexprs is empty.
+ * For partitioned join relations, each base relation within the join
+ * contributes one partition key expression per partitioning column;
+ * that expression goes in the partexprs[i] list if the base relation
+ * is not nullable by this join or any lower outer join, or in the
+ * nullable_partexprs[i] list if the base relation is nullable.
+ * Furthermore, FULL JOINs add extra nullable_partexprs expressions
+ * corresponding to COALESCE expressions of the left and right join columns,
+ * to simplify matching join clauses to those lists.
+ *
+ * Not all fields are printed. (In some cases, there is no print support for
+ * the field type.)
+ *----------
+ */
+
+/* Bitmask of flags supported by table AMs */
+#define AMFLAG_HAS_TID_RANGE (1 << 0)
+
+typedef enum RelOptKind
+{
+ RELOPT_BASEREL,
+ RELOPT_JOINREL,
+ RELOPT_OTHER_MEMBER_REL,
+ RELOPT_OTHER_JOINREL,
+ RELOPT_UPPER_REL,
+ RELOPT_OTHER_UPPER_REL
+} RelOptKind;
+
+/*
+ * Is the given relation a simple relation i.e a base or "other" member
+ * relation?
+ */
+#define IS_SIMPLE_REL(rel) \
+ ((rel)->reloptkind == RELOPT_BASEREL || \
+ (rel)->reloptkind == RELOPT_OTHER_MEMBER_REL)
+
+/* Is the given relation a join relation? */
+#define IS_JOIN_REL(rel) \
+ ((rel)->reloptkind == RELOPT_JOINREL || \
+ (rel)->reloptkind == RELOPT_OTHER_JOINREL)
+
+/* Is the given relation an upper relation? */
+#define IS_UPPER_REL(rel) \
+ ((rel)->reloptkind == RELOPT_UPPER_REL || \
+ (rel)->reloptkind == RELOPT_OTHER_UPPER_REL)
+
+/* Is the given relation an "other" relation? */
+#define IS_OTHER_REL(rel) \
+ ((rel)->reloptkind == RELOPT_OTHER_MEMBER_REL || \
+ (rel)->reloptkind == RELOPT_OTHER_JOINREL || \
+ (rel)->reloptkind == RELOPT_OTHER_UPPER_REL)
+
+typedef struct RelOptInfo
+{
+ pg_node_attr(no_copy_equal, no_read, no_query_jumble)
+
+ NodeTag type;
+
+ RelOptKind reloptkind;
+
+ /*
+ * all relations included in this RelOptInfo; set of base + OJ relids
+ * (rangetable indexes)
+ */
+ Relids relids;
+
+ /*
+ * size estimates generated by planner
+ */
+ /* estimated number of result tuples */
+ Cardinality rows;
+
+ /*
+ * per-relation planner control flags
+ */
+ /* keep cheap-startup-cost paths? */
+ bool consider_startup;
+ /* ditto, for parameterized paths? */
+ bool consider_param_startup;
+ /* consider parallel paths? */
+ bool consider_parallel;
+
+ /*
+ * default result targetlist for Paths scanning this relation; list of
+ * Vars/Exprs, cost, width
+ */
+ struct PathTarget *reltarget;
+
+ /*
+ * materialization information
+ */
+ List *pathlist; /* Path structures */
+ List *ppilist; /* ParamPathInfos used in pathlist */
+ List *partial_pathlist; /* partial Paths */
+ struct Path *cheapest_startup_path;
+ struct Path *cheapest_total_path;
+ struct Path *cheapest_unique_path;
+ List *cheapest_parameterized_paths;
+
+ /*
+ * parameterization information needed for both base rels and join rels
+ * (see also lateral_vars and lateral_referencers)
+ */
+ /* rels directly laterally referenced */
+ Relids direct_lateral_relids;
+ /* minimum parameterization of rel */
+ Relids lateral_relids;
+
+ /*
+ * information about a base rel (not set for join rels!)
+ */
+ Index relid;
+ /* containing tablespace */
+ Oid reltablespace;
+ /* RELATION, SUBQUERY, FUNCTION, etc */
+ RTEKind rtekind;
+ /* smallest attrno of rel (often <0) */
+ AttrNumber min_attr;
+ /* largest attrno of rel */
+ AttrNumber max_attr;
+ /* array indexed [min_attr .. max_attr] */
+ Relids *attr_needed pg_node_attr(read_write_ignore);
+ /* array indexed [min_attr .. max_attr] */
+ int32 *attr_widths pg_node_attr(read_write_ignore);
+ /* relids of outer joins that can null this baserel */
+ Relids nulling_relids;
+ /* LATERAL Vars and PHVs referenced by rel */
+ List *lateral_vars;
+ /* rels that reference this baserel laterally */
+ Relids lateral_referencers;
+ /* list of IndexOptInfo */
+ List *indexlist;
+ /* list of StatisticExtInfo */
+ List *statlist;
+ /* size estimates derived from pg_class */
+ BlockNumber pages;
+ Cardinality tuples;
+ double allvisfrac;
+ /* indexes in PlannerInfo's eq_classes list of ECs that mention this rel */
+ Bitmapset *eclass_indexes;
+ PlannerInfo *subroot; /* if subquery */
+ List *subplan_params; /* if subquery */
+ /* wanted number of parallel workers */
+ int rel_parallel_workers;
+ /* Bitmask of optional features supported by the table AM */
+ uint32 amflags;
+
+ /*
+ * Information about foreign tables and foreign joins
+ */
+ /* identifies server for the table or join */
+ Oid serverid;
+ /* identifies user to check access as; 0 means to check as current user */
+ Oid userid;
+ /* join is only valid for current user */
+ bool useridiscurrent;
+ /* use "struct FdwRoutine" to avoid including fdwapi.h here */
+ struct FdwRoutine *fdwroutine pg_node_attr(read_write_ignore);
+ void *fdw_private pg_node_attr(read_write_ignore);
+
+ /*
+ * cache space for remembering if we have proven this relation unique
+ */
+ /* known unique for these other relid set(s) */
+ List *unique_for_rels;
+ /* known not unique for these set(s) */
+ List *non_unique_for_rels;
+
+ /*
+ * used by various scans and joins:
+ */
+ /* RestrictInfo structures (if base rel) */
+ List *baserestrictinfo;
+ /* cost of evaluating the above */
+ QualCost baserestrictcost;
+ /* min security_level found in baserestrictinfo */
+ Index baserestrict_min_security;
+ /* RestrictInfo structures for join clauses involving this rel */
+ List *joininfo;
+ /* T means joininfo is incomplete */
+ bool has_eclass_joins;
+
+ /*
+ * used by partitionwise joins:
+ */
+ /* consider partitionwise join paths? (if partitioned rel) */
+ bool consider_partitionwise_join;
+
+ /*
+ * inheritance links, if this is an otherrel (otherwise NULL):
+ */
+ /* Immediate parent relation (dumping it would be too verbose) */
+ struct RelOptInfo *parent pg_node_attr(read_write_ignore);
+ /* Topmost parent relation (dumping it would be too verbose) */
+ struct RelOptInfo *top_parent pg_node_attr(read_write_ignore);
+ /* Relids of topmost parent (redundant, but handy) */
+ Relids top_parent_relids;
+
+ /*
+ * used for partitioned relations:
+ */
+ /* Partitioning scheme */
+ PartitionScheme part_scheme pg_node_attr(read_write_ignore);
+
+ /*
+ * Number of partitions; -1 if not yet set; in case of a join relation 0
+ * means it's considered unpartitioned
+ */
+ int nparts;
+ /* Partition bounds */
+ struct PartitionBoundInfoData *boundinfo pg_node_attr(read_write_ignore);
+ /* True if partition bounds were created by partition_bounds_merge() */
+ bool partbounds_merged;
+ /* Partition constraint, if not the root */
+ List *partition_qual;
+
+ /*
+ * Array of RelOptInfos of partitions, stored in the same order as bounds
+ * (don't print, too bulky and duplicative)
+ */
+ struct RelOptInfo **part_rels pg_node_attr(read_write_ignore);
+
+ /*
+ * Bitmap with members acting as indexes into the part_rels[] array to
+ * indicate which partitions survived partition pruning.
+ */
+ Bitmapset *live_parts;
+ /* Relids set of all partition relids */
+ Relids all_partrels;
+
+ /*
+ * These arrays are of length partkey->partnatts, which we don't have at
+ * hand, so don't try to print
+ */
+
+ /* Non-nullable partition key expressions */
+ List **partexprs pg_node_attr(read_write_ignore);
+ /* Nullable partition key expressions */
+ List **nullable_partexprs pg_node_attr(read_write_ignore);
+} RelOptInfo;
+
+/*
+ * Is given relation partitioned?
+ *
+ * It's not enough to test whether rel->part_scheme is set, because it might
+ * be that the basic partitioning properties of the input relations matched
+ * but the partition bounds did not. Also, if we are able to prove a rel
+ * dummy (empty), we should henceforth treat it as unpartitioned.
+ */
+#define IS_PARTITIONED_REL(rel) \
+ ((rel)->part_scheme && (rel)->boundinfo && (rel)->nparts > 0 && \
+ (rel)->part_rels && !IS_DUMMY_REL(rel))
+
+/*
+ * Convenience macro to make sure that a partitioned relation has all the
+ * required members set.
+ */
+#define REL_HAS_ALL_PART_PROPS(rel) \
+ ((rel)->part_scheme && (rel)->boundinfo && (rel)->nparts > 0 && \
+ (rel)->part_rels && (rel)->partexprs && (rel)->nullable_partexprs)
+
+/*
+ * IndexOptInfo
+ * Per-index information for planning/optimization
+ *
+ * indexkeys[], indexcollations[] each have ncolumns entries.
+ * opfamily[], and opcintype[] each have nkeycolumns entries. They do
+ * not contain any information about included attributes.
+ *
+ * sortopfamily[], reverse_sort[], and nulls_first[] have
+ * nkeycolumns entries, if the index is ordered; but if it is unordered,
+ * those pointers are NULL.
+ *
+ * Zeroes in the indexkeys[] array indicate index columns that are
+ * expressions; there is one element in indexprs for each such column.
+ *
+ * For an ordered index, reverse_sort[] and nulls_first[] describe the
+ * sort ordering of a forward indexscan; we can also consider a backward
+ * indexscan, which will generate the reverse ordering.
+ *
+ * The indexprs and indpred expressions have been run through
+ * prepqual.c and eval_const_expressions() for ease of matching to
+ * WHERE clauses. indpred is in implicit-AND form.
+ *
+ * indextlist is a TargetEntry list representing the index columns.
+ * It provides an equivalent base-relation Var for each simple column,
+ * and links to the matching indexprs element for each expression column.
+ *
+ * While most of these fields are filled when the IndexOptInfo is created
+ * (by plancat.c), indrestrictinfo and predOK are set later, in
+ * check_index_predicates().
+ */
+#ifndef HAVE_INDEXOPTINFO_TYPEDEF
+typedef struct IndexOptInfo IndexOptInfo;
+#define HAVE_INDEXOPTINFO_TYPEDEF 1
+#endif
+
+struct IndexOptInfo
+{
+ pg_node_attr(no_copy_equal, no_read, no_query_jumble)
+
+ NodeTag type;
+
+ /* OID of the index relation */
+ Oid indexoid;
+ /* tablespace of index (not table) */
+ Oid reltablespace;
+ /* back-link to index's table; don't print, else infinite recursion */
+ RelOptInfo *rel pg_node_attr(read_write_ignore);
+
+ /*
+ * index-size statistics (from pg_class and elsewhere)
+ */
+ /* number of disk pages in index */
+ BlockNumber pages;
+ /* number of index tuples in index */
+ Cardinality tuples;
+ /* index tree height, or -1 if unknown */
+ int tree_height;
+
+ /*
+ * index descriptor information
+ */
+ /* number of columns in index */
+ int ncolumns;
+ /* number of key columns in index */
+ int nkeycolumns;
+
+ /*
+ * table column numbers of index's columns (both key and included
+ * columns), or 0 for expression columns
+ */
+ int *indexkeys pg_node_attr(array_size(ncolumns));
+ /* OIDs of collations of index columns */
+ Oid *indexcollations pg_node_attr(array_size(nkeycolumns));
+ /* OIDs of operator families for columns */
+ Oid *opfamily pg_node_attr(array_size(nkeycolumns));
+ /* OIDs of opclass declared input data types */
+ Oid *opcintype pg_node_attr(array_size(nkeycolumns));
+ /* OIDs of btree opfamilies, if orderable. NULL if partitioned index */
+ Oid *sortopfamily pg_node_attr(array_size(nkeycolumns));
+ /* is sort order descending? or NULL if partitioned index */
+ bool *reverse_sort pg_node_attr(array_size(nkeycolumns));
+ /* do NULLs come first in the sort order? or NULL if partitioned index */
+ bool *nulls_first pg_node_attr(array_size(nkeycolumns));
+ /* opclass-specific options for columns */
+ bytea **opclassoptions pg_node_attr(read_write_ignore);
+ /* which index cols can be returned in an index-only scan? */
+ bool *canreturn pg_node_attr(array_size(ncolumns));
+ /* OID of the access method (in pg_am) */
+ Oid relam;
+
+ /*
+ * expressions for non-simple index columns; redundant to print since we
+ * print indextlist
+ */
+ List *indexprs pg_node_attr(read_write_ignore);
+ /* predicate if a partial index, else NIL */
+ List *indpred;
+
+ /* targetlist representing index columns */
+ List *indextlist;
+
+ /*
+ * parent relation's baserestrictinfo list, less any conditions implied by
+ * the index's predicate (unless it's a target rel, see comments in
+ * check_index_predicates())
+ */
+ List *indrestrictinfo;
+
+ /* true if index predicate matches query */
+ bool predOK;
+ /* true if a unique index */
+ bool unique;
+ /* is uniqueness enforced immediately? */
+ bool immediate;
+ /* true if index doesn't really exist */
+ bool hypothetical;
+
+ /*
+ * Remaining fields are copied from the index AM's API struct
+ * (IndexAmRoutine). These fields are not set for partitioned indexes.
+ */
+ bool amcanorderbyop;
+ bool amoptionalkey;
+ bool amsearcharray;
+ bool amsearchnulls;
+ /* does AM have amgettuple interface? */
+ bool amhasgettuple;
+ /* does AM have amgetbitmap interface? */
+ bool amhasgetbitmap;
+ bool amcanparallel;
+ /* does AM have ammarkpos interface? */
+ bool amcanmarkpos;
+ /* AM's cost estimator */
+ /* Rather than include amapi.h here, we declare amcostestimate like this */
+ void (*amcostestimate) () pg_node_attr(read_write_ignore);
+};
+
+/*
+ * ForeignKeyOptInfo
+ * Per-foreign-key information for planning/optimization
+ *
+ * The per-FK-column arrays can be fixed-size because we allow at most
+ * INDEX_MAX_KEYS columns in a foreign key constraint. Each array has
+ * nkeys valid entries.
+ */
+typedef struct ForeignKeyOptInfo
+{
+ pg_node_attr(custom_read_write, no_copy_equal, no_read, no_query_jumble)
+
+ NodeTag type;
+
+ /*
+ * Basic data about the foreign key (fetched from catalogs):
+ */
+
+ /* RT index of the referencing table */
+ Index con_relid;
+ /* RT index of the referenced table */
+ Index ref_relid;
+ /* number of columns in the foreign key */
+ int nkeys;
+ /* cols in referencing table */
+ AttrNumber conkey[INDEX_MAX_KEYS] pg_node_attr(array_size(nkeys));
+ /* cols in referenced table */
+ AttrNumber confkey[INDEX_MAX_KEYS] pg_node_attr(array_size(nkeys));
+ /* PK = FK operator OIDs */
+ Oid conpfeqop[INDEX_MAX_KEYS] pg_node_attr(array_size(nkeys));
+
+ /*
+ * Derived info about whether FK's equality conditions match the query:
+ */
+
+ /* # of FK cols matched by ECs */
+ int nmatched_ec;
+ /* # of these ECs that are ec_has_const */
+ int nconst_ec;
+ /* # of FK cols matched by non-EC rinfos */
+ int nmatched_rcols;
+ /* total # of non-EC rinfos matched to FK */
+ int nmatched_ri;
+ /* Pointer to eclass matching each column's condition, if there is one */
+ struct EquivalenceClass *eclass[INDEX_MAX_KEYS];
+ /* Pointer to eclass member for the referencing Var, if there is one */
+ struct EquivalenceMember *fk_eclass_member[INDEX_MAX_KEYS];
+ /* List of non-EC RestrictInfos matching each column's condition */
+ List *rinfos[INDEX_MAX_KEYS];
+} ForeignKeyOptInfo;
+
+/*
+ * StatisticExtInfo
+ * Information about extended statistics for planning/optimization
+ *
+ * Each pg_statistic_ext row is represented by one or more nodes of this
+ * type, or even zero if ANALYZE has not computed them.
+ */
+typedef struct StatisticExtInfo
+{
+ pg_node_attr(no_copy_equal, no_read, no_query_jumble)
+
+ NodeTag type;
+
+ /* OID of the statistics row */
+ Oid statOid;
+
+ /* includes child relations */
+ bool inherit;
+
+ /* back-link to statistic's table; don't print, else infinite recursion */
+ RelOptInfo *rel pg_node_attr(read_write_ignore);
+
+ /* statistics kind of this entry */
+ char kind;
+
+ /* attnums of the columns covered */
+ Bitmapset *keys;
+
+ /* expressions */
+ List *exprs;
+} StatisticExtInfo;
+
+/*
+ * JoinDomains
+ *
+ * A "join domain" defines the scope of applicability of deductions made via
+ * the EquivalenceClass mechanism. Roughly speaking, a join domain is a set
+ * of base+OJ relations that are inner-joined together. More precisely, it is
+ * the set of relations at which equalities deduced from an EquivalenceClass
+ * can be enforced or should be expected to hold. The topmost JoinDomain
+ * covers the whole query (so its jd_relids should equal all_query_rels).
+ * An outer join creates a new JoinDomain that includes all base+OJ relids
+ * within its nullable side, but (by convention) not the OJ's own relid.
+ * A FULL join creates two new JoinDomains, one for each side.
+ *
+ * Notice that a rel that is below outer join(s) will thus appear to belong
+ * to multiple join domains. However, any of its Vars that appear in
+ * EquivalenceClasses belonging to higher join domains will have nullingrel
+ * bits preventing them from being evaluated at the rel's scan level, so that
+ * we will not be able to derive enforceable-at-the-rel-scan-level clauses
+ * from such ECs. We define the join domain relid sets this way so that
+ * domains can be said to be "higher" or "lower" when one domain relid set
+ * includes another.
+ *
+ * The JoinDomains for a query are computed in deconstruct_jointree.
+ * We do not copy JoinDomain structs once made, so they can be compared
+ * for equality by simple pointer equality.
+ */
+typedef struct JoinDomain
+{
+ pg_node_attr(no_copy_equal, no_read, no_query_jumble)
+
+ NodeTag type;
+
+ Relids jd_relids; /* all relids contained within the domain */
+} JoinDomain;
+
+/*
+ * EquivalenceClasses
+ *
+ * Whenever we identify a mergejoinable equality clause A = B that is
+ * not an outer-join clause, we create an EquivalenceClass containing
+ * the expressions A and B to record this knowledge. If we later find another
+ * equivalence B = C, we add C to the existing EquivalenceClass; this may
+ * require merging two existing EquivalenceClasses. At the end of the qual
+ * distribution process, we have sets of values that are known all transitively
+ * equal to each other, where "equal" is according to the rules of the btree
+ * operator family(s) shown in ec_opfamilies, as well as the collation shown
+ * by ec_collation. (We restrict an EC to contain only equalities whose
+ * operators belong to the same set of opfamilies. This could probably be
+ * relaxed, but for now it's not worth the trouble, since nearly all equality
+ * operators belong to only one btree opclass anyway. Similarly, we suppose
+ * that all or none of the input datatypes are collatable, so that a single
+ * collation value is sufficient.)
+ *
+ * Strictly speaking, deductions from an EquivalenceClass hold only within
+ * a "join domain", that is a set of relations that are innerjoined together
+ * (see JoinDomain above). For the most part we don't need to account for
+ * this explicitly, because equality clauses from different join domains
+ * will contain Vars that are not equal() because they have different
+ * nullingrel sets, and thus we will never falsely merge ECs from different
+ * join domains. But Var-free (pseudoconstant) expressions lack that safety
+ * feature. We handle that by marking "const" EC members with the JoinDomain
+ * of the clause they came from; two nominally-equal const members will be
+ * considered different if they came from different JoinDomains. This ensures
+ * no false EquivalenceClass merges will occur.
+ *
+ * We also use EquivalenceClasses as the base structure for PathKeys, letting
+ * us represent knowledge about different sort orderings being equivalent.
+ * Since every PathKey must reference an EquivalenceClass, we will end up
+ * with single-member EquivalenceClasses whenever a sort key expression has
+ * not been equivalenced to anything else. It is also possible that such an
+ * EquivalenceClass will contain a volatile expression ("ORDER BY random()"),
+ * which is a case that can't arise otherwise since clauses containing
+ * volatile functions are never considered mergejoinable. We mark such
+ * EquivalenceClasses specially to prevent them from being merged with
+ * ordinary EquivalenceClasses. Also, for volatile expressions we have
+ * to be careful to match the EquivalenceClass to the correct targetlist
+ * entry: consider SELECT random() AS a, random() AS b ... ORDER BY b,a.
+ * So we record the SortGroupRef of the originating sort clause.
+ *
+ * NB: if ec_merged isn't NULL, this class has been merged into another, and
+ * should be ignored in favor of using the pointed-to class.
+ *
+ * NB: EquivalenceClasses are never copied after creation. Therefore,
+ * copyObject() copies pointers to them as pointers, and equal() compares
+ * pointers to EquivalenceClasses via pointer equality. This is implemented
+ * by putting copy_as_scalar and equal_as_scalar attributes on fields that
+ * are pointers to EquivalenceClasses. The same goes for EquivalenceMembers.
+ */
+typedef struct EquivalenceClass
+{
+ pg_node_attr(custom_read_write, no_copy_equal, no_read, no_query_jumble)
+
+ NodeTag type;
+
+ List *ec_opfamilies; /* btree operator family OIDs */
+ Oid ec_collation; /* collation, if datatypes are collatable */
+ List *ec_members; /* list of EquivalenceMembers */
+ List *ec_sources; /* list of generating RestrictInfos */
+ List *ec_derives; /* list of derived RestrictInfos */
+ Relids ec_relids; /* all relids appearing in ec_members, except
+ * for child members (see below) */
+ bool ec_has_const; /* any pseudoconstants in ec_members? */
+ bool ec_has_volatile; /* the (sole) member is a volatile expr */
+ bool ec_broken; /* failed to generate needed clauses? */
+ Index ec_sortref; /* originating sortclause label, or 0 */
+ Index ec_min_security; /* minimum security_level in ec_sources */
+ Index ec_max_security; /* maximum security_level in ec_sources */
+ struct EquivalenceClass *ec_merged; /* set if merged into another EC */
+} EquivalenceClass;
+
+/*
+ * If an EC contains a constant, any PathKey depending on it must be
+ * redundant, since there's only one possible value of the key.
+ */
+#define EC_MUST_BE_REDUNDANT(eclass) \
+ ((eclass)->ec_has_const)
+
+/*
+ * EquivalenceMember - one member expression of an EquivalenceClass
+ *
+ * em_is_child signifies that this element was built by transposing a member
+ * for an appendrel parent relation to represent the corresponding expression
+ * for an appendrel child. These members are used for determining the
+ * pathkeys of scans on the child relation and for explicitly sorting the
+ * child when necessary to build a MergeAppend path for the whole appendrel
+ * tree. An em_is_child member has no impact on the properties of the EC as a
+ * whole; in particular the EC's ec_relids field does NOT include the child
+ * relation. An em_is_child member should never be marked em_is_const nor
+ * cause ec_has_const or ec_has_volatile to be set, either. Thus, em_is_child
+ * members are not really full-fledged members of the EC, but just reflections
+ * or doppelgangers of real members. Most operations on EquivalenceClasses
+ * should ignore em_is_child members, and those that don't should test
+ * em_relids to make sure they only consider relevant members.
+ *
+ * em_datatype is usually the same as exprType(em_expr), but can be
+ * different when dealing with a binary-compatible opfamily; in particular
+ * anyarray_ops would never work without this. Use em_datatype when
+ * looking up a specific btree operator to work with this expression.
+ */
+typedef struct EquivalenceMember
+{
+ pg_node_attr(no_copy_equal, no_read, no_query_jumble)
+
+ NodeTag type;
+
+ Expr *em_expr; /* the expression represented */
+ Relids em_relids; /* all relids appearing in em_expr */
+ bool em_is_const; /* expression is pseudoconstant? */
+ bool em_is_child; /* derived version for a child relation? */
+ Oid em_datatype; /* the "nominal type" used by the opfamily */
+ JoinDomain *em_jdomain; /* join domain containing the source clause */
+ /* if em_is_child is true, this links to corresponding EM for top parent */
+ struct EquivalenceMember *em_parent pg_node_attr(read_write_ignore);
+} EquivalenceMember;
+
+/*
+ * PathKeys
+ *
+ * The sort ordering of a path is represented by a list of PathKey nodes.
+ * An empty list implies no known ordering. Otherwise the first item
+ * represents the primary sort key, the second the first secondary sort key,
+ * etc. The value being sorted is represented by linking to an
+ * EquivalenceClass containing that value and including pk_opfamily among its
+ * ec_opfamilies. The EquivalenceClass tells which collation to use, too.
+ * This is a convenient method because it makes it trivial to detect
+ * equivalent and closely-related orderings. (See optimizer/README for more
+ * information.)
+ *
+ * Note: pk_strategy is either BTLessStrategyNumber (for ASC) or
+ * BTGreaterStrategyNumber (for DESC). We assume that all ordering-capable
+ * index types will use btree-compatible strategy numbers.
+ */
+typedef struct PathKey
+{
+ pg_node_attr(no_read, no_query_jumble)
+
+ NodeTag type;
+
+ /* the value that is ordered */
+ EquivalenceClass *pk_eclass pg_node_attr(copy_as_scalar, equal_as_scalar);
+ Oid pk_opfamily; /* btree opfamily defining the ordering */
+ int pk_strategy; /* sort direction (ASC or DESC) */
+ bool pk_nulls_first; /* do NULLs come before normal values? */
+} PathKey;
+
+/*
+ * VolatileFunctionStatus -- allows nodes to cache their
+ * contain_volatile_functions properties. VOLATILITY_UNKNOWN means not yet
+ * determined.
+ */
+typedef enum VolatileFunctionStatus
+{
+ VOLATILITY_UNKNOWN = 0,
+ VOLATILITY_VOLATILE,
+ VOLATILITY_NOVOLATILE
+} VolatileFunctionStatus;
+
+/*
+ * PathTarget
+ *
+ * This struct contains what we need to know during planning about the
+ * targetlist (output columns) that a Path will compute. Each RelOptInfo
+ * includes a default PathTarget, which its individual Paths may simply
+ * reference. However, in some cases a Path may compute outputs different
+ * from other Paths, and in that case we make a custom PathTarget for it.
+ * For example, an indexscan might return index expressions that would
+ * otherwise need to be explicitly calculated. (Note also that "upper"
+ * relations generally don't have useful default PathTargets.)
+ *
+ * exprs contains bare expressions; they do not have TargetEntry nodes on top,
+ * though those will appear in finished Plans.
+ *
+ * sortgrouprefs[] is an array of the same length as exprs, containing the
+ * corresponding sort/group refnos, or zeroes for expressions not referenced
+ * by sort/group clauses. If sortgrouprefs is NULL (which it generally is in
+ * RelOptInfo.reltarget targets; only upper-level Paths contain this info),
+ * we have not identified sort/group columns in this tlist. This allows us to
+ * deal with sort/group refnos when needed with less expense than including
+ * TargetEntry nodes in the exprs list.
+ */
+typedef struct PathTarget
+{
+ pg_node_attr(no_copy_equal, no_read, no_query_jumble)
+
+ NodeTag type;
+
+ /* list of expressions to be computed */
+ List *exprs;
+
+ /* corresponding sort/group refnos, or 0 */
+ Index *sortgrouprefs pg_node_attr(array_size(exprs));
+
+ /* cost of evaluating the expressions */
+ QualCost cost;
+
+ /* estimated avg width of result tuples */
+ int width;
+
+ /* indicates if exprs contain any volatile functions */
+ VolatileFunctionStatus has_volatile_expr;
+} PathTarget;
+
+/* Convenience macro to get a sort/group refno from a PathTarget */
+#define get_pathtarget_sortgroupref(target, colno) \
+ ((target)->sortgrouprefs ? (target)->sortgrouprefs[colno] : (Index) 0)
+
+
+/*
+ * ParamPathInfo
+ *
+ * All parameterized paths for a given relation with given required outer rels
+ * link to a single ParamPathInfo, which stores common information such as
+ * the estimated rowcount for this parameterization. We do this partly to
+ * avoid recalculations, but mostly to ensure that the estimated rowcount
+ * is in fact the same for every such path.
+ *
+ * Note: ppi_clauses is only used in ParamPathInfos for base relation paths;
+ * in join cases it's NIL because the set of relevant clauses varies depending
+ * on how the join is formed. The relevant clauses will appear in each
+ * parameterized join path's joinrestrictinfo list, instead. ParamPathInfos
+ * for append relations don't bother with this, either.
+ *
+ * ppi_serials is the set of rinfo_serial numbers for quals that are enforced
+ * by this path. As with ppi_clauses, it's only maintained for baserels.
+ * (We could construct it on-the-fly from ppi_clauses, but it seems better
+ * to materialize a copy.)
+ */
+typedef struct ParamPathInfo
+{
+ pg_node_attr(no_copy_equal, no_read, no_query_jumble)
+
+ NodeTag type;
+
+ Relids ppi_req_outer; /* rels supplying parameters used by path */
+ Cardinality ppi_rows; /* estimated number of result tuples */
+ List *ppi_clauses; /* join clauses available from outer rels */
+ Bitmapset *ppi_serials; /* set of rinfo_serial for enforced quals */
+} ParamPathInfo;
+
+
+/*
+ * Type "Path" is used as-is for sequential-scan paths, as well as some other
+ * simple plan types that we don't need any extra information in the path for.
+ * For other path types it is the first component of a larger struct.
+ *
+ * "pathtype" is the NodeTag of the Plan node we could build from this Path.
+ * It is partially redundant with the Path's NodeTag, but allows us to use
+ * the same Path type for multiple Plan types when there is no need to
+ * distinguish the Plan type during path processing.
+ *
+ * "parent" identifies the relation this Path scans, and "pathtarget"
+ * describes the precise set of output columns the Path would compute.
+ * In simple cases all Paths for a given rel share the same targetlist,
+ * which we represent by having path->pathtarget equal to parent->reltarget.
+ *
+ * "param_info", if not NULL, links to a ParamPathInfo that identifies outer
+ * relation(s) that provide parameter values to each scan of this path.
+ * That means this path can only be joined to those rels by means of nestloop
+ * joins with this path on the inside. Also note that a parameterized path
+ * is responsible for testing all "movable" joinclauses involving this rel
+ * and the specified outer rel(s).
+ *
+ * "rows" is the same as parent->rows in simple paths, but in parameterized
+ * paths and UniquePaths it can be less than parent->rows, reflecting the
+ * fact that we've filtered by extra join conditions or removed duplicates.
+ *
+ * "pathkeys" is a List of PathKey nodes (see above), describing the sort
+ * ordering of the path's output rows.
+ *
+ * We do not support copying Path trees, mainly because the circular linkages
+ * between RelOptInfo and Path nodes can't be handled easily in a simple
+ * depth-first traversal. We also don't have read support at the moment.
+ */
+typedef struct Path
+{
+ pg_node_attr(no_copy_equal, no_read, no_query_jumble)
+
+ NodeTag type;
+
+ /* tag identifying scan/join method */
+ NodeTag pathtype;
+
+ /*
+ * the relation this path can build
+ *
+ * We do NOT print the parent, else we'd be in infinite recursion. We can
+ * print the parent's relids for identification purposes, though.
+ */
+ RelOptInfo *parent pg_node_attr(write_only_relids);
+
+ /*
+ * list of Vars/Exprs, cost, width
+ *
+ * We print the pathtarget only if it's not the default one for the rel.
+ */
+ PathTarget *pathtarget pg_node_attr(write_only_nondefault_pathtarget);
+
+ /*
+ * parameterization info, or NULL if none
+ *
+ * We do not print the whole of param_info, since it's printed via
+ * RelOptInfo; it's sufficient and less cluttering to print just the
+ * required outer relids.
+ */
+ ParamPathInfo *param_info pg_node_attr(write_only_req_outer);
+
+ /* engage parallel-aware logic? */
+ bool parallel_aware;
+ /* OK to use as part of parallel plan? */
+ bool parallel_safe;
+ /* desired # of workers; 0 = not parallel */
+ int parallel_workers;
+
+ /* estimated size/costs for path (see costsize.c for more info) */
+ Cardinality rows; /* estimated number of result tuples */
+ Cost startup_cost; /* cost expended before fetching any tuples */
+ Cost total_cost; /* total cost (assuming all tuples fetched) */
+
+ /* sort ordering of path's output; a List of PathKey nodes; see above */
+ List *pathkeys;
+} Path;
+
+/* Macro for extracting a path's parameterization relids; beware double eval */
+#define PATH_REQ_OUTER(path) \
+ ((path)->param_info ? (path)->param_info->ppi_req_outer : (Relids) NULL)
+
+/*----------
+ * IndexPath represents an index scan over a single index.
+ *
+ * This struct is used for both regular indexscans and index-only scans;
+ * path.pathtype is T_IndexScan or T_IndexOnlyScan to show which is meant.
+ *
+ * 'indexinfo' is the index to be scanned.
+ *
+ * 'indexclauses' is a list of IndexClause nodes, each representing one
+ * index-checkable restriction, with implicit AND semantics across the list.
+ * An empty list implies a full index scan.
+ *
+ * 'indexorderbys', if not NIL, is a list of ORDER BY expressions that have
+ * been found to be usable as ordering operators for an amcanorderbyop index.
+ * The list must match the path's pathkeys, ie, one expression per pathkey
+ * in the same order. These are not RestrictInfos, just bare expressions,
+ * since they generally won't yield booleans. It's guaranteed that each
+ * expression has the index key on the left side of the operator.
+ *
+ * 'indexorderbycols' is an integer list of index column numbers (zero-based)
+ * of the same length as 'indexorderbys', showing which index column each
+ * ORDER BY expression is meant to be used with. (There is no restriction
+ * on which index column each ORDER BY can be used with.)
+ *
+ * 'indexscandir' is one of:
+ * ForwardScanDirection: forward scan of an index
+ * BackwardScanDirection: backward scan of an ordered index
+ * Unordered indexes will always have an indexscandir of ForwardScanDirection.
+ *
+ * 'indextotalcost' and 'indexselectivity' are saved in the IndexPath so that
+ * we need not recompute them when considering using the same index in a
+ * bitmap index/heap scan (see BitmapHeapPath). The costs of the IndexPath
+ * itself represent the costs of an IndexScan or IndexOnlyScan plan type.
+ *----------
+ */
+typedef struct IndexPath
+{
+ Path path;
+ IndexOptInfo *indexinfo;
+ List *indexclauses;
+ List *indexorderbys;
+ List *indexorderbycols;
+ ScanDirection indexscandir;
+ Cost indextotalcost;
+ Selectivity indexselectivity;
+} IndexPath;
+
+/*
+ * Each IndexClause references a RestrictInfo node from the query's WHERE
+ * or JOIN conditions, and shows how that restriction can be applied to
+ * the particular index. We support both indexclauses that are directly
+ * usable by the index machinery, which are typically of the form
+ * "indexcol OP pseudoconstant", and those from which an indexable qual
+ * can be derived. The simplest such transformation is that a clause
+ * of the form "pseudoconstant OP indexcol" can be commuted to produce an
+ * indexable qual (the index machinery expects the indexcol to be on the
+ * left always). Another example is that we might be able to extract an
+ * indexable range condition from a LIKE condition, as in "x LIKE 'foo%bar'"
+ * giving rise to "x >= 'foo' AND x < 'fop'". Derivation of such lossy
+ * conditions is done by a planner support function attached to the
+ * indexclause's top-level function or operator.
+ *
+ * indexquals is a list of RestrictInfos for the directly-usable index
+ * conditions associated with this IndexClause. In the simplest case
+ * it's a one-element list whose member is iclause->rinfo. Otherwise,
+ * it contains one or more directly-usable indexqual conditions extracted
+ * from the given clause. The 'lossy' flag indicates whether the
+ * indexquals are semantically equivalent to the original clause, or
+ * represent a weaker condition.
+ *
+ * Normally, indexcol is the index of the single index column the clause
+ * works on, and indexcols is NIL. But if the clause is a RowCompareExpr,
+ * indexcol is the index of the leading column, and indexcols is a list of
+ * all the affected columns. (Note that indexcols matches up with the
+ * columns of the actual indexable RowCompareExpr in indexquals, which
+ * might be different from the original in rinfo.)
+ *
+ * An IndexPath's IndexClause list is required to be ordered by index
+ * column, i.e. the indexcol values must form a nondecreasing sequence.
+ * (The order of multiple clauses for the same index column is unspecified.)
+ */
+typedef struct IndexClause
+{
+ pg_node_attr(no_copy_equal, no_read, no_query_jumble)
+
+ NodeTag type;
+ struct RestrictInfo *rinfo; /* original restriction or join clause */
+ List *indexquals; /* indexqual(s) derived from it */
+ bool lossy; /* are indexquals a lossy version of clause? */
+ AttrNumber indexcol; /* index column the clause uses (zero-based) */
+ List *indexcols; /* multiple index columns, if RowCompare */
+} IndexClause;
+
+/*
+ * BitmapHeapPath represents one or more indexscans that generate TID bitmaps
+ * instead of directly accessing the heap, followed by AND/OR combinations
+ * to produce a single bitmap, followed by a heap scan that uses the bitmap.
+ * Note that the output is always considered unordered, since it will come
+ * out in physical heap order no matter what the underlying indexes did.
+ *
+ * The individual indexscans are represented by IndexPath nodes, and any
+ * logic on top of them is represented by a tree of BitmapAndPath and
+ * BitmapOrPath nodes. Notice that we can use the same IndexPath node both
+ * to represent a regular (or index-only) index scan plan, and as the child
+ * of a BitmapHeapPath that represents scanning the same index using a
+ * BitmapIndexScan. The startup_cost and total_cost figures of an IndexPath
+ * always represent the costs to use it as a regular (or index-only)
+ * IndexScan. The costs of a BitmapIndexScan can be computed using the
+ * IndexPath's indextotalcost and indexselectivity.
+ */
+typedef struct BitmapHeapPath
+{
+ Path path;
+ Path *bitmapqual; /* IndexPath, BitmapAndPath, BitmapOrPath */
+} BitmapHeapPath;
+
+/*
+ * BitmapAndPath represents a BitmapAnd plan node; it can only appear as
+ * part of the substructure of a BitmapHeapPath. The Path structure is
+ * a bit more heavyweight than we really need for this, but for simplicity
+ * we make it a derivative of Path anyway.
+ */
+typedef struct BitmapAndPath
+{
+ Path path;
+ List *bitmapquals; /* IndexPaths and BitmapOrPaths */
+ Selectivity bitmapselectivity;
+} BitmapAndPath;
+
+/*
+ * BitmapOrPath represents a BitmapOr plan node; it can only appear as
+ * part of the substructure of a BitmapHeapPath. The Path structure is
+ * a bit more heavyweight than we really need for this, but for simplicity
+ * we make it a derivative of Path anyway.
+ */
+typedef struct BitmapOrPath
+{
+ Path path;
+ List *bitmapquals; /* IndexPaths and BitmapAndPaths */
+ Selectivity bitmapselectivity;
+} BitmapOrPath;
+
+/*
+ * TidPath represents a scan by TID
+ *
+ * tidquals is an implicitly OR'ed list of qual expressions of the form
+ * "CTID = pseudoconstant", or "CTID = ANY(pseudoconstant_array)",
+ * or a CurrentOfExpr for the relation.
+ */
+typedef struct TidPath
+{
+ Path path;
+ List *tidquals; /* qual(s) involving CTID = something */
+} TidPath;
+
+/*
+ * TidRangePath represents a scan by a contiguous range of TIDs
+ *
+ * tidrangequals is an implicitly AND'ed list of qual expressions of the form
+ * "CTID relop pseudoconstant", where relop is one of >,>=,<,<=.
+ */
+typedef struct TidRangePath
+{
+ Path path;
+ List *tidrangequals;
+} TidRangePath;
+
+/*
+ * SubqueryScanPath represents a scan of an unflattened subquery-in-FROM
+ *
+ * Note that the subpath comes from a different planning domain; for example
+ * RTE indexes within it mean something different from those known to the
+ * SubqueryScanPath. path.parent->subroot is the planning context needed to
+ * interpret the subpath.
+ */
+typedef struct SubqueryScanPath
+{
+ Path path;
+ Path *subpath; /* path representing subquery execution */
+} SubqueryScanPath;
+
+/*
+ * ForeignPath represents a potential scan of a foreign table, foreign join
+ * or foreign upper-relation.
+ *
+ * fdw_private stores FDW private data about the scan. While fdw_private is
+ * not actually touched by the core code during normal operations, it's
+ * generally a good idea to use a representation that can be dumped by
+ * nodeToString(), so that you can examine the structure during debugging
+ * with tools like pprint().
+ */
+typedef struct ForeignPath
+{
+ Path path;
+ Path *fdw_outerpath;
+ List *fdw_private;
+} ForeignPath;
+
+/*
+ * CustomPath represents a table scan or a table join done by some out-of-core
+ * extension.
+ *
+ * We provide a set of hooks here - which the provider must take care to set
+ * up correctly - to allow extensions to supply their own methods of scanning
+ * a relation or joing relations. For example, a provider might provide GPU
+ * acceleration, a cache-based scan, or some other kind of logic we haven't
+ * dreamed up yet.
+ *
+ * CustomPaths can be injected into the planning process for a base or join
+ * relation by set_rel_pathlist_hook or set_join_pathlist_hook functions,
+ * respectively.
+ *
+ * Core code must avoid assuming that the CustomPath is only as large as
+ * the structure declared here; providers are allowed to make it the first
+ * element in a larger structure. (Since the planner never copies Paths,
+ * this doesn't add any complication.) However, for consistency with the
+ * FDW case, we provide a "custom_private" field in CustomPath; providers
+ * may prefer to use that rather than define another struct type.
+ */
+
+struct CustomPathMethods;
+
+typedef struct CustomPath
+{
+ Path path;
+ uint32 flags; /* mask of CUSTOMPATH_* flags, see
+ * nodes/extensible.h */
+ List *custom_paths; /* list of child Path nodes, if any */
+ List *custom_private;
+ const struct CustomPathMethods *methods;
+} CustomPath;
+
+/*
+ * AppendPath represents an Append plan, ie, successive execution of
+ * several member plans.
+ *
+ * For partial Append, 'subpaths' contains non-partial subpaths followed by
+ * partial subpaths.
+ *
+ * Note: it is possible for "subpaths" to contain only one, or even no,
+ * elements. These cases are optimized during create_append_plan.
+ * In particular, an AppendPath with no subpaths is a "dummy" path that
+ * is created to represent the case that a relation is provably empty.
+ * (This is a convenient representation because it means that when we build
+ * an appendrel and find that all its children have been excluded, no extra
+ * action is needed to recognize the relation as dummy.)
+ */
+typedef struct AppendPath
+{
+ Path path;
+ List *subpaths; /* list of component Paths */
+ /* Index of first partial path in subpaths; list_length(subpaths) if none */
+ int first_partial_path;
+ Cardinality limit_tuples; /* hard limit on output tuples, or -1 */
+} AppendPath;
+
+#define IS_DUMMY_APPEND(p) \
+ (IsA((p), AppendPath) && ((AppendPath *) (p))->subpaths == NIL)
+
+/*
+ * A relation that's been proven empty will have one path that is dummy
+ * (but might have projection paths on top). For historical reasons,
+ * this is provided as a macro that wraps is_dummy_rel().
+ */
+#define IS_DUMMY_REL(r) is_dummy_rel(r)
+extern bool is_dummy_rel(RelOptInfo *rel);
+
+/*
+ * MergeAppendPath represents a MergeAppend plan, ie, the merging of sorted
+ * results from several member plans to produce similarly-sorted output.
+ */
+typedef struct MergeAppendPath
+{
+ Path path;
+ List *subpaths; /* list of component Paths */
+ Cardinality limit_tuples; /* hard limit on output tuples, or -1 */
+} MergeAppendPath;
+
+/*
+ * GroupResultPath represents use of a Result plan node to compute the
+ * output of a degenerate GROUP BY case, wherein we know we should produce
+ * exactly one row, which might then be filtered by a HAVING qual.
+ *
+ * Note that quals is a list of bare clauses, not RestrictInfos.
+ */
+typedef struct GroupResultPath
+{
+ Path path;
+ List *quals;
+} GroupResultPath;
+
+/*
+ * MaterialPath represents use of a Material plan node, i.e., caching of
+ * the output of its subpath. This is used when the subpath is expensive
+ * and needs to be scanned repeatedly, or when we need mark/restore ability
+ * and the subpath doesn't have it.
+ */
+typedef struct MaterialPath
+{
+ Path path;
+ Path *subpath;
+} MaterialPath;
+
+/*
+ * MemoizePath represents a Memoize plan node, i.e., a cache that caches
+ * tuples from parameterized paths to save the underlying node from having to
+ * be rescanned for parameter values which are already cached.
+ */
+typedef struct MemoizePath
+{
+ Path path;
+ Path *subpath; /* outerpath to cache tuples from */
+ List *hash_operators; /* OIDs of hash equality ops for cache keys */
+ List *param_exprs; /* expressions that are cache keys */
+ bool singlerow; /* true if the cache entry is to be marked as
+ * complete after caching the first record. */
+ bool binary_mode; /* true when cache key should be compared bit
+ * by bit, false when using hash equality ops */
+ Cardinality calls; /* expected number of rescans */
+ uint32 est_entries; /* The maximum number of entries that the
+ * planner expects will fit in the cache, or 0
+ * if unknown */
+} MemoizePath;
+
+/*
+ * UniquePath represents elimination of distinct rows from the output of
+ * its subpath.
+ *
+ * This can represent significantly different plans: either hash-based or
+ * sort-based implementation, or a no-op if the input path can be proven
+ * distinct already. The decision is sufficiently localized that it's not
+ * worth having separate Path node types. (Note: in the no-op case, we could
+ * eliminate the UniquePath node entirely and just return the subpath; but
+ * it's convenient to have a UniquePath in the path tree to signal upper-level
+ * routines that the input is known distinct.)
+ */
+typedef enum UniquePathMethod
+{
+ UNIQUE_PATH_NOOP, /* input is known unique already */
+ UNIQUE_PATH_HASH, /* use hashing */
+ UNIQUE_PATH_SORT /* use sorting */
+} UniquePathMethod;
+
+typedef struct UniquePath
+{
+ Path path;
+ Path *subpath;
+ UniquePathMethod umethod;
+ List *in_operators; /* equality operators of the IN clause */
+ List *uniq_exprs; /* expressions to be made unique */
+} UniquePath;
+
+/*
+ * GatherPath runs several copies of a plan in parallel and collects the
+ * results. The parallel leader may also execute the plan, unless the
+ * single_copy flag is set.
+ */
+typedef struct GatherPath
+{
+ Path path;
+ Path *subpath; /* path for each worker */
+ bool single_copy; /* don't execute path more than once */
+ int num_workers; /* number of workers sought to help */
+} GatherPath;
+
+/*
+ * GatherMergePath runs several copies of a plan in parallel and collects
+ * the results, preserving their common sort order.
+ */
+typedef struct GatherMergePath
+{
+ Path path;
+ Path *subpath; /* path for each worker */
+ int num_workers; /* number of workers sought to help */
+} GatherMergePath;
+
+
+/*
+ * All join-type paths share these fields.
+ */
+
+typedef struct JoinPath
+{
+ pg_node_attr(abstract)
+
+ Path path;
+
+ JoinType jointype;
+
+ bool inner_unique; /* each outer tuple provably matches no more
+ * than one inner tuple */
+
+ Path *outerjoinpath; /* path for the outer side of the join */
+ Path *innerjoinpath; /* path for the inner side of the join */
+
+ List *joinrestrictinfo; /* RestrictInfos to apply to join */
+
+ /*
+ * See the notes for RelOptInfo and ParamPathInfo to understand why
+ * joinrestrictinfo is needed in JoinPath, and can't be merged into the
+ * parent RelOptInfo.
+ */
+} JoinPath;
+
+/*
+ * A nested-loop path needs no special fields.
+ */
+
+typedef struct NestPath
+{
+ JoinPath jpath;
+} NestPath;
+
+/*
+ * A mergejoin path has these fields.
+ *
+ * Unlike other path types, a MergePath node doesn't represent just a single
+ * run-time plan node: it can represent up to four. Aside from the MergeJoin
+ * node itself, there can be a Sort node for the outer input, a Sort node
+ * for the inner input, and/or a Material node for the inner input. We could
+ * represent these nodes by separate path nodes, but considering how many
+ * different merge paths are investigated during a complex join problem,
+ * it seems better to avoid unnecessary palloc overhead.
+ *
+ * path_mergeclauses lists the clauses (in the form of RestrictInfos)
+ * that will be used in the merge.
+ *
+ * Note that the mergeclauses are a subset of the parent relation's
+ * restriction-clause list. Any join clauses that are not mergejoinable
+ * appear only in the parent's restrict list, and must be checked by a
+ * qpqual at execution time.
+ *
+ * outersortkeys (resp. innersortkeys) is NIL if the outer path
+ * (resp. inner path) is already ordered appropriately for the
+ * mergejoin. If it is not NIL then it is a PathKeys list describing
+ * the ordering that must be created by an explicit Sort node.
+ *
+ * skip_mark_restore is true if the executor need not do mark/restore calls.
+ * Mark/restore overhead is usually required, but can be skipped if we know
+ * that the executor need find only one match per outer tuple, and that the
+ * mergeclauses are sufficient to identify a match. In such cases the
+ * executor can immediately advance the outer relation after processing a
+ * match, and therefore it need never back up the inner relation.
+ *
+ * materialize_inner is true if a Material node should be placed atop the
+ * inner input. This may appear with or without an inner Sort step.
+ */
+
+typedef struct MergePath
+{
+ JoinPath jpath;
+ List *path_mergeclauses; /* join clauses to be used for merge */
+ List *outersortkeys; /* keys for explicit sort, if any */
+ List *innersortkeys; /* keys for explicit sort, if any */
+ bool skip_mark_restore; /* can executor skip mark/restore? */
+ bool materialize_inner; /* add Materialize to inner? */
+} MergePath;
+
+/*
+ * A hashjoin path has these fields.
+ *
+ * The remarks above for mergeclauses apply for hashclauses as well.
+ *
+ * Hashjoin does not care what order its inputs appear in, so we have
+ * no need for sortkeys.
+ */
+
+typedef struct HashPath
+{
+ JoinPath jpath;
+ List *path_hashclauses; /* join clauses used for hashing */
+ int num_batches; /* number of batches expected */
+ Cardinality inner_rows_total; /* total inner rows expected */
+} HashPath;
+
+/*
+ * ProjectionPath represents a projection (that is, targetlist computation)
+ *
+ * Nominally, this path node represents using a Result plan node to do a
+ * projection step. However, if the input plan node supports projection,
+ * we can just modify its output targetlist to do the required calculations
+ * directly, and not need a Result. In some places in the planner we can just
+ * jam the desired PathTarget into the input path node (and adjust its cost
+ * accordingly), so we don't need a ProjectionPath. But in other places
+ * it's necessary to not modify the input path node, so we need a separate
+ * ProjectionPath node, which is marked dummy to indicate that we intend to
+ * assign the work to the input plan node. The estimated cost for the
+ * ProjectionPath node will account for whether a Result will be used or not.
+ */
+typedef struct ProjectionPath
+{
+ Path path;
+ Path *subpath; /* path representing input source */
+ bool dummypp; /* true if no separate Result is needed */
+} ProjectionPath;
+
+/*
+ * ProjectSetPath represents evaluation of a targetlist that includes
+ * set-returning function(s), which will need to be implemented by a
+ * ProjectSet plan node.
+ */
+typedef struct ProjectSetPath
+{
+ Path path;
+ Path *subpath; /* path representing input source */
+} ProjectSetPath;
+
+/*
+ * SortPath represents an explicit sort step
+ *
+ * The sort keys are, by definition, the same as path.pathkeys.
+ *
+ * Note: the Sort plan node cannot project, so path.pathtarget must be the
+ * same as the input's pathtarget.
+ */
+typedef struct SortPath
+{
+ Path path;
+ Path *subpath; /* path representing input source */
+} SortPath;
+
+/*
+ * IncrementalSortPath represents an incremental sort step
+ *
+ * This is like a regular sort, except some leading key columns are assumed
+ * to be ordered already.
+ */
+typedef struct IncrementalSortPath
+{
+ SortPath spath;
+ int nPresortedCols; /* number of presorted columns */
+} IncrementalSortPath;
+
+/*
+ * GroupPath represents grouping (of presorted input)
+ *
+ * groupClause represents the columns to be grouped on; the input path
+ * must be at least that well sorted.
+ *
+ * We can also apply a qual to the grouped rows (equivalent of HAVING)
+ */
+typedef struct GroupPath
+{
+ Path path;
+ Path *subpath; /* path representing input source */
+ List *groupClause; /* a list of SortGroupClause's */
+ List *qual; /* quals (HAVING quals), if any */
+} GroupPath;
+
+/*
+ * UpperUniquePath represents adjacent-duplicate removal (in presorted input)
+ *
+ * The columns to be compared are the first numkeys columns of the path's
+ * pathkeys. The input is presumed already sorted that way.
+ */
+typedef struct UpperUniquePath
+{
+ Path path;
+ Path *subpath; /* path representing input source */
+ int numkeys; /* number of pathkey columns to compare */
+} UpperUniquePath;
+
+/*
+ * AggPath represents generic computation of aggregate functions
+ *
+ * This may involve plain grouping (but not grouping sets), using either
+ * sorted or hashed grouping; for the AGG_SORTED case, the input must be
+ * appropriately presorted.
+ */
+typedef struct AggPath
+{
+ Path path;
+ Path *subpath; /* path representing input source */
+ AggStrategy aggstrategy; /* basic strategy, see nodes.h */
+ AggSplit aggsplit; /* agg-splitting mode, see nodes.h */
+ Cardinality numGroups; /* estimated number of groups in input */
+ uint64 transitionSpace; /* for pass-by-ref transition data */
+ List *groupClause; /* a list of SortGroupClause's */
+ List *qual; /* quals (HAVING quals), if any */
+} AggPath;
+
+/*
+ * Various annotations used for grouping sets in the planner.
+ */
+
+typedef struct GroupingSetData
+{
+ pg_node_attr(no_copy_equal, no_read, no_query_jumble)
+
+ NodeTag type;
+ List *set; /* grouping set as list of sortgrouprefs */
+ Cardinality numGroups; /* est. number of result groups */
+} GroupingSetData;
+
+typedef struct RollupData
+{
+ pg_node_attr(no_copy_equal, no_read, no_query_jumble)
+
+ NodeTag type;
+ List *groupClause; /* applicable subset of parse->groupClause */
+ List *gsets; /* lists of integer indexes into groupClause */
+ List *gsets_data; /* list of GroupingSetData */
+ Cardinality numGroups; /* est. number of result groups */
+ bool hashable; /* can be hashed */
+ bool is_hashed; /* to be implemented as a hashagg */
+} RollupData;
+
+/*
+ * GroupingSetsPath represents a GROUPING SETS aggregation
+ */
+
+typedef struct GroupingSetsPath
+{
+ Path path;
+ Path *subpath; /* path representing input source */
+ AggStrategy aggstrategy; /* basic strategy */
+ List *rollups; /* list of RollupData */
+ List *qual; /* quals (HAVING quals), if any */
+ uint64 transitionSpace; /* for pass-by-ref transition data */
+} GroupingSetsPath;
+
+/*
+ * MinMaxAggPath represents computation of MIN/MAX aggregates from indexes
+ */
+typedef struct MinMaxAggPath
+{
+ Path path;
+ List *mmaggregates; /* list of MinMaxAggInfo */
+ List *quals; /* HAVING quals, if any */
+} MinMaxAggPath;
+
+/*
+ * WindowAggPath represents generic computation of window functions
+ */
+typedef struct WindowAggPath
+{
+ Path path;
+ Path *subpath; /* path representing input source */
+ WindowClause *winclause; /* WindowClause we'll be using */
+ List *qual; /* lower-level WindowAgg runconditions */
+ bool topwindow; /* false for all apart from the WindowAgg
+ * that's closest to the root of the plan */
+} WindowAggPath;
+
+/*
+ * SetOpPath represents a set-operation, that is INTERSECT or EXCEPT
+ */
+typedef struct SetOpPath
+{
+ Path path;
+ Path *subpath; /* path representing input source */
+ SetOpCmd cmd; /* what to do, see nodes.h */
+ SetOpStrategy strategy; /* how to do it, see nodes.h */
+ List *distinctList; /* SortGroupClauses identifying target cols */
+ AttrNumber flagColIdx; /* where is the flag column, if any */
+ int firstFlag; /* flag value for first input relation */
+ Cardinality numGroups; /* estimated number of groups in input */
+} SetOpPath;
+
+/*
+ * RecursiveUnionPath represents a recursive UNION node
+ */
+typedef struct RecursiveUnionPath
+{
+ Path path;
+ Path *leftpath; /* paths representing input sources */
+ Path *rightpath;
+ List *distinctList; /* SortGroupClauses identifying target cols */
+ int wtParam; /* ID of Param representing work table */
+ Cardinality numGroups; /* estimated number of groups in input */
+} RecursiveUnionPath;
+
+/*
+ * LockRowsPath represents acquiring row locks for SELECT FOR UPDATE/SHARE
+ */
+typedef struct LockRowsPath
+{
+ Path path;
+ Path *subpath; /* path representing input source */
+ List *rowMarks; /* a list of PlanRowMark's */
+ int epqParam; /* ID of Param for EvalPlanQual re-eval */
+} LockRowsPath;
+
+/*
+ * ModifyTablePath represents performing INSERT/UPDATE/DELETE/MERGE
+ *
+ * We represent most things that will be in the ModifyTable plan node
+ * literally, except we have a child Path not Plan. But analysis of the
+ * OnConflictExpr is deferred to createplan.c, as is collection of FDW data.
+ */
+typedef struct ModifyTablePath
+{
+ Path path;
+ Path *subpath; /* Path producing source data */
+ CmdType operation; /* INSERT, UPDATE, DELETE, or MERGE */
+ bool canSetTag; /* do we set the command tag/es_processed? */
+ Index nominalRelation; /* Parent RT index for use of EXPLAIN */
+ Index rootRelation; /* Root RT index, if partitioned/inherited */
+ bool partColsUpdated; /* some part key in hierarchy updated? */
+ List *resultRelations; /* integer list of RT indexes */
+ List *updateColnosLists; /* per-target-table update_colnos lists */
+ List *withCheckOptionLists; /* per-target-table WCO lists */
+ List *returningLists; /* per-target-table RETURNING tlists */
+ List *rowMarks; /* PlanRowMarks (non-locking only) */
+ OnConflictExpr *onconflict; /* ON CONFLICT clause, or NULL */
+ int epqParam; /* ID of Param for EvalPlanQual re-eval */
+ List *mergeActionLists; /* per-target-table lists of actions for
+ * MERGE */
+} ModifyTablePath;
+
+/*
+ * LimitPath represents applying LIMIT/OFFSET restrictions
+ */
+typedef struct LimitPath
+{
+ Path path;
+ Path *subpath; /* path representing input source */
+ Node *limitOffset; /* OFFSET parameter, or NULL if none */
+ Node *limitCount; /* COUNT parameter, or NULL if none */
+ LimitOption limitOption; /* FETCH FIRST with ties or exact number */
+} LimitPath;
+
+
+/*
+ * Restriction clause info.
+ *
+ * We create one of these for each AND sub-clause of a restriction condition
+ * (WHERE or JOIN/ON clause). Since the restriction clauses are logically
+ * ANDed, we can use any one of them or any subset of them to filter out
+ * tuples, without having to evaluate the rest. The RestrictInfo node itself
+ * stores data used by the optimizer while choosing the best query plan.
+ *
+ * If a restriction clause references a single base relation, it will appear
+ * in the baserestrictinfo list of the RelOptInfo for that base rel.
+ *
+ * If a restriction clause references more than one base+OJ relation, it will
+ * appear in the joininfo list of every RelOptInfo that describes a strict
+ * subset of the relations mentioned in the clause. The joininfo lists are
+ * used to drive join tree building by selecting plausible join candidates.
+ * The clause cannot actually be applied until we have built a join rel
+ * containing all the relations it references, however.
+ *
+ * When we construct a join rel that includes all the relations referenced
+ * in a multi-relation restriction clause, we place that clause into the
+ * joinrestrictinfo lists of paths for the join rel, if neither left nor
+ * right sub-path includes all relations referenced in the clause. The clause
+ * will be applied at that join level, and will not propagate any further up
+ * the join tree. (Note: the "predicate migration" code was once intended to
+ * push restriction clauses up and down the plan tree based on evaluation
+ * costs, but it's dead code and is unlikely to be resurrected in the
+ * foreseeable future.)
+ *
+ * Note that in the presence of more than two rels, a multi-rel restriction
+ * might reach different heights in the join tree depending on the join
+ * sequence we use. So, these clauses cannot be associated directly with
+ * the join RelOptInfo, but must be kept track of on a per-join-path basis.
+ *
+ * RestrictInfos that represent equivalence conditions (i.e., mergejoinable
+ * equalities that are not outerjoin-delayed) are handled a bit differently.
+ * Initially we attach them to the EquivalenceClasses that are derived from
+ * them. When we construct a scan or join path, we look through all the
+ * EquivalenceClasses and generate derived RestrictInfos representing the
+ * minimal set of conditions that need to be checked for this particular scan
+ * or join to enforce that all members of each EquivalenceClass are in fact
+ * equal in all rows emitted by the scan or join.
+ *
+ * The clause_relids field lists the base plus outer-join RT indexes that
+ * actually appear in the clause. required_relids lists the minimum set of
+ * relids needed to evaluate the clause; while this is often equal to
+ * clause_relids, it can be more. We will add relids to required_relids when
+ * we need to force an outer join ON clause to be evaluated exactly at the
+ * level of the outer join, which is true except when it is a "degenerate"
+ * condition that references only Vars from the nullable side of the join.
+ *
+ * RestrictInfo nodes contain a flag to indicate whether a qual has been
+ * pushed down to a lower level than its original syntactic placement in the
+ * join tree would suggest. If an outer join prevents us from pushing a qual
+ * down to its "natural" semantic level (the level associated with just the
+ * base rels used in the qual) then we mark the qual with a "required_relids"
+ * value including more than just the base rels it actually uses. By
+ * pretending that the qual references all the rels required to form the outer
+ * join, we prevent it from being evaluated below the outer join's joinrel.
+ * When we do form the outer join's joinrel, we still need to distinguish
+ * those quals that are actually in that join's JOIN/ON condition from those
+ * that appeared elsewhere in the tree and were pushed down to the join rel
+ * because they used no other rels. That's what the is_pushed_down flag is
+ * for; it tells us that a qual is not an OUTER JOIN qual for the set of base
+ * rels listed in required_relids. A clause that originally came from WHERE
+ * or an INNER JOIN condition will *always* have its is_pushed_down flag set.
+ * It's possible for an OUTER JOIN clause to be marked is_pushed_down too,
+ * if we decide that it can be pushed down into the nullable side of the join.
+ * In that case it acts as a plain filter qual for wherever it gets evaluated.
+ * (In short, is_pushed_down is only false for non-degenerate outer join
+ * conditions. Possibly we should rename it to reflect that meaning? But
+ * see also the comments for RINFO_IS_PUSHED_DOWN, below.)
+ *
+ * There is also an incompatible_relids field, which is a set of outer-join
+ * relids above which we cannot evaluate the clause (because they might null
+ * Vars it uses that should not be nulled yet). In principle this could be
+ * filled in any RestrictInfo as the set of OJ relids that appear above the
+ * clause and null Vars that it uses. In practice we only bother to populate
+ * it for "clone" clauses, as it's currently only needed to prevent multiple
+ * clones of the same clause from being accepted for evaluation at the same
+ * join level.
+ *
+ * There is also an outer_relids field, which is NULL except for outer join
+ * clauses; for those, it is the set of relids on the outer side of the
+ * clause's outer join. (These are rels that the clause cannot be applied to
+ * in parameterized scans, since pushing it into the join's outer side would
+ * lead to wrong answers.)
+ *
+ * To handle security-barrier conditions efficiently, we mark RestrictInfo
+ * nodes with a security_level field, in which higher values identify clauses
+ * coming from less-trusted sources. The exact semantics are that a clause
+ * cannot be evaluated before another clause with a lower security_level value
+ * unless the first clause is leakproof. As with outer-join clauses, this
+ * creates a reason for clauses to sometimes need to be evaluated higher in
+ * the join tree than their contents would suggest; and even at a single plan
+ * node, this rule constrains the order of application of clauses.
+ *
+ * In general, the referenced clause might be arbitrarily complex. The
+ * kinds of clauses we can handle as indexscan quals, mergejoin clauses,
+ * or hashjoin clauses are limited (e.g., no volatile functions). The code
+ * for each kind of path is responsible for identifying the restrict clauses
+ * it can use and ignoring the rest. Clauses not implemented by an indexscan,
+ * mergejoin, or hashjoin will be placed in the plan qual or joinqual field
+ * of the finished Plan node, where they will be enforced by general-purpose
+ * qual-expression-evaluation code. (But we are still entitled to count
+ * their selectivity when estimating the result tuple count, if we
+ * can guess what it is...)
+ *
+ * When the referenced clause is an OR clause, we generate a modified copy
+ * in which additional RestrictInfo nodes are inserted below the top-level
+ * OR/AND structure. This is a convenience for OR indexscan processing:
+ * indexquals taken from either the top level or an OR subclause will have
+ * associated RestrictInfo nodes.
+ *
+ * The can_join flag is set true if the clause looks potentially useful as
+ * a merge or hash join clause, that is if it is a binary opclause with
+ * nonoverlapping sets of relids referenced in the left and right sides.
+ * (Whether the operator is actually merge or hash joinable isn't checked,
+ * however.)
+ *
+ * The pseudoconstant flag is set true if the clause contains no Vars of
+ * the current query level and no volatile functions. Such a clause can be
+ * pulled out and used as a one-time qual in a gating Result node. We keep
+ * pseudoconstant clauses in the same lists as other RestrictInfos so that
+ * the regular clause-pushing machinery can assign them to the correct join
+ * level, but they need to be treated specially for cost and selectivity
+ * estimates. Note that a pseudoconstant clause can never be an indexqual
+ * or merge or hash join clause, so it's of no interest to large parts of
+ * the planner.
+ *
+ * When we generate multiple versions of a clause so as to have versions
+ * that will work after commuting some left joins per outer join identity 3,
+ * we mark the one with the fewest nullingrels bits with has_clone = true,
+ * and the rest with is_clone = true. This allows proper filtering of
+ * these redundant clauses, so that we apply only one version of them.
+ *
+ * When join clauses are generated from EquivalenceClasses, there may be
+ * several equally valid ways to enforce join equivalence, of which we need
+ * apply only one. We mark clauses of this kind by setting parent_ec to
+ * point to the generating EquivalenceClass. Multiple clauses with the same
+ * parent_ec in the same join are redundant.
+ *
+ * Most fields are ignored for equality, since they may not be set yet, and
+ * should be derivable from the clause anyway.
+ *
+ * parent_ec, left_ec, right_ec are not printed, lest it lead to infinite
+ * recursion in plan tree dump.
+ */
+
+typedef struct RestrictInfo
+{
+ pg_node_attr(no_read, no_query_jumble)
+
+ NodeTag type;
+
+ /* the represented clause of WHERE or JOIN */
+ Expr *clause;
+
+ /* true if clause was pushed down in level */
+ bool is_pushed_down;
+
+ /* see comment above */
+ bool can_join pg_node_attr(equal_ignore);
+
+ /* see comment above */
+ bool pseudoconstant pg_node_attr(equal_ignore);
+
+ /* see comment above */
+ bool has_clone;
+ bool is_clone;
+
+ /* true if known to contain no leaked Vars */
+ bool leakproof pg_node_attr(equal_ignore);
+
+ /* indicates if clause contains any volatile functions */
+ VolatileFunctionStatus has_volatile pg_node_attr(equal_ignore);
+
+ /* see comment above */
+ Index security_level;
+
+ /* number of base rels in clause_relids */
+ int num_base_rels pg_node_attr(equal_ignore);
+
+ /* The relids (varnos+varnullingrels) actually referenced in the clause: */
+ Relids clause_relids pg_node_attr(equal_ignore);
+
+ /* The set of relids required to evaluate the clause: */
+ Relids required_relids;
+
+ /* Relids above which we cannot evaluate the clause (see comment above) */
+ Relids incompatible_relids;
+
+ /* If an outer-join clause, the outer-side relations, else NULL: */
+ Relids outer_relids;
+
+ /*
+ * Relids in the left/right side of the clause. These fields are set for
+ * any binary opclause.
+ */
+ Relids left_relids pg_node_attr(equal_ignore);
+ Relids right_relids pg_node_attr(equal_ignore);
+
+ /*
+ * Modified clause with RestrictInfos. This field is NULL unless clause
+ * is an OR clause.
+ */
+ Expr *orclause pg_node_attr(equal_ignore);
+
+ /*----------
+ * Serial number of this RestrictInfo. This is unique within the current
+ * PlannerInfo context, with a few critical exceptions:
+ * 1. When we generate multiple clones of the same qual condition to
+ * cope with outer join identity 3, all the clones get the same serial
+ * number. This reflects that we only want to apply one of them in any
+ * given plan.
+ * 2. If we manufacture a commuted version of a qual to use as an index
+ * condition, it copies the original's rinfo_serial, since it is in
+ * practice the same condition.
+ * 3. RestrictInfos made for a child relation copy their parent's
+ * rinfo_serial. Likewise, when an EquivalenceClass makes a derived
+ * equality clause for a child relation, it copies the rinfo_serial of
+ * the matching equality clause for the parent. This allows detection
+ * of redundant pushed-down equality clauses.
+ *----------
+ */
+ int rinfo_serial;
+
+ /*
+ * Generating EquivalenceClass. This field is NULL unless clause is
+ * potentially redundant.
+ */
+ EquivalenceClass *parent_ec pg_node_attr(copy_as_scalar, equal_ignore, read_write_ignore);
+
+ /*
+ * cache space for cost and selectivity
+ */
+
+ /* eval cost of clause; -1 if not yet set */
+ QualCost eval_cost pg_node_attr(equal_ignore);
+
+ /* selectivity for "normal" (JOIN_INNER) semantics; -1 if not yet set */
+ Selectivity norm_selec pg_node_attr(equal_ignore);
+ /* selectivity for outer join semantics; -1 if not yet set */
+ Selectivity outer_selec pg_node_attr(equal_ignore);
+
+ /*
+ * opfamilies containing clause operator; valid if clause is
+ * mergejoinable, else NIL
+ */
+ List *mergeopfamilies pg_node_attr(equal_ignore);
+
+ /*
+ * cache space for mergeclause processing; NULL if not yet set
+ */
+
+ /* EquivalenceClass containing lefthand */
+ EquivalenceClass *left_ec pg_node_attr(copy_as_scalar, equal_ignore, read_write_ignore);
+ /* EquivalenceClass containing righthand */
+ EquivalenceClass *right_ec pg_node_attr(copy_as_scalar, equal_ignore, read_write_ignore);
+ /* EquivalenceMember for lefthand */
+ EquivalenceMember *left_em pg_node_attr(copy_as_scalar, equal_ignore);
+ /* EquivalenceMember for righthand */
+ EquivalenceMember *right_em pg_node_attr(copy_as_scalar, equal_ignore);
+
+ /*
+ * List of MergeScanSelCache structs. Those aren't Nodes, so hard to
+ * copy; instead replace with NIL. That has the effect that copying will
+ * just reset the cache. Likewise, can't compare or print them.
+ */
+ List *scansel_cache pg_node_attr(copy_as(NIL), equal_ignore, read_write_ignore);
+
+ /*
+ * transient workspace for use while considering a specific join path; T =
+ * outer var on left, F = on right
+ */
+ bool outer_is_left pg_node_attr(equal_ignore);
+
+ /*
+ * copy of clause operator; valid if clause is hashjoinable, else
+ * InvalidOid
+ */
+ Oid hashjoinoperator pg_node_attr(equal_ignore);
+
+ /*
+ * cache space for hashclause processing; -1 if not yet set
+ */
+ /* avg bucketsize of left side */
+ Selectivity left_bucketsize pg_node_attr(equal_ignore);
+ /* avg bucketsize of right side */
+ Selectivity right_bucketsize pg_node_attr(equal_ignore);
+ /* left side's most common val's freq */
+ Selectivity left_mcvfreq pg_node_attr(equal_ignore);
+ /* right side's most common val's freq */
+ Selectivity right_mcvfreq pg_node_attr(equal_ignore);
+
+ /* hash equality operators used for memoize nodes, else InvalidOid */
+ Oid left_hasheqoperator pg_node_attr(equal_ignore);
+ Oid right_hasheqoperator pg_node_attr(equal_ignore);
+} RestrictInfo;
+
+/*
+ * This macro embodies the correct way to test whether a RestrictInfo is
+ * "pushed down" to a given outer join, that is, should be treated as a filter
+ * clause rather than a join clause at that outer join. This is certainly so
+ * if is_pushed_down is true; but examining that is not sufficient anymore,
+ * because outer-join clauses will get pushed down to lower outer joins when
+ * we generate a path for the lower outer join that is parameterized by the
+ * LHS of the upper one. We can detect such a clause by noting that its
+ * required_relids exceed the scope of the join.
+ */
+#define RINFO_IS_PUSHED_DOWN(rinfo, joinrelids) \
+ ((rinfo)->is_pushed_down || \
+ !bms_is_subset((rinfo)->required_relids, joinrelids))
+
+/*
+ * Since mergejoinscansel() is a relatively expensive function, and would
+ * otherwise be invoked many times while planning a large join tree,
+ * we go out of our way to cache its results. Each mergejoinable
+ * RestrictInfo carries a list of the specific sort orderings that have
+ * been considered for use with it, and the resulting selectivities.
+ */
+typedef struct MergeScanSelCache
+{
+ /* Ordering details (cache lookup key) */
+ Oid opfamily; /* btree opfamily defining the ordering */
+ Oid collation; /* collation for the ordering */
+ int strategy; /* sort direction (ASC or DESC) */
+ bool nulls_first; /* do NULLs come before normal values? */
+ /* Results */
+ Selectivity leftstartsel; /* first-join fraction for clause left side */
+ Selectivity leftendsel; /* last-join fraction for clause left side */
+ Selectivity rightstartsel; /* first-join fraction for clause right side */
+ Selectivity rightendsel; /* last-join fraction for clause right side */
+} MergeScanSelCache;
+
+/*
+ * Placeholder node for an expression to be evaluated below the top level
+ * of a plan tree. This is used during planning to represent the contained
+ * expression. At the end of the planning process it is replaced by either
+ * the contained expression or a Var referring to a lower-level evaluation of
+ * the contained expression. Generally the evaluation occurs below an outer
+ * join, and Var references above the outer join might thereby yield NULL
+ * instead of the expression value.
+ *
+ * phrels and phlevelsup correspond to the varno/varlevelsup fields of a
+ * plain Var, except that phrels has to be a relid set since the evaluation
+ * level of a PlaceHolderVar might be a join rather than a base relation.
+ * Likewise, phnullingrels corresponds to varnullingrels.
+ *
+ * Although the planner treats this as an expression node type, it is not
+ * recognized by the parser or executor, so we declare it here rather than
+ * in primnodes.h.
+ *
+ * We intentionally do not compare phexpr. Two PlaceHolderVars with the
+ * same ID and levelsup should be considered equal even if the contained
+ * expressions have managed to mutate to different states. This will
+ * happen during final plan construction when there are nested PHVs, since
+ * the inner PHV will get replaced by a Param in some copies of the outer
+ * PHV. Another way in which it can happen is that initplan sublinks
+ * could get replaced by differently-numbered Params when sublink folding
+ * is done. (The end result of such a situation would be some
+ * unreferenced initplans, which is annoying but not really a problem.)
+ * On the same reasoning, there is no need to examine phrels. But we do
+ * need to compare phnullingrels, as that represents effects that are
+ * external to the original value of the PHV.
+ */
+
+typedef struct PlaceHolderVar
+{
+ pg_node_attr(no_query_jumble)
+
+ Expr xpr;
+
+ /* the represented expression */
+ Expr *phexpr pg_node_attr(equal_ignore);
+
+ /* base+OJ relids syntactically within expr src */
+ Relids phrels pg_node_attr(equal_ignore);
+
+ /* RT indexes of outer joins that can null PHV's value */
+ Relids phnullingrels;
+
+ /* ID for PHV (unique within planner run) */
+ Index phid;
+
+ /* > 0 if PHV belongs to outer query */
+ Index phlevelsup;
+} PlaceHolderVar;
+
+/*
+ * "Special join" info.
+ *
+ * One-sided outer joins constrain the order of joining partially but not
+ * completely. We flatten such joins into the planner's top-level list of
+ * relations to join, but record information about each outer join in a
+ * SpecialJoinInfo struct. These structs are kept in the PlannerInfo node's
+ * join_info_list.
+ *
+ * Similarly, semijoins and antijoins created by flattening IN (subselect)
+ * and EXISTS(subselect) clauses create partial constraints on join order.
+ * These are likewise recorded in SpecialJoinInfo structs.
+ *
+ * We make SpecialJoinInfos for FULL JOINs even though there is no flexibility
+ * of planning for them, because this simplifies make_join_rel()'s API.
+ *
+ * min_lefthand and min_righthand are the sets of base+OJ relids that must be
+ * available on each side when performing the special join.
+ * It is not valid for either min_lefthand or min_righthand to be empty sets;
+ * if they were, this would break the logic that enforces join order.
+ *
+ * syn_lefthand and syn_righthand are the sets of base+OJ relids that are
+ * syntactically below this special join. (These are needed to help compute
+ * min_lefthand and min_righthand for higher joins.)
+ *
+ * jointype is never JOIN_RIGHT; a RIGHT JOIN is handled by switching
+ * the inputs to make it a LEFT JOIN. It's never JOIN_RIGHT_ANTI either.
+ * So the allowed values of jointype in a join_info_list member are only
+ * LEFT, FULL, SEMI, or ANTI.
+ *
+ * ojrelid is the RT index of the join RTE representing this outer join,
+ * if there is one. It is zero when jointype is INNER or SEMI, and can be
+ * zero for jointype ANTI (if the join was transformed from a SEMI join).
+ * One use for this field is that when constructing the output targetlist of a
+ * join relation that implements this OJ, we add ojrelid to the varnullingrels
+ * and phnullingrels fields of nullable (RHS) output columns, so that the
+ * output Vars and PlaceHolderVars correctly reflect the nulling that has
+ * potentially happened to them.
+ *
+ * commute_above_l is filled with the relids of syntactically-higher outer
+ * joins that have been found to commute with this one per outer join identity
+ * 3 (see optimizer/README), when this join is in the LHS of the upper join
+ * (so, this is the lower join in the first form of the identity).
+ *
+ * commute_above_r is filled with the relids of syntactically-higher outer
+ * joins that have been found to commute with this one per outer join identity
+ * 3, when this join is in the RHS of the upper join (so, this is the lower
+ * join in the second form of the identity).
+ *
+ * commute_below_l is filled with the relids of syntactically-lower outer
+ * joins that have been found to commute with this one per outer join identity
+ * 3 and are in the LHS of this join (so, this is the upper join in the first
+ * form of the identity).
+ *
+ * commute_below_r is filled with the relids of syntactically-lower outer
+ * joins that have been found to commute with this one per outer join identity
+ * 3 and are in the RHS of this join (so, this is the upper join in the second
+ * form of the identity).
+ *
+ * lhs_strict is true if the special join's condition cannot succeed when the
+ * LHS variables are all NULL (this means that an outer join can commute with
+ * upper-level outer joins even if it appears in their RHS). We don't bother
+ * to set lhs_strict for FULL JOINs, however.
+ *
+ * For a semijoin, we also extract the join operators and their RHS arguments
+ * and set semi_operators, semi_rhs_exprs, semi_can_btree, and semi_can_hash.
+ * This is done in support of possibly unique-ifying the RHS, so we don't
+ * bother unless at least one of semi_can_btree and semi_can_hash can be set
+ * true. (You might expect that this information would be computed during
+ * join planning; but it's helpful to have it available during planning of
+ * parameterized table scans, so we store it in the SpecialJoinInfo structs.)
+ *
+ * For purposes of join selectivity estimation, we create transient
+ * SpecialJoinInfo structures for regular inner joins; so it is possible
+ * to have jointype == JOIN_INNER in such a structure, even though this is
+ * not allowed within join_info_list. We also create transient
+ * SpecialJoinInfos with jointype == JOIN_INNER for outer joins, since for
+ * cost estimation purposes it is sometimes useful to know the join size under
+ * plain innerjoin semantics. Note that lhs_strict and the semi_xxx fields
+ * are not set meaningfully within such structs.
+ */
+#ifndef HAVE_SPECIALJOININFO_TYPEDEF
+typedef struct SpecialJoinInfo SpecialJoinInfo;
+#define HAVE_SPECIALJOININFO_TYPEDEF 1
+#endif
+
+struct SpecialJoinInfo
+{
+ pg_node_attr(no_read, no_query_jumble)
+
+ NodeTag type;
+ Relids min_lefthand; /* base+OJ relids in minimum LHS for join */
+ Relids min_righthand; /* base+OJ relids in minimum RHS for join */
+ Relids syn_lefthand; /* base+OJ relids syntactically within LHS */
+ Relids syn_righthand; /* base+OJ relids syntactically within RHS */
+ JoinType jointype; /* always INNER, LEFT, FULL, SEMI, or ANTI */
+ Index ojrelid; /* outer join's RT index; 0 if none */
+ Relids commute_above_l; /* commuting OJs above this one, if LHS */
+ Relids commute_above_r; /* commuting OJs above this one, if RHS */
+ Relids commute_below_l; /* commuting OJs in this one's LHS */
+ Relids commute_below_r; /* commuting OJs in this one's RHS */
+ bool lhs_strict; /* joinclause is strict for some LHS rel */
+ /* Remaining fields are set only for JOIN_SEMI jointype: */
+ bool semi_can_btree; /* true if semi_operators are all btree */
+ bool semi_can_hash; /* true if semi_operators are all hash */
+ List *semi_operators; /* OIDs of equality join operators */
+ List *semi_rhs_exprs; /* righthand-side expressions of these ops */
+};
+
+/*
+ * Transient outer-join clause info.
+ *
+ * We set aside every outer join ON clause that looks mergejoinable,
+ * and process it specially at the end of qual distribution.
+ */
+typedef struct OuterJoinClauseInfo
+{
+ pg_node_attr(no_copy_equal, no_read, no_query_jumble)
+
+ NodeTag type;
+ RestrictInfo *rinfo; /* a mergejoinable outer-join clause */
+ SpecialJoinInfo *sjinfo; /* the outer join's SpecialJoinInfo */
+} OuterJoinClauseInfo;
+
+/*
+ * Append-relation info.
+ *
+ * When we expand an inheritable table or a UNION-ALL subselect into an
+ * "append relation" (essentially, a list of child RTEs), we build an
+ * AppendRelInfo for each child RTE. The list of AppendRelInfos indicates
+ * which child RTEs must be included when expanding the parent, and each node
+ * carries information needed to translate between columns of the parent and
+ * columns of the child.
+ *
+ * These structs are kept in the PlannerInfo node's append_rel_list, with
+ * append_rel_array[] providing a convenient lookup method for the struct
+ * associated with a particular child relid (there can be only one, though
+ * parent rels may have many entries in append_rel_list).
+ *
+ * Note: after completion of the planner prep phase, any given RTE is an
+ * append parent having entries in append_rel_list if and only if its
+ * "inh" flag is set. We clear "inh" for plain tables that turn out not
+ * to have inheritance children, and (in an abuse of the original meaning
+ * of the flag) we set "inh" for subquery RTEs that turn out to be
+ * flattenable UNION ALL queries. This lets us avoid useless searches
+ * of append_rel_list.
+ *
+ * Note: the data structure assumes that append-rel members are single
+ * baserels. This is OK for inheritance, but it prevents us from pulling
+ * up a UNION ALL member subquery if it contains a join. While that could
+ * be fixed with a more complex data structure, at present there's not much
+ * point because no improvement in the plan could result.
+ */
+
+typedef struct AppendRelInfo
+{
+ pg_node_attr(no_query_jumble)
+
+ NodeTag type;
+
+ /*
+ * These fields uniquely identify this append relationship. There can be
+ * (in fact, always should be) multiple AppendRelInfos for the same
+ * parent_relid, but never more than one per child_relid, since a given
+ * RTE cannot be a child of more than one append parent.
+ */
+ Index parent_relid; /* RT index of append parent rel */
+ Index child_relid; /* RT index of append child rel */
+
+ /*
+ * For an inheritance appendrel, the parent and child are both regular
+ * relations, and we store their rowtype OIDs here for use in translating
+ * whole-row Vars. For a UNION-ALL appendrel, the parent and child are
+ * both subqueries with no named rowtype, and we store InvalidOid here.
+ */
+ Oid parent_reltype; /* OID of parent's composite type */
+ Oid child_reltype; /* OID of child's composite type */
+
+ /*
+ * The N'th element of this list is a Var or expression representing the
+ * child column corresponding to the N'th column of the parent. This is
+ * used to translate Vars referencing the parent rel into references to
+ * the child. A list element is NULL if it corresponds to a dropped
+ * column of the parent (this is only possible for inheritance cases, not
+ * UNION ALL). The list elements are always simple Vars for inheritance
+ * cases, but can be arbitrary expressions in UNION ALL cases.
+ *
+ * Notice we only store entries for user columns (attno > 0). Whole-row
+ * Vars are special-cased, and system columns (attno < 0) need no special
+ * translation since their attnos are the same for all tables.
+ *
+ * Caution: the Vars have varlevelsup = 0. Be careful to adjust as needed
+ * when copying into a subquery.
+ */
+ List *translated_vars; /* Expressions in the child's Vars */
+
+ /*
+ * This array simplifies translations in the reverse direction, from
+ * child's column numbers to parent's. The entry at [ccolno - 1] is the
+ * 1-based parent column number for child column ccolno, or zero if that
+ * child column is dropped or doesn't exist in the parent.
+ */
+ int num_child_cols; /* length of array */
+ AttrNumber *parent_colnos pg_node_attr(array_size(num_child_cols));
+
+ /*
+ * We store the parent table's OID here for inheritance, or InvalidOid for
+ * UNION ALL. This is only needed to help in generating error messages if
+ * an attempt is made to reference a dropped parent column.
+ */
+ Oid parent_reloid; /* OID of parent relation */
+} AppendRelInfo;
+
+/*
+ * Information about a row-identity "resjunk" column in UPDATE/DELETE/MERGE.
+ *
+ * In partitioned UPDATE/DELETE/MERGE it's important for child partitions to
+ * share row-identity columns whenever possible, so as not to chew up too many
+ * targetlist columns. We use these structs to track which identity columns
+ * have been requested. In the finished plan, each of these will give rise
+ * to one resjunk entry in the targetlist of the ModifyTable's subplan node.
+ *
+ * All the Vars stored in RowIdentityVarInfos must have varno ROWID_VAR, for
+ * convenience of detecting duplicate requests. We'll replace that, in the
+ * final plan, with the varno of the generating rel.
+ *
+ * Outside this list, a Var with varno ROWID_VAR and varattno k is a reference
+ * to the k-th element of the row_identity_vars list (k counting from 1).
+ * We add such a reference to root->processed_tlist when creating the entry,
+ * and it propagates into the plan tree from there.
+ */
+typedef struct RowIdentityVarInfo
+{
+ pg_node_attr(no_copy_equal, no_read, no_query_jumble)
+
+ NodeTag type;
+
+ Var *rowidvar; /* Var to be evaluated (but varno=ROWID_VAR) */
+ int32 rowidwidth; /* estimated average width */
+ char *rowidname; /* name of the resjunk column */
+ Relids rowidrels; /* RTE indexes of target rels using this */
+} RowIdentityVarInfo;
+
+/*
+ * For each distinct placeholder expression generated during planning, we
+ * store a PlaceHolderInfo node in the PlannerInfo node's placeholder_list.
+ * This stores info that is needed centrally rather than in each copy of the
+ * PlaceHolderVar. The phid fields identify which PlaceHolderInfo goes with
+ * each PlaceHolderVar. Note that phid is unique throughout a planner run,
+ * not just within a query level --- this is so that we need not reassign ID's
+ * when pulling a subquery into its parent.
+ *
+ * The idea is to evaluate the expression at (only) the ph_eval_at join level,
+ * then allow it to bubble up like a Var until the ph_needed join level.
+ * ph_needed has the same definition as attr_needed for a regular Var.
+ *
+ * The PlaceHolderVar's expression might contain LATERAL references to vars
+ * coming from outside its syntactic scope. If so, those rels are *not*
+ * included in ph_eval_at, but they are recorded in ph_lateral.
+ *
+ * Notice that when ph_eval_at is a join rather than a single baserel, the
+ * PlaceHolderInfo may create constraints on join order: the ph_eval_at join
+ * has to be formed below any outer joins that should null the PlaceHolderVar.
+ *
+ * We create a PlaceHolderInfo only after determining that the PlaceHolderVar
+ * is actually referenced in the plan tree, so that unreferenced placeholders
+ * don't result in unnecessary constraints on join order.
+ */
+
+typedef struct PlaceHolderInfo
+{
+ pg_node_attr(no_read, no_query_jumble)
+
+ NodeTag type;
+
+ /* ID for PH (unique within planner run) */
+ Index phid;
+
+ /*
+ * copy of PlaceHolderVar tree (should be redundant for comparison, could
+ * be ignored)
+ */
+ PlaceHolderVar *ph_var;
+
+ /* lowest level we can evaluate value at */
+ Relids ph_eval_at;
+
+ /* relids of contained lateral refs, if any */
+ Relids ph_lateral;
+
+ /* highest level the value is needed at */
+ Relids ph_needed;
+
+ /* estimated attribute width */
+ int32 ph_width;
+} PlaceHolderInfo;
+
+/*
+ * This struct describes one potentially index-optimizable MIN/MAX aggregate
+ * function. MinMaxAggPath contains a list of these, and if we accept that
+ * path, the list is stored into root->minmax_aggs for use during setrefs.c.
+ */
+typedef struct MinMaxAggInfo
+{
+ pg_node_attr(no_copy_equal, no_read, no_query_jumble)
+
+ NodeTag type;
+
+ /* pg_proc Oid of the aggregate */
+ Oid aggfnoid;
+
+ /* Oid of its sort operator */
+ Oid aggsortop;
+
+ /* expression we are aggregating on */
+ Expr *target;
+
+ /*
+ * modified "root" for planning the subquery; not printed, too large, not
+ * interesting enough
+ */
+ PlannerInfo *subroot pg_node_attr(read_write_ignore);
+
+ /* access path for subquery */
+ Path *path;
+
+ /* estimated cost to fetch first row */
+ Cost pathcost;
+
+ /* param for subplan's output */
+ Param *param;
+} MinMaxAggInfo;
+
+/*
+ * At runtime, PARAM_EXEC slots are used to pass values around from one plan
+ * node to another. They can be used to pass values down into subqueries (for
+ * outer references in subqueries), or up out of subqueries (for the results
+ * of a subplan), or from a NestLoop plan node into its inner relation (when
+ * the inner scan is parameterized with values from the outer relation).
+ * The planner is responsible for assigning nonconflicting PARAM_EXEC IDs to
+ * the PARAM_EXEC Params it generates.
+ *
+ * Outer references are managed via root->plan_params, which is a list of
+ * PlannerParamItems. While planning a subquery, each parent query level's
+ * plan_params contains the values required from it by the current subquery.
+ * During create_plan(), we use plan_params to track values that must be
+ * passed from outer to inner sides of NestLoop plan nodes.
+ *
+ * The item a PlannerParamItem represents can be one of three kinds:
+ *
+ * A Var: the slot represents a variable of this level that must be passed
+ * down because subqueries have outer references to it, or must be passed
+ * from a NestLoop node to its inner scan. The varlevelsup value in the Var
+ * will always be zero.
+ *
+ * A PlaceHolderVar: this works much like the Var case, except that the
+ * entry is a PlaceHolderVar node with a contained expression. The PHV
+ * will have phlevelsup = 0, and the contained expression is adjusted
+ * to match in level.
+ *
+ * An Aggref (with an expression tree representing its argument): the slot
+ * represents an aggregate expression that is an outer reference for some
+ * subquery. The Aggref itself has agglevelsup = 0, and its argument tree
+ * is adjusted to match in level.
+ *
+ * Note: we detect duplicate Var and PlaceHolderVar parameters and coalesce
+ * them into one slot, but we do not bother to do that for Aggrefs.
+ * The scope of duplicate-elimination only extends across the set of
+ * parameters passed from one query level into a single subquery, or for
+ * nestloop parameters across the set of nestloop parameters used in a single
+ * query level. So there is no possibility of a PARAM_EXEC slot being used
+ * for conflicting purposes.
+ *
+ * In addition, PARAM_EXEC slots are assigned for Params representing outputs
+ * from subplans (values that are setParam items for those subplans). These
+ * IDs need not be tracked via PlannerParamItems, since we do not need any
+ * duplicate-elimination nor later processing of the represented expressions.
+ * Instead, we just record the assignment of the slot number by appending to
+ * root->glob->paramExecTypes.
+ */
+typedef struct PlannerParamItem
+{
+ pg_node_attr(no_copy_equal, no_read, no_query_jumble)
+
+ NodeTag type;
+
+ Node *item; /* the Var, PlaceHolderVar, or Aggref */
+ int paramId; /* its assigned PARAM_EXEC slot number */
+} PlannerParamItem;
+
+/*
+ * When making cost estimates for a SEMI/ANTI/inner_unique join, there are
+ * some correction factors that are needed in both nestloop and hash joins
+ * to account for the fact that the executor can stop scanning inner rows
+ * as soon as it finds a match to the current outer row. These numbers
+ * depend only on the selected outer and inner join relations, not on the
+ * particular paths used for them, so it's worthwhile to calculate them
+ * just once per relation pair not once per considered path. This struct
+ * is filled by compute_semi_anti_join_factors and must be passed along
+ * to the join cost estimation functions.
+ *
+ * outer_match_frac is the fraction of the outer tuples that are
+ * expected to have at least one match.
+ * match_count is the average number of matches expected for
+ * outer tuples that have at least one match.
+ */
+typedef struct SemiAntiJoinFactors
+{
+ Selectivity outer_match_frac;
+ Selectivity match_count;
+} SemiAntiJoinFactors;
+
+/*
+ * Struct for extra information passed to subroutines of add_paths_to_joinrel
+ *
+ * restrictlist contains all of the RestrictInfo nodes for restriction
+ * clauses that apply to this join
+ * mergeclause_list is a list of RestrictInfo nodes for available
+ * mergejoin clauses in this join
+ * inner_unique is true if each outer tuple provably matches no more
+ * than one inner tuple
+ * sjinfo is extra info about special joins for selectivity estimation
+ * semifactors is as shown above (only valid for SEMI/ANTI/inner_unique joins)
+ * param_source_rels are OK targets for parameterization of result paths
+ */
+typedef struct JoinPathExtraData
+{
+ List *restrictlist;
+ List *mergeclause_list;
+ bool inner_unique;
+ SpecialJoinInfo *sjinfo;
+ SemiAntiJoinFactors semifactors;
+ Relids param_source_rels;
+} JoinPathExtraData;
+
+/*
+ * Various flags indicating what kinds of grouping are possible.
+ *
+ * GROUPING_CAN_USE_SORT should be set if it's possible to perform
+ * sort-based implementations of grouping. When grouping sets are in use,
+ * this will be true if sorting is potentially usable for any of the grouping
+ * sets, even if it's not usable for all of them.
+ *
+ * GROUPING_CAN_USE_HASH should be set if it's possible to perform
+ * hash-based implementations of grouping.
+ *
+ * GROUPING_CAN_PARTIAL_AGG should be set if the aggregation is of a type
+ * for which we support partial aggregation (not, for example, grouping sets).
+ * It says nothing about parallel-safety or the availability of suitable paths.
+ */
+#define GROUPING_CAN_USE_SORT 0x0001
+#define GROUPING_CAN_USE_HASH 0x0002
+#define GROUPING_CAN_PARTIAL_AGG 0x0004
+
+/*
+ * What kind of partitionwise aggregation is in use?
+ *
+ * PARTITIONWISE_AGGREGATE_NONE: Not used.
+ *
+ * PARTITIONWISE_AGGREGATE_FULL: Aggregate each partition separately, and
+ * append the results.
+ *
+ * PARTITIONWISE_AGGREGATE_PARTIAL: Partially aggregate each partition
+ * separately, append the results, and then finalize aggregation.
+ */
+typedef enum
+{
+ PARTITIONWISE_AGGREGATE_NONE,
+ PARTITIONWISE_AGGREGATE_FULL,
+ PARTITIONWISE_AGGREGATE_PARTIAL
+} PartitionwiseAggregateType;
+
+/*
+ * Struct for extra information passed to subroutines of create_grouping_paths
+ *
+ * flags indicating what kinds of grouping are possible.
+ * partial_costs_set is true if the agg_partial_costs and agg_final_costs
+ * have been initialized.
+ * agg_partial_costs gives partial aggregation costs.
+ * agg_final_costs gives finalization costs.
+ * target_parallel_safe is true if target is parallel safe.
+ * havingQual gives list of quals to be applied after aggregation.
+ * targetList gives list of columns to be projected.
+ * patype is the type of partitionwise aggregation that is being performed.
+ */
+typedef struct
+{
+ /* Data which remains constant once set. */
+ int flags;
+ bool partial_costs_set;
+ AggClauseCosts agg_partial_costs;
+ AggClauseCosts agg_final_costs;
+
+ /* Data which may differ across partitions. */
+ bool target_parallel_safe;
+ Node *havingQual;
+ List *targetList;
+ PartitionwiseAggregateType patype;
+} GroupPathExtraData;
+
+/*
+ * Struct for extra information passed to subroutines of grouping_planner
+ *
+ * limit_needed is true if we actually need a Limit plan node.
+ * limit_tuples is an estimated bound on the number of output tuples,
+ * or -1 if no LIMIT or couldn't estimate.
+ * count_est and offset_est are the estimated values of the LIMIT and OFFSET
+ * expressions computed by preprocess_limit() (see comments for
+ * preprocess_limit() for more information).
+ */
+typedef struct
+{
+ bool limit_needed;
+ Cardinality limit_tuples;
+ int64 count_est;
+ int64 offset_est;
+} FinalPathExtraData;
+
+/*
+ * For speed reasons, cost estimation for join paths is performed in two
+ * phases: the first phase tries to quickly derive a lower bound for the
+ * join cost, and then we check if that's sufficient to reject the path.
+ * If not, we come back for a more refined cost estimate. The first phase
+ * fills a JoinCostWorkspace struct with its preliminary cost estimates
+ * and possibly additional intermediate values. The second phase takes
+ * these values as inputs to avoid repeating work.
+ *
+ * (Ideally we'd declare this in cost.h, but it's also needed in pathnode.h,
+ * so seems best to put it here.)
+ */
+typedef struct JoinCostWorkspace
+{
+ /* Preliminary cost estimates --- must not be larger than final ones! */
+ Cost startup_cost; /* cost expended before fetching any tuples */
+ Cost total_cost; /* total cost (assuming all tuples fetched) */
+
+ /* Fields below here should be treated as private to costsize.c */
+ Cost run_cost; /* non-startup cost components */
+
+ /* private for cost_nestloop code */
+ Cost inner_run_cost; /* also used by cost_mergejoin code */
+ Cost inner_rescan_run_cost;
+
+ /* private for cost_mergejoin code */
+ Cardinality outer_rows;
+ Cardinality inner_rows;
+ Cardinality outer_skip_rows;
+ Cardinality inner_skip_rows;
+
+ /* private for cost_hashjoin code */
+ int numbuckets;
+ int numbatches;
+ Cardinality inner_rows_total;
+} JoinCostWorkspace;
+
+/*
+ * AggInfo holds information about an aggregate that needs to be computed.
+ * Multiple Aggrefs in a query can refer to the same AggInfo by having the
+ * same 'aggno' value, so that the aggregate is computed only once.
+ */
+typedef struct AggInfo
+{
+ pg_node_attr(no_copy_equal, no_read, no_query_jumble)
+
+ NodeTag type;
+
+ /*
+ * List of Aggref exprs that this state value is for.
+ *
+ * There will always be at least one, but there can be multiple identical
+ * Aggref's sharing the same per-agg.
+ */
+ List *aggrefs;
+
+ /* Transition state number for this aggregate */
+ int transno;
+
+ /*
+ * "shareable" is false if this agg cannot share state values with other
+ * aggregates because the final function is read-write.
+ */
+ bool shareable;
+
+ /* Oid of the final function, or InvalidOid if none */
+ Oid finalfn_oid;
+} AggInfo;
+
+/*
+ * AggTransInfo holds information about transition state that is used by one
+ * or more aggregates in the query. Multiple aggregates can share the same
+ * transition state, if they have the same inputs and the same transition
+ * function. Aggrefs that share the same transition info have the same
+ * 'aggtransno' value.
+ */
+typedef struct AggTransInfo
+{
+ pg_node_attr(no_copy_equal, no_read, no_query_jumble)
+
+ NodeTag type;
+
+ /* Inputs for this transition state */
+ List *args;
+ Expr *aggfilter;
+
+ /* Oid of the state transition function */
+ Oid transfn_oid;
+
+ /* Oid of the serialization function, or InvalidOid if none */
+ Oid serialfn_oid;
+
+ /* Oid of the deserialization function, or InvalidOid if none */
+ Oid deserialfn_oid;
+
+ /* Oid of the combine function, or InvalidOid if none */
+ Oid combinefn_oid;
+
+ /* Oid of state value's datatype */
+ Oid aggtranstype;
+
+ /* Additional data about transtype */
+ int32 aggtranstypmod;
+ int transtypeLen;
+ bool transtypeByVal;
+
+ /* Space-consumption estimate */
+ int32 aggtransspace;
+
+ /* Initial value from pg_aggregate entry */
+ Datum initValue pg_node_attr(read_write_ignore);
+ bool initValueIsNull;
+} AggTransInfo;
+
+#endif /* PATHNODES_H */
diff --git a/src/include/nodes/pg_list.h b/src/include/nodes/pg_list.h
new file mode 100644
index 0000000..529a382
--- /dev/null
+++ b/src/include/nodes/pg_list.h
@@ -0,0 +1,635 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_list.h
+ * interface for PostgreSQL generic list package
+ *
+ * Once upon a time, parts of Postgres were written in Lisp and used real
+ * cons-cell lists for major data structures. When that code was rewritten
+ * in C, we initially had a faithful emulation of cons-cell lists, which
+ * unsurprisingly was a performance bottleneck. A couple of major rewrites
+ * later, these data structures are actually simple expansible arrays;
+ * but the "List" name and a lot of the notation survives.
+ *
+ * One important concession to the original implementation is that an empty
+ * list is always represented by a null pointer (preferentially written NIL).
+ * Non-empty lists have a header, which will not be relocated as long as the
+ * list remains non-empty, and an expansible data array.
+ *
+ * We support four types of lists:
+ *
+ * T_List: lists of pointers
+ * (in practice usually pointers to Nodes, but not always;
+ * declared as "void *" to minimize casting annoyances)
+ * T_IntList: lists of integers
+ * T_OidList: lists of Oids
+ * T_XidList: lists of TransactionIds
+ * (the XidList infrastructure is less complete than the other cases)
+ *
+ * (At the moment, ints, Oids, and XIDs are the same size, but they may not
+ * always be so; be careful to use the appropriate list type for your data.)
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/nodes/pg_list.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_LIST_H
+#define PG_LIST_H
+
+#include "nodes/nodes.h"
+
+
+typedef union ListCell
+{
+ void *ptr_value;
+ int int_value;
+ Oid oid_value;
+ TransactionId xid_value;
+} ListCell;
+
+typedef struct List
+{
+ NodeTag type; /* T_List, T_IntList, T_OidList, or T_XidList */
+ int length; /* number of elements currently present */
+ int max_length; /* allocated length of elements[] */
+ ListCell *elements; /* re-allocatable array of cells */
+ /* We may allocate some cells along with the List header: */
+ ListCell initial_elements[FLEXIBLE_ARRAY_MEMBER];
+ /* If elements == initial_elements, it's not a separate allocation */
+} List;
+
+/*
+ * The *only* valid representation of an empty list is NIL; in other
+ * words, a non-NIL list is guaranteed to have length >= 1.
+ */
+#define NIL ((List *) NULL)
+
+/*
+ * State structs for various looping macros below.
+ */
+typedef struct ForEachState
+{
+ const List *l; /* list we're looping through */
+ int i; /* current element index */
+} ForEachState;
+
+typedef struct ForBothState
+{
+ const List *l1; /* lists we're looping through */
+ const List *l2;
+ int i; /* common element index */
+} ForBothState;
+
+typedef struct ForBothCellState
+{
+ const List *l1; /* lists we're looping through */
+ const List *l2;
+ int i1; /* current element indexes */
+ int i2;
+} ForBothCellState;
+
+typedef struct ForThreeState
+{
+ const List *l1; /* lists we're looping through */
+ const List *l2;
+ const List *l3;
+ int i; /* common element index */
+} ForThreeState;
+
+typedef struct ForFourState
+{
+ const List *l1; /* lists we're looping through */
+ const List *l2;
+ const List *l3;
+ const List *l4;
+ int i; /* common element index */
+} ForFourState;
+
+typedef struct ForFiveState
+{
+ const List *l1; /* lists we're looping through */
+ const List *l2;
+ const List *l3;
+ const List *l4;
+ const List *l5;
+ int i; /* common element index */
+} ForFiveState;
+
+/*
+ * These routines are small enough, and used often enough, to justify being
+ * inline.
+ */
+
+/* Fetch address of list's first cell; NULL if empty list */
+static inline ListCell *
+list_head(const List *l)
+{
+ return l ? &l->elements[0] : NULL;
+}
+
+/* Fetch address of list's last cell; NULL if empty list */
+static inline ListCell *
+list_tail(const List *l)
+{
+ return l ? &l->elements[l->length - 1] : NULL;
+}
+
+/* Fetch address of list's second cell, if it has one, else NULL */
+static inline ListCell *
+list_second_cell(const List *l)
+{
+ if (l && l->length >= 2)
+ return &l->elements[1];
+ else
+ return NULL;
+}
+
+/* Fetch list's length */
+static inline int
+list_length(const List *l)
+{
+ return l ? l->length : 0;
+}
+
+/*
+ * Macros to access the data values within List cells.
+ *
+ * Note that with the exception of the "xxx_node" macros, these are
+ * lvalues and can be assigned to.
+ *
+ * NB: There is an unfortunate legacy from a previous incarnation of
+ * the List API: the macro lfirst() was used to mean "the data in this
+ * cons cell". To avoid changing every usage of lfirst(), that meaning
+ * has been kept. As a result, lfirst() takes a ListCell and returns
+ * the data it contains; to get the data in the first cell of a
+ * List, use linitial(). Worse, lsecond() is more closely related to
+ * linitial() than lfirst(): given a List, lsecond() returns the data
+ * in the second list cell.
+ */
+#define lfirst(lc) ((lc)->ptr_value)
+#define lfirst_int(lc) ((lc)->int_value)
+#define lfirst_oid(lc) ((lc)->oid_value)
+#define lfirst_xid(lc) ((lc)->xid_value)
+#define lfirst_node(type,lc) castNode(type, lfirst(lc))
+
+#define linitial(l) lfirst(list_nth_cell(l, 0))
+#define linitial_int(l) lfirst_int(list_nth_cell(l, 0))
+#define linitial_oid(l) lfirst_oid(list_nth_cell(l, 0))
+#define linitial_node(type,l) castNode(type, linitial(l))
+
+#define lsecond(l) lfirst(list_nth_cell(l, 1))
+#define lsecond_int(l) lfirst_int(list_nth_cell(l, 1))
+#define lsecond_oid(l) lfirst_oid(list_nth_cell(l, 1))
+#define lsecond_node(type,l) castNode(type, lsecond(l))
+
+#define lthird(l) lfirst(list_nth_cell(l, 2))
+#define lthird_int(l) lfirst_int(list_nth_cell(l, 2))
+#define lthird_oid(l) lfirst_oid(list_nth_cell(l, 2))
+#define lthird_node(type,l) castNode(type, lthird(l))
+
+#define lfourth(l) lfirst(list_nth_cell(l, 3))
+#define lfourth_int(l) lfirst_int(list_nth_cell(l, 3))
+#define lfourth_oid(l) lfirst_oid(list_nth_cell(l, 3))
+#define lfourth_node(type,l) castNode(type, lfourth(l))
+
+#define llast(l) lfirst(list_last_cell(l))
+#define llast_int(l) lfirst_int(list_last_cell(l))
+#define llast_oid(l) lfirst_oid(list_last_cell(l))
+#define llast_xid(l) lfirst_xid(list_last_cell(l))
+#define llast_node(type,l) castNode(type, llast(l))
+
+/*
+ * Convenience macros for building fixed-length lists
+ */
+#define list_make_ptr_cell(v) ((ListCell) {.ptr_value = (v)})
+#define list_make_int_cell(v) ((ListCell) {.int_value = (v)})
+#define list_make_oid_cell(v) ((ListCell) {.oid_value = (v)})
+#define list_make_xid_cell(v) ((ListCell) {.xid_value = (v)})
+
+#define list_make1(x1) \
+ list_make1_impl(T_List, list_make_ptr_cell(x1))
+#define list_make2(x1,x2) \
+ list_make2_impl(T_List, list_make_ptr_cell(x1), list_make_ptr_cell(x2))
+#define list_make3(x1,x2,x3) \
+ list_make3_impl(T_List, list_make_ptr_cell(x1), list_make_ptr_cell(x2), \
+ list_make_ptr_cell(x3))
+#define list_make4(x1,x2,x3,x4) \
+ list_make4_impl(T_List, list_make_ptr_cell(x1), list_make_ptr_cell(x2), \
+ list_make_ptr_cell(x3), list_make_ptr_cell(x4))
+#define list_make5(x1,x2,x3,x4,x5) \
+ list_make5_impl(T_List, list_make_ptr_cell(x1), list_make_ptr_cell(x2), \
+ list_make_ptr_cell(x3), list_make_ptr_cell(x4), \
+ list_make_ptr_cell(x5))
+
+#define list_make1_int(x1) \
+ list_make1_impl(T_IntList, list_make_int_cell(x1))
+#define list_make2_int(x1,x2) \
+ list_make2_impl(T_IntList, list_make_int_cell(x1), list_make_int_cell(x2))
+#define list_make3_int(x1,x2,x3) \
+ list_make3_impl(T_IntList, list_make_int_cell(x1), list_make_int_cell(x2), \
+ list_make_int_cell(x3))
+#define list_make4_int(x1,x2,x3,x4) \
+ list_make4_impl(T_IntList, list_make_int_cell(x1), list_make_int_cell(x2), \
+ list_make_int_cell(x3), list_make_int_cell(x4))
+#define list_make5_int(x1,x2,x3,x4,x5) \
+ list_make5_impl(T_IntList, list_make_int_cell(x1), list_make_int_cell(x2), \
+ list_make_int_cell(x3), list_make_int_cell(x4), \
+ list_make_int_cell(x5))
+
+#define list_make1_oid(x1) \
+ list_make1_impl(T_OidList, list_make_oid_cell(x1))
+#define list_make2_oid(x1,x2) \
+ list_make2_impl(T_OidList, list_make_oid_cell(x1), list_make_oid_cell(x2))
+#define list_make3_oid(x1,x2,x3) \
+ list_make3_impl(T_OidList, list_make_oid_cell(x1), list_make_oid_cell(x2), \
+ list_make_oid_cell(x3))
+#define list_make4_oid(x1,x2,x3,x4) \
+ list_make4_impl(T_OidList, list_make_oid_cell(x1), list_make_oid_cell(x2), \
+ list_make_oid_cell(x3), list_make_oid_cell(x4))
+#define list_make5_oid(x1,x2,x3,x4,x5) \
+ list_make5_impl(T_OidList, list_make_oid_cell(x1), list_make_oid_cell(x2), \
+ list_make_oid_cell(x3), list_make_oid_cell(x4), \
+ list_make_oid_cell(x5))
+
+#define list_make1_xid(x1) \
+ list_make1_impl(T_XidList, list_make_xid_cell(x1))
+#define list_make2_xid(x1,x2) \
+ list_make2_impl(T_XidList, list_make_xid_cell(x1), list_make_xid_cell(x2))
+#define list_make3_xid(x1,x2,x3) \
+ list_make3_impl(T_XidList, list_make_xid_cell(x1), list_make_xid_cell(x2), \
+ list_make_xid_cell(x3))
+#define list_make4_xid(x1,x2,x3,x4) \
+ list_make4_impl(T_XidList, list_make_xid_cell(x1), list_make_xid_cell(x2), \
+ list_make_xid_cell(x3), list_make_xid_cell(x4))
+#define list_make5_xid(x1,x2,x3,x4,x5) \
+ list_make5_impl(T_XidList, list_make_xid_cell(x1), list_make_xid_cell(x2), \
+ list_make_xid_cell(x3), list_make_xid_cell(x4), \
+ list_make_xid_cell(x5))
+
+/*
+ * Locate the n'th cell (counting from 0) of the list.
+ * It is an assertion failure if there is no such cell.
+ */
+static inline ListCell *
+list_nth_cell(const List *list, int n)
+{
+ Assert(list != NIL);
+ Assert(n >= 0 && n < list->length);
+ return &list->elements[n];
+}
+
+/*
+ * Return the last cell in a non-NIL List.
+ */
+static inline ListCell *
+list_last_cell(const List *list)
+{
+ Assert(list != NIL);
+ return &list->elements[list->length - 1];
+}
+
+/*
+ * Return the pointer value contained in the n'th element of the
+ * specified list. (List elements begin at 0.)
+ */
+static inline void *
+list_nth(const List *list, int n)
+{
+ Assert(IsA(list, List));
+ return lfirst(list_nth_cell(list, n));
+}
+
+/*
+ * Return the integer value contained in the n'th element of the
+ * specified list.
+ */
+static inline int
+list_nth_int(const List *list, int n)
+{
+ Assert(IsA(list, IntList));
+ return lfirst_int(list_nth_cell(list, n));
+}
+
+/*
+ * Return the OID value contained in the n'th element of the specified
+ * list.
+ */
+static inline Oid
+list_nth_oid(const List *list, int n)
+{
+ Assert(IsA(list, OidList));
+ return lfirst_oid(list_nth_cell(list, n));
+}
+
+#define list_nth_node(type,list,n) castNode(type, list_nth(list, n))
+
+/*
+ * Get the given ListCell's index (from 0) in the given List.
+ */
+static inline int
+list_cell_number(const List *l, const ListCell *c)
+{
+ Assert(c >= &l->elements[0] && c < &l->elements[l->length]);
+ return c - l->elements;
+}
+
+/*
+ * Get the address of the next cell after "c" within list "l", or NULL if none.
+ */
+static inline ListCell *
+lnext(const List *l, const ListCell *c)
+{
+ Assert(c >= &l->elements[0] && c < &l->elements[l->length]);
+ c++;
+ if (c < &l->elements[l->length])
+ return (ListCell *) c;
+ else
+ return NULL;
+}
+
+/*
+ * foreach -
+ * a convenience macro for looping through a list
+ *
+ * "cell" must be the name of a "ListCell *" variable; it's made to point
+ * to each List element in turn. "cell" will be NULL after normal exit from
+ * the loop, but an early "break" will leave it pointing at the current
+ * List element.
+ *
+ * Beware of changing the List object while the loop is iterating.
+ * The current semantics are that we examine successive list indices in
+ * each iteration, so that insertion or deletion of list elements could
+ * cause elements to be re-visited or skipped unexpectedly. Previous
+ * implementations of foreach() behaved differently. However, it's safe
+ * to append elements to the List (or in general, insert them after the
+ * current element); such new elements are guaranteed to be visited.
+ * Also, the current element of the List can be deleted, if you use
+ * foreach_delete_current() to do so. BUT: either of these actions will
+ * invalidate the "cell" pointer for the remainder of the current iteration.
+ */
+#define foreach(cell, lst) \
+ for (ForEachState cell##__state = {(lst), 0}; \
+ (cell##__state.l != NIL && \
+ cell##__state.i < cell##__state.l->length) ? \
+ (cell = &cell##__state.l->elements[cell##__state.i], true) : \
+ (cell = NULL, false); \
+ cell##__state.i++)
+
+/*
+ * foreach_delete_current -
+ * delete the current list element from the List associated with a
+ * surrounding foreach() loop, returning the new List pointer.
+ *
+ * This is equivalent to list_delete_cell(), but it also adjusts the foreach
+ * loop's state so that no list elements will be missed. Do not delete
+ * elements from an active foreach loop's list in any other way!
+ */
+#define foreach_delete_current(lst, cell) \
+ (cell##__state.i--, \
+ (List *) (cell##__state.l = list_delete_cell(lst, cell)))
+
+/*
+ * foreach_current_index -
+ * get the zero-based list index of a surrounding foreach() loop's
+ * current element; pass the name of the "ListCell *" iterator variable.
+ *
+ * Beware of using this after foreach_delete_current(); the value will be
+ * out of sync for the rest of the current loop iteration. Anyway, since
+ * you just deleted the current element, the value is pretty meaningless.
+ */
+#define foreach_current_index(cell) (cell##__state.i)
+
+/*
+ * for_each_from -
+ * Like foreach(), but start from the N'th (zero-based) list element,
+ * not necessarily the first one.
+ *
+ * It's okay for N to exceed the list length, but not for it to be negative.
+ *
+ * The caveats for foreach() apply equally here.
+ */
+#define for_each_from(cell, lst, N) \
+ for (ForEachState cell##__state = for_each_from_setup(lst, N); \
+ (cell##__state.l != NIL && \
+ cell##__state.i < cell##__state.l->length) ? \
+ (cell = &cell##__state.l->elements[cell##__state.i], true) : \
+ (cell = NULL, false); \
+ cell##__state.i++)
+
+static inline ForEachState
+for_each_from_setup(const List *lst, int N)
+{
+ ForEachState r = {lst, N};
+
+ Assert(N >= 0);
+ return r;
+}
+
+/*
+ * for_each_cell -
+ * a convenience macro which loops through a list starting from a
+ * specified cell
+ *
+ * The caveats for foreach() apply equally here.
+ */
+#define for_each_cell(cell, lst, initcell) \
+ for (ForEachState cell##__state = for_each_cell_setup(lst, initcell); \
+ (cell##__state.l != NIL && \
+ cell##__state.i < cell##__state.l->length) ? \
+ (cell = &cell##__state.l->elements[cell##__state.i], true) : \
+ (cell = NULL, false); \
+ cell##__state.i++)
+
+static inline ForEachState
+for_each_cell_setup(const List *lst, const ListCell *initcell)
+{
+ ForEachState r = {lst,
+ initcell ? list_cell_number(lst, initcell) : list_length(lst)};
+
+ return r;
+}
+
+/*
+ * forboth -
+ * a convenience macro for advancing through two linked lists
+ * simultaneously. This macro loops through both lists at the same
+ * time, stopping when either list runs out of elements. Depending
+ * on the requirements of the call site, it may also be wise to
+ * assert that the lengths of the two lists are equal. (But, if they
+ * are not, some callers rely on the ending cell values being separately
+ * NULL or non-NULL as defined here; don't try to optimize that.)
+ *
+ * The caveats for foreach() apply equally here.
+ */
+#define forboth(cell1, list1, cell2, list2) \
+ for (ForBothState cell1##__state = {(list1), (list2), 0}; \
+ multi_for_advance_cell(cell1, cell1##__state, l1, i), \
+ multi_for_advance_cell(cell2, cell1##__state, l2, i), \
+ (cell1 != NULL && cell2 != NULL); \
+ cell1##__state.i++)
+
+#define multi_for_advance_cell(cell, state, l, i) \
+ (cell = (state.l != NIL && state.i < state.l->length) ? \
+ &state.l->elements[state.i] : NULL)
+
+/*
+ * for_both_cell -
+ * a convenience macro which loops through two lists starting from the
+ * specified cells of each. This macro loops through both lists at the same
+ * time, stopping when either list runs out of elements. Depending on the
+ * requirements of the call site, it may also be wise to assert that the
+ * lengths of the two lists are equal, and initcell1 and initcell2 are at
+ * the same position in the respective lists.
+ *
+ * The caveats for foreach() apply equally here.
+ */
+#define for_both_cell(cell1, list1, initcell1, cell2, list2, initcell2) \
+ for (ForBothCellState cell1##__state = \
+ for_both_cell_setup(list1, initcell1, list2, initcell2); \
+ multi_for_advance_cell(cell1, cell1##__state, l1, i1), \
+ multi_for_advance_cell(cell2, cell1##__state, l2, i2), \
+ (cell1 != NULL && cell2 != NULL); \
+ cell1##__state.i1++, cell1##__state.i2++)
+
+static inline ForBothCellState
+for_both_cell_setup(const List *list1, const ListCell *initcell1,
+ const List *list2, const ListCell *initcell2)
+{
+ ForBothCellState r = {list1, list2,
+ initcell1 ? list_cell_number(list1, initcell1) : list_length(list1),
+ initcell2 ? list_cell_number(list2, initcell2) : list_length(list2)};
+
+ return r;
+}
+
+/*
+ * forthree -
+ * the same for three lists
+ */
+#define forthree(cell1, list1, cell2, list2, cell3, list3) \
+ for (ForThreeState cell1##__state = {(list1), (list2), (list3), 0}; \
+ multi_for_advance_cell(cell1, cell1##__state, l1, i), \
+ multi_for_advance_cell(cell2, cell1##__state, l2, i), \
+ multi_for_advance_cell(cell3, cell1##__state, l3, i), \
+ (cell1 != NULL && cell2 != NULL && cell3 != NULL); \
+ cell1##__state.i++)
+
+/*
+ * forfour -
+ * the same for four lists
+ */
+#define forfour(cell1, list1, cell2, list2, cell3, list3, cell4, list4) \
+ for (ForFourState cell1##__state = {(list1), (list2), (list3), (list4), 0}; \
+ multi_for_advance_cell(cell1, cell1##__state, l1, i), \
+ multi_for_advance_cell(cell2, cell1##__state, l2, i), \
+ multi_for_advance_cell(cell3, cell1##__state, l3, i), \
+ multi_for_advance_cell(cell4, cell1##__state, l4, i), \
+ (cell1 != NULL && cell2 != NULL && cell3 != NULL && cell4 != NULL); \
+ cell1##__state.i++)
+
+/*
+ * forfive -
+ * the same for five lists
+ */
+#define forfive(cell1, list1, cell2, list2, cell3, list3, cell4, list4, cell5, list5) \
+ for (ForFiveState cell1##__state = {(list1), (list2), (list3), (list4), (list5), 0}; \
+ multi_for_advance_cell(cell1, cell1##__state, l1, i), \
+ multi_for_advance_cell(cell2, cell1##__state, l2, i), \
+ multi_for_advance_cell(cell3, cell1##__state, l3, i), \
+ multi_for_advance_cell(cell4, cell1##__state, l4, i), \
+ multi_for_advance_cell(cell5, cell1##__state, l5, i), \
+ (cell1 != NULL && cell2 != NULL && cell3 != NULL && \
+ cell4 != NULL && cell5 != NULL); \
+ cell1##__state.i++)
+
+/* Functions in src/backend/nodes/list.c */
+
+extern List *list_make1_impl(NodeTag t, ListCell datum1);
+extern List *list_make2_impl(NodeTag t, ListCell datum1, ListCell datum2);
+extern List *list_make3_impl(NodeTag t, ListCell datum1, ListCell datum2,
+ ListCell datum3);
+extern List *list_make4_impl(NodeTag t, ListCell datum1, ListCell datum2,
+ ListCell datum3, ListCell datum4);
+extern List *list_make5_impl(NodeTag t, ListCell datum1, ListCell datum2,
+ ListCell datum3, ListCell datum4,
+ ListCell datum5);
+
+extern pg_nodiscard List *lappend(List *list, void *datum);
+extern pg_nodiscard List *lappend_int(List *list, int datum);
+extern pg_nodiscard List *lappend_oid(List *list, Oid datum);
+extern pg_nodiscard List *lappend_xid(List *list, TransactionId datum);
+
+extern pg_nodiscard List *list_insert_nth(List *list, int pos, void *datum);
+extern pg_nodiscard List *list_insert_nth_int(List *list, int pos, int datum);
+extern pg_nodiscard List *list_insert_nth_oid(List *list, int pos, Oid datum);
+
+extern pg_nodiscard List *lcons(void *datum, List *list);
+extern pg_nodiscard List *lcons_int(int datum, List *list);
+extern pg_nodiscard List *lcons_oid(Oid datum, List *list);
+
+extern pg_nodiscard List *list_concat(List *list1, const List *list2);
+extern pg_nodiscard List *list_concat_copy(const List *list1, const List *list2);
+
+extern pg_nodiscard List *list_truncate(List *list, int new_size);
+
+extern bool list_member(const List *list, const void *datum);
+extern bool list_member_ptr(const List *list, const void *datum);
+extern bool list_member_int(const List *list, int datum);
+extern bool list_member_oid(const List *list, Oid datum);
+extern bool list_member_xid(const List *list, TransactionId datum);
+
+extern pg_nodiscard List *list_delete(List *list, void *datum);
+extern pg_nodiscard List *list_delete_ptr(List *list, void *datum);
+extern pg_nodiscard List *list_delete_int(List *list, int datum);
+extern pg_nodiscard List *list_delete_oid(List *list, Oid datum);
+extern pg_nodiscard List *list_delete_first(List *list);
+extern pg_nodiscard List *list_delete_last(List *list);
+extern pg_nodiscard List *list_delete_first_n(List *list, int n);
+extern pg_nodiscard List *list_delete_nth_cell(List *list, int n);
+extern pg_nodiscard List *list_delete_cell(List *list, ListCell *cell);
+
+extern List *list_union(const List *list1, const List *list2);
+extern List *list_union_ptr(const List *list1, const List *list2);
+extern List *list_union_int(const List *list1, const List *list2);
+extern List *list_union_oid(const List *list1, const List *list2);
+
+extern List *list_intersection(const List *list1, const List *list2);
+extern List *list_intersection_int(const List *list1, const List *list2);
+
+/* currently, there's no need for list_intersection_ptr etc */
+
+extern List *list_difference(const List *list1, const List *list2);
+extern List *list_difference_ptr(const List *list1, const List *list2);
+extern List *list_difference_int(const List *list1, const List *list2);
+extern List *list_difference_oid(const List *list1, const List *list2);
+
+extern pg_nodiscard List *list_append_unique(List *list, void *datum);
+extern pg_nodiscard List *list_append_unique_ptr(List *list, void *datum);
+extern pg_nodiscard List *list_append_unique_int(List *list, int datum);
+extern pg_nodiscard List *list_append_unique_oid(List *list, Oid datum);
+
+extern pg_nodiscard List *list_concat_unique(List *list1, const List *list2);
+extern pg_nodiscard List *list_concat_unique_ptr(List *list1, const List *list2);
+extern pg_nodiscard List *list_concat_unique_int(List *list1, const List *list2);
+extern pg_nodiscard List *list_concat_unique_oid(List *list1, const List *list2);
+
+extern void list_deduplicate_oid(List *list);
+
+extern void list_free(List *list);
+extern void list_free_deep(List *list);
+
+extern pg_nodiscard List *list_copy(const List *oldlist);
+extern pg_nodiscard List *list_copy_head(const List *oldlist, int len);
+extern pg_nodiscard List *list_copy_tail(const List *oldlist, int nskip);
+extern pg_nodiscard List *list_copy_deep(const List *oldlist);
+
+typedef int (*list_sort_comparator) (const ListCell *a, const ListCell *b);
+extern void list_sort(List *list, list_sort_comparator cmp);
+
+extern int list_int_cmp(const ListCell *p1, const ListCell *p2);
+extern int list_oid_cmp(const ListCell *p1, const ListCell *p2);
+
+#endif /* PG_LIST_H */
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
new file mode 100644
index 0000000..d64fe6a
--- /dev/null
+++ b/src/include/nodes/plannodes.h
@@ -0,0 +1,1592 @@
+/*-------------------------------------------------------------------------
+ *
+ * plannodes.h
+ * definitions for query plan nodes
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/nodes/plannodes.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PLANNODES_H
+#define PLANNODES_H
+
+#include "access/sdir.h"
+#include "access/stratnum.h"
+#include "common/relpath.h"
+#include "lib/stringinfo.h"
+#include "nodes/bitmapset.h"
+#include "nodes/lockoptions.h"
+#include "nodes/parsenodes.h"
+#include "nodes/primnodes.h"
+
+
+/* ----------------------------------------------------------------
+ * node definitions
+ * ----------------------------------------------------------------
+ */
+
+/* ----------------
+ * PlannedStmt node
+ *
+ * The output of the planner is a Plan tree headed by a PlannedStmt node.
+ * PlannedStmt holds the "one time" information needed by the executor.
+ *
+ * For simplicity in APIs, we also wrap utility statements in PlannedStmt
+ * nodes; in such cases, commandType == CMD_UTILITY, the statement itself
+ * is in the utilityStmt field, and the rest of the struct is mostly dummy.
+ * (We do use canSetTag, stmt_location, stmt_len, and possibly queryId.)
+ *
+ * PlannedStmt, as well as all varieties of Plan, do not support equal(),
+ * not because it's not sensible but because we currently have no need.
+ * ----------------
+ */
+typedef struct PlannedStmt
+{
+ pg_node_attr(no_equal, no_query_jumble)
+
+ NodeTag type;
+
+ CmdType commandType; /* select|insert|update|delete|merge|utility */
+
+ uint64 queryId; /* query identifier (copied from Query) */
+
+ bool hasReturning; /* is it insert|update|delete RETURNING? */
+
+ bool hasModifyingCTE; /* has insert|update|delete in WITH? */
+
+ bool canSetTag; /* do I set the command result tag? */
+
+ bool transientPlan; /* redo plan when TransactionXmin changes? */
+
+ bool dependsOnRole; /* is plan specific to current role? */
+
+ bool parallelModeNeeded; /* parallel mode required to execute? */
+
+ int jitFlags; /* which forms of JIT should be performed */
+
+ struct Plan *planTree; /* tree of Plan nodes */
+
+ List *rtable; /* list of RangeTblEntry nodes */
+
+ List *permInfos; /* list of RTEPermissionInfo nodes for rtable
+ * entries needing one */
+
+ /* rtable indexes of target relations for INSERT/UPDATE/DELETE/MERGE */
+ List *resultRelations; /* integer list of RT indexes, or NIL */
+
+ List *appendRelations; /* list of AppendRelInfo nodes */
+
+ List *subplans; /* Plan trees for SubPlan expressions; note
+ * that some could be NULL */
+
+ Bitmapset *rewindPlanIDs; /* indices of subplans that require REWIND */
+
+ List *rowMarks; /* a list of PlanRowMark's */
+
+ List *relationOids; /* OIDs of relations the plan depends on */
+
+ List *invalItems; /* other dependencies, as PlanInvalItems */
+
+ List *paramExecTypes; /* type OIDs for PARAM_EXEC Params */
+
+ Node *utilityStmt; /* non-null if this is utility stmt */
+
+ /* statement location in source string (copied from Query) */
+ int stmt_location; /* start location, or -1 if unknown */
+ int stmt_len; /* length in bytes; 0 means "rest of string" */
+} PlannedStmt;
+
+/* macro for fetching the Plan associated with a SubPlan node */
+#define exec_subplan_get_plan(plannedstmt, subplan) \
+ ((Plan *) list_nth((plannedstmt)->subplans, (subplan)->plan_id - 1))
+
+
+/* ----------------
+ * Plan node
+ *
+ * All plan nodes "derive" from the Plan structure by having the
+ * Plan structure as the first field. This ensures that everything works
+ * when nodes are cast to Plan's. (node pointers are frequently cast to Plan*
+ * when passed around generically in the executor)
+ *
+ * We never actually instantiate any Plan nodes; this is just the common
+ * abstract superclass for all Plan-type nodes.
+ * ----------------
+ */
+typedef struct Plan
+{
+ pg_node_attr(abstract, no_equal, no_query_jumble)
+
+ NodeTag type;
+
+ /*
+ * estimated execution costs for plan (see costsize.c for more info)
+ */
+ Cost startup_cost; /* cost expended before fetching any tuples */
+ Cost total_cost; /* total cost (assuming all tuples fetched) */
+
+ /*
+ * planner's estimate of result size of this plan step
+ */
+ Cardinality plan_rows; /* number of rows plan is expected to emit */
+ int plan_width; /* average row width in bytes */
+
+ /*
+ * information needed for parallel query
+ */
+ bool parallel_aware; /* engage parallel-aware logic? */
+ bool parallel_safe; /* OK to use as part of parallel plan? */
+
+ /*
+ * information needed for asynchronous execution
+ */
+ bool async_capable; /* engage asynchronous-capable logic? */
+
+ /*
+ * Common structural data for all Plan types.
+ */
+ int plan_node_id; /* unique across entire final plan tree */
+ List *targetlist; /* target list to be computed at this node */
+ List *qual; /* implicitly-ANDed qual conditions */
+ struct Plan *lefttree; /* input plan tree(s) */
+ struct Plan *righttree;
+ List *initPlan; /* Init Plan nodes (un-correlated expr
+ * subselects) */
+
+ /*
+ * Information for management of parameter-change-driven rescanning
+ *
+ * extParam includes the paramIDs of all external PARAM_EXEC params
+ * affecting this plan node or its children. setParam params from the
+ * node's initPlans are not included, but their extParams are.
+ *
+ * allParam includes all the extParam paramIDs, plus the IDs of local
+ * params that affect the node (i.e., the setParams of its initplans).
+ * These are _all_ the PARAM_EXEC params that affect this node.
+ */
+ Bitmapset *extParam;
+ Bitmapset *allParam;
+} Plan;
+
+/* ----------------
+ * these are defined to avoid confusion problems with "left"
+ * and "right" and "inner" and "outer". The convention is that
+ * the "left" plan is the "outer" plan and the "right" plan is
+ * the inner plan, but these make the code more readable.
+ * ----------------
+ */
+#define innerPlan(node) (((Plan *)(node))->righttree)
+#define outerPlan(node) (((Plan *)(node))->lefttree)
+
+
+/* ----------------
+ * Result node -
+ * If no outer plan, evaluate a variable-free targetlist.
+ * If outer plan, return tuples from outer plan (after a level of
+ * projection as shown by targetlist).
+ *
+ * If resconstantqual isn't NULL, it represents a one-time qualification
+ * test (i.e., one that doesn't depend on any variables from the outer plan,
+ * so needs to be evaluated only once).
+ * ----------------
+ */
+typedef struct Result
+{
+ Plan plan;
+ Node *resconstantqual;
+} Result;
+
+/* ----------------
+ * ProjectSet node -
+ * Apply a projection that includes set-returning functions to the
+ * output tuples of the outer plan.
+ * ----------------
+ */
+typedef struct ProjectSet
+{
+ Plan plan;
+} ProjectSet;
+
+/* ----------------
+ * ModifyTable node -
+ * Apply rows produced by outer plan to result table(s),
+ * by inserting, updating, or deleting.
+ *
+ * If the originally named target table is a partitioned table or inheritance
+ * tree, both nominalRelation and rootRelation contain the RT index of the
+ * partition root or appendrel RTE, which is not otherwise mentioned in the
+ * plan. Otherwise rootRelation is zero. However, nominalRelation will
+ * always be set, as it's the rel that EXPLAIN should claim is the
+ * INSERT/UPDATE/DELETE/MERGE target.
+ *
+ * Note that rowMarks and epqParam are presumed to be valid for all the
+ * table(s); they can't contain any info that varies across tables.
+ * ----------------
+ */
+typedef struct ModifyTable
+{
+ Plan plan;
+ CmdType operation; /* INSERT, UPDATE, DELETE, or MERGE */
+ bool canSetTag; /* do we set the command tag/es_processed? */
+ Index nominalRelation; /* Parent RT index for use of EXPLAIN */
+ Index rootRelation; /* Root RT index, if partitioned/inherited */
+ bool partColsUpdated; /* some part key in hierarchy updated? */
+ List *resultRelations; /* integer list of RT indexes */
+ List *updateColnosLists; /* per-target-table update_colnos lists */
+ List *withCheckOptionLists; /* per-target-table WCO lists */
+ List *returningLists; /* per-target-table RETURNING tlists */
+ List *fdwPrivLists; /* per-target-table FDW private data lists */
+ Bitmapset *fdwDirectModifyPlans; /* indices of FDW DM plans */
+ List *rowMarks; /* PlanRowMarks (non-locking only) */
+ int epqParam; /* ID of Param for EvalPlanQual re-eval */
+ OnConflictAction onConflictAction; /* ON CONFLICT action */
+ List *arbiterIndexes; /* List of ON CONFLICT arbiter index OIDs */
+ List *onConflictSet; /* INSERT ON CONFLICT DO UPDATE targetlist */
+ List *onConflictCols; /* target column numbers for onConflictSet */
+ Node *onConflictWhere; /* WHERE for ON CONFLICT UPDATE */
+ Index exclRelRTI; /* RTI of the EXCLUDED pseudo relation */
+ List *exclRelTlist; /* tlist of the EXCLUDED pseudo relation */
+ List *mergeActionLists; /* per-target-table lists of actions for
+ * MERGE */
+} ModifyTable;
+
+struct PartitionPruneInfo; /* forward reference to struct below */
+
+/* ----------------
+ * Append node -
+ * Generate the concatenation of the results of sub-plans.
+ * ----------------
+ */
+typedef struct Append
+{
+ Plan plan;
+ Bitmapset *apprelids; /* RTIs of appendrel(s) formed by this node */
+ List *appendplans;
+ int nasyncplans; /* # of asynchronous plans */
+
+ /*
+ * All 'appendplans' preceding this index are non-partial plans. All
+ * 'appendplans' from this index onwards are partial plans.
+ */
+ int first_partial_plan;
+
+ /* Info for run-time subplan pruning; NULL if we're not doing that */
+ struct PartitionPruneInfo *part_prune_info;
+} Append;
+
+/* ----------------
+ * MergeAppend node -
+ * Merge the results of pre-sorted sub-plans to preserve the ordering.
+ * ----------------
+ */
+typedef struct MergeAppend
+{
+ Plan plan;
+
+ /* RTIs of appendrel(s) formed by this node */
+ Bitmapset *apprelids;
+
+ List *mergeplans;
+
+ /* these fields are just like the sort-key info in struct Sort: */
+
+ /* number of sort-key columns */
+ int numCols;
+
+ /* their indexes in the target list */
+ AttrNumber *sortColIdx pg_node_attr(array_size(numCols));
+
+ /* OIDs of operators to sort them by */
+ Oid *sortOperators pg_node_attr(array_size(numCols));
+
+ /* OIDs of collations */
+ Oid *collations pg_node_attr(array_size(numCols));
+
+ /* NULLS FIRST/LAST directions */
+ bool *nullsFirst pg_node_attr(array_size(numCols));
+
+ /* Info for run-time subplan pruning; NULL if we're not doing that */
+ struct PartitionPruneInfo *part_prune_info;
+} MergeAppend;
+
+/* ----------------
+ * RecursiveUnion node -
+ * Generate a recursive union of two subplans.
+ *
+ * The "outer" subplan is always the non-recursive term, and the "inner"
+ * subplan is the recursive term.
+ * ----------------
+ */
+typedef struct RecursiveUnion
+{
+ Plan plan;
+
+ /* ID of Param representing work table */
+ int wtParam;
+
+ /* Remaining fields are zero/null in UNION ALL case */
+
+ /* number of columns to check for duplicate-ness */
+ int numCols;
+
+ /* their indexes in the target list */
+ AttrNumber *dupColIdx pg_node_attr(array_size(numCols));
+
+ /* equality operators to compare with */
+ Oid *dupOperators pg_node_attr(array_size(numCols));
+ Oid *dupCollations pg_node_attr(array_size(numCols));
+
+ /* estimated number of groups in input */
+ long numGroups;
+} RecursiveUnion;
+
+/* ----------------
+ * BitmapAnd node -
+ * Generate the intersection of the results of sub-plans.
+ *
+ * The subplans must be of types that yield tuple bitmaps. The targetlist
+ * and qual fields of the plan are unused and are always NIL.
+ * ----------------
+ */
+typedef struct BitmapAnd
+{
+ Plan plan;
+ List *bitmapplans;
+} BitmapAnd;
+
+/* ----------------
+ * BitmapOr node -
+ * Generate the union of the results of sub-plans.
+ *
+ * The subplans must be of types that yield tuple bitmaps. The targetlist
+ * and qual fields of the plan are unused and are always NIL.
+ * ----------------
+ */
+typedef struct BitmapOr
+{
+ Plan plan;
+ bool isshared;
+ List *bitmapplans;
+} BitmapOr;
+
+/*
+ * ==========
+ * Scan nodes
+ *
+ * Scan is an abstract type that all relation scan plan types inherit from.
+ * ==========
+ */
+typedef struct Scan
+{
+ pg_node_attr(abstract)
+
+ Plan plan;
+ Index scanrelid; /* relid is index into the range table */
+} Scan;
+
+/* ----------------
+ * sequential scan node
+ * ----------------
+ */
+typedef struct SeqScan
+{
+ Scan scan;
+} SeqScan;
+
+/* ----------------
+ * table sample scan node
+ * ----------------
+ */
+typedef struct SampleScan
+{
+ Scan scan;
+ /* use struct pointer to avoid including parsenodes.h here */
+ struct TableSampleClause *tablesample;
+} SampleScan;
+
+/* ----------------
+ * index scan node
+ *
+ * indexqualorig is an implicitly-ANDed list of index qual expressions, each
+ * in the same form it appeared in the query WHERE condition. Each should
+ * be of the form (indexkey OP comparisonval) or (comparisonval OP indexkey).
+ * The indexkey is a Var or expression referencing column(s) of the index's
+ * base table. The comparisonval might be any expression, but it won't use
+ * any columns of the base table. The expressions are ordered by index
+ * column position (but items referencing the same index column can appear
+ * in any order). indexqualorig is used at runtime only if we have to recheck
+ * a lossy indexqual.
+ *
+ * indexqual has the same form, but the expressions have been commuted if
+ * necessary to put the indexkeys on the left, and the indexkeys are replaced
+ * by Var nodes identifying the index columns (their varno is INDEX_VAR and
+ * their varattno is the index column number).
+ *
+ * indexorderbyorig is similarly the original form of any ORDER BY expressions
+ * that are being implemented by the index, while indexorderby is modified to
+ * have index column Vars on the left-hand side. Here, multiple expressions
+ * must appear in exactly the ORDER BY order, and this is not necessarily the
+ * index column order. Only the expressions are provided, not the auxiliary
+ * sort-order information from the ORDER BY SortGroupClauses; it's assumed
+ * that the sort ordering is fully determinable from the top-level operators.
+ * indexorderbyorig is used at runtime to recheck the ordering, if the index
+ * cannot calculate an accurate ordering. It is also needed for EXPLAIN.
+ *
+ * indexorderbyops is a list of the OIDs of the operators used to sort the
+ * ORDER BY expressions. This is used together with indexorderbyorig to
+ * recheck ordering at run time. (Note that indexorderby, indexorderbyorig,
+ * and indexorderbyops are used for amcanorderbyop cases, not amcanorder.)
+ *
+ * indexorderdir specifies the scan ordering, for indexscans on amcanorder
+ * indexes (for other indexes it should be "don't care").
+ * ----------------
+ */
+typedef struct IndexScan
+{
+ Scan scan;
+ Oid indexid; /* OID of index to scan */
+ List *indexqual; /* list of index quals (usually OpExprs) */
+ List *indexqualorig; /* the same in original form */
+ List *indexorderby; /* list of index ORDER BY exprs */
+ List *indexorderbyorig; /* the same in original form */
+ List *indexorderbyops; /* OIDs of sort ops for ORDER BY exprs */
+ ScanDirection indexorderdir; /* forward or backward or don't care */
+} IndexScan;
+
+/* ----------------
+ * index-only scan node
+ *
+ * IndexOnlyScan is very similar to IndexScan, but it specifies an
+ * index-only scan, in which the data comes from the index not the heap.
+ * Because of this, *all* Vars in the plan node's targetlist, qual, and
+ * index expressions reference index columns and have varno = INDEX_VAR.
+ *
+ * We could almost use indexqual directly against the index's output tuple
+ * when rechecking lossy index operators, but that won't work for quals on
+ * index columns that are not retrievable. Hence, recheckqual is needed
+ * for rechecks: it expresses the same condition as indexqual, but using
+ * only index columns that are retrievable. (We will not generate an
+ * index-only scan if this is not possible. An example is that if an
+ * index has table column "x" in a retrievable index column "ind1", plus
+ * an expression f(x) in a non-retrievable column "ind2", an indexable
+ * query on f(x) will use "ind2" in indexqual and f(ind1) in recheckqual.
+ * Without the "ind1" column, an index-only scan would be disallowed.)
+ *
+ * We don't currently need a recheckable equivalent of indexorderby,
+ * because we don't support lossy operators in index ORDER BY.
+ *
+ * To help EXPLAIN interpret the index Vars for display, we provide
+ * indextlist, which represents the contents of the index as a targetlist
+ * with one TLE per index column. Vars appearing in this list reference
+ * the base table, and this is the only field in the plan node that may
+ * contain such Vars. Also, for the convenience of setrefs.c, TLEs in
+ * indextlist are marked as resjunk if they correspond to columns that
+ * the index AM cannot reconstruct.
+ * ----------------
+ */
+typedef struct IndexOnlyScan
+{
+ Scan scan;
+ Oid indexid; /* OID of index to scan */
+ List *indexqual; /* list of index quals (usually OpExprs) */
+ List *recheckqual; /* index quals in recheckable form */
+ List *indexorderby; /* list of index ORDER BY exprs */
+ List *indextlist; /* TargetEntry list describing index's cols */
+ ScanDirection indexorderdir; /* forward or backward or don't care */
+} IndexOnlyScan;
+
+/* ----------------
+ * bitmap index scan node
+ *
+ * BitmapIndexScan delivers a bitmap of potential tuple locations;
+ * it does not access the heap itself. The bitmap is used by an
+ * ancestor BitmapHeapScan node, possibly after passing through
+ * intermediate BitmapAnd and/or BitmapOr nodes to combine it with
+ * the results of other BitmapIndexScans.
+ *
+ * The fields have the same meanings as for IndexScan, except we don't
+ * store a direction flag because direction is uninteresting.
+ *
+ * In a BitmapIndexScan plan node, the targetlist and qual fields are
+ * not used and are always NIL. The indexqualorig field is unused at
+ * run time too, but is saved for the benefit of EXPLAIN.
+ * ----------------
+ */
+typedef struct BitmapIndexScan
+{
+ Scan scan;
+ Oid indexid; /* OID of index to scan */
+ bool isshared; /* Create shared bitmap if set */
+ List *indexqual; /* list of index quals (OpExprs) */
+ List *indexqualorig; /* the same in original form */
+} BitmapIndexScan;
+
+/* ----------------
+ * bitmap sequential scan node
+ *
+ * This needs a copy of the qual conditions being used by the input index
+ * scans because there are various cases where we need to recheck the quals;
+ * for example, when the bitmap is lossy about the specific rows on a page
+ * that meet the index condition.
+ * ----------------
+ */
+typedef struct BitmapHeapScan
+{
+ Scan scan;
+ List *bitmapqualorig; /* index quals, in standard expr form */
+} BitmapHeapScan;
+
+/* ----------------
+ * tid scan node
+ *
+ * tidquals is an implicitly OR'ed list of qual expressions of the form
+ * "CTID = pseudoconstant", or "CTID = ANY(pseudoconstant_array)",
+ * or a CurrentOfExpr for the relation.
+ * ----------------
+ */
+typedef struct TidScan
+{
+ Scan scan;
+ List *tidquals; /* qual(s) involving CTID = something */
+} TidScan;
+
+/* ----------------
+ * tid range scan node
+ *
+ * tidrangequals is an implicitly AND'ed list of qual expressions of the form
+ * "CTID relop pseudoconstant", where relop is one of >,>=,<,<=.
+ * ----------------
+ */
+typedef struct TidRangeScan
+{
+ Scan scan;
+ List *tidrangequals; /* qual(s) involving CTID op something */
+} TidRangeScan;
+
+/* ----------------
+ * subquery scan node
+ *
+ * SubqueryScan is for scanning the output of a sub-query in the range table.
+ * We often need an extra plan node above the sub-query's plan to perform
+ * expression evaluations (which we can't push into the sub-query without
+ * risking changing its semantics). Although we are not scanning a physical
+ * relation, we make this a descendant of Scan anyway for code-sharing
+ * purposes.
+ *
+ * SubqueryScanStatus caches the trivial_subqueryscan property of the node.
+ * SUBQUERY_SCAN_UNKNOWN means not yet determined. This is only used during
+ * planning.
+ *
+ * Note: we store the sub-plan in the type-specific subplan field, not in
+ * the generic lefttree field as you might expect. This is because we do
+ * not want plan-tree-traversal routines to recurse into the subplan without
+ * knowing that they are changing Query contexts.
+ * ----------------
+ */
+typedef enum SubqueryScanStatus
+{
+ SUBQUERY_SCAN_UNKNOWN,
+ SUBQUERY_SCAN_TRIVIAL,
+ SUBQUERY_SCAN_NONTRIVIAL
+} SubqueryScanStatus;
+
+typedef struct SubqueryScan
+{
+ Scan scan;
+ Plan *subplan;
+ SubqueryScanStatus scanstatus;
+} SubqueryScan;
+
+/* ----------------
+ * FunctionScan node
+ * ----------------
+ */
+typedef struct FunctionScan
+{
+ Scan scan;
+ List *functions; /* list of RangeTblFunction nodes */
+ bool funcordinality; /* WITH ORDINALITY */
+} FunctionScan;
+
+/* ----------------
+ * ValuesScan node
+ * ----------------
+ */
+typedef struct ValuesScan
+{
+ Scan scan;
+ List *values_lists; /* list of expression lists */
+} ValuesScan;
+
+/* ----------------
+ * TableFunc scan node
+ * ----------------
+ */
+typedef struct TableFuncScan
+{
+ Scan scan;
+ TableFunc *tablefunc; /* table function node */
+} TableFuncScan;
+
+/* ----------------
+ * CteScan node
+ * ----------------
+ */
+typedef struct CteScan
+{
+ Scan scan;
+ int ctePlanId; /* ID of init SubPlan for CTE */
+ int cteParam; /* ID of Param representing CTE output */
+} CteScan;
+
+/* ----------------
+ * NamedTuplestoreScan node
+ * ----------------
+ */
+typedef struct NamedTuplestoreScan
+{
+ Scan scan;
+ char *enrname; /* Name given to Ephemeral Named Relation */
+} NamedTuplestoreScan;
+
+/* ----------------
+ * WorkTableScan node
+ * ----------------
+ */
+typedef struct WorkTableScan
+{
+ Scan scan;
+ int wtParam; /* ID of Param representing work table */
+} WorkTableScan;
+
+/* ----------------
+ * ForeignScan node
+ *
+ * fdw_exprs and fdw_private are both under the control of the foreign-data
+ * wrapper, but fdw_exprs is presumed to contain expression trees and will
+ * be post-processed accordingly by the planner; fdw_private won't be.
+ * Note that everything in both lists must be copiable by copyObject().
+ * One way to store an arbitrary blob of bytes is to represent it as a bytea
+ * Const. Usually, though, you'll be better off choosing a representation
+ * that can be dumped usefully by nodeToString().
+ *
+ * fdw_scan_tlist is a targetlist describing the contents of the scan tuple
+ * returned by the FDW; it can be NIL if the scan tuple matches the declared
+ * rowtype of the foreign table, which is the normal case for a simple foreign
+ * table scan. (If the plan node represents a foreign join, fdw_scan_tlist
+ * is required since there is no rowtype available from the system catalogs.)
+ * When fdw_scan_tlist is provided, Vars in the node's tlist and quals must
+ * have varno INDEX_VAR, and their varattnos correspond to resnos in the
+ * fdw_scan_tlist (which are also column numbers in the actual scan tuple).
+ * fdw_scan_tlist is never actually executed; it just holds expression trees
+ * describing what is in the scan tuple's columns.
+ *
+ * fdw_recheck_quals should contain any quals which the core system passed to
+ * the FDW but which were not added to scan.plan.qual; that is, it should
+ * contain the quals being checked remotely. This is needed for correct
+ * behavior during EvalPlanQual rechecks.
+ *
+ * When the plan node represents a foreign join, scan.scanrelid is zero and
+ * fs_relids must be consulted to identify the join relation. (fs_relids
+ * is valid for simple scans as well, but will always match scan.scanrelid.)
+ * fs_relids includes outer joins; fs_base_relids does not.
+ *
+ * If the FDW's PlanDirectModify() callback decides to repurpose a ForeignScan
+ * node to perform the UPDATE or DELETE operation directly in the remote
+ * server, it sets 'operation' and 'resultRelation' to identify the operation
+ * type and target relation. Note that these fields are only set if the
+ * modification is performed *fully* remotely; otherwise, the modification is
+ * driven by a local ModifyTable node and 'operation' is left to CMD_SELECT.
+ * ----------------
+ */
+typedef struct ForeignScan
+{
+ Scan scan;
+ CmdType operation; /* SELECT/INSERT/UPDATE/DELETE */
+ Index resultRelation; /* direct modification target's RT index */
+ Oid checkAsUser; /* user to perform the scan as; 0 means to
+ * check as current user */
+ Oid fs_server; /* OID of foreign server */
+ List *fdw_exprs; /* expressions that FDW may evaluate */
+ List *fdw_private; /* private data for FDW */
+ List *fdw_scan_tlist; /* optional tlist describing scan tuple */
+ List *fdw_recheck_quals; /* original quals not in scan.plan.qual */
+ Bitmapset *fs_relids; /* base+OJ RTIs generated by this scan */
+ Bitmapset *fs_base_relids; /* base RTIs generated by this scan */
+ bool fsSystemCol; /* true if any "system column" is needed */
+} ForeignScan;
+
+/* ----------------
+ * CustomScan node
+ *
+ * The comments for ForeignScan's fdw_exprs, fdw_private, fdw_scan_tlist,
+ * and fs_relids fields apply equally to CustomScan's custom_exprs,
+ * custom_private, custom_scan_tlist, and custom_relids fields. The
+ * convention of setting scan.scanrelid to zero for joins applies as well.
+ *
+ * Note that since Plan trees can be copied, custom scan providers *must*
+ * fit all plan data they need into those fields; embedding CustomScan in
+ * a larger struct will not work.
+ * ----------------
+ */
+struct CustomScanMethods;
+
+typedef struct CustomScan
+{
+ Scan scan;
+ uint32 flags; /* mask of CUSTOMPATH_* flags, see
+ * nodes/extensible.h */
+ List *custom_plans; /* list of Plan nodes, if any */
+ List *custom_exprs; /* expressions that custom code may evaluate */
+ List *custom_private; /* private data for custom code */
+ List *custom_scan_tlist; /* optional tlist describing scan tuple */
+ Bitmapset *custom_relids; /* RTIs generated by this scan */
+
+ /*
+ * NOTE: The method field of CustomScan is required to be a pointer to a
+ * static table of callback functions. So we don't copy the table itself,
+ * just reference the original one.
+ */
+ const struct CustomScanMethods *methods;
+} CustomScan;
+
+/*
+ * ==========
+ * Join nodes
+ * ==========
+ */
+
+/* ----------------
+ * Join node
+ *
+ * jointype: rule for joining tuples from left and right subtrees
+ * inner_unique each outer tuple can match to no more than one inner tuple
+ * joinqual: qual conditions that came from JOIN/ON or JOIN/USING
+ * (plan.qual contains conditions that came from WHERE)
+ *
+ * When jointype is INNER, joinqual and plan.qual are semantically
+ * interchangeable. For OUTER jointypes, the two are *not* interchangeable;
+ * only joinqual is used to determine whether a match has been found for
+ * the purpose of deciding whether to generate null-extended tuples.
+ * (But plan.qual is still applied before actually returning a tuple.)
+ * For an outer join, only joinquals are allowed to be used as the merge
+ * or hash condition of a merge or hash join.
+ *
+ * inner_unique is set if the joinquals are such that no more than one inner
+ * tuple could match any given outer tuple. This allows the executor to
+ * skip searching for additional matches. (This must be provable from just
+ * the joinquals, ignoring plan.qual, due to where the executor tests it.)
+ * ----------------
+ */
+typedef struct Join
+{
+ pg_node_attr(abstract)
+
+ Plan plan;
+ JoinType jointype;
+ bool inner_unique;
+ List *joinqual; /* JOIN quals (in addition to plan.qual) */
+} Join;
+
+/* ----------------
+ * nest loop join node
+ *
+ * The nestParams list identifies any executor Params that must be passed
+ * into execution of the inner subplan carrying values from the current row
+ * of the outer subplan. Currently we restrict these values to be simple
+ * Vars, but perhaps someday that'd be worth relaxing. (Note: during plan
+ * creation, the paramval can actually be a PlaceHolderVar expression; but it
+ * must be a Var with varno OUTER_VAR by the time it gets to the executor.)
+ * ----------------
+ */
+typedef struct NestLoop
+{
+ Join join;
+ List *nestParams; /* list of NestLoopParam nodes */
+} NestLoop;
+
+typedef struct NestLoopParam
+{
+ pg_node_attr(no_equal, no_query_jumble)
+
+ NodeTag type;
+ int paramno; /* number of the PARAM_EXEC Param to set */
+ Var *paramval; /* outer-relation Var to assign to Param */
+} NestLoopParam;
+
+/* ----------------
+ * merge join node
+ *
+ * The expected ordering of each mergeable column is described by a btree
+ * opfamily OID, a collation OID, a direction (BTLessStrategyNumber or
+ * BTGreaterStrategyNumber) and a nulls-first flag. Note that the two sides
+ * of each mergeclause may be of different datatypes, but they are ordered the
+ * same way according to the common opfamily and collation. The operator in
+ * each mergeclause must be an equality operator of the indicated opfamily.
+ * ----------------
+ */
+typedef struct MergeJoin
+{
+ Join join;
+
+ /* Can we skip mark/restore calls? */
+ bool skip_mark_restore;
+
+ /* mergeclauses as expression trees */
+ List *mergeclauses;
+
+ /* these are arrays, but have the same length as the mergeclauses list: */
+
+ /* per-clause OIDs of btree opfamilies */
+ Oid *mergeFamilies pg_node_attr(array_size(mergeclauses));
+
+ /* per-clause OIDs of collations */
+ Oid *mergeCollations pg_node_attr(array_size(mergeclauses));
+
+ /* per-clause ordering (ASC or DESC) */
+ int *mergeStrategies pg_node_attr(array_size(mergeclauses));
+
+ /* per-clause nulls ordering */
+ bool *mergeNullsFirst pg_node_attr(array_size(mergeclauses));
+} MergeJoin;
+
+/* ----------------
+ * hash join node
+ * ----------------
+ */
+typedef struct HashJoin
+{
+ Join join;
+ List *hashclauses;
+ List *hashoperators;
+ List *hashcollations;
+
+ /*
+ * List of expressions to be hashed for tuples from the outer plan, to
+ * perform lookups in the hashtable over the inner plan.
+ */
+ List *hashkeys;
+} HashJoin;
+
+/* ----------------
+ * materialization node
+ * ----------------
+ */
+typedef struct Material
+{
+ Plan plan;
+} Material;
+
+/* ----------------
+ * memoize node
+ * ----------------
+ */
+typedef struct Memoize
+{
+ Plan plan;
+
+ /* size of the two arrays below */
+ int numKeys;
+
+ /* hash operators for each key */
+ Oid *hashOperators pg_node_attr(array_size(numKeys));
+
+ /* collations for each key */
+ Oid *collations pg_node_attr(array_size(numKeys));
+
+ /* cache keys in the form of exprs containing parameters */
+ List *param_exprs;
+
+ /*
+ * true if the cache entry should be marked as complete after we store the
+ * first tuple in it.
+ */
+ bool singlerow;
+
+ /*
+ * true when cache key should be compared bit by bit, false when using
+ * hash equality ops
+ */
+ bool binary_mode;
+
+ /*
+ * The maximum number of entries that the planner expects will fit in the
+ * cache, or 0 if unknown
+ */
+ uint32 est_entries;
+
+ /* paramids from param_exprs */
+ Bitmapset *keyparamids;
+} Memoize;
+
+/* ----------------
+ * sort node
+ * ----------------
+ */
+typedef struct Sort
+{
+ Plan plan;
+
+ /* number of sort-key columns */
+ int numCols;
+
+ /* their indexes in the target list */
+ AttrNumber *sortColIdx pg_node_attr(array_size(numCols));
+
+ /* OIDs of operators to sort them by */
+ Oid *sortOperators pg_node_attr(array_size(numCols));
+
+ /* OIDs of collations */
+ Oid *collations pg_node_attr(array_size(numCols));
+
+ /* NULLS FIRST/LAST directions */
+ bool *nullsFirst pg_node_attr(array_size(numCols));
+} Sort;
+
+/* ----------------
+ * incremental sort node
+ * ----------------
+ */
+typedef struct IncrementalSort
+{
+ Sort sort;
+ int nPresortedCols; /* number of presorted columns */
+} IncrementalSort;
+
+/* ---------------
+ * group node -
+ * Used for queries with GROUP BY (but no aggregates) specified.
+ * The input must be presorted according to the grouping columns.
+ * ---------------
+ */
+typedef struct Group
+{
+ Plan plan;
+
+ /* number of grouping columns */
+ int numCols;
+
+ /* their indexes in the target list */
+ AttrNumber *grpColIdx pg_node_attr(array_size(numCols));
+
+ /* equality operators to compare with */
+ Oid *grpOperators pg_node_attr(array_size(numCols));
+ Oid *grpCollations pg_node_attr(array_size(numCols));
+} Group;
+
+/* ---------------
+ * aggregate node
+ *
+ * An Agg node implements plain or grouped aggregation. For grouped
+ * aggregation, we can work with presorted input or unsorted input;
+ * the latter strategy uses an internal hashtable.
+ *
+ * Notice the lack of any direct info about the aggregate functions to be
+ * computed. They are found by scanning the node's tlist and quals during
+ * executor startup. (It is possible that there are no aggregate functions;
+ * this could happen if they get optimized away by constant-folding, or if
+ * we are using the Agg node to implement hash-based grouping.)
+ * ---------------
+ */
+typedef struct Agg
+{
+ Plan plan;
+
+ /* basic strategy, see nodes.h */
+ AggStrategy aggstrategy;
+
+ /* agg-splitting mode, see nodes.h */
+ AggSplit aggsplit;
+
+ /* number of grouping columns */
+ int numCols;
+
+ /* their indexes in the target list */
+ AttrNumber *grpColIdx pg_node_attr(array_size(numCols));
+
+ /* equality operators to compare with */
+ Oid *grpOperators pg_node_attr(array_size(numCols));
+ Oid *grpCollations pg_node_attr(array_size(numCols));
+
+ /* estimated number of groups in input */
+ long numGroups;
+
+ /* for pass-by-ref transition data */
+ uint64 transitionSpace;
+
+ /* IDs of Params used in Aggref inputs */
+ Bitmapset *aggParams;
+
+ /* Note: planner provides numGroups & aggParams only in HASHED/MIXED case */
+
+ /* grouping sets to use */
+ List *groupingSets;
+
+ /* chained Agg/Sort nodes */
+ List *chain;
+} Agg;
+
+/* ----------------
+ * window aggregate node
+ * ----------------
+ */
+typedef struct WindowAgg
+{
+ Plan plan;
+
+ /* ID referenced by window functions */
+ Index winref;
+
+ /* number of columns in partition clause */
+ int partNumCols;
+
+ /* their indexes in the target list */
+ AttrNumber *partColIdx pg_node_attr(array_size(partNumCols));
+
+ /* equality operators for partition columns */
+ Oid *partOperators pg_node_attr(array_size(partNumCols));
+
+ /* collations for partition columns */
+ Oid *partCollations pg_node_attr(array_size(partNumCols));
+
+ /* number of columns in ordering clause */
+ int ordNumCols;
+
+ /* their indexes in the target list */
+ AttrNumber *ordColIdx pg_node_attr(array_size(ordNumCols));
+
+ /* equality operators for ordering columns */
+ Oid *ordOperators pg_node_attr(array_size(ordNumCols));
+
+ /* collations for ordering columns */
+ Oid *ordCollations pg_node_attr(array_size(ordNumCols));
+
+ /* frame_clause options, see WindowDef */
+ int frameOptions;
+
+ /* expression for starting bound, if any */
+ Node *startOffset;
+
+ /* expression for ending bound, if any */
+ Node *endOffset;
+
+ /* qual to help short-circuit execution */
+ List *runCondition;
+
+ /* runCondition for display in EXPLAIN */
+ List *runConditionOrig;
+
+ /* these fields are used with RANGE offset PRECEDING/FOLLOWING: */
+
+ /* in_range function for startOffset */
+ Oid startInRangeFunc;
+
+ /* in_range function for endOffset */
+ Oid endInRangeFunc;
+
+ /* collation for in_range tests */
+ Oid inRangeColl;
+
+ /* use ASC sort order for in_range tests? */
+ bool inRangeAsc;
+
+ /* nulls sort first for in_range tests? */
+ bool inRangeNullsFirst;
+
+ /*
+ * false for all apart from the WindowAgg that's closest to the root of
+ * the plan
+ */
+ bool topWindow;
+} WindowAgg;
+
+/* ----------------
+ * unique node
+ * ----------------
+ */
+typedef struct Unique
+{
+ Plan plan;
+
+ /* number of columns to check for uniqueness */
+ int numCols;
+
+ /* their indexes in the target list */
+ AttrNumber *uniqColIdx pg_node_attr(array_size(numCols));
+
+ /* equality operators to compare with */
+ Oid *uniqOperators pg_node_attr(array_size(numCols));
+
+ /* collations for equality comparisons */
+ Oid *uniqCollations pg_node_attr(array_size(numCols));
+} Unique;
+
+/* ------------
+ * gather node
+ *
+ * Note: rescan_param is the ID of a PARAM_EXEC parameter slot. That slot
+ * will never actually contain a value, but the Gather node must flag it as
+ * having changed whenever it is rescanned. The child parallel-aware scan
+ * nodes are marked as depending on that parameter, so that the rescan
+ * machinery is aware that their output is likely to change across rescans.
+ * In some cases we don't need a rescan Param, so rescan_param is set to -1.
+ * ------------
+ */
+typedef struct Gather
+{
+ Plan plan;
+ int num_workers; /* planned number of worker processes */
+ int rescan_param; /* ID of Param that signals a rescan, or -1 */
+ bool single_copy; /* don't execute plan more than once */
+ bool invisible; /* suppress EXPLAIN display (for testing)? */
+ Bitmapset *initParam; /* param id's of initplans which are referred
+ * at gather or one of it's child node */
+} Gather;
+
+/* ------------
+ * gather merge node
+ * ------------
+ */
+typedef struct GatherMerge
+{
+ Plan plan;
+
+ /* planned number of worker processes */
+ int num_workers;
+
+ /* ID of Param that signals a rescan, or -1 */
+ int rescan_param;
+
+ /* remaining fields are just like the sort-key info in struct Sort */
+
+ /* number of sort-key columns */
+ int numCols;
+
+ /* their indexes in the target list */
+ AttrNumber *sortColIdx pg_node_attr(array_size(numCols));
+
+ /* OIDs of operators to sort them by */
+ Oid *sortOperators pg_node_attr(array_size(numCols));
+
+ /* OIDs of collations */
+ Oid *collations pg_node_attr(array_size(numCols));
+
+ /* NULLS FIRST/LAST directions */
+ bool *nullsFirst pg_node_attr(array_size(numCols));
+
+ /*
+ * param id's of initplans which are referred at gather merge or one of
+ * it's child node
+ */
+ Bitmapset *initParam;
+} GatherMerge;
+
+/* ----------------
+ * hash build node
+ *
+ * If the executor is supposed to try to apply skew join optimization, then
+ * skewTable/skewColumn/skewInherit identify the outer relation's join key
+ * column, from which the relevant MCV statistics can be fetched.
+ * ----------------
+ */
+typedef struct Hash
+{
+ Plan plan;
+
+ /*
+ * List of expressions to be hashed for tuples from Hash's outer plan,
+ * needed to put them into the hashtable.
+ */
+ List *hashkeys; /* hash keys for the hashjoin condition */
+ Oid skewTable; /* outer join key's table OID, or InvalidOid */
+ AttrNumber skewColumn; /* outer join key's column #, or zero */
+ bool skewInherit; /* is outer join rel an inheritance tree? */
+ /* all other info is in the parent HashJoin node */
+ Cardinality rows_total; /* estimate total rows if parallel_aware */
+} Hash;
+
+/* ----------------
+ * setop node
+ * ----------------
+ */
+typedef struct SetOp
+{
+ Plan plan;
+
+ /* what to do, see nodes.h */
+ SetOpCmd cmd;
+
+ /* how to do it, see nodes.h */
+ SetOpStrategy strategy;
+
+ /* number of columns to check for duplicate-ness */
+ int numCols;
+
+ /* their indexes in the target list */
+ AttrNumber *dupColIdx pg_node_attr(array_size(numCols));
+
+ /* equality operators to compare with */
+ Oid *dupOperators pg_node_attr(array_size(numCols));
+ Oid *dupCollations pg_node_attr(array_size(numCols));
+
+ /* where is the flag column, if any */
+ AttrNumber flagColIdx;
+
+ /* flag value for first input relation */
+ int firstFlag;
+
+ /* estimated number of groups in input */
+ long numGroups;
+} SetOp;
+
+/* ----------------
+ * lock-rows node
+ *
+ * rowMarks identifies the rels to be locked by this node; it should be
+ * a subset of the rowMarks listed in the top-level PlannedStmt.
+ * epqParam is a Param that all scan nodes below this one must depend on.
+ * It is used to force re-evaluation of the plan during EvalPlanQual.
+ * ----------------
+ */
+typedef struct LockRows
+{
+ Plan plan;
+ List *rowMarks; /* a list of PlanRowMark's */
+ int epqParam; /* ID of Param for EvalPlanQual re-eval */
+} LockRows;
+
+/* ----------------
+ * limit node
+ *
+ * Note: as of Postgres 8.2, the offset and count expressions are expected
+ * to yield int8, rather than int4 as before.
+ * ----------------
+ */
+typedef struct Limit
+{
+ Plan plan;
+
+ /* OFFSET parameter, or NULL if none */
+ Node *limitOffset;
+
+ /* COUNT parameter, or NULL if none */
+ Node *limitCount;
+
+ /* limit type */
+ LimitOption limitOption;
+
+ /* number of columns to check for similarity */
+ int uniqNumCols;
+
+ /* their indexes in the target list */
+ AttrNumber *uniqColIdx pg_node_attr(array_size(uniqNumCols));
+
+ /* equality operators to compare with */
+ Oid *uniqOperators pg_node_attr(array_size(uniqNumCols));
+
+ /* collations for equality comparisons */
+ Oid *uniqCollations pg_node_attr(array_size(uniqNumCols));
+} Limit;
+
+
+/*
+ * RowMarkType -
+ * enums for types of row-marking operations
+ *
+ * The first four of these values represent different lock strengths that
+ * we can take on tuples according to SELECT FOR [KEY] UPDATE/SHARE requests.
+ * We support these on regular tables, as well as on foreign tables whose FDWs
+ * report support for late locking. For other foreign tables, any locking
+ * that might be done for such requests must happen during the initial row
+ * fetch; their FDWs provide no mechanism for going back to lock a row later.
+ * This means that the semantics will be a bit different than for a local
+ * table; in particular we are likely to lock more rows than would be locked
+ * locally, since remote rows will be locked even if they then fail
+ * locally-checked restriction or join quals. However, the prospect of
+ * doing a separate remote query to lock each selected row is usually pretty
+ * unappealing, so early locking remains a credible design choice for FDWs.
+ *
+ * When doing UPDATE/DELETE/MERGE/SELECT FOR UPDATE/SHARE, we have to uniquely
+ * identify all the source rows, not only those from the target relations, so
+ * that we can perform EvalPlanQual rechecking at need. For plain tables we
+ * can just fetch the TID, much as for a target relation; this case is
+ * represented by ROW_MARK_REFERENCE. Otherwise (for example for VALUES or
+ * FUNCTION scans) we have to copy the whole row value. ROW_MARK_COPY is
+ * pretty inefficient, since most of the time we'll never need the data; but
+ * fortunately the overhead is usually not performance-critical in practice.
+ * By default we use ROW_MARK_COPY for foreign tables, but if the FDW has
+ * a concept of rowid it can request to use ROW_MARK_REFERENCE instead.
+ * (Again, this probably doesn't make sense if a physical remote fetch is
+ * needed, but for FDWs that map to local storage it might be credible.)
+ */
+typedef enum RowMarkType
+{
+ ROW_MARK_EXCLUSIVE, /* obtain exclusive tuple lock */
+ ROW_MARK_NOKEYEXCLUSIVE, /* obtain no-key exclusive tuple lock */
+ ROW_MARK_SHARE, /* obtain shared tuple lock */
+ ROW_MARK_KEYSHARE, /* obtain keyshare tuple lock */
+ ROW_MARK_REFERENCE, /* just fetch the TID, don't lock it */
+ ROW_MARK_COPY /* physically copy the row value */
+} RowMarkType;
+
+#define RowMarkRequiresRowShareLock(marktype) ((marktype) <= ROW_MARK_KEYSHARE)
+
+/*
+ * PlanRowMark -
+ * plan-time representation of FOR [KEY] UPDATE/SHARE clauses
+ *
+ * When doing UPDATE/DELETE/MERGE/SELECT FOR UPDATE/SHARE, we create a separate
+ * PlanRowMark node for each non-target relation in the query. Relations that
+ * are not specified as FOR UPDATE/SHARE are marked ROW_MARK_REFERENCE (if
+ * regular tables or supported foreign tables) or ROW_MARK_COPY (if not).
+ *
+ * Initially all PlanRowMarks have rti == prti and isParent == false.
+ * When the planner discovers that a relation is the root of an inheritance
+ * tree, it sets isParent true, and adds an additional PlanRowMark to the
+ * list for each child relation (including the target rel itself in its role
+ * as a child, if it is not a partitioned table). Any non-leaf partitioned
+ * child relations will also have entries with isParent = true. The child
+ * entries have rti == child rel's RT index and prti == top parent's RT index,
+ * and can therefore be recognized as children by the fact that prti != rti.
+ * The parent's allMarkTypes field gets the OR of (1<<markType) across all
+ * its children (this definition allows children to use different markTypes).
+ *
+ * The planner also adds resjunk output columns to the plan that carry
+ * information sufficient to identify the locked or fetched rows. When
+ * markType != ROW_MARK_COPY, these columns are named
+ * tableoid%u OID of table
+ * ctid%u TID of row
+ * The tableoid column is only present for an inheritance hierarchy.
+ * When markType == ROW_MARK_COPY, there is instead a single column named
+ * wholerow%u whole-row value of relation
+ * (An inheritance hierarchy could have all three resjunk output columns,
+ * if some children use a different markType than others.)
+ * In all three cases, %u represents the rowmark ID number (rowmarkId).
+ * This number is unique within a plan tree, except that child relation
+ * entries copy their parent's rowmarkId. (Assigning unique numbers
+ * means we needn't renumber rowmarkIds when flattening subqueries, which
+ * would require finding and renaming the resjunk columns as well.)
+ * Note this means that all tables in an inheritance hierarchy share the
+ * same resjunk column names.
+ */
+typedef struct PlanRowMark
+{
+ pg_node_attr(no_equal, no_query_jumble)
+
+ NodeTag type;
+ Index rti; /* range table index of markable relation */
+ Index prti; /* range table index of parent relation */
+ Index rowmarkId; /* unique identifier for resjunk columns */
+ RowMarkType markType; /* see enum above */
+ int allMarkTypes; /* OR of (1<<markType) for all children */
+ LockClauseStrength strength; /* LockingClause's strength, or LCS_NONE */
+ LockWaitPolicy waitPolicy; /* NOWAIT and SKIP LOCKED options */
+ bool isParent; /* true if this is a "dummy" parent entry */
+} PlanRowMark;
+
+
+/*
+ * Node types to represent partition pruning information.
+ */
+
+/*
+ * PartitionPruneInfo - Details required to allow the executor to prune
+ * partitions.
+ *
+ * Here we store mapping details to allow translation of a partitioned table's
+ * index as returned by the partition pruning code into subplan indexes for
+ * plan types which support arbitrary numbers of subplans, such as Append.
+ * We also store various details to tell the executor when it should be
+ * performing partition pruning.
+ *
+ * Each PartitionedRelPruneInfo describes the partitioning rules for a single
+ * partitioned table (a/k/a level of partitioning). Since a partitioning
+ * hierarchy could contain multiple levels, we represent it by a List of
+ * PartitionedRelPruneInfos, where the first entry represents the topmost
+ * partitioned table and additional entries represent non-leaf child
+ * partitions, ordered such that parents appear before their children.
+ * Then, since an Append-type node could have multiple partitioning
+ * hierarchies among its children, we have an unordered List of those Lists.
+ *
+ * prune_infos List of Lists containing PartitionedRelPruneInfo nodes,
+ * one sublist per run-time-prunable partition hierarchy
+ * appearing in the parent plan node's subplans.
+ * other_subplans Indexes of any subplans that are not accounted for
+ * by any of the PartitionedRelPruneInfo nodes in
+ * "prune_infos". These subplans must not be pruned.
+ */
+typedef struct PartitionPruneInfo
+{
+ pg_node_attr(no_equal, no_query_jumble)
+
+ NodeTag type;
+ List *prune_infos;
+ Bitmapset *other_subplans;
+} PartitionPruneInfo;
+
+/*
+ * PartitionedRelPruneInfo - Details required to allow the executor to prune
+ * partitions for a single partitioned table.
+ *
+ * subplan_map[] and subpart_map[] are indexed by partition index of the
+ * partitioned table referenced by 'rtindex', the partition index being the
+ * order that the partitions are defined in the table's PartitionDesc. For a
+ * leaf partition p, subplan_map[p] contains the zero-based index of the
+ * partition's subplan in the parent plan's subplan list; it is -1 if the
+ * partition is non-leaf or has been pruned. For a non-leaf partition p,
+ * subpart_map[p] contains the zero-based index of that sub-partition's
+ * PartitionedRelPruneInfo in the hierarchy's PartitionedRelPruneInfo list;
+ * it is -1 if the partition is a leaf or has been pruned. Note that subplan
+ * indexes, as stored in 'subplan_map', are global across the parent plan
+ * node, but partition indexes are valid only within a particular hierarchy.
+ * relid_map[p] contains the partition's OID, or 0 if the partition was pruned.
+ */
+typedef struct PartitionedRelPruneInfo
+{
+ pg_node_attr(no_equal, no_query_jumble)
+
+ NodeTag type;
+
+ /* RT index of partition rel for this level */
+ Index rtindex;
+
+ /* Indexes of all partitions which subplans or subparts are present for */
+ Bitmapset *present_parts;
+
+ /* Length of the following arrays: */
+ int nparts;
+
+ /* subplan index by partition index, or -1 */
+ int *subplan_map pg_node_attr(array_size(nparts));
+
+ /* subpart index by partition index, or -1 */
+ int *subpart_map pg_node_attr(array_size(nparts));
+
+ /* relation OID by partition index, or 0 */
+ Oid *relid_map pg_node_attr(array_size(nparts));
+
+ /*
+ * initial_pruning_steps shows how to prune during executor startup (i.e.,
+ * without use of any PARAM_EXEC Params); it is NIL if no startup pruning
+ * is required. exec_pruning_steps shows how to prune with PARAM_EXEC
+ * Params; it is NIL if no per-scan pruning is required.
+ */
+ List *initial_pruning_steps; /* List of PartitionPruneStep */
+ List *exec_pruning_steps; /* List of PartitionPruneStep */
+
+ /* All PARAM_EXEC Param IDs in exec_pruning_steps */
+ Bitmapset *execparamids;
+} PartitionedRelPruneInfo;
+
+/*
+ * Abstract Node type for partition pruning steps (there are no concrete
+ * Nodes of this type).
+ *
+ * step_id is the global identifier of the step within its pruning context.
+ */
+typedef struct PartitionPruneStep
+{
+ pg_node_attr(abstract, no_equal, no_query_jumble)
+
+ NodeTag type;
+ int step_id;
+} PartitionPruneStep;
+
+/*
+ * PartitionPruneStepOp - Information to prune using a set of mutually ANDed
+ * OpExpr clauses
+ *
+ * This contains information extracted from up to partnatts OpExpr clauses,
+ * where partnatts is the number of partition key columns. 'opstrategy' is the
+ * strategy of the operator in the clause matched to the last partition key.
+ * 'exprs' contains expressions which comprise the lookup key to be passed to
+ * the partition bound search function. 'cmpfns' contains the OIDs of
+ * comparison functions used to compare aforementioned expressions with
+ * partition bounds. Both 'exprs' and 'cmpfns' contain the same number of
+ * items, up to partnatts items.
+ *
+ * Once we find the offset of a partition bound using the lookup key, we
+ * determine which partitions to include in the result based on the value of
+ * 'opstrategy'. For example, if it were equality, we'd return just the
+ * partition that would contain that key or a set of partitions if the key
+ * didn't consist of all partitioning columns. For non-equality strategies,
+ * we'd need to include other partitions as appropriate.
+ *
+ * 'nullkeys' is the set containing the offset of the partition keys (0 to
+ * partnatts - 1) that were matched to an IS NULL clause. This is only
+ * considered for hash partitioning as we need to pass which keys are null
+ * to the hash partition bound search function. It is never possible to
+ * have an expression be present in 'exprs' for a given partition key and
+ * the corresponding bit set in 'nullkeys'.
+ */
+typedef struct PartitionPruneStepOp
+{
+ PartitionPruneStep step;
+
+ StrategyNumber opstrategy;
+ List *exprs;
+ List *cmpfns;
+ Bitmapset *nullkeys;
+} PartitionPruneStepOp;
+
+/*
+ * PartitionPruneStepCombine - Information to prune using a BoolExpr clause
+ *
+ * For BoolExpr clauses, we combine the set of partitions determined for each
+ * of the argument clauses.
+ */
+typedef enum PartitionPruneCombineOp
+{
+ PARTPRUNE_COMBINE_UNION,
+ PARTPRUNE_COMBINE_INTERSECT
+} PartitionPruneCombineOp;
+
+typedef struct PartitionPruneStepCombine
+{
+ PartitionPruneStep step;
+
+ PartitionPruneCombineOp combineOp;
+ List *source_stepids;
+} PartitionPruneStepCombine;
+
+
+/*
+ * Plan invalidation info
+ *
+ * We track the objects on which a PlannedStmt depends in two ways:
+ * relations are recorded as a simple list of OIDs, and everything else
+ * is represented as a list of PlanInvalItems. A PlanInvalItem is designed
+ * to be used with the syscache invalidation mechanism, so it identifies a
+ * system catalog entry by cache ID and hash value.
+ */
+typedef struct PlanInvalItem
+{
+ pg_node_attr(no_equal, no_query_jumble)
+
+ NodeTag type;
+ int cacheId; /* a syscache ID, see utils/syscache.h */
+ uint32 hashValue; /* hash value of object's cache lookup key */
+} PlanInvalItem;
+
+/*
+ * MonotonicFunction
+ *
+ * Allows the planner to track monotonic properties of functions. A function
+ * is monotonically increasing if a subsequent call cannot yield a lower value
+ * than the previous call. A monotonically decreasing function cannot yield a
+ * higher value on subsequent calls, and a function which is both must return
+ * the same value on each call.
+ */
+typedef enum MonotonicFunction
+{
+ MONOTONICFUNC_NONE = 0,
+ MONOTONICFUNC_INCREASING = (1 << 0),
+ MONOTONICFUNC_DECREASING = (1 << 1),
+ MONOTONICFUNC_BOTH = MONOTONICFUNC_INCREASING | MONOTONICFUNC_DECREASING
+} MonotonicFunction;
+
+#endif /* PLANNODES_H */
diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h
new file mode 100644
index 0000000..e1aadc3
--- /dev/null
+++ b/src/include/nodes/primnodes.h
@@ -0,0 +1,2041 @@
+/*-------------------------------------------------------------------------
+ *
+ * primnodes.h
+ * Definitions for "primitive" node types, those that are used in more
+ * than one of the parse/plan/execute stages of the query pipeline.
+ * Currently, these are mostly nodes for executable expressions
+ * and join trees.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/nodes/primnodes.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PRIMNODES_H
+#define PRIMNODES_H
+
+#include "access/attnum.h"
+#include "nodes/bitmapset.h"
+#include "nodes/pg_list.h"
+
+
+/* ----------------------------------------------------------------
+ * node definitions
+ * ----------------------------------------------------------------
+ */
+
+/*
+ * Alias -
+ * specifies an alias for a range variable; the alias might also
+ * specify renaming of columns within the table.
+ *
+ * Note: colnames is a list of String nodes. In Alias structs
+ * associated with RTEs, there may be entries corresponding to dropped
+ * columns; these are normally empty strings (""). See parsenodes.h for info.
+ */
+typedef struct Alias
+{
+ NodeTag type;
+ char *aliasname; /* aliased rel name (never qualified) */
+ List *colnames; /* optional list of column aliases */
+} Alias;
+
+/* What to do at commit time for temporary relations */
+typedef enum OnCommitAction
+{
+ ONCOMMIT_NOOP, /* No ON COMMIT clause (do nothing) */
+ ONCOMMIT_PRESERVE_ROWS, /* ON COMMIT PRESERVE ROWS (do nothing) */
+ ONCOMMIT_DELETE_ROWS, /* ON COMMIT DELETE ROWS */
+ ONCOMMIT_DROP /* ON COMMIT DROP */
+} OnCommitAction;
+
+/*
+ * RangeVar - range variable, used in FROM clauses
+ *
+ * Also used to represent table names in utility statements; there, the alias
+ * field is not used, and inh tells whether to apply the operation
+ * recursively to child tables. In some contexts it is also useful to carry
+ * a TEMP table indication here.
+ */
+typedef struct RangeVar
+{
+ NodeTag type;
+
+ /* the catalog (database) name, or NULL */
+ char *catalogname;
+
+ /* the schema name, or NULL */
+ char *schemaname;
+
+ /* the relation/sequence name */
+ char *relname;
+
+ /* expand rel by inheritance? recursively act on children? */
+ bool inh;
+
+ /* see RELPERSISTENCE_* in pg_class.h */
+ char relpersistence;
+
+ /* table alias & optional column aliases */
+ Alias *alias;
+
+ /* token location, or -1 if unknown */
+ int location;
+} RangeVar;
+
+/*
+ * TableFunc - node for a table function, such as XMLTABLE.
+ *
+ * Entries in the ns_names list are either String nodes containing
+ * literal namespace names, or NULL pointers to represent DEFAULT.
+ */
+typedef struct TableFunc
+{
+ NodeTag type;
+ /* list of namespace URI expressions */
+ List *ns_uris pg_node_attr(query_jumble_ignore);
+ /* list of namespace names or NULL */
+ List *ns_names pg_node_attr(query_jumble_ignore);
+ /* input document expression */
+ Node *docexpr;
+ /* row filter expression */
+ Node *rowexpr;
+ /* column names (list of String) */
+ List *colnames pg_node_attr(query_jumble_ignore);
+ /* OID list of column type OIDs */
+ List *coltypes pg_node_attr(query_jumble_ignore);
+ /* integer list of column typmods */
+ List *coltypmods pg_node_attr(query_jumble_ignore);
+ /* OID list of column collation OIDs */
+ List *colcollations pg_node_attr(query_jumble_ignore);
+ /* list of column filter expressions */
+ List *colexprs;
+ /* list of column default expressions */
+ List *coldefexprs pg_node_attr(query_jumble_ignore);
+ /* nullability flag for each output column */
+ Bitmapset *notnulls pg_node_attr(query_jumble_ignore);
+ /* counts from 0; -1 if none specified */
+ int ordinalitycol pg_node_attr(query_jumble_ignore);
+ /* token location, or -1 if unknown */
+ int location;
+} TableFunc;
+
+/*
+ * IntoClause - target information for SELECT INTO, CREATE TABLE AS, and
+ * CREATE MATERIALIZED VIEW
+ *
+ * For CREATE MATERIALIZED VIEW, viewQuery is the parsed-but-not-rewritten
+ * SELECT Query for the view; otherwise it's NULL. This is irrelevant in
+ * the query jumbling as CreateTableAsStmt already includes a reference to
+ * its own Query, so ignore it. (Although it's actually Query*, we declare
+ * it as Node* to avoid a forward reference.)
+ */
+typedef struct IntoClause
+{
+ NodeTag type;
+
+ RangeVar *rel; /* target relation name */
+ List *colNames; /* column names to assign, or NIL */
+ char *accessMethod; /* table access method */
+ List *options; /* options from WITH clause */
+ OnCommitAction onCommit; /* what do we do at COMMIT? */
+ char *tableSpaceName; /* table space to use, or NULL */
+ /* materialized view's SELECT query */
+ Node *viewQuery pg_node_attr(query_jumble_ignore);
+ bool skipData; /* true for WITH NO DATA */
+} IntoClause;
+
+
+/* ----------------------------------------------------------------
+ * node types for executable expressions
+ * ----------------------------------------------------------------
+ */
+
+/*
+ * Expr - generic superclass for executable-expression nodes
+ *
+ * All node types that are used in executable expression trees should derive
+ * from Expr (that is, have Expr as their first field). Since Expr only
+ * contains NodeTag, this is a formality, but it is an easy form of
+ * documentation. See also the ExprState node types in execnodes.h.
+ */
+typedef struct Expr
+{
+ pg_node_attr(abstract)
+
+ NodeTag type;
+} Expr;
+
+/*
+ * Var - expression node representing a variable (ie, a table column)
+ *
+ * In the parser and planner, varno and varattno identify the semantic
+ * referent, which is a base-relation column unless the reference is to a join
+ * USING column that isn't semantically equivalent to either join input column
+ * (because it is a FULL join or the input column requires a type coercion).
+ * In those cases varno and varattno refer to the JOIN RTE. (Early in the
+ * planner, we replace such join references by the implied expression; but up
+ * till then we want join reference Vars to keep their original identity for
+ * query-printing purposes.)
+ *
+ * At the end of planning, Var nodes appearing in upper-level plan nodes are
+ * reassigned to point to the outputs of their subplans; for example, in a
+ * join node varno becomes INNER_VAR or OUTER_VAR and varattno becomes the
+ * index of the proper element of that subplan's target list. Similarly,
+ * INDEX_VAR is used to identify Vars that reference an index column rather
+ * than a heap column. (In ForeignScan and CustomScan plan nodes, INDEX_VAR
+ * is abused to signify references to columns of a custom scan tuple type.)
+ *
+ * ROWID_VAR is used in the planner to identify nonce variables that carry
+ * row identity information during UPDATE/DELETE/MERGE. This value should
+ * never be seen outside the planner.
+ *
+ * varnullingrels is the set of RT indexes of outer joins that can force
+ * the Var's value to null (at the point where it appears in the query).
+ * See optimizer/README for discussion of that.
+ *
+ * varlevelsup is greater than zero in Vars that represent outer references.
+ * Note that it affects the meaning of all of varno, varnullingrels, and
+ * varnosyn, all of which refer to the range table of that query level.
+ *
+ * In the parser, varnosyn and varattnosyn are either identical to
+ * varno/varattno, or they specify the column's position in an aliased JOIN
+ * RTE that hides the semantic referent RTE's refname. This is a syntactic
+ * identifier as opposed to the semantic identifier; it tells ruleutils.c
+ * how to print the Var properly. varnosyn/varattnosyn retain their values
+ * throughout planning and execution, so they are particularly helpful to
+ * identify Vars when debugging. Note, however, that a Var that is generated
+ * in the planner and doesn't correspond to any simple relation column may
+ * have varnosyn = varattnosyn = 0.
+ */
+#define INNER_VAR (-1) /* reference to inner subplan */
+#define OUTER_VAR (-2) /* reference to outer subplan */
+#define INDEX_VAR (-3) /* reference to index column */
+#define ROWID_VAR (-4) /* row identity column during planning */
+
+#define IS_SPECIAL_VARNO(varno) ((int) (varno) < 0)
+
+/* Symbols for the indexes of the special RTE entries in rules */
+#define PRS2_OLD_VARNO 1
+#define PRS2_NEW_VARNO 2
+
+typedef struct Var
+{
+ Expr xpr;
+
+ /*
+ * index of this var's relation in the range table, or
+ * INNER_VAR/OUTER_VAR/etc
+ */
+ int varno;
+
+ /*
+ * attribute number of this var, or zero for all attrs ("whole-row Var")
+ */
+ AttrNumber varattno;
+
+ /* pg_type OID for the type of this var */
+ Oid vartype pg_node_attr(query_jumble_ignore);
+ /* pg_attribute typmod value */
+ int32 vartypmod pg_node_attr(query_jumble_ignore);
+ /* OID of collation, or InvalidOid if none */
+ Oid varcollid pg_node_attr(query_jumble_ignore);
+
+ /*
+ * RT indexes of outer joins that can replace the Var's value with null.
+ * We can omit varnullingrels in the query jumble, because it's fully
+ * determined by varno/varlevelsup plus the Var's query location.
+ */
+ Bitmapset *varnullingrels pg_node_attr(query_jumble_ignore);
+
+ /*
+ * for subquery variables referencing outer relations; 0 in a normal var,
+ * >0 means N levels up
+ */
+ Index varlevelsup;
+
+ /*
+ * varnosyn/varattnosyn are ignored for equality, because Vars with
+ * different syntactic identifiers are semantically the same as long as
+ * their varno/varattno match.
+ */
+ /* syntactic relation index (0 if unknown) */
+ Index varnosyn pg_node_attr(equal_ignore, query_jumble_ignore);
+ /* syntactic attribute number */
+ AttrNumber varattnosyn pg_node_attr(equal_ignore, query_jumble_ignore);
+
+ /* token location, or -1 if unknown */
+ int location;
+} Var;
+
+/*
+ * Const
+ *
+ * Note: for varlena data types, we make a rule that a Const node's value
+ * must be in non-extended form (4-byte header, no compression or external
+ * references). This ensures that the Const node is self-contained and makes
+ * it more likely that equal() will see logically identical values as equal.
+ *
+ * Only the constant type OID is relevant for the query jumbling.
+ */
+typedef struct Const
+{
+ pg_node_attr(custom_copy_equal, custom_read_write)
+
+ Expr xpr;
+ /* pg_type OID of the constant's datatype */
+ Oid consttype;
+ /* typmod value, if any */
+ int32 consttypmod pg_node_attr(query_jumble_ignore);
+ /* OID of collation, or InvalidOid if none */
+ Oid constcollid pg_node_attr(query_jumble_ignore);
+ /* typlen of the constant's datatype */
+ int constlen pg_node_attr(query_jumble_ignore);
+ /* the constant's value */
+ Datum constvalue pg_node_attr(query_jumble_ignore);
+ /* whether the constant is null (if true, constvalue is undefined) */
+ bool constisnull pg_node_attr(query_jumble_ignore);
+
+ /*
+ * Whether this datatype is passed by value. If true, then all the
+ * information is stored in the Datum. If false, then the Datum contains
+ * a pointer to the information.
+ */
+ bool constbyval pg_node_attr(query_jumble_ignore);
+
+ /*
+ * token location, or -1 if unknown. All constants are tracked as
+ * locations in query jumbling, to be marked as parameters.
+ */
+ int location pg_node_attr(query_jumble_location);
+} Const;
+
+/*
+ * Param
+ *
+ * paramkind specifies the kind of parameter. The possible values
+ * for this field are:
+ *
+ * PARAM_EXTERN: The parameter value is supplied from outside the plan.
+ * Such parameters are numbered from 1 to n.
+ *
+ * PARAM_EXEC: The parameter is an internal executor parameter, used
+ * for passing values into and out of sub-queries or from
+ * nestloop joins to their inner scans.
+ * For historical reasons, such parameters are numbered from 0.
+ * These numbers are independent of PARAM_EXTERN numbers.
+ *
+ * PARAM_SUBLINK: The parameter represents an output column of a SubLink
+ * node's sub-select. The column number is contained in the
+ * `paramid' field. (This type of Param is converted to
+ * PARAM_EXEC during planning.)
+ *
+ * PARAM_MULTIEXPR: Like PARAM_SUBLINK, the parameter represents an
+ * output column of a SubLink node's sub-select, but here, the
+ * SubLink is always a MULTIEXPR SubLink. The high-order 16 bits
+ * of the `paramid' field contain the SubLink's subLinkId, and
+ * the low-order 16 bits contain the column number. (This type
+ * of Param is also converted to PARAM_EXEC during planning.)
+ */
+typedef enum ParamKind
+{
+ PARAM_EXTERN,
+ PARAM_EXEC,
+ PARAM_SUBLINK,
+ PARAM_MULTIEXPR
+} ParamKind;
+
+typedef struct Param
+{
+ Expr xpr;
+ ParamKind paramkind; /* kind of parameter. See above */
+ int paramid; /* numeric ID for parameter */
+ Oid paramtype; /* pg_type OID of parameter's datatype */
+ /* typmod value, if known */
+ int32 paramtypmod pg_node_attr(query_jumble_ignore);
+ /* OID of collation, or InvalidOid if none */
+ Oid paramcollid pg_node_attr(query_jumble_ignore);
+ /* token location, or -1 if unknown */
+ int location;
+} Param;
+
+/*
+ * Aggref
+ *
+ * The aggregate's args list is a targetlist, ie, a list of TargetEntry nodes.
+ *
+ * For a normal (non-ordered-set) aggregate, the non-resjunk TargetEntries
+ * represent the aggregate's regular arguments (if any) and resjunk TLEs can
+ * be added at the end to represent ORDER BY expressions that are not also
+ * arguments. As in a top-level Query, the TLEs can be marked with
+ * ressortgroupref indexes to let them be referenced by SortGroupClause
+ * entries in the aggorder and/or aggdistinct lists. This represents ORDER BY
+ * and DISTINCT operations to be applied to the aggregate input rows before
+ * they are passed to the transition function. The grammar only allows a
+ * simple "DISTINCT" specifier for the arguments, but we use the full
+ * query-level representation to allow more code sharing.
+ *
+ * For an ordered-set aggregate, the args list represents the WITHIN GROUP
+ * (aggregated) arguments, all of which will be listed in the aggorder list.
+ * DISTINCT is not supported in this case, so aggdistinct will be NIL.
+ * The direct arguments appear in aggdirectargs (as a list of plain
+ * expressions, not TargetEntry nodes).
+ *
+ * aggtranstype is the data type of the state transition values for this
+ * aggregate (resolved to an actual type, if agg's transtype is polymorphic).
+ * This is determined during planning and is InvalidOid before that.
+ *
+ * aggargtypes is an OID list of the data types of the direct and regular
+ * arguments. Normally it's redundant with the aggdirectargs and args lists,
+ * but in a combining aggregate, it's not because the args list has been
+ * replaced with a single argument representing the partial-aggregate
+ * transition values.
+ *
+ * aggpresorted is set by the query planner for ORDER BY and DISTINCT
+ * aggregates where the chosen plan provides presorted input for this
+ * aggregate during execution.
+ *
+ * aggsplit indicates the expected partial-aggregation mode for the Aggref's
+ * parent plan node. It's always set to AGGSPLIT_SIMPLE in the parser, but
+ * the planner might change it to something else. We use this mainly as
+ * a crosscheck that the Aggrefs match the plan; but note that when aggsplit
+ * indicates a non-final mode, aggtype reflects the transition data type
+ * not the SQL-level output type of the aggregate.
+ *
+ * aggno and aggtransno are -1 in the parse stage, and are set in planning.
+ * Aggregates with the same 'aggno' represent the same aggregate expression,
+ * and can share the result. Aggregates with same 'transno' but different
+ * 'aggno' can share the same transition state, only the final function needs
+ * to be called separately.
+ *
+ * Information related to collations, transition types and internal states
+ * are irrelevant for the query jumbling.
+ */
+typedef struct Aggref
+{
+ Expr xpr;
+
+ /* pg_proc Oid of the aggregate */
+ Oid aggfnoid;
+
+ /* type Oid of result of the aggregate */
+ Oid aggtype pg_node_attr(query_jumble_ignore);
+
+ /* OID of collation of result */
+ Oid aggcollid pg_node_attr(query_jumble_ignore);
+
+ /* OID of collation that function should use */
+ Oid inputcollid pg_node_attr(query_jumble_ignore);
+
+ /*
+ * type Oid of aggregate's transition value; ignored for equal since it
+ * might not be set yet
+ */
+ Oid aggtranstype pg_node_attr(equal_ignore, query_jumble_ignore);
+
+ /* type Oids of direct and aggregated args */
+ List *aggargtypes pg_node_attr(query_jumble_ignore);
+
+ /* direct arguments, if an ordered-set agg */
+ List *aggdirectargs;
+
+ /* aggregated arguments and sort expressions */
+ List *args;
+
+ /* ORDER BY (list of SortGroupClause) */
+ List *aggorder;
+
+ /* DISTINCT (list of SortGroupClause) */
+ List *aggdistinct;
+
+ /* FILTER expression, if any */
+ Expr *aggfilter;
+
+ /* true if argument list was really '*' */
+ bool aggstar pg_node_attr(query_jumble_ignore);
+
+ /*
+ * true if variadic arguments have been combined into an array last
+ * argument
+ */
+ bool aggvariadic pg_node_attr(query_jumble_ignore);
+
+ /* aggregate kind (see pg_aggregate.h) */
+ char aggkind pg_node_attr(query_jumble_ignore);
+
+ /* aggregate input already sorted */
+ bool aggpresorted pg_node_attr(equal_ignore, query_jumble_ignore);
+
+ /* > 0 if agg belongs to outer query */
+ Index agglevelsup pg_node_attr(query_jumble_ignore);
+
+ /* expected agg-splitting mode of parent Agg */
+ AggSplit aggsplit pg_node_attr(query_jumble_ignore);
+
+ /* unique ID within the Agg node */
+ int aggno pg_node_attr(query_jumble_ignore);
+
+ /* unique ID of transition state in the Agg */
+ int aggtransno pg_node_attr(query_jumble_ignore);
+
+ /* token location, or -1 if unknown */
+ int location;
+} Aggref;
+
+/*
+ * GroupingFunc
+ *
+ * A GroupingFunc is a GROUPING(...) expression, which behaves in many ways
+ * like an aggregate function (e.g. it "belongs" to a specific query level,
+ * which might not be the one immediately containing it), but also differs in
+ * an important respect: it never evaluates its arguments, they merely
+ * designate expressions from the GROUP BY clause of the query level to which
+ * it belongs.
+ *
+ * The spec defines the evaluation of GROUPING() purely by syntactic
+ * replacement, but we make it a real expression for optimization purposes so
+ * that one Agg node can handle multiple grouping sets at once. Evaluating the
+ * result only needs the column positions to check against the grouping set
+ * being projected. However, for EXPLAIN to produce meaningful output, we have
+ * to keep the original expressions around, since expression deparse does not
+ * give us any feasible way to get at the GROUP BY clause.
+ *
+ * Also, we treat two GroupingFunc nodes as equal if they have equal arguments
+ * lists and agglevelsup, without comparing the refs and cols annotations.
+ *
+ * In raw parse output we have only the args list; parse analysis fills in the
+ * refs list, and the planner fills in the cols list.
+ *
+ * All the fields used as information for an internal state are irrelevant
+ * for the query jumbling.
+ */
+typedef struct GroupingFunc
+{
+ Expr xpr;
+
+ /* arguments, not evaluated but kept for benefit of EXPLAIN etc. */
+ List *args pg_node_attr(query_jumble_ignore);
+
+ /* ressortgrouprefs of arguments */
+ List *refs pg_node_attr(equal_ignore);
+
+ /* actual column positions set by planner */
+ List *cols pg_node_attr(equal_ignore, query_jumble_ignore);
+
+ /* same as Aggref.agglevelsup */
+ Index agglevelsup;
+
+ /* token location */
+ int location;
+} GroupingFunc;
+
+/*
+ * WindowFunc
+ *
+ * Collation information is irrelevant for the query jumbling, as is the
+ * internal state information of the node like "winstar" and "winagg".
+ */
+typedef struct WindowFunc
+{
+ Expr xpr;
+ /* pg_proc Oid of the function */
+ Oid winfnoid;
+ /* type Oid of result of the window function */
+ Oid wintype pg_node_attr(query_jumble_ignore);
+ /* OID of collation of result */
+ Oid wincollid pg_node_attr(query_jumble_ignore);
+ /* OID of collation that function should use */
+ Oid inputcollid pg_node_attr(query_jumble_ignore);
+ /* arguments to the window function */
+ List *args;
+ /* FILTER expression, if any */
+ Expr *aggfilter;
+ /* index of associated WindowClause */
+ Index winref;
+ /* true if argument list was really '*' */
+ bool winstar pg_node_attr(query_jumble_ignore);
+ /* is function a simple aggregate? */
+ bool winagg pg_node_attr(query_jumble_ignore);
+ /* token location, or -1 if unknown */
+ int location;
+} WindowFunc;
+
+/*
+ * SubscriptingRef: describes a subscripting operation over a container
+ * (array, etc).
+ *
+ * A SubscriptingRef can describe fetching a single element from a container,
+ * fetching a part of a container (e.g. an array slice), storing a single
+ * element into a container, or storing a slice. The "store" cases work with
+ * an initial container value and a source value that is inserted into the
+ * appropriate part of the container; the result of the operation is an
+ * entire new modified container value.
+ *
+ * If reflowerindexpr = NIL, then we are fetching or storing a single container
+ * element at the subscripts given by refupperindexpr. Otherwise we are
+ * fetching or storing a container slice, that is a rectangular subcontainer
+ * with lower and upper bounds given by the index expressions.
+ * reflowerindexpr must be the same length as refupperindexpr when it
+ * is not NIL.
+ *
+ * In the slice case, individual expressions in the subscript lists can be
+ * NULL, meaning "substitute the array's current lower or upper bound".
+ * (Non-array containers may or may not support this.)
+ *
+ * refcontainertype is the actual container type that determines the
+ * subscripting semantics. (This will generally be either the exposed type of
+ * refexpr, or the base type if that is a domain.) refelemtype is the type of
+ * the container's elements; this is saved for the use of the subscripting
+ * functions, but is not used by the core code. refrestype, reftypmod, and
+ * refcollid describe the type of the SubscriptingRef's result. In a store
+ * expression, refrestype will always match refcontainertype; in a fetch,
+ * it could be refelemtype for an element fetch, or refcontainertype for a
+ * slice fetch, or possibly something else as determined by type-specific
+ * subscripting logic. Likewise, reftypmod and refcollid will match the
+ * container's properties in a store, but could be different in a fetch.
+ *
+ * Any internal state data is ignored for the query jumbling.
+ *
+ * Note: for the cases where a container is returned, if refexpr yields a R/W
+ * expanded container, then the implementation is allowed to modify that
+ * object in-place and return the same object.
+ */
+typedef struct SubscriptingRef
+{
+ Expr xpr;
+ /* type of the container proper */
+ Oid refcontainertype pg_node_attr(query_jumble_ignore);
+ /* the container type's pg_type.typelem */
+ Oid refelemtype pg_node_attr(query_jumble_ignore);
+ /* type of the SubscriptingRef's result */
+ Oid refrestype pg_node_attr(query_jumble_ignore);
+ /* typmod of the result */
+ int32 reftypmod pg_node_attr(query_jumble_ignore);
+ /* collation of result, or InvalidOid if none */
+ Oid refcollid pg_node_attr(query_jumble_ignore);
+ /* expressions that evaluate to upper container indexes */
+ List *refupperindexpr;
+
+ /*
+ * expressions that evaluate to lower container indexes, or NIL for single
+ * container element.
+ */
+ List *reflowerindexpr;
+ /* the expression that evaluates to a container value */
+ Expr *refexpr;
+ /* expression for the source value, or NULL if fetch */
+ Expr *refassgnexpr;
+} SubscriptingRef;
+
+/*
+ * CoercionContext - distinguishes the allowed set of type casts
+ *
+ * NB: ordering of the alternatives is significant; later (larger) values
+ * allow more casts than earlier ones.
+ */
+typedef enum CoercionContext
+{
+ COERCION_IMPLICIT, /* coercion in context of expression */
+ COERCION_ASSIGNMENT, /* coercion in context of assignment */
+ COERCION_PLPGSQL, /* if no assignment cast, use CoerceViaIO */
+ COERCION_EXPLICIT /* explicit cast operation */
+} CoercionContext;
+
+/*
+ * CoercionForm - how to display a FuncExpr or related node
+ *
+ * "Coercion" is a bit of a misnomer, since this value records other
+ * special syntaxes besides casts, but for now we'll keep this naming.
+ *
+ * NB: equal() ignores CoercionForm fields, therefore this *must* not carry
+ * any semantically significant information. We need that behavior so that
+ * the planner will consider equivalent implicit and explicit casts to be
+ * equivalent. In cases where those actually behave differently, the coercion
+ * function's arguments will be different.
+ */
+typedef enum CoercionForm
+{
+ COERCE_EXPLICIT_CALL, /* display as a function call */
+ COERCE_EXPLICIT_CAST, /* display as an explicit cast */
+ COERCE_IMPLICIT_CAST, /* implicit cast, so hide it */
+ COERCE_SQL_SYNTAX /* display with SQL-mandated special syntax */
+} CoercionForm;
+
+/*
+ * FuncExpr - expression node for a function call
+ *
+ * Collation information is irrelevant for the query jumbling, only the
+ * arguments and the function OID matter.
+ */
+typedef struct FuncExpr
+{
+ Expr xpr;
+ /* PG_PROC OID of the function */
+ Oid funcid;
+ /* PG_TYPE OID of result value */
+ Oid funcresulttype pg_node_attr(query_jumble_ignore);
+ /* true if function returns set */
+ bool funcretset pg_node_attr(query_jumble_ignore);
+
+ /*
+ * true if variadic arguments have been combined into an array last
+ * argument
+ */
+ bool funcvariadic pg_node_attr(query_jumble_ignore);
+ /* how to display this function call */
+ CoercionForm funcformat pg_node_attr(query_jumble_ignore);
+ /* OID of collation of result */
+ Oid funccollid pg_node_attr(query_jumble_ignore);
+ /* OID of collation that function should use */
+ Oid inputcollid pg_node_attr(query_jumble_ignore);
+ /* arguments to the function */
+ List *args;
+ /* token location, or -1 if unknown */
+ int location;
+} FuncExpr;
+
+/*
+ * NamedArgExpr - a named argument of a function
+ *
+ * This node type can only appear in the args list of a FuncCall or FuncExpr
+ * node. We support pure positional call notation (no named arguments),
+ * named notation (all arguments are named), and mixed notation (unnamed
+ * arguments followed by named ones).
+ *
+ * Parse analysis sets argnumber to the positional index of the argument,
+ * but doesn't rearrange the argument list.
+ *
+ * The planner will convert argument lists to pure positional notation
+ * during expression preprocessing, so execution never sees a NamedArgExpr.
+ */
+typedef struct NamedArgExpr
+{
+ Expr xpr;
+ /* the argument expression */
+ Expr *arg;
+ /* the name */
+ char *name pg_node_attr(query_jumble_ignore);
+ /* argument's number in positional notation */
+ int argnumber;
+ /* argument name location, or -1 if unknown */
+ int location;
+} NamedArgExpr;
+
+/*
+ * OpExpr - expression node for an operator invocation
+ *
+ * Semantically, this is essentially the same as a function call.
+ *
+ * Note that opfuncid is not necessarily filled in immediately on creation
+ * of the node. The planner makes sure it is valid before passing the node
+ * tree to the executor, but during parsing/planning opfuncid can be 0.
+ * Therefore, equal() will accept a zero value as being equal to other values.
+ *
+ * Internal state information and collation data is irrelevant for the query
+ * jumbling.
+ */
+typedef struct OpExpr
+{
+ Expr xpr;
+
+ /* PG_OPERATOR OID of the operator */
+ Oid opno;
+
+ /* PG_PROC OID of underlying function */
+ Oid opfuncid pg_node_attr(equal_ignore_if_zero, query_jumble_ignore);
+
+ /* PG_TYPE OID of result value */
+ Oid opresulttype pg_node_attr(query_jumble_ignore);
+
+ /* true if operator returns set */
+ bool opretset pg_node_attr(query_jumble_ignore);
+
+ /* OID of collation of result */
+ Oid opcollid pg_node_attr(query_jumble_ignore);
+
+ /* OID of collation that operator should use */
+ Oid inputcollid pg_node_attr(query_jumble_ignore);
+
+ /* arguments to the operator (1 or 2) */
+ List *args;
+
+ /* token location, or -1 if unknown */
+ int location;
+} OpExpr;
+
+/*
+ * DistinctExpr - expression node for "x IS DISTINCT FROM y"
+ *
+ * Except for the nodetag, this is represented identically to an OpExpr
+ * referencing the "=" operator for x and y.
+ * We use "=", not the more obvious "<>", because more datatypes have "="
+ * than "<>". This means the executor must invert the operator result.
+ * Note that the operator function won't be called at all if either input
+ * is NULL, since then the result can be determined directly.
+ */
+typedef OpExpr DistinctExpr;
+
+/*
+ * NullIfExpr - a NULLIF expression
+ *
+ * Like DistinctExpr, this is represented the same as an OpExpr referencing
+ * the "=" operator for x and y.
+ */
+typedef OpExpr NullIfExpr;
+
+/*
+ * ScalarArrayOpExpr - expression node for "scalar op ANY/ALL (array)"
+ *
+ * The operator must yield boolean. It is applied to the left operand
+ * and each element of the righthand array, and the results are combined
+ * with OR or AND (for ANY or ALL respectively). The node representation
+ * is almost the same as for the underlying operator, but we need a useOr
+ * flag to remember whether it's ANY or ALL, and we don't have to store
+ * the result type (or the collation) because it must be boolean.
+ *
+ * A ScalarArrayOpExpr with a valid hashfuncid is evaluated during execution
+ * by building a hash table containing the Const values from the RHS arg.
+ * This table is probed during expression evaluation. The planner will set
+ * hashfuncid to the hash function which must be used to build and probe the
+ * hash table. The executor determines if it should use hash-based checks or
+ * the more traditional means based on if the hashfuncid is set or not.
+ *
+ * When performing hashed NOT IN, the negfuncid will also be set to the
+ * equality function which the hash table must use to build and probe the hash
+ * table. opno and opfuncid will remain set to the <> operator and its
+ * corresponding function and won't be used during execution. For
+ * non-hashtable based NOT INs, negfuncid will be set to InvalidOid. See
+ * convert_saop_to_hashed_saop().
+ *
+ * Similar to OpExpr, opfuncid, hashfuncid, and negfuncid are not necessarily
+ * filled in right away, so will be ignored for equality if they are not set
+ * yet.
+ *
+ * OID entries of the internal function types are irrelevant for the query
+ * jumbling, but the operator OID and the arguments are.
+ */
+typedef struct ScalarArrayOpExpr
+{
+ Expr xpr;
+
+ /* PG_OPERATOR OID of the operator */
+ Oid opno;
+
+ /* PG_PROC OID of comparison function */
+ Oid opfuncid pg_node_attr(equal_ignore_if_zero, query_jumble_ignore);
+
+ /* PG_PROC OID of hash func or InvalidOid */
+ Oid hashfuncid pg_node_attr(equal_ignore_if_zero, query_jumble_ignore);
+
+ /* PG_PROC OID of negator of opfuncid function or InvalidOid. See above */
+ Oid negfuncid pg_node_attr(equal_ignore_if_zero, query_jumble_ignore);
+
+ /* true for ANY, false for ALL */
+ bool useOr;
+
+ /* OID of collation that operator should use */
+ Oid inputcollid pg_node_attr(query_jumble_ignore);
+
+ /* the scalar and array operands */
+ List *args;
+
+ /* token location, or -1 if unknown */
+ int location;
+} ScalarArrayOpExpr;
+
+/*
+ * BoolExpr - expression node for the basic Boolean operators AND, OR, NOT
+ *
+ * Notice the arguments are given as a List. For NOT, of course the list
+ * must always have exactly one element. For AND and OR, there can be two
+ * or more arguments.
+ */
+typedef enum BoolExprType
+{
+ AND_EXPR, OR_EXPR, NOT_EXPR
+} BoolExprType;
+
+typedef struct BoolExpr
+{
+ pg_node_attr(custom_read_write)
+
+ Expr xpr;
+ BoolExprType boolop;
+ List *args; /* arguments to this expression */
+ int location; /* token location, or -1 if unknown */
+} BoolExpr;
+
+/*
+ * SubLink
+ *
+ * A SubLink represents a subselect appearing in an expression, and in some
+ * cases also the combining operator(s) just above it. The subLinkType
+ * indicates the form of the expression represented:
+ * EXISTS_SUBLINK EXISTS(SELECT ...)
+ * ALL_SUBLINK (lefthand) op ALL (SELECT ...)
+ * ANY_SUBLINK (lefthand) op ANY (SELECT ...)
+ * ROWCOMPARE_SUBLINK (lefthand) op (SELECT ...)
+ * EXPR_SUBLINK (SELECT with single targetlist item ...)
+ * MULTIEXPR_SUBLINK (SELECT with multiple targetlist items ...)
+ * ARRAY_SUBLINK ARRAY(SELECT with single targetlist item ...)
+ * CTE_SUBLINK WITH query (never actually part of an expression)
+ * For ALL, ANY, and ROWCOMPARE, the lefthand is a list of expressions of the
+ * same length as the subselect's targetlist. ROWCOMPARE will *always* have
+ * a list with more than one entry; if the subselect has just one target
+ * then the parser will create an EXPR_SUBLINK instead (and any operator
+ * above the subselect will be represented separately).
+ * ROWCOMPARE, EXPR, and MULTIEXPR require the subselect to deliver at most
+ * one row (if it returns no rows, the result is NULL).
+ * ALL, ANY, and ROWCOMPARE require the combining operators to deliver boolean
+ * results. ALL and ANY combine the per-row results using AND and OR
+ * semantics respectively.
+ * ARRAY requires just one target column, and creates an array of the target
+ * column's type using any number of rows resulting from the subselect.
+ *
+ * SubLink is classed as an Expr node, but it is not actually executable;
+ * it must be replaced in the expression tree by a SubPlan node during
+ * planning.
+ *
+ * NOTE: in the raw output of gram.y, testexpr contains just the raw form
+ * of the lefthand expression (if any), and operName is the String name of
+ * the combining operator. Also, subselect is a raw parsetree. During parse
+ * analysis, the parser transforms testexpr into a complete boolean expression
+ * that compares the lefthand value(s) to PARAM_SUBLINK nodes representing the
+ * output columns of the subselect. And subselect is transformed to a Query.
+ * This is the representation seen in saved rules and in the rewriter.
+ *
+ * In EXISTS, EXPR, MULTIEXPR, and ARRAY SubLinks, testexpr and operName
+ * are unused and are always null.
+ *
+ * subLinkId is currently used only for MULTIEXPR SubLinks, and is zero in
+ * other SubLinks. This number identifies different multiple-assignment
+ * subqueries within an UPDATE statement's SET list. It is unique only
+ * within a particular targetlist. The output column(s) of the MULTIEXPR
+ * are referenced by PARAM_MULTIEXPR Params appearing elsewhere in the tlist.
+ *
+ * The CTE_SUBLINK case never occurs in actual SubLink nodes, but it is used
+ * in SubPlans generated for WITH subqueries.
+ */
+typedef enum SubLinkType
+{
+ EXISTS_SUBLINK,
+ ALL_SUBLINK,
+ ANY_SUBLINK,
+ ROWCOMPARE_SUBLINK,
+ EXPR_SUBLINK,
+ MULTIEXPR_SUBLINK,
+ ARRAY_SUBLINK,
+ CTE_SUBLINK /* for SubPlans only */
+} SubLinkType;
+
+
+typedef struct SubLink
+{
+ Expr xpr;
+ SubLinkType subLinkType; /* see above */
+ int subLinkId; /* ID (1..n); 0 if not MULTIEXPR */
+ Node *testexpr; /* outer-query test for ALL/ANY/ROWCOMPARE */
+ /* originally specified operator name */
+ List *operName pg_node_attr(query_jumble_ignore);
+ /* subselect as Query* or raw parsetree */
+ Node *subselect;
+ int location; /* token location, or -1 if unknown */
+} SubLink;
+
+/*
+ * SubPlan - executable expression node for a subplan (sub-SELECT)
+ *
+ * The planner replaces SubLink nodes in expression trees with SubPlan
+ * nodes after it has finished planning the subquery. SubPlan references
+ * a sub-plantree stored in the subplans list of the toplevel PlannedStmt.
+ * (We avoid a direct link to make it easier to copy expression trees
+ * without causing multiple processing of the subplan.)
+ *
+ * In an ordinary subplan, testexpr points to an executable expression
+ * (OpExpr, an AND/OR tree of OpExprs, or RowCompareExpr) for the combining
+ * operator(s); the left-hand arguments are the original lefthand expressions,
+ * and the right-hand arguments are PARAM_EXEC Param nodes representing the
+ * outputs of the sub-select. (NOTE: runtime coercion functions may be
+ * inserted as well.) This is just the same expression tree as testexpr in
+ * the original SubLink node, but the PARAM_SUBLINK nodes are replaced by
+ * suitably numbered PARAM_EXEC nodes.
+ *
+ * If the sub-select becomes an initplan rather than a subplan, the executable
+ * expression is part of the outer plan's expression tree (and the SubPlan
+ * node itself is not, but rather is found in the outer plan's initPlan
+ * list). In this case testexpr is NULL to avoid duplication.
+ *
+ * The planner also derives lists of the values that need to be passed into
+ * and out of the subplan. Input values are represented as a list "args" of
+ * expressions to be evaluated in the outer-query context (currently these
+ * args are always just Vars, but in principle they could be any expression).
+ * The values are assigned to the global PARAM_EXEC params indexed by parParam
+ * (the parParam and args lists must have the same ordering). setParam is a
+ * list of the PARAM_EXEC params that are computed by the sub-select, if it
+ * is an initplan or MULTIEXPR plan; they are listed in order by sub-select
+ * output column position. (parParam and setParam are integer Lists, not
+ * Bitmapsets, because their ordering is significant.)
+ *
+ * Also, the planner computes startup and per-call costs for use of the
+ * SubPlan. Note that these include the cost of the subquery proper,
+ * evaluation of the testexpr if any, and any hashtable management overhead.
+ */
+typedef struct SubPlan
+{
+ pg_node_attr(no_query_jumble)
+
+ Expr xpr;
+ /* Fields copied from original SubLink: */
+ SubLinkType subLinkType; /* see above */
+ /* The combining operators, transformed to an executable expression: */
+ Node *testexpr; /* OpExpr or RowCompareExpr expression tree */
+ List *paramIds; /* IDs of Params embedded in the above */
+ /* Identification of the Plan tree to use: */
+ int plan_id; /* Index (from 1) in PlannedStmt.subplans */
+ /* Identification of the SubPlan for EXPLAIN and debugging purposes: */
+ char *plan_name; /* A name assigned during planning */
+ /* Extra data useful for determining subplan's output type: */
+ Oid firstColType; /* Type of first column of subplan result */
+ int32 firstColTypmod; /* Typmod of first column of subplan result */
+ Oid firstColCollation; /* Collation of first column of subplan
+ * result */
+ /* Information about execution strategy: */
+ bool useHashTable; /* true to store subselect output in a hash
+ * table (implies we are doing "IN") */
+ bool unknownEqFalse; /* true if it's okay to return FALSE when the
+ * spec result is UNKNOWN; this allows much
+ * simpler handling of null values */
+ bool parallel_safe; /* is the subplan parallel-safe? */
+ /* Note: parallel_safe does not consider contents of testexpr or args */
+ /* Information for passing params into and out of the subselect: */
+ /* setParam and parParam are lists of integers (param IDs) */
+ List *setParam; /* initplan and MULTIEXPR subqueries have to
+ * set these Params for parent plan */
+ List *parParam; /* indices of input Params from parent plan */
+ List *args; /* exprs to pass as parParam values */
+ /* Estimated execution costs: */
+ Cost startup_cost; /* one-time setup cost */
+ Cost per_call_cost; /* cost for each subplan evaluation */
+} SubPlan;
+
+/*
+ * AlternativeSubPlan - expression node for a choice among SubPlans
+ *
+ * This is used only transiently during planning: by the time the plan
+ * reaches the executor, all AlternativeSubPlan nodes have been removed.
+ *
+ * The subplans are given as a List so that the node definition need not
+ * change if there's ever more than two alternatives. For the moment,
+ * though, there are always exactly two; and the first one is the fast-start
+ * plan.
+ */
+typedef struct AlternativeSubPlan
+{
+ pg_node_attr(no_query_jumble)
+
+ Expr xpr;
+ List *subplans; /* SubPlan(s) with equivalent results */
+} AlternativeSubPlan;
+
+/* ----------------
+ * FieldSelect
+ *
+ * FieldSelect represents the operation of extracting one field from a tuple
+ * value. At runtime, the input expression is expected to yield a rowtype
+ * Datum. The specified field number is extracted and returned as a Datum.
+ * ----------------
+ */
+
+typedef struct FieldSelect
+{
+ Expr xpr;
+ Expr *arg; /* input expression */
+ AttrNumber fieldnum; /* attribute number of field to extract */
+ /* type of the field (result type of this node) */
+ Oid resulttype pg_node_attr(query_jumble_ignore);
+ /* output typmod (usually -1) */
+ int32 resulttypmod pg_node_attr(query_jumble_ignore);
+ /* OID of collation of the field */
+ Oid resultcollid pg_node_attr(query_jumble_ignore);
+} FieldSelect;
+
+/* ----------------
+ * FieldStore
+ *
+ * FieldStore represents the operation of modifying one field in a tuple
+ * value, yielding a new tuple value (the input is not touched!). Like
+ * the assign case of SubscriptingRef, this is used to implement UPDATE of a
+ * portion of a column.
+ *
+ * resulttype is always a named composite type (not a domain). To update
+ * a composite domain value, apply CoerceToDomain to the FieldStore.
+ *
+ * A single FieldStore can actually represent updates of several different
+ * fields. The parser only generates FieldStores with single-element lists,
+ * but the planner will collapse multiple updates of the same base column
+ * into one FieldStore.
+ * ----------------
+ */
+
+typedef struct FieldStore
+{
+ Expr xpr;
+ Expr *arg; /* input tuple value */
+ List *newvals; /* new value(s) for field(s) */
+ /* integer list of field attnums */
+ List *fieldnums pg_node_attr(query_jumble_ignore);
+ /* type of result (same as type of arg) */
+ Oid resulttype pg_node_attr(query_jumble_ignore);
+ /* Like RowExpr, we deliberately omit a typmod and collation here */
+} FieldStore;
+
+/* ----------------
+ * RelabelType
+ *
+ * RelabelType represents a "dummy" type coercion between two binary-
+ * compatible datatypes, such as reinterpreting the result of an OID
+ * expression as an int4. It is a no-op at runtime; we only need it
+ * to provide a place to store the correct type to be attributed to
+ * the expression result during type resolution. (We can't get away
+ * with just overwriting the type field of the input expression node,
+ * so we need a separate node to show the coercion's result type.)
+ * ----------------
+ */
+
+typedef struct RelabelType
+{
+ Expr xpr;
+ Expr *arg; /* input expression */
+ Oid resulttype; /* output type of coercion expression */
+ /* output typmod (usually -1) */
+ int32 resulttypmod pg_node_attr(query_jumble_ignore);
+ /* OID of collation, or InvalidOid if none */
+ Oid resultcollid pg_node_attr(query_jumble_ignore);
+ /* how to display this node */
+ CoercionForm relabelformat pg_node_attr(query_jumble_ignore);
+ int location; /* token location, or -1 if unknown */
+} RelabelType;
+
+/* ----------------
+ * CoerceViaIO
+ *
+ * CoerceViaIO represents a type coercion between two types whose textual
+ * representations are compatible, implemented by invoking the source type's
+ * typoutput function then the destination type's typinput function.
+ * ----------------
+ */
+
+typedef struct CoerceViaIO
+{
+ Expr xpr;
+ Expr *arg; /* input expression */
+ Oid resulttype; /* output type of coercion */
+ /* output typmod is not stored, but is presumed -1 */
+ /* OID of collation, or InvalidOid if none */
+ Oid resultcollid pg_node_attr(query_jumble_ignore);
+ /* how to display this node */
+ CoercionForm coerceformat pg_node_attr(query_jumble_ignore);
+ int location; /* token location, or -1 if unknown */
+} CoerceViaIO;
+
+/* ----------------
+ * ArrayCoerceExpr
+ *
+ * ArrayCoerceExpr represents a type coercion from one array type to another,
+ * which is implemented by applying the per-element coercion expression
+ * "elemexpr" to each element of the source array. Within elemexpr, the
+ * source element is represented by a CaseTestExpr node. Note that even if
+ * elemexpr is a no-op (that is, just CaseTestExpr + RelabelType), the
+ * coercion still requires some effort: we have to fix the element type OID
+ * stored in the array header.
+ * ----------------
+ */
+
+typedef struct ArrayCoerceExpr
+{
+ Expr xpr;
+ Expr *arg; /* input expression (yields an array) */
+ Expr *elemexpr; /* expression representing per-element work */
+ Oid resulttype; /* output type of coercion (an array type) */
+ /* output typmod (also element typmod) */
+ int32 resulttypmod pg_node_attr(query_jumble_ignore);
+ /* OID of collation, or InvalidOid if none */
+ Oid resultcollid pg_node_attr(query_jumble_ignore);
+ /* how to display this node */
+ CoercionForm coerceformat pg_node_attr(query_jumble_ignore);
+ int location; /* token location, or -1 if unknown */
+} ArrayCoerceExpr;
+
+/* ----------------
+ * ConvertRowtypeExpr
+ *
+ * ConvertRowtypeExpr represents a type coercion from one composite type
+ * to another, where the source type is guaranteed to contain all the columns
+ * needed for the destination type plus possibly others; the columns need not
+ * be in the same positions, but are matched up by name. This is primarily
+ * used to convert a whole-row value of an inheritance child table into a
+ * valid whole-row value of its parent table's rowtype. Both resulttype
+ * and the exposed type of "arg" must be named composite types (not domains).
+ * ----------------
+ */
+
+typedef struct ConvertRowtypeExpr
+{
+ Expr xpr;
+ Expr *arg; /* input expression */
+ Oid resulttype; /* output type (always a composite type) */
+ /* Like RowExpr, we deliberately omit a typmod and collation here */
+ /* how to display this node */
+ CoercionForm convertformat pg_node_attr(query_jumble_ignore);
+ int location; /* token location, or -1 if unknown */
+} ConvertRowtypeExpr;
+
+/*----------
+ * CollateExpr - COLLATE
+ *
+ * The planner replaces CollateExpr with RelabelType during expression
+ * preprocessing, so execution never sees a CollateExpr.
+ *----------
+ */
+typedef struct CollateExpr
+{
+ Expr xpr;
+ Expr *arg; /* input expression */
+ Oid collOid; /* collation's OID */
+ int location; /* token location, or -1 if unknown */
+} CollateExpr;
+
+/*----------
+ * CaseExpr - a CASE expression
+ *
+ * We support two distinct forms of CASE expression:
+ * CASE WHEN boolexpr THEN expr [ WHEN boolexpr THEN expr ... ]
+ * CASE testexpr WHEN compexpr THEN expr [ WHEN compexpr THEN expr ... ]
+ * These are distinguishable by the "arg" field being NULL in the first case
+ * and the testexpr in the second case.
+ *
+ * In the raw grammar output for the second form, the condition expressions
+ * of the WHEN clauses are just the comparison values. Parse analysis
+ * converts these to valid boolean expressions of the form
+ * CaseTestExpr '=' compexpr
+ * where the CaseTestExpr node is a placeholder that emits the correct
+ * value at runtime. This structure is used so that the testexpr need be
+ * evaluated only once. Note that after parse analysis, the condition
+ * expressions always yield boolean.
+ *
+ * Note: we can test whether a CaseExpr has been through parse analysis
+ * yet by checking whether casetype is InvalidOid or not.
+ *----------
+ */
+typedef struct CaseExpr
+{
+ Expr xpr;
+ /* type of expression result */
+ Oid casetype pg_node_attr(query_jumble_ignore);
+ /* OID of collation, or InvalidOid if none */
+ Oid casecollid pg_node_attr(query_jumble_ignore);
+ Expr *arg; /* implicit equality comparison argument */
+ List *args; /* the arguments (list of WHEN clauses) */
+ Expr *defresult; /* the default result (ELSE clause) */
+ int location; /* token location, or -1 if unknown */
+} CaseExpr;
+
+/*
+ * CaseWhen - one arm of a CASE expression
+ */
+typedef struct CaseWhen
+{
+ Expr xpr;
+ Expr *expr; /* condition expression */
+ Expr *result; /* substitution result */
+ int location; /* token location, or -1 if unknown */
+} CaseWhen;
+
+/*
+ * Placeholder node for the test value to be processed by a CASE expression.
+ * This is effectively like a Param, but can be implemented more simply
+ * since we need only one replacement value at a time.
+ *
+ * We also abuse this node type for some other purposes, including:
+ * * Placeholder for the current array element value in ArrayCoerceExpr;
+ * see build_coercion_expression().
+ * * Nested FieldStore/SubscriptingRef assignment expressions in INSERT/UPDATE;
+ * see transformAssignmentIndirection().
+ * * Placeholder for intermediate results in some SQL/JSON expression nodes,
+ * such as JsonConstructorExpr.
+ *
+ * The uses in CaseExpr and ArrayCoerceExpr are safe only to the extent that
+ * there is not any other CaseExpr or ArrayCoerceExpr between the value source
+ * node and its child CaseTestExpr(s). This is true in the parse analysis
+ * output, but the planner's function-inlining logic has to be careful not to
+ * break it.
+ *
+ * The nested-assignment-expression case is safe because the only node types
+ * that can be above such CaseTestExprs are FieldStore and SubscriptingRef.
+ */
+typedef struct CaseTestExpr
+{
+ Expr xpr;
+ Oid typeId; /* type for substituted value */
+ /* typemod for substituted value */
+ int32 typeMod pg_node_attr(query_jumble_ignore);
+ /* collation for the substituted value */
+ Oid collation pg_node_attr(query_jumble_ignore);
+} CaseTestExpr;
+
+/*
+ * ArrayExpr - an ARRAY[] expression
+ *
+ * Note: if multidims is false, the constituent expressions all yield the
+ * scalar type identified by element_typeid. If multidims is true, the
+ * constituent expressions all yield arrays of element_typeid (ie, the same
+ * type as array_typeid); at runtime we must check for compatible subscripts.
+ */
+typedef struct ArrayExpr
+{
+ Expr xpr;
+ /* type of expression result */
+ Oid array_typeid pg_node_attr(query_jumble_ignore);
+ /* OID of collation, or InvalidOid if none */
+ Oid array_collid pg_node_attr(query_jumble_ignore);
+ /* common type of array elements */
+ Oid element_typeid pg_node_attr(query_jumble_ignore);
+ /* the array elements or sub-arrays */
+ List *elements;
+ /* true if elements are sub-arrays */
+ bool multidims pg_node_attr(query_jumble_ignore);
+ /* token location, or -1 if unknown */
+ int location;
+} ArrayExpr;
+
+/*
+ * RowExpr - a ROW() expression
+ *
+ * Note: the list of fields must have a one-for-one correspondence with
+ * physical fields of the associated rowtype, although it is okay for it
+ * to be shorter than the rowtype. That is, the N'th list element must
+ * match up with the N'th physical field. When the N'th physical field
+ * is a dropped column (attisdropped) then the N'th list element can just
+ * be a NULL constant. (This case can only occur for named composite types,
+ * not RECORD types, since those are built from the RowExpr itself rather
+ * than vice versa.) It is important not to assume that length(args) is
+ * the same as the number of columns logically present in the rowtype.
+ *
+ * colnames provides field names if the ROW() result is of type RECORD.
+ * Names *must* be provided if row_typeid is RECORDOID; but if it is a
+ * named composite type, colnames will be ignored in favor of using the
+ * type's cataloged field names, so colnames should be NIL. Like the
+ * args list, colnames is defined to be one-for-one with physical fields
+ * of the rowtype (although dropped columns shouldn't appear in the
+ * RECORD case, so this fine point is currently moot).
+ */
+typedef struct RowExpr
+{
+ Expr xpr;
+ List *args; /* the fields */
+
+ /* RECORDOID or a composite type's ID */
+ Oid row_typeid pg_node_attr(query_jumble_ignore);
+
+ /*
+ * row_typeid cannot be a domain over composite, only plain composite. To
+ * create a composite domain value, apply CoerceToDomain to the RowExpr.
+ *
+ * Note: we deliberately do NOT store a typmod. Although a typmod will be
+ * associated with specific RECORD types at runtime, it will differ for
+ * different backends, and so cannot safely be stored in stored
+ * parsetrees. We must assume typmod -1 for a RowExpr node.
+ *
+ * We don't need to store a collation either. The result type is
+ * necessarily composite, and composite types never have a collation.
+ */
+
+ /* how to display this node */
+ CoercionForm row_format pg_node_attr(query_jumble_ignore);
+
+ /* list of String, or NIL */
+ List *colnames pg_node_attr(query_jumble_ignore);
+
+ int location; /* token location, or -1 if unknown */
+} RowExpr;
+
+/*
+ * RowCompareExpr - row-wise comparison, such as (a, b) <= (1, 2)
+ *
+ * We support row comparison for any operator that can be determined to
+ * act like =, <>, <, <=, >, or >= (we determine this by looking for the
+ * operator in btree opfamilies). Note that the same operator name might
+ * map to a different operator for each pair of row elements, since the
+ * element datatypes can vary.
+ *
+ * A RowCompareExpr node is only generated for the < <= > >= cases;
+ * the = and <> cases are translated to simple AND or OR combinations
+ * of the pairwise comparisons. However, we include = and <> in the
+ * RowCompareType enum for the convenience of parser logic.
+ */
+typedef enum RowCompareType
+{
+ /* Values of this enum are chosen to match btree strategy numbers */
+ ROWCOMPARE_LT = 1, /* BTLessStrategyNumber */
+ ROWCOMPARE_LE = 2, /* BTLessEqualStrategyNumber */
+ ROWCOMPARE_EQ = 3, /* BTEqualStrategyNumber */
+ ROWCOMPARE_GE = 4, /* BTGreaterEqualStrategyNumber */
+ ROWCOMPARE_GT = 5, /* BTGreaterStrategyNumber */
+ ROWCOMPARE_NE = 6 /* no such btree strategy */
+} RowCompareType;
+
+typedef struct RowCompareExpr
+{
+ Expr xpr;
+
+ /* LT LE GE or GT, never EQ or NE */
+ RowCompareType rctype;
+ /* OID list of pairwise comparison ops */
+ List *opnos pg_node_attr(query_jumble_ignore);
+ /* OID list of containing operator families */
+ List *opfamilies pg_node_attr(query_jumble_ignore);
+ /* OID list of collations for comparisons */
+ List *inputcollids pg_node_attr(query_jumble_ignore);
+ /* the left-hand input arguments */
+ List *largs;
+ /* the right-hand input arguments */
+ List *rargs;
+} RowCompareExpr;
+
+/*
+ * CoalesceExpr - a COALESCE expression
+ */
+typedef struct CoalesceExpr
+{
+ Expr xpr;
+ /* type of expression result */
+ Oid coalescetype pg_node_attr(query_jumble_ignore);
+ /* OID of collation, or InvalidOid if none */
+ Oid coalescecollid pg_node_attr(query_jumble_ignore);
+ /* the arguments */
+ List *args;
+ /* token location, or -1 if unknown */
+ int location;
+} CoalesceExpr;
+
+/*
+ * MinMaxExpr - a GREATEST or LEAST function
+ */
+typedef enum MinMaxOp
+{
+ IS_GREATEST,
+ IS_LEAST
+} MinMaxOp;
+
+typedef struct MinMaxExpr
+{
+ Expr xpr;
+ /* common type of arguments and result */
+ Oid minmaxtype pg_node_attr(query_jumble_ignore);
+ /* OID of collation of result */
+ Oid minmaxcollid pg_node_attr(query_jumble_ignore);
+ /* OID of collation that function should use */
+ Oid inputcollid pg_node_attr(query_jumble_ignore);
+ /* function to execute */
+ MinMaxOp op;
+ /* the arguments */
+ List *args;
+ /* token location, or -1 if unknown */
+ int location;
+} MinMaxExpr;
+
+/*
+ * SQLValueFunction - parameterless functions with special grammar productions
+ *
+ * The SQL standard categorizes some of these as <datetime value function>
+ * and others as <general value specification>. We call 'em SQLValueFunctions
+ * for lack of a better term. We store type and typmod of the result so that
+ * some code doesn't need to know each function individually, and because
+ * we would need to store typmod anyway for some of the datetime functions.
+ * Note that currently, all variants return non-collating datatypes, so we do
+ * not need a collation field; also, all these functions are stable.
+ */
+typedef enum SQLValueFunctionOp
+{
+ SVFOP_CURRENT_DATE,
+ SVFOP_CURRENT_TIME,
+ SVFOP_CURRENT_TIME_N,
+ SVFOP_CURRENT_TIMESTAMP,
+ SVFOP_CURRENT_TIMESTAMP_N,
+ SVFOP_LOCALTIME,
+ SVFOP_LOCALTIME_N,
+ SVFOP_LOCALTIMESTAMP,
+ SVFOP_LOCALTIMESTAMP_N,
+ SVFOP_CURRENT_ROLE,
+ SVFOP_CURRENT_USER,
+ SVFOP_USER,
+ SVFOP_SESSION_USER,
+ SVFOP_CURRENT_CATALOG,
+ SVFOP_CURRENT_SCHEMA
+} SQLValueFunctionOp;
+
+typedef struct SQLValueFunction
+{
+ Expr xpr;
+ SQLValueFunctionOp op; /* which function this is */
+
+ /*
+ * Result type/typmod. Type is fully determined by "op", so no need to
+ * include this Oid in the query jumbling.
+ */
+ Oid type pg_node_attr(query_jumble_ignore);
+ int32 typmod;
+ int location; /* token location, or -1 if unknown */
+} SQLValueFunction;
+
+/*
+ * XmlExpr - various SQL/XML functions requiring special grammar productions
+ *
+ * 'name' carries the "NAME foo" argument (already XML-escaped).
+ * 'named_args' and 'arg_names' represent an xml_attribute list.
+ * 'args' carries all other arguments.
+ *
+ * Note: result type/typmod/collation are not stored, but can be deduced
+ * from the XmlExprOp. The type/typmod fields are just used for display
+ * purposes, and are NOT necessarily the true result type of the node.
+ */
+typedef enum XmlExprOp
+{
+ IS_XMLCONCAT, /* XMLCONCAT(args) */
+ IS_XMLELEMENT, /* XMLELEMENT(name, xml_attributes, args) */
+ IS_XMLFOREST, /* XMLFOREST(xml_attributes) */
+ IS_XMLPARSE, /* XMLPARSE(text, is_doc, preserve_ws) */
+ IS_XMLPI, /* XMLPI(name [, args]) */
+ IS_XMLROOT, /* XMLROOT(xml, version, standalone) */
+ IS_XMLSERIALIZE, /* XMLSERIALIZE(is_document, xmlval, indent) */
+ IS_DOCUMENT /* xmlval IS DOCUMENT */
+} XmlExprOp;
+
+typedef enum XmlOptionType
+{
+ XMLOPTION_DOCUMENT,
+ XMLOPTION_CONTENT
+} XmlOptionType;
+
+typedef struct XmlExpr
+{
+ Expr xpr;
+ /* xml function ID */
+ XmlExprOp op;
+ /* name in xml(NAME foo ...) syntaxes */
+ char *name pg_node_attr(query_jumble_ignore);
+ /* non-XML expressions for xml_attributes */
+ List *named_args;
+ /* parallel list of String values */
+ List *arg_names pg_node_attr(query_jumble_ignore);
+ /* list of expressions */
+ List *args;
+ /* DOCUMENT or CONTENT */
+ XmlOptionType xmloption pg_node_attr(query_jumble_ignore);
+ /* INDENT option for XMLSERIALIZE */
+ bool indent;
+ /* target type/typmod for XMLSERIALIZE */
+ Oid type pg_node_attr(query_jumble_ignore);
+ int32 typmod pg_node_attr(query_jumble_ignore);
+ /* token location, or -1 if unknown */
+ int location;
+} XmlExpr;
+
+/*
+ * JsonEncoding -
+ * representation of JSON ENCODING clause
+ */
+typedef enum JsonEncoding
+{
+ JS_ENC_DEFAULT, /* unspecified */
+ JS_ENC_UTF8,
+ JS_ENC_UTF16,
+ JS_ENC_UTF32,
+} JsonEncoding;
+
+/*
+ * JsonFormatType -
+ * enumeration of JSON formats used in JSON FORMAT clause
+ */
+typedef enum JsonFormatType
+{
+ JS_FORMAT_DEFAULT, /* unspecified */
+ JS_FORMAT_JSON, /* FORMAT JSON [ENCODING ...] */
+ JS_FORMAT_JSONB /* implicit internal format for RETURNING
+ * jsonb */
+} JsonFormatType;
+
+/*
+ * JsonFormat -
+ * representation of JSON FORMAT clause
+ */
+typedef struct JsonFormat
+{
+ NodeTag type;
+ JsonFormatType format_type; /* format type */
+ JsonEncoding encoding; /* JSON encoding */
+ int location; /* token location, or -1 if unknown */
+} JsonFormat;
+
+/*
+ * JsonReturning -
+ * transformed representation of JSON RETURNING clause
+ */
+typedef struct JsonReturning
+{
+ NodeTag type;
+ JsonFormat *format; /* output JSON format */
+ Oid typid; /* target type Oid */
+ int32 typmod; /* target type modifier */
+} JsonReturning;
+
+/*
+ * JsonValueExpr -
+ * representation of JSON value expression (expr [FORMAT JsonFormat])
+ *
+ * The actual value is obtained by evaluating formatted_expr. raw_expr is
+ * only there for displaying the original user-written expression and is not
+ * evaluated by ExecInterpExpr() and eval_const_exprs_mutator().
+ */
+typedef struct JsonValueExpr
+{
+ NodeTag type;
+ Expr *raw_expr; /* raw expression */
+ Expr *formatted_expr; /* formatted expression */
+ JsonFormat *format; /* FORMAT clause, if specified */
+} JsonValueExpr;
+
+typedef enum JsonConstructorType
+{
+ JSCTOR_JSON_OBJECT = 1,
+ JSCTOR_JSON_ARRAY = 2,
+ JSCTOR_JSON_OBJECTAGG = 3,
+ JSCTOR_JSON_ARRAYAGG = 4
+} JsonConstructorType;
+
+/*
+ * JsonConstructorExpr -
+ * wrapper over FuncExpr/Aggref/WindowFunc for SQL/JSON constructors
+ */
+typedef struct JsonConstructorExpr
+{
+ Expr xpr;
+ JsonConstructorType type; /* constructor type */
+ List *args;
+ Expr *func; /* underlying json[b]_xxx() function call */
+ Expr *coercion; /* coercion to RETURNING type */
+ JsonReturning *returning; /* RETURNING clause */
+ bool absent_on_null; /* ABSENT ON NULL? */
+ bool unique; /* WITH UNIQUE KEYS? (JSON_OBJECT[AGG] only) */
+ int location;
+} JsonConstructorExpr;
+
+/*
+ * JsonValueType -
+ * representation of JSON item type in IS JSON predicate
+ */
+typedef enum JsonValueType
+{
+ JS_TYPE_ANY, /* IS JSON [VALUE] */
+ JS_TYPE_OBJECT, /* IS JSON OBJECT */
+ JS_TYPE_ARRAY, /* IS JSON ARRAY */
+ JS_TYPE_SCALAR /* IS JSON SCALAR */
+} JsonValueType;
+
+/*
+ * JsonIsPredicate -
+ * representation of IS JSON predicate
+ */
+typedef struct JsonIsPredicate
+{
+ NodeTag type;
+ Node *expr; /* subject expression */
+ JsonFormat *format; /* FORMAT clause, if specified */
+ JsonValueType item_type; /* JSON item type */
+ bool unique_keys; /* check key uniqueness? */
+ int location; /* token location, or -1 if unknown */
+} JsonIsPredicate;
+
+/* ----------------
+ * NullTest
+ *
+ * NullTest represents the operation of testing a value for NULLness.
+ * The appropriate test is performed and returned as a boolean Datum.
+ *
+ * When argisrow is false, this simply represents a test for the null value.
+ *
+ * When argisrow is true, the input expression must yield a rowtype, and
+ * the node implements "row IS [NOT] NULL" per the SQL standard. This
+ * includes checking individual fields for NULLness when the row datum
+ * itself isn't NULL.
+ *
+ * NOTE: the combination of a rowtype input and argisrow==false does NOT
+ * correspond to the SQL notation "row IS [NOT] NULL"; instead, this case
+ * represents the SQL notation "row IS [NOT] DISTINCT FROM NULL".
+ * ----------------
+ */
+
+typedef enum NullTestType
+{
+ IS_NULL, IS_NOT_NULL
+} NullTestType;
+
+typedef struct NullTest
+{
+ Expr xpr;
+ Expr *arg; /* input expression */
+ NullTestType nulltesttype; /* IS NULL, IS NOT NULL */
+ /* T to perform field-by-field null checks */
+ bool argisrow pg_node_attr(query_jumble_ignore);
+ int location; /* token location, or -1 if unknown */
+} NullTest;
+
+/*
+ * BooleanTest
+ *
+ * BooleanTest represents the operation of determining whether a boolean
+ * is TRUE, FALSE, or UNKNOWN (ie, NULL). All six meaningful combinations
+ * are supported. Note that a NULL input does *not* cause a NULL result.
+ * The appropriate test is performed and returned as a boolean Datum.
+ */
+
+typedef enum BoolTestType
+{
+ IS_TRUE, IS_NOT_TRUE, IS_FALSE, IS_NOT_FALSE, IS_UNKNOWN, IS_NOT_UNKNOWN
+} BoolTestType;
+
+typedef struct BooleanTest
+{
+ Expr xpr;
+ Expr *arg; /* input expression */
+ BoolTestType booltesttype; /* test type */
+ int location; /* token location, or -1 if unknown */
+} BooleanTest;
+
+/*
+ * CoerceToDomain
+ *
+ * CoerceToDomain represents the operation of coercing a value to a domain
+ * type. At runtime (and not before) the precise set of constraints to be
+ * checked will be determined. If the value passes, it is returned as the
+ * result; if not, an error is raised. Note that this is equivalent to
+ * RelabelType in the scenario where no constraints are applied.
+ */
+typedef struct CoerceToDomain
+{
+ Expr xpr;
+ Expr *arg; /* input expression */
+ Oid resulttype; /* domain type ID (result type) */
+ /* output typmod (currently always -1) */
+ int32 resulttypmod pg_node_attr(query_jumble_ignore);
+ /* OID of collation, or InvalidOid if none */
+ Oid resultcollid pg_node_attr(query_jumble_ignore);
+ /* how to display this node */
+ CoercionForm coercionformat pg_node_attr(query_jumble_ignore);
+ int location; /* token location, or -1 if unknown */
+} CoerceToDomain;
+
+/*
+ * Placeholder node for the value to be processed by a domain's check
+ * constraint. This is effectively like a Param, but can be implemented more
+ * simply since we need only one replacement value at a time.
+ *
+ * Note: the typeId/typeMod/collation will be set from the domain's base type,
+ * not the domain itself. This is because we shouldn't consider the value
+ * to be a member of the domain if we haven't yet checked its constraints.
+ */
+typedef struct CoerceToDomainValue
+{
+ Expr xpr;
+ /* type for substituted value */
+ Oid typeId;
+ /* typemod for substituted value */
+ int32 typeMod pg_node_attr(query_jumble_ignore);
+ /* collation for the substituted value */
+ Oid collation pg_node_attr(query_jumble_ignore);
+ /* token location, or -1 if unknown */
+ int location;
+} CoerceToDomainValue;
+
+/*
+ * Placeholder node for a DEFAULT marker in an INSERT or UPDATE command.
+ *
+ * This is not an executable expression: it must be replaced by the actual
+ * column default expression during rewriting. But it is convenient to
+ * treat it as an expression node during parsing and rewriting.
+ */
+typedef struct SetToDefault
+{
+ Expr xpr;
+ /* type for substituted value */
+ Oid typeId;
+ /* typemod for substituted value */
+ int32 typeMod pg_node_attr(query_jumble_ignore);
+ /* collation for the substituted value */
+ Oid collation pg_node_attr(query_jumble_ignore);
+ /* token location, or -1 if unknown */
+ int location;
+} SetToDefault;
+
+/*
+ * Node representing [WHERE] CURRENT OF cursor_name
+ *
+ * CURRENT OF is a bit like a Var, in that it carries the rangetable index
+ * of the target relation being constrained; this aids placing the expression
+ * correctly during planning. We can assume however that its "levelsup" is
+ * always zero, due to the syntactic constraints on where it can appear.
+ * Also, cvarno will always be a true RT index, never INNER_VAR etc.
+ *
+ * The referenced cursor can be represented either as a hardwired string
+ * or as a reference to a run-time parameter of type REFCURSOR. The latter
+ * case is for the convenience of plpgsql.
+ */
+typedef struct CurrentOfExpr
+{
+ Expr xpr;
+ Index cvarno; /* RT index of target relation */
+ char *cursor_name; /* name of referenced cursor, or NULL */
+ int cursor_param; /* refcursor parameter number, or 0 */
+} CurrentOfExpr;
+
+/*
+ * NextValueExpr - get next value from sequence
+ *
+ * This has the same effect as calling the nextval() function, but it does not
+ * check permissions on the sequence. This is used for identity columns,
+ * where the sequence is an implicit dependency without its own permissions.
+ */
+typedef struct NextValueExpr
+{
+ Expr xpr;
+ Oid seqid;
+ Oid typeId;
+} NextValueExpr;
+
+/*
+ * InferenceElem - an element of a unique index inference specification
+ *
+ * This mostly matches the structure of IndexElems, but having a dedicated
+ * primnode allows for a clean separation between the use of index parameters
+ * by utility commands, and this node.
+ */
+typedef struct InferenceElem
+{
+ Expr xpr;
+ Node *expr; /* expression to infer from, or NULL */
+ Oid infercollid; /* OID of collation, or InvalidOid */
+ Oid inferopclass; /* OID of att opclass, or InvalidOid */
+} InferenceElem;
+
+/*--------------------
+ * TargetEntry -
+ * a target entry (used in query target lists)
+ *
+ * Strictly speaking, a TargetEntry isn't an expression node (since it can't
+ * be evaluated by ExecEvalExpr). But we treat it as one anyway, since in
+ * very many places it's convenient to process a whole query targetlist as a
+ * single expression tree.
+ *
+ * In a SELECT's targetlist, resno should always be equal to the item's
+ * ordinal position (counting from 1). However, in an INSERT or UPDATE
+ * targetlist, resno represents the attribute number of the destination
+ * column for the item; so there may be missing or out-of-order resnos.
+ * It is even legal to have duplicated resnos; consider
+ * UPDATE table SET arraycol[1] = ..., arraycol[2] = ..., ...
+ * In an INSERT, the rewriter and planner will normalize the tlist by
+ * reordering it into physical column order and filling in default values
+ * for any columns not assigned values by the original query. In an UPDATE,
+ * after the rewriter merges multiple assignments for the same column, the
+ * planner extracts the target-column numbers into a separate "update_colnos"
+ * list, and then renumbers the tlist elements serially. Thus, tlist resnos
+ * match ordinal position in all tlists seen by the executor; but it is wrong
+ * to assume that before planning has happened.
+ *
+ * resname is required to represent the correct column name in non-resjunk
+ * entries of top-level SELECT targetlists, since it will be used as the
+ * column title sent to the frontend. In most other contexts it is only
+ * a debugging aid, and may be wrong or even NULL. (In particular, it may
+ * be wrong in a tlist from a stored rule, if the referenced column has been
+ * renamed by ALTER TABLE since the rule was made. Also, the planner tends
+ * to store NULL rather than look up a valid name for tlist entries in
+ * non-toplevel plan nodes.) In resjunk entries, resname should be either
+ * a specific system-generated name (such as "ctid") or NULL; anything else
+ * risks confusing ExecGetJunkAttribute!
+ *
+ * ressortgroupref is used in the representation of ORDER BY, GROUP BY, and
+ * DISTINCT items. Targetlist entries with ressortgroupref=0 are not
+ * sort/group items. If ressortgroupref>0, then this item is an ORDER BY,
+ * GROUP BY, and/or DISTINCT target value. No two entries in a targetlist
+ * may have the same nonzero ressortgroupref --- but there is no particular
+ * meaning to the nonzero values, except as tags. (For example, one must
+ * not assume that lower ressortgroupref means a more significant sort key.)
+ * The order of the associated SortGroupClause lists determine the semantics.
+ *
+ * resorigtbl/resorigcol identify the source of the column, if it is a
+ * simple reference to a column of a base table (or view). If it is not
+ * a simple reference, these fields are zeroes.
+ *
+ * If resjunk is true then the column is a working column (such as a sort key)
+ * that should be removed from the final output of the query. Resjunk columns
+ * must have resnos that cannot duplicate any regular column's resno. Also
+ * note that there are places that assume resjunk columns come after non-junk
+ * columns.
+ *--------------------
+ */
+typedef struct TargetEntry
+{
+ Expr xpr;
+ /* expression to evaluate */
+ Expr *expr;
+ /* attribute number (see notes above) */
+ AttrNumber resno;
+ /* name of the column (could be NULL) */
+ char *resname pg_node_attr(query_jumble_ignore);
+ /* nonzero if referenced by a sort/group clause */
+ Index ressortgroupref;
+ /* OID of column's source table */
+ Oid resorigtbl pg_node_attr(query_jumble_ignore);
+ /* column's number in source table */
+ AttrNumber resorigcol pg_node_attr(query_jumble_ignore);
+ /* set to true to eliminate the attribute from final target list */
+ bool resjunk pg_node_attr(query_jumble_ignore);
+} TargetEntry;
+
+
+/* ----------------------------------------------------------------
+ * node types for join trees
+ *
+ * The leaves of a join tree structure are RangeTblRef nodes. Above
+ * these, JoinExpr nodes can appear to denote a specific kind of join
+ * or qualified join. Also, FromExpr nodes can appear to denote an
+ * ordinary cross-product join ("FROM foo, bar, baz WHERE ...").
+ * FromExpr is like a JoinExpr of jointype JOIN_INNER, except that it
+ * may have any number of child nodes, not just two.
+ *
+ * NOTE: the top level of a Query's jointree is always a FromExpr.
+ * Even if the jointree contains no rels, there will be a FromExpr.
+ *
+ * NOTE: the qualification expressions present in JoinExpr nodes are
+ * *in addition to* the query's main WHERE clause, which appears as the
+ * qual of the top-level FromExpr. The reason for associating quals with
+ * specific nodes in the jointree is that the position of a qual is critical
+ * when outer joins are present. (If we enforce a qual too soon or too late,
+ * that may cause the outer join to produce the wrong set of NULL-extended
+ * rows.) If all joins are inner joins then all the qual positions are
+ * semantically interchangeable.
+ *
+ * NOTE: in the raw output of gram.y, a join tree contains RangeVar,
+ * RangeSubselect, and RangeFunction nodes, which are all replaced by
+ * RangeTblRef nodes during the parse analysis phase. Also, the top-level
+ * FromExpr is added during parse analysis; the grammar regards FROM and
+ * WHERE as separate.
+ * ----------------------------------------------------------------
+ */
+
+/*
+ * RangeTblRef - reference to an entry in the query's rangetable
+ *
+ * We could use direct pointers to the RT entries and skip having these
+ * nodes, but multiple pointers to the same node in a querytree cause
+ * lots of headaches, so it seems better to store an index into the RT.
+ */
+typedef struct RangeTblRef
+{
+ NodeTag type;
+ int rtindex;
+} RangeTblRef;
+
+/*----------
+ * JoinExpr - for SQL JOIN expressions
+ *
+ * isNatural, usingClause, and quals are interdependent. The user can write
+ * only one of NATURAL, USING(), or ON() (this is enforced by the grammar).
+ * If he writes NATURAL then parse analysis generates the equivalent USING()
+ * list, and from that fills in "quals" with the right equality comparisons.
+ * If he writes USING() then "quals" is filled with equality comparisons.
+ * If he writes ON() then only "quals" is set. Note that NATURAL/USING
+ * are not equivalent to ON() since they also affect the output column list.
+ *
+ * alias is an Alias node representing the AS alias-clause attached to the
+ * join expression, or NULL if no clause. NB: presence or absence of the
+ * alias has a critical impact on semantics, because a join with an alias
+ * restricts visibility of the tables/columns inside it.
+ *
+ * join_using_alias is an Alias node representing the join correlation
+ * name that SQL:2016 and later allow to be attached to JOIN/USING.
+ * Its column alias list includes only the common column names from USING,
+ * and it does not restrict visibility of the join's input tables.
+ *
+ * During parse analysis, an RTE is created for the Join, and its index
+ * is filled into rtindex. This RTE is present mainly so that Vars can
+ * be created that refer to the outputs of the join. The planner sometimes
+ * generates JoinExprs internally; these can have rtindex = 0 if there are
+ * no join alias variables referencing such joins.
+ *----------
+ */
+typedef struct JoinExpr
+{
+ NodeTag type;
+ JoinType jointype; /* type of join */
+ bool isNatural; /* Natural join? Will need to shape table */
+ Node *larg; /* left subtree */
+ Node *rarg; /* right subtree */
+ /* USING clause, if any (list of String) */
+ List *usingClause pg_node_attr(query_jumble_ignore);
+ /* alias attached to USING clause, if any */
+ Alias *join_using_alias pg_node_attr(query_jumble_ignore);
+ /* qualifiers on join, if any */
+ Node *quals;
+ /* user-written alias clause, if any */
+ Alias *alias pg_node_attr(query_jumble_ignore);
+ /* RT index assigned for join, or 0 */
+ int rtindex;
+} JoinExpr;
+
+/*----------
+ * FromExpr - represents a FROM ... WHERE ... construct
+ *
+ * This is both more flexible than a JoinExpr (it can have any number of
+ * children, including zero) and less so --- we don't need to deal with
+ * aliases and so on. The output column set is implicitly just the union
+ * of the outputs of the children.
+ *----------
+ */
+typedef struct FromExpr
+{
+ NodeTag type;
+ List *fromlist; /* List of join subtrees */
+ Node *quals; /* qualifiers on join, if any */
+} FromExpr;
+
+/*----------
+ * OnConflictExpr - represents an ON CONFLICT DO ... expression
+ *
+ * The optimizer requires a list of inference elements, and optionally a WHERE
+ * clause to infer a unique index. The unique index (or, occasionally,
+ * indexes) inferred are used to arbitrate whether or not the alternative ON
+ * CONFLICT path is taken.
+ *----------
+ */
+typedef struct OnConflictExpr
+{
+ NodeTag type;
+ OnConflictAction action; /* DO NOTHING or UPDATE? */
+
+ /* Arbiter */
+ List *arbiterElems; /* unique index arbiter list (of
+ * InferenceElem's) */
+ Node *arbiterWhere; /* unique index arbiter WHERE clause */
+ Oid constraint; /* pg_constraint OID for arbiter */
+
+ /* ON CONFLICT UPDATE */
+ List *onConflictSet; /* List of ON CONFLICT SET TargetEntrys */
+ Node *onConflictWhere; /* qualifiers to restrict UPDATE to */
+ int exclRelIndex; /* RT index of 'excluded' relation */
+ List *exclRelTlist; /* tlist of the EXCLUDED pseudo relation */
+} OnConflictExpr;
+
+#endif /* PRIMNODES_H */
diff --git a/src/include/nodes/print.h b/src/include/nodes/print.h
new file mode 100644
index 0000000..3c0473f
--- /dev/null
+++ b/src/include/nodes/print.h
@@ -0,0 +1,34 @@
+/*-------------------------------------------------------------------------
+ *
+ * print.h
+ * definitions for nodes/print.c
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/nodes/print.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PRINT_H
+#define PRINT_H
+
+#include "executor/tuptable.h"
+
+
+#define nodeDisplay(x) pprint(x)
+
+extern void print(const void *obj);
+extern void pprint(const void *obj);
+extern void elog_node_display(int lev, const char *title,
+ const void *obj, bool pretty);
+extern char *format_node_dump(const char *dump);
+extern char *pretty_format_node_dump(const char *dump);
+extern void print_rt(const List *rtable);
+extern void print_expr(const Node *expr, const List *rtable);
+extern void print_pathkeys(const List *pathkeys, const List *rtable);
+extern void print_tl(const List *tlist, const List *rtable);
+extern void print_slot(TupleTableSlot *slot);
+
+#endif /* PRINT_H */
diff --git a/src/include/nodes/queryjumble.h b/src/include/nodes/queryjumble.h
new file mode 100644
index 0000000..7649e09
--- /dev/null
+++ b/src/include/nodes/queryjumble.h
@@ -0,0 +1,86 @@
+/*-------------------------------------------------------------------------
+ *
+ * queryjumble.h
+ * Query normalization and fingerprinting.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/include/nodes/queryjumble.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef QUERYJUMBLE_H
+#define QUERYJUMBLE_H
+
+#include "nodes/parsenodes.h"
+
+/*
+ * Struct for tracking locations/lengths of constants during normalization
+ */
+typedef struct LocationLen
+{
+ int location; /* start offset in query text */
+ int length; /* length in bytes, or -1 to ignore */
+} LocationLen;
+
+/*
+ * Working state for computing a query jumble and producing a normalized
+ * query string
+ */
+typedef struct JumbleState
+{
+ /* Jumble of current query tree */
+ unsigned char *jumble;
+
+ /* Number of bytes used in jumble[] */
+ Size jumble_len;
+
+ /* Array of locations of constants that should be removed */
+ LocationLen *clocations;
+
+ /* Allocated length of clocations array */
+ int clocations_buf_size;
+
+ /* Current number of valid entries in clocations array */
+ int clocations_count;
+
+ /* highest Param id we've seen, in order to start normalization correctly */
+ int highest_extern_param_id;
+} JumbleState;
+
+/* Values for the compute_query_id GUC */
+enum ComputeQueryIdType
+{
+ COMPUTE_QUERY_ID_OFF,
+ COMPUTE_QUERY_ID_ON,
+ COMPUTE_QUERY_ID_AUTO,
+ COMPUTE_QUERY_ID_REGRESS
+};
+
+/* GUC parameters */
+extern PGDLLIMPORT int compute_query_id;
+
+
+extern const char *CleanQuerytext(const char *query, int *location, int *len);
+extern JumbleState *JumbleQuery(Query *query);
+extern void EnableQueryId(void);
+
+extern PGDLLIMPORT bool query_id_enabled;
+
+/*
+ * Returns whether query identifier computation has been enabled, either
+ * directly in the GUC or by a module when the setting is 'auto'.
+ */
+static inline bool
+IsQueryIdEnabled(void)
+{
+ if (compute_query_id == COMPUTE_QUERY_ID_OFF)
+ return false;
+ if (compute_query_id == COMPUTE_QUERY_ID_ON)
+ return true;
+ return query_id_enabled;
+}
+
+#endif /* QUERYJUMBLE_H */
diff --git a/src/include/nodes/readfuncs.h b/src/include/nodes/readfuncs.h
new file mode 100644
index 0000000..cba6f0b
--- /dev/null
+++ b/src/include/nodes/readfuncs.h
@@ -0,0 +1,38 @@
+/*-------------------------------------------------------------------------
+ *
+ * readfuncs.h
+ * header file for read.c and readfuncs.c. These functions are internal
+ * to the stringToNode interface and should not be used by anyone else.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/nodes/readfuncs.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef READFUNCS_H
+#define READFUNCS_H
+
+#include "nodes/nodes.h"
+
+/*
+ * variable in read.c that needs to be accessible to readfuncs.c
+ */
+#ifdef WRITE_READ_PARSE_PLAN_TREES
+extern PGDLLIMPORT bool restore_location_fields;
+#endif
+
+/*
+ * prototypes for functions in read.c (the lisp token parser)
+ */
+extern const char *pg_strtok(int *length);
+extern char *debackslash(const char *token, int length);
+extern void *nodeRead(const char *token, int tok_len);
+
+/*
+ * prototypes for functions in readfuncs.c
+ */
+extern Node *parseNodeString(void);
+
+#endif /* READFUNCS_H */
diff --git a/src/include/nodes/replnodes.h b/src/include/nodes/replnodes.h
new file mode 100644
index 0000000..4321ba8
--- /dev/null
+++ b/src/include/nodes/replnodes.h
@@ -0,0 +1,111 @@
+/*-------------------------------------------------------------------------
+ *
+ * replnodes.h
+ * definitions for replication grammar parse nodes
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/nodes/replnodes.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef REPLNODES_H
+#define REPLNODES_H
+
+#include "access/xlogdefs.h"
+#include "nodes/pg_list.h"
+
+typedef enum ReplicationKind
+{
+ REPLICATION_KIND_PHYSICAL,
+ REPLICATION_KIND_LOGICAL
+} ReplicationKind;
+
+
+/* ----------------------
+ * IDENTIFY_SYSTEM command
+ * ----------------------
+ */
+typedef struct IdentifySystemCmd
+{
+ NodeTag type;
+} IdentifySystemCmd;
+
+
+/* ----------------------
+ * BASE_BACKUP command
+ * ----------------------
+ */
+typedef struct BaseBackupCmd
+{
+ NodeTag type;
+ List *options;
+} BaseBackupCmd;
+
+
+/* ----------------------
+ * CREATE_REPLICATION_SLOT command
+ * ----------------------
+ */
+typedef struct CreateReplicationSlotCmd
+{
+ NodeTag type;
+ char *slotname;
+ ReplicationKind kind;
+ char *plugin;
+ bool temporary;
+ List *options;
+} CreateReplicationSlotCmd;
+
+
+/* ----------------------
+ * DROP_REPLICATION_SLOT command
+ * ----------------------
+ */
+typedef struct DropReplicationSlotCmd
+{
+ NodeTag type;
+ char *slotname;
+ bool wait;
+} DropReplicationSlotCmd;
+
+
+/* ----------------------
+ * START_REPLICATION command
+ * ----------------------
+ */
+typedef struct StartReplicationCmd
+{
+ NodeTag type;
+ ReplicationKind kind;
+ char *slotname;
+ TimeLineID timeline;
+ XLogRecPtr startpoint;
+ List *options;
+} StartReplicationCmd;
+
+
+/* ----------------------
+ * READ_REPLICATION_SLOT command
+ * ----------------------
+ */
+typedef struct ReadReplicationSlotCmd
+{
+ NodeTag type;
+ char *slotname;
+} ReadReplicationSlotCmd;
+
+
+/* ----------------------
+ * TIMELINE_HISTORY command
+ * ----------------------
+ */
+typedef struct TimeLineHistoryCmd
+{
+ NodeTag type;
+ TimeLineID timeline;
+} TimeLineHistoryCmd;
+
+#endif /* REPLNODES_H */
diff --git a/src/include/nodes/subscripting.h b/src/include/nodes/subscripting.h
new file mode 100644
index 0000000..02d98f2
--- /dev/null
+++ b/src/include/nodes/subscripting.h
@@ -0,0 +1,167 @@
+/*-------------------------------------------------------------------------
+ *
+ * subscripting.h
+ * API for generic type subscripting
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/nodes/subscripting.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SUBSCRIPTING_H
+#define SUBSCRIPTING_H
+
+#include "nodes/primnodes.h"
+
+/* Forward declarations, to avoid including other headers */
+struct ParseState;
+struct SubscriptingRefState;
+struct SubscriptExecSteps;
+
+/*
+ * The SQL-visible function that defines a subscripting method is declared
+ * subscripting_function(internal) returns internal
+ * but it actually is not passed any parameter. It must return a pointer
+ * to a "struct SubscriptRoutines" that provides pointers to the individual
+ * subscript parsing and execution methods. Typically the pointer will point
+ * to a "static const" variable, but at need it can point to palloc'd space.
+ * The type (after domain-flattening) of the head variable or expression
+ * of a subscripting construct determines which subscripting function is
+ * called for that construct.
+ *
+ * In addition to the method pointers, struct SubscriptRoutines includes
+ * several bool flags that specify properties of the subscripting actions
+ * this data type can perform:
+ *
+ * fetch_strict indicates that a fetch SubscriptRef is strict, i.e., returns
+ * NULL if any input (either the container or any subscript) is NULL.
+ *
+ * fetch_leakproof indicates that a fetch SubscriptRef is leakproof, i.e.,
+ * will not throw any data-value-dependent errors. Typically this requires
+ * silently returning NULL for invalid subscripts.
+ *
+ * store_leakproof similarly indicates whether an assignment SubscriptRef is
+ * leakproof. (It is common to prefer throwing errors for invalid subscripts
+ * in assignments; that's fine, but it makes the operation not leakproof.
+ * In current usage there is no advantage in making assignments leakproof.)
+ *
+ * There is no store_strict flag. Such behavior would generally be
+ * undesirable, since for example a null subscript in an assignment would
+ * cause the entire container to become NULL.
+ *
+ * Regardless of these flags, all SubscriptRefs are expected to be immutable,
+ * that is they must always give the same results for the same inputs.
+ * They are expected to always be parallel-safe, as well.
+ */
+
+/*
+ * The transform method is called during parse analysis of a subscripting
+ * construct. The SubscriptingRef node has been constructed, but some of
+ * its fields still need to be filled in, and the subscript expression(s)
+ * are still in raw form. The transform method is responsible for doing
+ * parse analysis of each subscript expression (using transformExpr),
+ * coercing the subscripts to whatever type it needs, and building the
+ * refupperindexpr and reflowerindexpr lists from those results. The
+ * reflowerindexpr list must be empty for an element operation, or the
+ * same length as refupperindexpr for a slice operation. Insert NULLs
+ * (that is, an empty parse tree, not a null Const node) for any omitted
+ * subscripts in a slice operation. (Of course, if the transform method
+ * does not care to support slicing, it can just throw an error if isSlice.)
+ * See array_subscript_transform() for sample code.
+ *
+ * The transform method is also responsible for identifying the result type
+ * of the subscripting operation. At call, refcontainertype and reftypmod
+ * describe the container type (this will be a base type not a domain), and
+ * refelemtype is set to the container type's pg_type.typelem value. The
+ * transform method must set refrestype and reftypmod to describe the result
+ * of subscripting. For arrays, refrestype is set to refelemtype for an
+ * element operation or refcontainertype for a slice, while reftypmod stays
+ * the same in either case; but other types might use other rules. The
+ * transform method should ignore refcollid, as that's determined later on
+ * during parsing.
+ *
+ * At call, refassgnexpr has not been filled in, so the SubscriptingRef node
+ * always looks like a fetch; refrestype should be set as though for a
+ * fetch, too. (The isAssignment parameter is typically only useful if the
+ * transform method wishes to throw an error for not supporting assignment.)
+ * To complete processing of an assignment, the core parser will coerce the
+ * element/slice source expression to the returned refrestype and reftypmod
+ * before putting it into refassgnexpr. It will then set refrestype and
+ * reftypmod to again describe the container type, since that's what an
+ * assignment must return.
+ */
+typedef void (*SubscriptTransform) (SubscriptingRef *sbsref,
+ List *indirection,
+ struct ParseState *pstate,
+ bool isSlice,
+ bool isAssignment);
+
+/*
+ * The exec_setup method is called during executor-startup compilation of a
+ * SubscriptingRef node in an expression. It must fill *methods with pointers
+ * to functions that can be called for execution of the node. Optionally,
+ * exec_setup can initialize sbsrefstate->workspace to point to some palloc'd
+ * workspace for execution. (Typically, such workspace is used to hold
+ * looked-up catalog data and/or provide space for the check_subscripts step
+ * to pass data forward to the other step functions.) See executor/execExpr.h
+ * for the definitions of these structs and other ones used in expression
+ * execution.
+ *
+ * The methods to be provided are:
+ *
+ * sbs_check_subscripts: examine the just-computed subscript values available
+ * in sbsrefstate's arrays, and possibly convert them into another form
+ * (stored in sbsrefstate->workspace). Return TRUE to continue with
+ * evaluation of the subscripting construct, or FALSE to skip it and return an
+ * overall NULL result. If this is a fetch and the data type's fetch_strict
+ * flag is true, then sbs_check_subscripts must return FALSE if there are any
+ * NULL subscripts. Otherwise it can choose to throw an error, or return
+ * FALSE, or let sbs_fetch or sbs_assign deal with the null subscripts.
+ *
+ * sbs_fetch: perform a subscripting fetch, using the container value in
+ * *op->resvalue and the subscripts from sbs_check_subscripts. If
+ * fetch_strict is true then all these inputs can be assumed non-NULL,
+ * otherwise sbs_fetch must check for null inputs. Place the result in
+ * *op->resvalue / *op->resnull.
+ *
+ * sbs_assign: perform a subscripting assignment, using the original
+ * container value in *op->resvalue / *op->resnull, the subscripts from
+ * sbs_check_subscripts, and the new element/slice value in
+ * sbsrefstate->replacevalue/replacenull. Any of these inputs might be NULL
+ * (unless sbs_check_subscripts rejected null subscripts). Place the result
+ * (an entire new container value) in *op->resvalue / *op->resnull.
+ *
+ * sbs_fetch_old: this is only used in cases where an element or slice
+ * assignment involves an assignment to a sub-field or sub-element
+ * (i.e., nested containers are involved). It must fetch the existing
+ * value of the target element or slice. This is exactly the same as
+ * sbs_fetch except that (a) it must cope with a NULL container, and
+ * with NULL subscripts if sbs_check_subscripts allows them (typically,
+ * returning NULL is good enough); and (b) the result must be placed in
+ * sbsrefstate->prevvalue/prevnull, without overwriting *op->resvalue.
+ *
+ * Subscripting implementations that do not support assignment need not
+ * provide sbs_assign or sbs_fetch_old methods. It might be reasonable
+ * to also omit sbs_check_subscripts, in which case the sbs_fetch method must
+ * combine the functionality of sbs_check_subscripts and sbs_fetch. (The
+ * main reason to have a separate sbs_check_subscripts method is so that
+ * sbs_fetch_old and sbs_assign need not duplicate subscript processing.)
+ * Set the relevant pointers to NULL for any omitted methods.
+ */
+typedef void (*SubscriptExecSetup) (const SubscriptingRef *sbsref,
+ struct SubscriptingRefState *sbsrefstate,
+ struct SubscriptExecSteps *methods);
+
+/* Struct returned by the SQL-visible subscript handler function */
+typedef struct SubscriptRoutines
+{
+ SubscriptTransform transform; /* parse analysis function */
+ SubscriptExecSetup exec_setup; /* expression compilation function */
+ bool fetch_strict; /* is fetch SubscriptRef strict? */
+ bool fetch_leakproof; /* is fetch SubscriptRef leakproof? */
+ bool store_leakproof; /* is assignment SubscriptRef leakproof? */
+} SubscriptRoutines;
+
+#endif /* SUBSCRIPTING_H */
diff --git a/src/include/nodes/supportnodes.h b/src/include/nodes/supportnodes.h
new file mode 100644
index 0000000..4cfa661
--- /dev/null
+++ b/src/include/nodes/supportnodes.h
@@ -0,0 +1,346 @@
+/*-------------------------------------------------------------------------
+ *
+ * supportnodes.h
+ * Definitions for planner support functions.
+ *
+ * This file defines the API for "planner support functions", which
+ * are SQL functions (normally written in C) that can be attached to
+ * another "target" function to give the system additional knowledge
+ * about the target function. All the current capabilities have to do
+ * with planning queries that use the target function, though it is
+ * possible that future extensions will add functionality to be invoked
+ * by the parser or executor.
+ *
+ * A support function must have the SQL signature
+ * supportfn(internal) returns internal
+ * The argument is a pointer to one of the Node types defined in this file.
+ * The result is usually also a Node pointer, though its type depends on
+ * which capability is being invoked. In all cases, a NULL pointer result
+ * (that's PG_RETURN_POINTER(NULL), not PG_RETURN_NULL()) indicates that
+ * the support function cannot do anything useful for the given request.
+ * Support functions must return a NULL pointer, not fail, if they do not
+ * recognize the request node type or cannot handle the given case; this
+ * allows for future extensions of the set of request cases.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/nodes/supportnodes.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SUPPORTNODES_H
+#define SUPPORTNODES_H
+
+#include "nodes/plannodes.h"
+
+struct PlannerInfo; /* avoid including pathnodes.h here */
+struct IndexOptInfo;
+struct SpecialJoinInfo;
+struct WindowClause;
+
+/*
+ * The Simplify request allows the support function to perform plan-time
+ * simplification of a call to its target function. For example, a varchar
+ * length coercion that does not decrease the allowed length of its argument
+ * could be replaced by a RelabelType node, or "x + 0" could be replaced by
+ * "x". This is invoked during the planner's constant-folding pass, so the
+ * function's arguments can be presumed already simplified.
+ *
+ * The planner's PlannerInfo "root" is typically not needed, but can be
+ * consulted if it's necessary to obtain info about Vars present in
+ * the given node tree. Beware that root could be NULL in some usages.
+ *
+ * "fcall" will be a FuncExpr invoking the support function's target
+ * function. (This is true even if the original parsetree node was an
+ * operator call; a FuncExpr is synthesized for this purpose.)
+ *
+ * The result should be a semantically-equivalent transformed node tree,
+ * or NULL if no simplification could be performed. Do *not* return or
+ * modify *fcall, as it isn't really a separately allocated Node. But
+ * it's okay to use fcall->args, or parts of it, in the result tree.
+ */
+typedef struct SupportRequestSimplify
+{
+ NodeTag type;
+
+ struct PlannerInfo *root; /* Planner's infrastructure */
+ FuncExpr *fcall; /* Function call to be simplified */
+} SupportRequestSimplify;
+
+/*
+ * The Selectivity request allows the support function to provide a
+ * selectivity estimate for a function appearing at top level of a WHERE
+ * clause (so it applies only to functions returning boolean).
+ *
+ * The input arguments are the same as are supplied to operator restriction
+ * and join estimators, except that we unify those two APIs into just one
+ * request type. See clause_selectivity() for the details.
+ *
+ * If an estimate can be made, store it into the "selectivity" field and
+ * return the address of the SupportRequestSelectivity node; the estimate
+ * must be between 0 and 1 inclusive. Return NULL if no estimate can be
+ * made (in which case the planner will fall back to a default estimate,
+ * traditionally 1/3).
+ *
+ * If the target function is being used as the implementation of an operator,
+ * the support function will not be used for this purpose; the operator's
+ * restriction or join estimator is consulted instead.
+ */
+typedef struct SupportRequestSelectivity
+{
+ NodeTag type;
+
+ /* Input fields: */
+ struct PlannerInfo *root; /* Planner's infrastructure */
+ Oid funcid; /* function we are inquiring about */
+ List *args; /* pre-simplified arguments to function */
+ Oid inputcollid; /* function's input collation */
+ bool is_join; /* is this a join or restriction case? */
+ int varRelid; /* if restriction, RTI of target relation */
+ JoinType jointype; /* if join, outer join type */
+ struct SpecialJoinInfo *sjinfo; /* if outer join, info about join */
+
+ /* Output fields: */
+ Selectivity selectivity; /* returned selectivity estimate */
+} SupportRequestSelectivity;
+
+/*
+ * The Cost request allows the support function to provide an execution
+ * cost estimate for its target function. The cost estimate can include
+ * both a one-time (query startup) component and a per-execution component.
+ * The estimate should *not* include the costs of evaluating the target
+ * function's arguments, only the target function itself.
+ *
+ * The "node" argument is normally the parse node that is invoking the
+ * target function. This is a FuncExpr in the simplest case, but it could
+ * also be an OpExpr, DistinctExpr, NullIfExpr, or WindowFunc, or possibly
+ * other cases in future. NULL is passed if the function cannot presume
+ * its arguments to be equivalent to what the calling node presents as
+ * arguments; that happens for, e.g., aggregate support functions and
+ * per-column comparison operators used by RowExprs.
+ *
+ * If an estimate can be made, store it into the cost fields and return the
+ * address of the SupportRequestCost node. Return NULL if no estimate can be
+ * made, in which case the planner will rely on the target function's procost
+ * field. (Note: while procost is automatically scaled by cpu_operator_cost,
+ * this is not the case for the outputs of the Cost request; the support
+ * function must scale its results appropriately on its own.)
+ */
+typedef struct SupportRequestCost
+{
+ NodeTag type;
+
+ /* Input fields: */
+ struct PlannerInfo *root; /* Planner's infrastructure (could be NULL) */
+ Oid funcid; /* function we are inquiring about */
+ Node *node; /* parse node invoking function, or NULL */
+
+ /* Output fields: */
+ Cost startup; /* one-time cost */
+ Cost per_tuple; /* per-evaluation cost */
+} SupportRequestCost;
+
+/*
+ * The Rows request allows the support function to provide an output rowcount
+ * estimate for its target function (so it applies only to set-returning
+ * functions).
+ *
+ * The "node" argument is the parse node that is invoking the target function;
+ * currently this will always be a FuncExpr or OpExpr.
+ *
+ * If an estimate can be made, store it into the rows field and return the
+ * address of the SupportRequestRows node. Return NULL if no estimate can be
+ * made, in which case the planner will rely on the target function's prorows
+ * field.
+ */
+typedef struct SupportRequestRows
+{
+ NodeTag type;
+
+ /* Input fields: */
+ struct PlannerInfo *root; /* Planner's infrastructure (could be NULL) */
+ Oid funcid; /* function we are inquiring about */
+ Node *node; /* parse node invoking function */
+
+ /* Output fields: */
+ double rows; /* number of rows expected to be returned */
+} SupportRequestRows;
+
+/*
+ * The IndexCondition request allows the support function to generate
+ * a directly-indexable condition based on a target function call that is
+ * not itself indexable. The target function call must appear at the top
+ * level of WHERE or JOIN/ON, so this applies only to functions returning
+ * boolean.
+ *
+ * The "node" argument is the parse node that is invoking the target function;
+ * currently this will always be a FuncExpr or OpExpr. The call is made
+ * only if at least one function argument matches an index column's variable
+ * or expression. "indexarg" identifies the matching argument (it's the
+ * argument's zero-based index in the node's args list).
+ *
+ * If the transformation is possible, return a List of directly-indexable
+ * condition expressions, else return NULL. (A List is used because it's
+ * sometimes useful to generate more than one indexable condition, such as
+ * when a LIKE with constant prefix gives rise to both >= and < conditions.)
+ *
+ * "Directly indexable" means that the condition must be directly executable
+ * by the index machinery. Typically this means that it is a binary OpExpr
+ * with the index column value on the left, a pseudo-constant on the right,
+ * and an operator that is in the index column's operator family. Other
+ * possibilities include RowCompareExpr, ScalarArrayOpExpr, and NullTest,
+ * depending on the index type; but those seem less likely to be useful for
+ * derived index conditions. "Pseudo-constant" means that the right-hand
+ * expression must not contain any volatile functions, nor any Vars of the
+ * table the index is for; use is_pseudo_constant_for_index() to check this.
+ * (Note: if the passed "node" is an OpExpr, the core planner already verified
+ * that the non-indexkey operand is pseudo-constant; but when the "node"
+ * is a FuncExpr, it does not check, since it doesn't know which of the
+ * function's arguments you might need to use in an index comparison value.)
+ *
+ * In many cases, an index condition can be generated but it is weaker than
+ * the function condition itself; for example, a LIKE with a constant prefix
+ * can produce an index range check based on the prefix, but we still need
+ * to execute the LIKE operator to verify the rest of the pattern. We say
+ * that such an index condition is "lossy". When returning an index condition,
+ * you should set the "lossy" request field to true if the condition is lossy,
+ * or false if it is an exact equivalent of the function's result. The core
+ * code will initialize that field to true, which is the common case.
+ *
+ * It is important to verify that the index operator family is the correct
+ * one for the condition you want to generate. Core support functions tend
+ * to use the known OID of a built-in opfamily for this, but extensions need
+ * to work harder, since their OIDs aren't fixed. A possibly workable
+ * answer for an index on an extension datatype is to verify the index AM's
+ * OID instead, and then assume that there's only one relevant opclass for
+ * your datatype so the opfamily must be the right one. Generating OpExpr
+ * nodes may also require knowing extension datatype OIDs (often you can
+ * find these out by applying exprType() to a function argument) and
+ * operator OIDs (which you can look up using get_opfamily_member).
+ */
+typedef struct SupportRequestIndexCondition
+{
+ NodeTag type;
+
+ /* Input fields: */
+ struct PlannerInfo *root; /* Planner's infrastructure */
+ Oid funcid; /* function we are inquiring about */
+ Node *node; /* parse node invoking function */
+ int indexarg; /* index of function arg matching indexcol */
+ struct IndexOptInfo *index; /* planner's info about target index */
+ int indexcol; /* index of target index column (0-based) */
+ Oid opfamily; /* index column's operator family */
+ Oid indexcollation; /* index column's collation */
+
+ /* Output fields: */
+ bool lossy; /* set to false if index condition is an exact
+ * equivalent of the function call */
+} SupportRequestIndexCondition;
+
+/* ----------
+ * To support more efficient query execution of any monotonically increasing
+ * and/or monotonically decreasing window functions, we support calling the
+ * window function's prosupport function passing along this struct whenever
+ * the planner sees an OpExpr qual directly reference a window function in a
+ * subquery. When the planner encounters this, we populate this struct and
+ * pass it along to the window function's prosupport function so that it can
+ * evaluate if the given WindowFunc is;
+ *
+ * a) monotonically increasing, or
+ * b) monotonically decreasing, or
+ * c) both monotonically increasing and decreasing, or
+ * d) none of the above.
+ *
+ * A function that is monotonically increasing can never return a value that
+ * is lower than a value returned in a "previous call". A monotonically
+ * decreasing function can never return a value higher than a value returned
+ * in a previous call. A function that is both must return the same value
+ * each time.
+ *
+ * We define "previous call" to mean a previous call to the same WindowFunc
+ * struct in the same window partition.
+ *
+ * row_number() is an example of a monotonically increasing function. The
+ * return value will be reset back to 1 in each new partition. An example of
+ * a monotonically increasing and decreasing function is COUNT(*) OVER ().
+ * Since there is no ORDER BY clause in this example, all rows in the
+ * partition are peers and all rows within the partition will be within the
+ * frame bound. Likewise for COUNT(*) OVER(ORDER BY a ROWS BETWEEN UNBOUNDED
+ * PRECEDING AND UNBOUNDED FOLLOWING).
+ *
+ * COUNT(*) OVER (ORDER BY a ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
+ * is an example of a monotonically decreasing function.
+ *
+ * Implementations must only concern themselves with the given WindowFunc
+ * being monotonic in a single partition.
+ *
+ * Inputs:
+ * 'window_func' is the pointer to the window function being called.
+ *
+ * 'window_clause' pointer to the WindowClause data. Support functions can
+ * use this to check frame bounds, etc.
+ *
+ * Outputs:
+ * 'monotonic' the resulting MonotonicFunction value for the given input
+ * window function and window clause.
+ * ----------
+ */
+typedef struct SupportRequestWFuncMonotonic
+{
+ NodeTag type;
+
+ /* Input fields: */
+ WindowFunc *window_func; /* Pointer to the window function data */
+ struct WindowClause *window_clause; /* Pointer to the window clause data */
+
+ /* Output fields: */
+ MonotonicFunction monotonic;
+} SupportRequestWFuncMonotonic;
+
+/*
+ * Some WindowFunc behavior might not be affected by certain variations in
+ * the WindowClause's frameOptions. For example, row_number() is coded in
+ * such a way that the frame options don't change the returned row number.
+ * nodeWindowAgg.c will have less work to do if the ROWS option is used
+ * instead of the RANGE option as no check needs to be done for peer rows.
+ * Since RANGE is included in the default frame options, window functions
+ * such as row_number() might want to change that to ROW.
+ *
+ * Here we allow a WindowFunc's support function to determine which, if
+ * anything, can be changed about the WindowClause which the WindowFunc
+ * belongs to. Currently only the frameOptions can be modified. However,
+ * we may want to allow more optimizations in the future.
+ *
+ * The support function is responsible for ensuring the optimized version of
+ * the frameOptions doesn't affect the result of the window function. The
+ * planner is responsible for only changing the frame options when all
+ * WindowFuncs using this particular WindowClause agree on what the optimized
+ * version of the frameOptions are. If a particular WindowFunc being used
+ * does not have a support function then the planner will not make any changes
+ * to the WindowClause's frameOptions.
+ *
+ * 'window_func' and 'window_clause' are set by the planner before calling the
+ * support function so that the support function has these fields available.
+ * These may be required in order to determine which optimizations are
+ * possible.
+ *
+ * 'frameOptions' is set by the planner to WindowClause.frameOptions. The
+ * support function must only adjust this if optimizations are possible for
+ * the given WindowFunc.
+ */
+typedef struct SupportRequestOptimizeWindowClause
+{
+ NodeTag type;
+
+ /* Input fields: */
+ WindowFunc *window_func; /* Pointer to the window function data */
+ struct WindowClause *window_clause; /* Pointer to the window clause data */
+
+ /* Input/Output fields: */
+ int frameOptions; /* New frameOptions, or left untouched if no
+ * optimizations are possible. */
+} SupportRequestOptimizeWindowClause;
+
+#endif /* SUPPORTNODES_H */
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
new file mode 100644
index 0000000..b64e364
--- /dev/null
+++ b/src/include/nodes/tidbitmap.h
@@ -0,0 +1,75 @@
+/*-------------------------------------------------------------------------
+ *
+ * tidbitmap.h
+ * PostgreSQL tuple-id (TID) bitmap package
+ *
+ * This module provides bitmap data structures that are spiritually
+ * similar to Bitmapsets, but are specially adapted to store sets of
+ * tuple identifiers (TIDs), or ItemPointers. In particular, the division
+ * of an ItemPointer into BlockNumber and OffsetNumber is catered for.
+ * Also, since we wish to be able to store very large tuple sets in
+ * memory with this data structure, we support "lossy" storage, in which
+ * we no longer remember individual tuple offsets on a page but only the
+ * fact that a particular page needs to be visited.
+ *
+ *
+ * Copyright (c) 2003-2023, PostgreSQL Global Development Group
+ *
+ * src/include/nodes/tidbitmap.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef TIDBITMAP_H
+#define TIDBITMAP_H
+
+#include "storage/itemptr.h"
+#include "utils/dsa.h"
+
+
+/*
+ * Actual bitmap representation is private to tidbitmap.c. Callers can
+ * do IsA(x, TIDBitmap) on it, but nothing else.
+ */
+typedef struct TIDBitmap TIDBitmap;
+
+/* Likewise, TBMIterator is private */
+typedef struct TBMIterator TBMIterator;
+typedef struct TBMSharedIterator TBMSharedIterator;
+
+/* Result structure for tbm_iterate */
+typedef struct TBMIterateResult
+{
+ BlockNumber blockno; /* page number containing tuples */
+ int ntuples; /* -1 indicates lossy result */
+ bool recheck; /* should the tuples be rechecked? */
+ /* Note: recheck is always true if ntuples < 0 */
+ OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
+} TBMIterateResult;
+
+/* function prototypes in nodes/tidbitmap.c */
+
+extern TIDBitmap *tbm_create(long maxbytes, dsa_area *dsa);
+extern void tbm_free(TIDBitmap *tbm);
+extern void tbm_free_shared_area(dsa_area *dsa, dsa_pointer dp);
+
+extern void tbm_add_tuples(TIDBitmap *tbm,
+ const ItemPointer tids, int ntids,
+ bool recheck);
+extern void tbm_add_page(TIDBitmap *tbm, BlockNumber pageno);
+
+extern void tbm_union(TIDBitmap *a, const TIDBitmap *b);
+extern void tbm_intersect(TIDBitmap *a, const TIDBitmap *b);
+
+extern bool tbm_is_empty(const TIDBitmap *tbm);
+
+extern TBMIterator *tbm_begin_iterate(TIDBitmap *tbm);
+extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
+extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
+extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
+extern void tbm_end_iterate(TBMIterator *iterator);
+extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
+extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
+ dsa_pointer dp);
+extern long tbm_calculate_entries(double maxbytes);
+
+#endif /* TIDBITMAP_H */
diff --git a/src/include/nodes/value.h b/src/include/nodes/value.h
new file mode 100644
index 0000000..b24c4c1
--- /dev/null
+++ b/src/include/nodes/value.h
@@ -0,0 +1,90 @@
+/*-------------------------------------------------------------------------
+ *
+ * value.h
+ * interface for value nodes
+ *
+ *
+ * Copyright (c) 2003-2023, PostgreSQL Global Development Group
+ *
+ * src/include/nodes/value.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef VALUE_H
+#define VALUE_H
+
+#include "nodes/nodes.h"
+
+/*
+ * The node types Integer, Float, String, and BitString are used to represent
+ * literals in the lexer and are also used to pass constants around in the
+ * parser. One difference between these node types and, say, a plain int or
+ * char * is that the nodes can be put into a List.
+ *
+ * (There used to be a Value node, which encompassed all these different node types. Hence the name of this file.)
+ */
+
+typedef struct Integer
+{
+ pg_node_attr(special_read_write)
+
+ NodeTag type;
+ int ival;
+} Integer;
+
+/*
+ * Float is internally represented as string. Using T_Float as the node type
+ * simply indicates that the contents of the string look like a valid numeric
+ * literal. The value might end up being converted to NUMERIC, so we can't
+ * store it internally as a C double, since that could lose precision. Since
+ * these nodes are generally only used in the parsing process, not for runtime
+ * data, it's better to use the more general representation.
+ *
+ * Note that an integer-looking string will get lexed as T_Float if the value
+ * is too large to fit in an 'int'.
+ */
+typedef struct Float
+{
+ pg_node_attr(special_read_write)
+
+ NodeTag type;
+ char *fval;
+} Float;
+
+typedef struct Boolean
+{
+ pg_node_attr(special_read_write)
+
+ NodeTag type;
+ bool boolval;
+} Boolean;
+
+typedef struct String
+{
+ pg_node_attr(special_read_write)
+
+ NodeTag type;
+ char *sval;
+} String;
+
+typedef struct BitString
+{
+ pg_node_attr(special_read_write)
+
+ NodeTag type;
+ char *bsval;
+} BitString;
+
+#define intVal(v) (castNode(Integer, v)->ival)
+#define floatVal(v) atof(castNode(Float, v)->fval)
+#define boolVal(v) (castNode(Boolean, v)->boolval)
+#define strVal(v) (castNode(String, v)->sval)
+
+extern Integer *makeInteger(int i);
+extern Float *makeFloat(char *numericStr);
+extern Boolean *makeBoolean(bool val);
+extern String *makeString(char *str);
+extern BitString *makeBitString(char *str);
+
+#endif /* VALUE_H */