mirror of
https://github.com/postgres/postgres.git
synced 2025-04-21 12:05:57 +03:00
291 lines
13 KiB
C
291 lines
13 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* parse_node.h
|
|
* Internal definitions for parser
|
|
*
|
|
*
|
|
* Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
*
|
|
* src/include/parser/parse_node.h
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
#ifndef PARSE_NODE_H
|
|
#define PARSE_NODE_H
|
|
|
|
#include "nodes/parsenodes.h"
|
|
#include "utils/queryenvironment.h"
|
|
#include "utils/relcache.h"
|
|
|
|
|
|
/*
|
|
* Expression kinds distinguished by transformExpr(). Many of these are not
|
|
* semantically distinct so far as expression transformation goes; rather,
|
|
* we distinguish them so that context-specific error messages can be printed.
|
|
*
|
|
* Note: EXPR_KIND_OTHER is not used in the core code, but is left for use
|
|
* by extension code that might need to call transformExpr(). The core code
|
|
* will not enforce any context-driven restrictions on EXPR_KIND_OTHER
|
|
* expressions, so the caller would have to check for sub-selects, aggregates,
|
|
* window functions, SRFs, etc if those need to be disallowed.
|
|
*/
|
|
typedef enum ParseExprKind
|
|
{
|
|
EXPR_KIND_NONE = 0, /* "not in an expression" */
|
|
EXPR_KIND_OTHER, /* reserved for extensions */
|
|
EXPR_KIND_JOIN_ON, /* JOIN ON */
|
|
EXPR_KIND_JOIN_USING, /* JOIN USING */
|
|
EXPR_KIND_FROM_SUBSELECT, /* sub-SELECT in FROM clause */
|
|
EXPR_KIND_FROM_FUNCTION, /* function in FROM clause */
|
|
EXPR_KIND_WHERE, /* WHERE */
|
|
EXPR_KIND_HAVING, /* HAVING */
|
|
EXPR_KIND_FILTER, /* FILTER */
|
|
EXPR_KIND_WINDOW_PARTITION, /* window definition PARTITION BY */
|
|
EXPR_KIND_WINDOW_ORDER, /* window definition ORDER BY */
|
|
EXPR_KIND_WINDOW_FRAME_RANGE, /* window frame clause with RANGE */
|
|
EXPR_KIND_WINDOW_FRAME_ROWS, /* window frame clause with ROWS */
|
|
EXPR_KIND_WINDOW_FRAME_GROUPS, /* window frame clause with GROUPS */
|
|
EXPR_KIND_SELECT_TARGET, /* SELECT target list item */
|
|
EXPR_KIND_INSERT_TARGET, /* INSERT target list item */
|
|
EXPR_KIND_UPDATE_SOURCE, /* UPDATE assignment source item */
|
|
EXPR_KIND_UPDATE_TARGET, /* UPDATE assignment target item */
|
|
EXPR_KIND_GROUP_BY, /* GROUP BY */
|
|
EXPR_KIND_ORDER_BY, /* ORDER BY */
|
|
EXPR_KIND_DISTINCT_ON, /* DISTINCT ON */
|
|
EXPR_KIND_LIMIT, /* LIMIT */
|
|
EXPR_KIND_OFFSET, /* OFFSET */
|
|
EXPR_KIND_RETURNING, /* RETURNING */
|
|
EXPR_KIND_VALUES, /* VALUES */
|
|
EXPR_KIND_VALUES_SINGLE, /* single-row VALUES (in INSERT only) */
|
|
EXPR_KIND_CHECK_CONSTRAINT, /* CHECK constraint for a table */
|
|
EXPR_KIND_DOMAIN_CHECK, /* CHECK constraint for a domain */
|
|
EXPR_KIND_COLUMN_DEFAULT, /* default value for a table column */
|
|
EXPR_KIND_FUNCTION_DEFAULT, /* default parameter value for function */
|
|
EXPR_KIND_INDEX_EXPRESSION, /* index expression */
|
|
EXPR_KIND_INDEX_PREDICATE, /* index predicate */
|
|
EXPR_KIND_ALTER_COL_TRANSFORM, /* transform expr in ALTER COLUMN TYPE */
|
|
EXPR_KIND_EXECUTE_PARAMETER, /* parameter value in EXECUTE */
|
|
EXPR_KIND_TRIGGER_WHEN, /* WHEN condition in CREATE TRIGGER */
|
|
EXPR_KIND_POLICY, /* USING or WITH CHECK expr in policy */
|
|
EXPR_KIND_PARTITION_BOUND, /* partition bound expression */
|
|
EXPR_KIND_PARTITION_EXPRESSION, /* PARTITION BY expression */
|
|
EXPR_KIND_CALL_ARGUMENT, /* procedure argument in CALL */
|
|
EXPR_KIND_COPY_WHERE, /* WHERE condition in COPY FROM */
|
|
EXPR_KIND_GENERATED_COLUMN, /* generation expression for a column */
|
|
} ParseExprKind;
|
|
|
|
|
|
/*
|
|
* Function signatures for parser hooks
|
|
*/
|
|
typedef struct ParseState ParseState;
|
|
|
|
typedef Node *(*PreParseColumnRefHook) (ParseState *pstate, ColumnRef *cref);
|
|
typedef Node *(*PostParseColumnRefHook) (ParseState *pstate, ColumnRef *cref, Node *var);
|
|
typedef Node *(*ParseParamRefHook) (ParseState *pstate, ParamRef *pref);
|
|
typedef Node *(*CoerceParamHook) (ParseState *pstate, Param *param,
|
|
Oid targetTypeId, int32 targetTypeMod,
|
|
int location);
|
|
|
|
|
|
/*
|
|
* State information used during parse analysis
|
|
*
|
|
* parentParseState: NULL in a top-level ParseState. When parsing a subquery,
|
|
* links to current parse state of outer query.
|
|
*
|
|
* p_sourcetext: source string that generated the raw parsetree being
|
|
* analyzed, or NULL if not available. (The string is used only to
|
|
* generate cursor positions in error messages: we need it to convert
|
|
* byte-wise locations in parse structures to character-wise cursor
|
|
* positions.)
|
|
*
|
|
* p_rtable: list of RTEs that will become the rangetable of the query.
|
|
* Note that neither relname nor refname of these entries are necessarily
|
|
* unique; searching the rtable by name is a bad idea.
|
|
*
|
|
* p_joinexprs: list of JoinExpr nodes associated with p_rtable entries.
|
|
* This is one-for-one with p_rtable, but contains NULLs for non-join
|
|
* RTEs, and may be shorter than p_rtable if the last RTE(s) aren't joins.
|
|
*
|
|
* p_joinlist: list of join items (RangeTblRef and JoinExpr nodes) that
|
|
* will become the fromlist of the query's top-level FromExpr node.
|
|
*
|
|
* p_namespace: list of ParseNamespaceItems that represents the current
|
|
* namespace for table and column lookup. (The RTEs listed here may be just
|
|
* a subset of the whole rtable. See ParseNamespaceItem comments below.)
|
|
*
|
|
* p_lateral_active: true if we are currently parsing a LATERAL subexpression
|
|
* of this parse level. This makes p_lateral_only namespace items visible,
|
|
* whereas they are not visible when p_lateral_active is FALSE.
|
|
*
|
|
* p_ctenamespace: list of CommonTableExprs (WITH items) that are visible
|
|
* at the moment. This is entirely different from p_namespace because a CTE
|
|
* is not an RTE, rather "visibility" means you could make an RTE from it.
|
|
*
|
|
* p_future_ctes: list of CommonTableExprs (WITH items) that are not yet
|
|
* visible due to scope rules. This is used to help improve error messages.
|
|
*
|
|
* p_parent_cte: CommonTableExpr that immediately contains the current query,
|
|
* if any.
|
|
*
|
|
* p_target_relation: target relation, if query is INSERT, UPDATE, or DELETE.
|
|
*
|
|
* p_target_rangetblentry: target relation's entry in the rtable list.
|
|
*
|
|
* p_target_rtindex: target relation's index in the rtable list.
|
|
*
|
|
* p_is_insert: true to process assignment expressions like INSERT, false
|
|
* to process them like UPDATE. (Note this can change intra-statement, for
|
|
* cases like INSERT ON CONFLICT UPDATE.)
|
|
*
|
|
* p_windowdefs: list of WindowDefs representing WINDOW and OVER clauses.
|
|
* We collect these while transforming expressions and then transform them
|
|
* afterwards (so that any resjunk tlist items needed for the sort/group
|
|
* clauses end up at the end of the query tlist). A WindowDef's location in
|
|
* this list, counting from 1, is the winref number to use to reference it.
|
|
*
|
|
* p_expr_kind: kind of expression we're currently parsing, as per enum above;
|
|
* EXPR_KIND_NONE when not in an expression.
|
|
*
|
|
* p_next_resno: next TargetEntry.resno to assign, starting from 1.
|
|
*
|
|
* p_multiassign_exprs: partially-processed MultiAssignRef source expressions.
|
|
*
|
|
* p_locking_clause: query's FOR UPDATE/FOR SHARE clause, if any.
|
|
*
|
|
* p_locked_from_parent: true if parent query level applies FOR UPDATE/SHARE
|
|
* to this subquery as a whole.
|
|
*
|
|
* p_resolve_unknowns: resolve unknown-type SELECT output columns as type TEXT
|
|
* (this is true by default).
|
|
*
|
|
* p_hasAggs, p_hasWindowFuncs, etc: true if we've found any of the indicated
|
|
* constructs in the query.
|
|
*
|
|
* p_last_srf: the set-returning FuncExpr or OpExpr most recently found in
|
|
* the query, or NULL if none.
|
|
*
|
|
* p_pre_columnref_hook, etc: optional parser hook functions for modifying the
|
|
* interpretation of ColumnRefs and ParamRefs.
|
|
*
|
|
* p_ref_hook_state: passthrough state for the parser hook functions.
|
|
*/
|
|
struct ParseState
|
|
{
|
|
struct ParseState *parentParseState; /* stack link */
|
|
const char *p_sourcetext; /* source text, or NULL if not available */
|
|
List *p_rtable; /* range table so far */
|
|
List *p_joinexprs; /* JoinExprs for RTE_JOIN p_rtable entries */
|
|
List *p_joinlist; /* join items so far (will become FromExpr
|
|
* node's fromlist) */
|
|
List *p_namespace; /* currently-referenceable RTEs (List of
|
|
* ParseNamespaceItem) */
|
|
bool p_lateral_active; /* p_lateral_only items visible? */
|
|
List *p_ctenamespace; /* current namespace for common table exprs */
|
|
List *p_future_ctes; /* common table exprs not yet in namespace */
|
|
CommonTableExpr *p_parent_cte; /* this query's containing CTE */
|
|
Relation p_target_relation; /* INSERT/UPDATE/DELETE target rel */
|
|
RangeTblEntry *p_target_rangetblentry; /* target rel's RTE, or NULL */
|
|
int p_target_rtindex; /* target rel's RT index, or 0 */
|
|
bool p_is_insert; /* process assignment like INSERT not UPDATE */
|
|
List *p_windowdefs; /* raw representations of window clauses */
|
|
ParseExprKind p_expr_kind; /* what kind of expression we're parsing */
|
|
int p_next_resno; /* next targetlist resno to assign */
|
|
List *p_multiassign_exprs; /* junk tlist entries for multiassign */
|
|
List *p_locking_clause; /* raw FOR UPDATE/FOR SHARE info */
|
|
bool p_locked_from_parent; /* parent has marked this subquery
|
|
* with FOR UPDATE/FOR SHARE */
|
|
bool p_resolve_unknowns; /* resolve unknown-type SELECT outputs as
|
|
* type text */
|
|
|
|
QueryEnvironment *p_queryEnv; /* curr env, incl refs to enclosing env */
|
|
|
|
/* Flags telling about things found in the query: */
|
|
bool p_hasAggs;
|
|
bool p_hasWindowFuncs;
|
|
bool p_hasTargetSRFs;
|
|
bool p_hasSubLinks;
|
|
bool p_hasModifyingCTE;
|
|
|
|
Node *p_last_srf; /* most recent set-returning func/op found */
|
|
|
|
/*
|
|
* Optional hook functions for parser callbacks. These are null unless
|
|
* set up by the caller of make_parsestate.
|
|
*/
|
|
PreParseColumnRefHook p_pre_columnref_hook;
|
|
PostParseColumnRefHook p_post_columnref_hook;
|
|
ParseParamRefHook p_paramref_hook;
|
|
CoerceParamHook p_coerce_param_hook;
|
|
void *p_ref_hook_state; /* common passthrough link for above */
|
|
};
|
|
|
|
/*
|
|
* An element of a namespace list.
|
|
*
|
|
* Namespace items with p_rel_visible set define which RTEs are accessible by
|
|
* qualified names, while those with p_cols_visible set define which RTEs are
|
|
* accessible by unqualified names. These sets are different because a JOIN
|
|
* without an alias does not hide the contained tables (so they must be
|
|
* visible for qualified references) but it does hide their columns
|
|
* (unqualified references to the columns refer to the JOIN, not the member
|
|
* tables, so we must not complain that such a reference is ambiguous).
|
|
* Various special RTEs such as NEW/OLD for rules may also appear with only
|
|
* one flag set.
|
|
*
|
|
* While processing the FROM clause, namespace items may appear with
|
|
* p_lateral_only set, meaning they are visible only to LATERAL
|
|
* subexpressions. (The pstate's p_lateral_active flag tells whether we are
|
|
* inside such a subexpression at the moment.) If p_lateral_ok is not set,
|
|
* it's an error to actually use such a namespace item. One might think it
|
|
* would be better to just exclude such items from visibility, but the wording
|
|
* of SQL:2008 requires us to do it this way. We also use p_lateral_ok to
|
|
* forbid LATERAL references to an UPDATE/DELETE target table.
|
|
*
|
|
* At no time should a namespace list contain two entries that conflict
|
|
* according to the rules in checkNameSpaceConflicts; but note that those
|
|
* are more complicated than "must have different alias names", so in practice
|
|
* code searching a namespace list has to check for ambiguous references.
|
|
*/
|
|
typedef struct ParseNamespaceItem
|
|
{
|
|
RangeTblEntry *p_rte; /* The relation's rangetable entry */
|
|
int p_rtindex; /* The relation's index in the rangetable */
|
|
bool p_rel_visible; /* Relation name is visible? */
|
|
bool p_cols_visible; /* Column names visible as unqualified refs? */
|
|
bool p_lateral_only; /* Is only visible to LATERAL expressions? */
|
|
bool p_lateral_ok; /* If so, does join type allow use? */
|
|
} ParseNamespaceItem;
|
|
|
|
/* Support for parser_errposition_callback function */
|
|
typedef struct ParseCallbackState
|
|
{
|
|
ParseState *pstate;
|
|
int location;
|
|
ErrorContextCallback errcallback;
|
|
} ParseCallbackState;
|
|
|
|
|
|
extern ParseState *make_parsestate(ParseState *parentParseState);
|
|
extern void free_parsestate(ParseState *pstate);
|
|
extern int parser_errposition(ParseState *pstate, int location);
|
|
|
|
extern void setup_parser_errposition_callback(ParseCallbackState *pcbstate,
|
|
ParseState *pstate, int location);
|
|
extern void cancel_parser_errposition_callback(ParseCallbackState *pcbstate);
|
|
|
|
extern Oid transformContainerType(Oid *containerType, int32 *containerTypmod);
|
|
|
|
extern SubscriptingRef *transformContainerSubscripts(ParseState *pstate,
|
|
Node *containerBase,
|
|
Oid containerType,
|
|
Oid elementType,
|
|
int32 containerTypMod,
|
|
List *indirection,
|
|
Node *assignFrom);
|
|
extern Const *make_const(ParseState *pstate, Value *value, int location);
|
|
|
|
#endif /* PARSE_NODE_H */
|