init
This commit is contained in:
122
db_include/nodes/bitmapset.h
Executable file
122
db_include/nodes/bitmapset.h
Executable file
@@ -0,0 +1,122 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* 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, a NULL pointer is always
|
||||
* accepted by all operations to represent the empty set. (But beware
|
||||
* that this is not the only representation of the empty set. Use
|
||||
* bms_is_empty() in preference to testing for NULL.)
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2003-2021, PostgreSQL Global Development Group
|
||||
*
|
||||
* src/include/nodes/bitmapset.h
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef BITMAPSET_H
|
||||
#define BITMAPSET_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
|
||||
{
|
||||
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);
|
||||
extern bool bms_is_empty(const Bitmapset *a);
|
||||
|
||||
/* 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_first_member(Bitmapset *a);
|
||||
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 */
|
||||
2646
db_include/nodes/execnodes.h
Executable file
2646
db_include/nodes/execnodes.h
Executable file
File diff suppressed because it is too large
Load Diff
160
db_include/nodes/extensible.h
Executable file
160
db_include/nodes/extensible.h
Executable file
@@ -0,0 +1,160 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* extensible.h
|
||||
* Definitions for extensible nodes and custom scans
|
||||
*
|
||||
*
|
||||
* Portions Copyright (c) 1996-2021, 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
|
||||
{
|
||||
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 *method);
|
||||
extern const ExtensibleNodeMethods *GetExtensibleNodeMethods(const char *name,
|
||||
bool missing_ok);
|
||||
|
||||
/*
|
||||
* Flags for custom paths, indicating what capabilities the resulting scan
|
||||
* will have.
|
||||
*/
|
||||
#define CUSTOMPATH_SUPPORT_BACKWARD_SCAN 0x0001
|
||||
#define CUSTOMPATH_SUPPORT_MARK_RESTORE 0x0002
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
61
db_include/nodes/lockoptions.h
Executable file
61
db_include/nodes/lockoptions.h
Executable file
@@ -0,0 +1,61 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* lockoptions.h
|
||||
* Common header for some locking-related declarations.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2014-2021, 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 */
|
||||
109
db_include/nodes/makefuncs.h
Executable file
109
db_include/nodes/makefuncs.h
Executable file
@@ -0,0 +1,109 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* makefuncs.h
|
||||
* prototypes for the creator functions of various nodes
|
||||
*
|
||||
*
|
||||
* Portions Copyright (c) 1996-2021, 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(Index varno,
|
||||
AttrNumber varattno,
|
||||
Oid vartype,
|
||||
int32 vartypmod,
|
||||
Oid varcollid,
|
||||
Index varlevelsup);
|
||||
|
||||
extern Var *makeVarFromTargetEntry(Index varno,
|
||||
TargetEntry *tle);
|
||||
|
||||
extern Var *makeWholeRowVar(RangeTblEntry *rte,
|
||||
Index 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 isready, bool concurrent);
|
||||
|
||||
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);
|
||||
|
||||
#endif /* MAKEFUNC_H */
|
||||
110
db_include/nodes/memnodes.h
Executable file
110
db_include/nodes/memnodes.h
Executable file
@@ -0,0 +1,110 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* memnodes.h
|
||||
* POSTGRES memory context node definitions.
|
||||
*
|
||||
*
|
||||
* Portions Copyright (c) 1996-2021, 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) (MemoryContext context, void *pointer);
|
||||
void *(*realloc) (MemoryContext context, void *pointer, Size size);
|
||||
void (*reset) (MemoryContext context);
|
||||
void (*delete_context) (MemoryContext context);
|
||||
Size (*get_chunk_space) (MemoryContext context, 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
|
||||
{
|
||||
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 */
|
||||
162
db_include/nodes/nodeFuncs.h
Executable file
162
db_include/nodes/nodeFuncs.h
Executable file
@@ -0,0 +1,162 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* nodeFuncs.h
|
||||
* Various general-purpose manipulations of Node trees
|
||||
*
|
||||
* Portions Copyright (c) 1996-2021, 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"
|
||||
|
||||
|
||||
/* 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 SortGroupNode lists */
|
||||
|
||||
/* callback function for check_functions_in_node */
|
||||
typedef bool (*check_function_callback) (Oid func_id, 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);
|
||||
|
||||
extern bool expression_tree_walker(Node *node, bool (*walker) (),
|
||||
void *context);
|
||||
extern Node *expression_tree_mutator(Node *node, Node *(*mutator) (),
|
||||
void *context);
|
||||
|
||||
extern bool query_tree_walker(Query *query, bool (*walker) (),
|
||||
void *context, int flags);
|
||||
extern Query *query_tree_mutator(Query *query, Node *(*mutator) (),
|
||||
void *context, int flags);
|
||||
|
||||
extern bool range_table_walker(List *rtable, bool (*walker) (),
|
||||
void *context, int flags);
|
||||
extern List *range_table_mutator(List *rtable, Node *(*mutator) (),
|
||||
void *context, int flags);
|
||||
|
||||
extern bool range_table_entry_walker(RangeTblEntry *rte, bool (*walker) (),
|
||||
void *context, int flags);
|
||||
|
||||
extern bool query_or_expression_tree_walker(Node *node, bool (*walker) (),
|
||||
void *context, int flags);
|
||||
extern Node *query_or_expression_tree_mutator(Node *node, Node *(*mutator) (),
|
||||
void *context, int flags);
|
||||
|
||||
extern bool raw_expression_tree_walker(Node *node, bool (*walker) (),
|
||||
void *context);
|
||||
|
||||
struct PlanState;
|
||||
extern bool planstate_tree_walker(struct PlanState *planstate, bool (*walker) (),
|
||||
void *context);
|
||||
|
||||
#endif /* NODEFUNCS_H */
|
||||
852
db_include/nodes/nodes.h
Executable file
852
db_include/nodes/nodes.h
Executable file
@@ -0,0 +1,852 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* nodes.h
|
||||
* Definitions for tagged nodes.
|
||||
*
|
||||
*
|
||||
* Portions Copyright (c) 1996-2021, 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,
|
||||
|
||||
/*
|
||||
* TAGS FOR EXECUTOR NODES (execnodes.h)
|
||||
*/
|
||||
T_IndexInfo,
|
||||
T_ExprContext,
|
||||
T_ProjectionInfo,
|
||||
T_JunkFilter,
|
||||
T_OnConflictSetState,
|
||||
T_ResultRelInfo,
|
||||
T_EState,
|
||||
T_TupleTableSlot,
|
||||
|
||||
/*
|
||||
* TAGS FOR PLAN NODES (plannodes.h)
|
||||
*/
|
||||
T_Plan,
|
||||
T_Result,
|
||||
T_ProjectSet,
|
||||
T_ModifyTable,
|
||||
T_Append,
|
||||
T_MergeAppend,
|
||||
T_RecursiveUnion,
|
||||
T_BitmapAnd,
|
||||
T_BitmapOr,
|
||||
T_Scan,
|
||||
T_SeqScan,
|
||||
T_SampleScan,
|
||||
T_IndexScan,
|
||||
T_IndexOnlyScan,
|
||||
T_BitmapIndexScan,
|
||||
T_BitmapHeapScan,
|
||||
T_TidScan,
|
||||
T_TidRangeScan,
|
||||
T_SubqueryScan,
|
||||
T_FunctionScan,
|
||||
T_ValuesScan,
|
||||
T_TableFuncScan,
|
||||
T_CteScan,
|
||||
T_NamedTuplestoreScan,
|
||||
T_WorkTableScan,
|
||||
T_ForeignScan,
|
||||
T_CustomScan,
|
||||
T_Join,
|
||||
T_NestLoop,
|
||||
T_MergeJoin,
|
||||
T_HashJoin,
|
||||
T_Material,
|
||||
T_Memoize,
|
||||
T_Sort,
|
||||
T_IncrementalSort,
|
||||
T_Group,
|
||||
T_Agg,
|
||||
T_WindowAgg,
|
||||
T_Unique,
|
||||
T_Gather,
|
||||
T_GatherMerge,
|
||||
T_Hash,
|
||||
T_SetOp,
|
||||
T_LockRows,
|
||||
T_Limit,
|
||||
/* these aren't subclasses of Plan: */
|
||||
T_NestLoopParam,
|
||||
T_PlanRowMark,
|
||||
T_PartitionPruneInfo,
|
||||
T_PartitionedRelPruneInfo,
|
||||
T_PartitionPruneStepOp,
|
||||
T_PartitionPruneStepCombine,
|
||||
T_PlanInvalItem,
|
||||
|
||||
/*
|
||||
* TAGS FOR PLAN STATE NODES (execnodes.h)
|
||||
*
|
||||
* These should correspond one-to-one with Plan node types.
|
||||
*/
|
||||
T_PlanState,
|
||||
T_ResultState,
|
||||
T_ProjectSetState,
|
||||
T_ModifyTableState,
|
||||
T_AppendState,
|
||||
T_MergeAppendState,
|
||||
T_RecursiveUnionState,
|
||||
T_BitmapAndState,
|
||||
T_BitmapOrState,
|
||||
T_ScanState,
|
||||
T_SeqScanState,
|
||||
T_SampleScanState,
|
||||
T_IndexScanState,
|
||||
T_IndexOnlyScanState,
|
||||
T_BitmapIndexScanState,
|
||||
T_BitmapHeapScanState,
|
||||
T_TidScanState,
|
||||
T_TidRangeScanState,
|
||||
T_SubqueryScanState,
|
||||
T_FunctionScanState,
|
||||
T_TableFuncScanState,
|
||||
T_ValuesScanState,
|
||||
T_CteScanState,
|
||||
T_NamedTuplestoreScanState,
|
||||
T_WorkTableScanState,
|
||||
T_ForeignScanState,
|
||||
T_CustomScanState,
|
||||
T_JoinState,
|
||||
T_NestLoopState,
|
||||
T_MergeJoinState,
|
||||
T_HashJoinState,
|
||||
T_MaterialState,
|
||||
T_MemoizeState,
|
||||
T_SortState,
|
||||
T_IncrementalSortState,
|
||||
T_GroupState,
|
||||
T_AggState,
|
||||
T_WindowAggState,
|
||||
T_UniqueState,
|
||||
T_GatherState,
|
||||
T_GatherMergeState,
|
||||
T_HashState,
|
||||
T_SetOpState,
|
||||
T_LockRowsState,
|
||||
T_LimitState,
|
||||
|
||||
/*
|
||||
* TAGS FOR PRIMITIVE NODES (primnodes.h)
|
||||
*/
|
||||
T_Alias,
|
||||
T_RangeVar,
|
||||
T_TableFunc,
|
||||
T_Expr,
|
||||
T_Var,
|
||||
T_Const,
|
||||
T_Param,
|
||||
T_Aggref,
|
||||
T_GroupingFunc,
|
||||
T_WindowFunc,
|
||||
T_SubscriptingRef,
|
||||
T_FuncExpr,
|
||||
T_NamedArgExpr,
|
||||
T_OpExpr,
|
||||
T_DistinctExpr,
|
||||
T_NullIfExpr,
|
||||
T_ScalarArrayOpExpr,
|
||||
T_BoolExpr,
|
||||
T_SubLink,
|
||||
T_SubPlan,
|
||||
T_AlternativeSubPlan,
|
||||
T_FieldSelect,
|
||||
T_FieldStore,
|
||||
T_RelabelType,
|
||||
T_CoerceViaIO,
|
||||
T_ArrayCoerceExpr,
|
||||
T_ConvertRowtypeExpr,
|
||||
T_CollateExpr,
|
||||
T_CaseExpr,
|
||||
T_CaseWhen,
|
||||
T_CaseTestExpr,
|
||||
T_ArrayExpr,
|
||||
T_RowExpr,
|
||||
T_RowCompareExpr,
|
||||
T_CoalesceExpr,
|
||||
T_MinMaxExpr,
|
||||
T_SQLValueFunction,
|
||||
T_XmlExpr,
|
||||
T_NullTest,
|
||||
T_BooleanTest,
|
||||
T_CoerceToDomain,
|
||||
T_CoerceToDomainValue,
|
||||
T_SetToDefault,
|
||||
T_CurrentOfExpr,
|
||||
T_NextValueExpr,
|
||||
T_InferenceElem,
|
||||
T_TargetEntry,
|
||||
T_RangeTblRef,
|
||||
T_JoinExpr,
|
||||
T_FromExpr,
|
||||
T_OnConflictExpr,
|
||||
T_IntoClause,
|
||||
|
||||
/*
|
||||
* TAGS FOR EXPRESSION STATE NODES (execnodes.h)
|
||||
*
|
||||
* ExprState represents the evaluation state for a whole expression tree.
|
||||
* Most Expr-based plan nodes do not have a corresponding expression state
|
||||
* node, they're fully handled within execExpr* - but sometimes the state
|
||||
* needs to be shared with other parts of the executor, as for example
|
||||
* with SubPlanState, which nodeSubplan.c has to modify.
|
||||
*/
|
||||
T_ExprState,
|
||||
T_WindowFuncExprState,
|
||||
T_SetExprState,
|
||||
T_SubPlanState,
|
||||
T_DomainConstraintState,
|
||||
|
||||
/*
|
||||
* TAGS FOR PLANNER NODES (pathnodes.h)
|
||||
*/
|
||||
T_PlannerInfo,
|
||||
T_PlannerGlobal,
|
||||
T_RelOptInfo,
|
||||
T_IndexOptInfo,
|
||||
T_ForeignKeyOptInfo,
|
||||
T_ParamPathInfo,
|
||||
T_Path,
|
||||
T_IndexPath,
|
||||
T_BitmapHeapPath,
|
||||
T_BitmapAndPath,
|
||||
T_BitmapOrPath,
|
||||
T_TidPath,
|
||||
T_TidRangePath,
|
||||
T_SubqueryScanPath,
|
||||
T_ForeignPath,
|
||||
T_CustomPath,
|
||||
T_NestPath,
|
||||
T_MergePath,
|
||||
T_HashPath,
|
||||
T_AppendPath,
|
||||
T_MergeAppendPath,
|
||||
T_GroupResultPath,
|
||||
T_MaterialPath,
|
||||
T_MemoizePath,
|
||||
T_UniquePath,
|
||||
T_GatherPath,
|
||||
T_GatherMergePath,
|
||||
T_ProjectionPath,
|
||||
T_ProjectSetPath,
|
||||
T_SortPath,
|
||||
T_IncrementalSortPath,
|
||||
T_GroupPath,
|
||||
T_UpperUniquePath,
|
||||
T_AggPath,
|
||||
T_GroupingSetsPath,
|
||||
T_MinMaxAggPath,
|
||||
T_WindowAggPath,
|
||||
T_SetOpPath,
|
||||
T_RecursiveUnionPath,
|
||||
T_LockRowsPath,
|
||||
T_ModifyTablePath,
|
||||
T_LimitPath,
|
||||
/* these aren't subclasses of Path: */
|
||||
T_EquivalenceClass,
|
||||
T_EquivalenceMember,
|
||||
T_PathKey,
|
||||
T_PathTarget,
|
||||
T_RestrictInfo,
|
||||
T_IndexClause,
|
||||
T_PlaceHolderVar,
|
||||
T_SpecialJoinInfo,
|
||||
T_AppendRelInfo,
|
||||
T_RowIdentityVarInfo,
|
||||
T_PlaceHolderInfo,
|
||||
T_MinMaxAggInfo,
|
||||
T_PlannerParamItem,
|
||||
T_RollupData,
|
||||
T_GroupingSetData,
|
||||
T_StatisticExtInfo,
|
||||
|
||||
/*
|
||||
* TAGS FOR MEMORY NODES (memnodes.h)
|
||||
*/
|
||||
T_MemoryContext,
|
||||
T_AllocSetContext,
|
||||
T_SlabContext,
|
||||
T_GenerationContext,
|
||||
|
||||
/*
|
||||
* TAGS FOR VALUE NODES (value.h)
|
||||
*/
|
||||
T_Value,
|
||||
T_Integer,
|
||||
T_Float,
|
||||
T_String,
|
||||
T_BitString,
|
||||
T_Null,
|
||||
|
||||
/*
|
||||
* TAGS FOR LIST NODES (pg_list.h)
|
||||
*/
|
||||
T_List,
|
||||
T_IntList,
|
||||
T_OidList,
|
||||
|
||||
/*
|
||||
* TAGS FOR EXTENSIBLE NODES (extensible.h)
|
||||
*/
|
||||
T_ExtensibleNode,
|
||||
|
||||
/*
|
||||
* TAGS FOR STATEMENT NODES (mostly in parsenodes.h)
|
||||
*/
|
||||
T_RawStmt,
|
||||
T_Query,
|
||||
T_PlannedStmt,
|
||||
T_InsertStmt,
|
||||
T_DeleteStmt,
|
||||
T_UpdateStmt,
|
||||
T_SelectStmt,
|
||||
T_ReturnStmt,
|
||||
T_PLAssignStmt,
|
||||
T_AlterTableStmt,
|
||||
T_AlterTableCmd,
|
||||
T_AlterDomainStmt,
|
||||
T_SetOperationStmt,
|
||||
T_GrantStmt,
|
||||
T_GrantRoleStmt,
|
||||
T_AlterDefaultPrivilegesStmt,
|
||||
T_ClosePortalStmt,
|
||||
T_ClusterStmt,
|
||||
T_CopyStmt,
|
||||
T_CreateStmt,
|
||||
T_DefineStmt,
|
||||
T_DropStmt,
|
||||
T_TruncateStmt,
|
||||
T_CommentStmt,
|
||||
T_FetchStmt,
|
||||
T_IndexStmt,
|
||||
T_CreateFunctionStmt,
|
||||
T_AlterFunctionStmt,
|
||||
T_DoStmt,
|
||||
T_RenameStmt,
|
||||
T_RuleStmt,
|
||||
T_NotifyStmt,
|
||||
T_ListenStmt,
|
||||
T_UnlistenStmt,
|
||||
T_TransactionStmt,
|
||||
T_ViewStmt,
|
||||
T_LoadStmt,
|
||||
T_CreateDomainStmt,
|
||||
T_CreatedbStmt,
|
||||
T_DropdbStmt,
|
||||
T_VacuumStmt,
|
||||
T_ExplainStmt,
|
||||
T_CreateTableAsStmt,
|
||||
T_CreateSeqStmt,
|
||||
T_AlterSeqStmt,
|
||||
T_VariableSetStmt,
|
||||
T_VariableShowStmt,
|
||||
T_DiscardStmt,
|
||||
T_CreateTrigStmt,
|
||||
T_CreatePLangStmt,
|
||||
T_CreateRoleStmt,
|
||||
T_AlterRoleStmt,
|
||||
T_DropRoleStmt,
|
||||
T_LockStmt,
|
||||
T_ConstraintsSetStmt,
|
||||
T_ReindexStmt,
|
||||
T_CheckPointStmt,
|
||||
T_CreateSchemaStmt,
|
||||
T_AlterDatabaseStmt,
|
||||
T_AlterDatabaseSetStmt,
|
||||
T_AlterRoleSetStmt,
|
||||
T_CreateConversionStmt,
|
||||
T_CreateCastStmt,
|
||||
T_CreateOpClassStmt,
|
||||
T_CreateOpFamilyStmt,
|
||||
T_AlterOpFamilyStmt,
|
||||
T_PrepareStmt,
|
||||
T_ExecuteStmt,
|
||||
T_DeallocateStmt,
|
||||
T_DeclareCursorStmt,
|
||||
T_CreateTableSpaceStmt,
|
||||
T_DropTableSpaceStmt,
|
||||
T_AlterObjectDependsStmt,
|
||||
T_AlterObjectSchemaStmt,
|
||||
T_AlterOwnerStmt,
|
||||
T_AlterOperatorStmt,
|
||||
T_AlterTypeStmt,
|
||||
T_DropOwnedStmt,
|
||||
T_ReassignOwnedStmt,
|
||||
T_CompositeTypeStmt,
|
||||
T_CreateEnumStmt,
|
||||
T_CreateRangeStmt,
|
||||
T_AlterEnumStmt,
|
||||
T_AlterTSDictionaryStmt,
|
||||
T_AlterTSConfigurationStmt,
|
||||
T_CreateFdwStmt,
|
||||
T_AlterFdwStmt,
|
||||
T_CreateForeignServerStmt,
|
||||
T_AlterForeignServerStmt,
|
||||
T_CreateUserMappingStmt,
|
||||
T_AlterUserMappingStmt,
|
||||
T_DropUserMappingStmt,
|
||||
T_AlterTableSpaceOptionsStmt,
|
||||
T_AlterTableMoveAllStmt,
|
||||
T_SecLabelStmt,
|
||||
T_CreateForeignTableStmt,
|
||||
T_ImportForeignSchemaStmt,
|
||||
T_CreateExtensionStmt,
|
||||
T_AlterExtensionStmt,
|
||||
T_AlterExtensionContentsStmt,
|
||||
T_CreateEventTrigStmt,
|
||||
T_AlterEventTrigStmt,
|
||||
T_RefreshMatViewStmt,
|
||||
T_ReplicaIdentityStmt,
|
||||
T_AlterSystemStmt,
|
||||
T_CreatePolicyStmt,
|
||||
T_AlterPolicyStmt,
|
||||
T_CreateTransformStmt,
|
||||
T_CreateAmStmt,
|
||||
T_CreatePublicationStmt,
|
||||
T_AlterPublicationStmt,
|
||||
T_CreateSubscriptionStmt,
|
||||
T_AlterSubscriptionStmt,
|
||||
T_DropSubscriptionStmt,
|
||||
T_CreateStatsStmt,
|
||||
T_AlterCollationStmt,
|
||||
T_CallStmt,
|
||||
T_AlterStatsStmt,
|
||||
|
||||
/*
|
||||
* TAGS FOR PARSE TREE NODES (parsenodes.h)
|
||||
*/
|
||||
T_A_Expr,
|
||||
T_ColumnRef,
|
||||
T_ParamRef,
|
||||
T_A_Const,
|
||||
T_FuncCall,
|
||||
T_A_Star,
|
||||
T_A_Indices,
|
||||
T_A_Indirection,
|
||||
T_A_ArrayExpr,
|
||||
T_ResTarget,
|
||||
T_MultiAssignRef,
|
||||
T_TypeCast,
|
||||
T_CollateClause,
|
||||
T_SortBy,
|
||||
T_WindowDef,
|
||||
T_RangeSubselect,
|
||||
T_RangeFunction,
|
||||
T_RangeTableSample,
|
||||
T_RangeTableFunc,
|
||||
T_RangeTableFuncCol,
|
||||
T_TypeName,
|
||||
T_ColumnDef,
|
||||
T_IndexElem,
|
||||
T_StatsElem,
|
||||
T_Constraint,
|
||||
T_DefElem,
|
||||
T_RangeTblEntry,
|
||||
T_RangeTblFunction,
|
||||
T_TableSampleClause,
|
||||
T_WithCheckOption,
|
||||
T_SortGroupClause,
|
||||
T_GroupingSet,
|
||||
T_WindowClause,
|
||||
T_ObjectWithArgs,
|
||||
T_AccessPriv,
|
||||
T_CreateOpClassItem,
|
||||
T_TableLikeClause,
|
||||
T_FunctionParameter,
|
||||
T_LockingClause,
|
||||
T_RowMarkClause,
|
||||
T_XmlSerialize,
|
||||
T_WithClause,
|
||||
T_InferClause,
|
||||
T_OnConflictClause,
|
||||
T_CTESearchClause,
|
||||
T_CTECycleClause,
|
||||
T_CommonTableExpr,
|
||||
T_RoleSpec,
|
||||
T_TriggerTransition,
|
||||
T_PartitionElem,
|
||||
T_PartitionSpec,
|
||||
T_PartitionBoundSpec,
|
||||
T_PartitionRangeDatum,
|
||||
T_PartitionCmd,
|
||||
T_VacuumRelation,
|
||||
|
||||
/*
|
||||
* TAGS FOR REPLICATION GRAMMAR PARSE NODES (replnodes.h)
|
||||
*/
|
||||
T_IdentifySystemCmd,
|
||||
T_BaseBackupCmd,
|
||||
T_CreateReplicationSlotCmd,
|
||||
T_DropReplicationSlotCmd,
|
||||
T_StartReplicationCmd,
|
||||
T_TimeLineHistoryCmd,
|
||||
T_SQLCmd,
|
||||
|
||||
/*
|
||||
* TAGS FOR RANDOM OTHER STUFF
|
||||
*
|
||||
* These are objects that aren't part of parse/plan/execute node tree
|
||||
* structures, but we give them NodeTags anyway for identification
|
||||
* purposes (usually because they are involved in APIs where we want to
|
||||
* pass multiple object types through the same pointer).
|
||||
*/
|
||||
T_TriggerData, /* in commands/trigger.h */
|
||||
T_EventTriggerData, /* in commands/event_trigger.h */
|
||||
T_ReturnSetInfo, /* in nodes/execnodes.h */
|
||||
T_WindowObjectData, /* private in nodeWindowAgg.c */
|
||||
T_TIDBitmap, /* in nodes/tidbitmap.h */
|
||||
T_InlineCodeBlock, /* in nodes/parsenodes.h */
|
||||
T_FdwRoutine, /* in foreign/fdwapi.h */
|
||||
T_IndexAmRoutine, /* in access/amapi.h */
|
||||
T_TableAmRoutine, /* in access/tableam.h */
|
||||
T_TsmRoutine, /* in access/tsmapi.h */
|
||||
T_ForeignKeyCacheInfo, /* in utils/rel.h */
|
||||
T_CallContext, /* in nodes/parsenodes.h */
|
||||
T_SupportRequestSimplify, /* in nodes/supportnodes.h */
|
||||
T_SupportRequestSelectivity, /* in nodes/supportnodes.h */
|
||||
T_SupportRequestCost, /* in nodes/supportnodes.h */
|
||||
T_SupportRequestRows, /* in nodes/supportnodes.h */
|
||||
T_SupportRequestIndexCondition /* in nodes/supportnodes.h */
|
||||
} NodeTag;
|
||||
|
||||
/*
|
||||
* 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 *obj);
|
||||
|
||||
/* 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) */
|
||||
|
||||
|
||||
/*
|
||||
* 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,
|
||||
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 */
|
||||
|
||||
/*
|
||||
* 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))) != 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 */
|
||||
170
db_include/nodes/params.h
Executable file
170
db_include/nodes/params.h
Executable file
@@ -0,0 +1,170 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* params.h
|
||||
* Support for finding the values associated with Param nodes.
|
||||
*
|
||||
*
|
||||
* Portions Copyright (c) 1996-2021, 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 **paramTextValues,
|
||||
int valueLen);
|
||||
extern void ParamsErrorCallback(void *arg);
|
||||
|
||||
#endif /* PARAMS_H */
|
||||
3688
db_include/nodes/parsenodes.h
Executable file
3688
db_include/nodes/parsenodes.h
Executable file
File diff suppressed because it is too large
Load Diff
2719
db_include/nodes/pathnodes.h
Executable file
2719
db_include/nodes/pathnodes.h
Executable file
File diff suppressed because it is too large
Load Diff
611
db_include/nodes/pg_list.h
Executable file
611
db_include/nodes/pg_list.h
Executable file
@@ -0,0 +1,611 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* 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 three 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
|
||||
*
|
||||
* (At the moment, ints and Oids are the same size, but they may not
|
||||
* always be so; try to be careful to maintain the distinction.)
|
||||
*
|
||||
*
|
||||
* Portions Copyright (c) 1996-2021, 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;
|
||||
} ListCell;
|
||||
|
||||
typedef struct List
|
||||
{
|
||||
NodeTag type; /* T_List, T_IntList, or T_OidList */
|
||||
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_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_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_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))
|
||||
|
||||
/*
|
||||
* 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 *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 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 *list);
|
||||
extern pg_nodiscard List *list_copy_tail(const List *list, 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 */
|
||||
1309
db_include/nodes/plannodes.h
Executable file
1309
db_include/nodes/plannodes.h
Executable file
File diff suppressed because it is too large
Load Diff
1584
db_include/nodes/primnodes.h
Executable file
1584
db_include/nodes/primnodes.h
Executable file
File diff suppressed because it is too large
Load Diff
34
db_include/nodes/print.h
Executable file
34
db_include/nodes/print.h
Executable file
@@ -0,0 +1,34 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* print.h
|
||||
* definitions for nodes/print.c
|
||||
*
|
||||
*
|
||||
* Portions Copyright (c) 1996-2021, 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 */
|
||||
38
db_include/nodes/readfuncs.h
Executable file
38
db_include/nodes/readfuncs.h
Executable file
@@ -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-2021, 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 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 */
|
||||
109
db_include/nodes/replnodes.h
Executable file
109
db_include/nodes/replnodes.h
Executable file
@@ -0,0 +1,109 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* replnodes.h
|
||||
* definitions for replication grammar parse nodes
|
||||
*
|
||||
*
|
||||
* Portions Copyright (c) 1996-2021, 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;
|
||||
|
||||
|
||||
/* ----------------------
|
||||
* TIMELINE_HISTORY command
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct TimeLineHistoryCmd
|
||||
{
|
||||
NodeTag type;
|
||||
TimeLineID timeline;
|
||||
} TimeLineHistoryCmd;
|
||||
|
||||
/* ----------------------
|
||||
* SQL commands
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct SQLCmd
|
||||
{
|
||||
NodeTag type;
|
||||
} SQLCmd;
|
||||
|
||||
#endif /* REPLNODES_H */
|
||||
167
db_include/nodes/subscripting.h
Executable file
167
db_include/nodes/subscripting.h
Executable file
@@ -0,0 +1,167 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* subscripting.h
|
||||
* API for generic type subscripting
|
||||
*
|
||||
* Portions Copyright (c) 1996-2021, 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 */
|
||||
242
db_include/nodes/supportnodes.h
Executable file
242
db_include/nodes/supportnodes.h
Executable file
@@ -0,0 +1,242 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* 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-2021, 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/primnodes.h"
|
||||
|
||||
struct PlannerInfo; /* avoid including pathnodes.h here */
|
||||
struct IndexOptInfo;
|
||||
struct SpecialJoinInfo;
|
||||
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
#endif /* SUPPORTNODES_H */
|
||||
75
db_include/nodes/tidbitmap.h
Executable file
75
db_include/nodes/tidbitmap.h
Executable file
@@ -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-2021, 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 */
|
||||
61
db_include/nodes/value.h
Executable file
61
db_include/nodes/value.h
Executable file
@@ -0,0 +1,61 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* value.h
|
||||
* interface for Value nodes
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2003-2021, PostgreSQL Global Development Group
|
||||
*
|
||||
* src/include/nodes/value.h
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef VALUE_H
|
||||
#define VALUE_H
|
||||
|
||||
#include "nodes/nodes.h"
|
||||
|
||||
/*----------------------
|
||||
* Value node
|
||||
*
|
||||
* The same Value struct is used for five node types: T_Integer,
|
||||
* T_Float, T_String, T_BitString, T_Null.
|
||||
*
|
||||
* Integral values are actually represented by a machine integer,
|
||||
* but both floats and strings are represented as strings.
|
||||
* Using T_Float as the node type simply indicates that
|
||||
* the contents of the string look like a valid numeric literal.
|
||||
*
|
||||
* (Before Postgres 7.0, we used a double to represent T_Float,
|
||||
* but that creates loss-of-precision problems when the value is
|
||||
* ultimately destined to be converted to NUMERIC. Since Value nodes
|
||||
* are 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'.
|
||||
*
|
||||
* Nulls, of course, don't need the value part at all.
|
||||
*----------------------
|
||||
*/
|
||||
typedef struct Value
|
||||
{
|
||||
NodeTag type; /* tag appropriately (eg. T_String) */
|
||||
union ValUnion
|
||||
{
|
||||
int ival; /* machine integer */
|
||||
char *str; /* string */
|
||||
} val;
|
||||
} Value;
|
||||
|
||||
#define intVal(v) (((Value *)(v))->val.ival)
|
||||
#define floatVal(v) atof(((Value *)(v))->val.str)
|
||||
#define strVal(v) (((Value *)(v))->val.str)
|
||||
|
||||
extern Value *makeInteger(int i);
|
||||
extern Value *makeFloat(char *numericStr);
|
||||
extern Value *makeString(char *str);
|
||||
extern Value *makeBitString(char *str);
|
||||
|
||||
#endif /* VALUE_H */
|
||||
Reference in New Issue
Block a user