[pgpool-hackers: 558] WIP patch for PG94 parser import
Muhammad Usama
m.usama at gmail.com
Wed Jun 25 20:50:47 JST 2014
Hi
I am working on updating pgpool-II parser to PG94's parser, and till time I
have imported the changes from PostgreSQL source to pgpool-II, There are
still some TODOs and compiler warnings needed to be fixed, which I am
currently working on and hopefully be finished soon. Meanwhile can you
please review the attached WIP patch if I have missed or overdone something.
Thanks
Usama
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.sraoss.jp/pipermail/pgpool-hackers/attachments/20140625/8407f29b/attachment-0001.html>
-------------- next part --------------
diff --git a/src/Makefile.am b/src/Makefile.am
index cb9b88e..69ced68 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -30,6 +30,7 @@ pgpool_SOURCES = main/main.c \
parallel_query/pool_rewrite_outfuncs.c \
utils/pool_select_walker.c \
utils/strlcpy.c \
+ utils/psprintf.c \
utils/pool_params.c \
utils/ps_status.c \
utils/pool_shmem.c \
diff --git a/src/config/pool_config.c b/src/config/pool_config.c
index 9227f80..e05346e 100644
--- a/src/config/pool_config.c
+++ b/src/config/pool_config.c
@@ -53,7 +53,6 @@ typedef int flex_int32_t;
typedef unsigned char flex_uint8_t;
typedef unsigned short int flex_uint16_t;
typedef unsigned int flex_uint32_t;
-#endif /* ! C99 */
/* Limits of integral types. */
#ifndef INT8_MIN
@@ -84,6 +83,8 @@ typedef unsigned int flex_uint32_t;
#define UINT32_MAX (4294967295U)
#endif
+#endif /* ! C99 */
+
#endif /* ! FLEXINT_H */
#ifdef __cplusplus
@@ -140,7 +141,15 @@ typedef unsigned int flex_uint32_t;
/* Size of default input buffer. */
#ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
#define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
#endif
/* The state buf must be large enough to hold one state per character in the main buffer.
@@ -554,7 +563,7 @@ static char *extract_string(char *value, POOL_TOKEN token);
static char **extract_string_tokens(char *str, char *delim, int *n);
static void clear_host_entry(int slot);
-#line 558 "config/pool_config.c"
+#line 567 "config/pool_config.c"
#define INITIAL 0
@@ -633,7 +642,12 @@ static int input (void );
/* Amount of stuff to slurp up with each read. */
#ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
#define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
#endif
/* Copy whatever the last rule matched to the standard output. */
@@ -652,7 +666,7 @@ static int input (void );
if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
{ \
int c = '*'; \
- unsigned n; \
+ size_t n; \
for ( n = 0; n < max_size && \
(c = getc( yyin )) != EOF && c != '\n'; ++n ) \
buf[n] = (char) c; \
@@ -737,7 +751,7 @@ YY_DECL
#line 98 "pool_config.l"
-#line 741 "config/pool_config.c"
+#line 755 "config/pool_config.c"
if ( !(yy_init) )
{
@@ -875,7 +889,7 @@ YY_RULE_SETUP
#line 113 "pool_config.l"
ECHO;
YY_BREAK
-#line 879 "config/pool_config.c"
+#line 893 "config/pool_config.c"
case YY_STATE_EOF(INITIAL):
yyterminate();
@@ -1593,8 +1607,8 @@ YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
* scan from a @e copy of @a bytes.
- * @param bytes the byte buffer to scan
- * @param len the number of bytes in the buffer pointed to by @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
*
* @return the newly allocated buffer state object.
*/
diff --git a/src/include/parser/gramparse.h b/src/include/parser/gramparse.h
index a4397af..205b16e 100644
--- a/src/include/parser/gramparse.h
+++ b/src/include/parser/gramparse.h
@@ -8,8 +8,8 @@
* outside the core parser should be in parser.h.
*
*
- * Portions Copyright (c) 2003-2012, PgPool Global Development Group
- * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
+ * Portions Copyright (c) 2003-2014, PgPool Global Development Group
+ * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/include/parser/gramparse.h
diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h
index 7f4bb10..c812600 100644
--- a/src/include/parser/kwlist.h
+++ b/src/include/parser/kwlist.h
@@ -7,8 +7,8 @@
* by the PG_KEYWORD macro, which is not defined in this file; it can
* be defined by the caller for special purposes.
*
- * Portions Copyright (c) 2003-2013, PgPool Global Development Group
- * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
+ * Portions Copyright (c) 2003-2014, PgPool Global Development Group
+ * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -142,6 +142,7 @@ PG_KEYWORD("encrypted", ENCRYPTED, UNRESERVED_KEYWORD)
PG_KEYWORD("end", END_P, RESERVED_KEYWORD)
PG_KEYWORD("enum", ENUM_P, UNRESERVED_KEYWORD)
PG_KEYWORD("escape", ESCAPE, UNRESERVED_KEYWORD)
+PG_KEYWORD("event", EVENT, UNRESERVED_KEYWORD)
PG_KEYWORD("except", EXCEPT, RESERVED_KEYWORD)
PG_KEYWORD("exclude", EXCLUDE, UNRESERVED_KEYWORD)
PG_KEYWORD("excluding", EXCLUDING, UNRESERVED_KEYWORD)
@@ -155,6 +156,7 @@ PG_KEYWORD("extract", EXTRACT, COL_NAME_KEYWORD)
PG_KEYWORD("false", FALSE_P, RESERVED_KEYWORD)
PG_KEYWORD("family", FAMILY, UNRESERVED_KEYWORD)
PG_KEYWORD("fetch", FETCH, RESERVED_KEYWORD)
+PG_KEYWORD("filter", FILTER, UNRESERVED_KEYWORD)
PG_KEYWORD("first", FIRST_P, UNRESERVED_KEYWORD)
PG_KEYWORD("float", FLOAT_P, COL_NAME_KEYWORD)
PG_KEYWORD("following", FOLLOWING, UNRESERVED_KEYWORD)
@@ -213,6 +215,7 @@ PG_KEYWORD("label", LABEL, UNRESERVED_KEYWORD)
PG_KEYWORD("language", LANGUAGE, UNRESERVED_KEYWORD)
PG_KEYWORD("large", LARGE_P, UNRESERVED_KEYWORD)
PG_KEYWORD("last", LAST_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("lateral", LATERAL_P, RESERVED_KEYWORD)
PG_KEYWORD("lc_collate", LC_COLLATE_P, UNRESERVED_KEYWORD)
PG_KEYWORD("lc_ctype", LC_CTYPE_P, UNRESERVED_KEYWORD)
PG_KEYWORD("leading", LEADING, RESERVED_KEYWORD)
@@ -231,6 +234,7 @@ PG_KEYWORD("location", LOCATION, UNRESERVED_KEYWORD)
PG_KEYWORD("lock", LOCK_P, UNRESERVED_KEYWORD)
PG_KEYWORD("mapping", MAPPING, UNRESERVED_KEYWORD)
PG_KEYWORD("match", MATCH, UNRESERVED_KEYWORD)
+PG_KEYWORD("materialized", MATERIALIZED, UNRESERVED_KEYWORD)
PG_KEYWORD("maxvalue", MAXVALUE, UNRESERVED_KEYWORD)
PG_KEYWORD("minute", MINUTE_P, UNRESERVED_KEYWORD)
PG_KEYWORD("minvalue", MINVALUE, UNRESERVED_KEYWORD)
@@ -266,9 +270,10 @@ PG_KEYWORD("option", OPTION, UNRESERVED_KEYWORD)
PG_KEYWORD("options", OPTIONS, UNRESERVED_KEYWORD)
PG_KEYWORD("or", OR, RESERVED_KEYWORD)
PG_KEYWORD("order", ORDER, RESERVED_KEYWORD)
+PG_KEYWORD("ordinality", ORDINALITY, UNRESERVED_KEYWORD)
PG_KEYWORD("out", OUT_P, COL_NAME_KEYWORD)
PG_KEYWORD("outer", OUTER_P, TYPE_FUNC_NAME_KEYWORD)
-PG_KEYWORD("over", OVER, TYPE_FUNC_NAME_KEYWORD)
+PG_KEYWORD("over", OVER, UNRESERVED_KEYWORD)
PG_KEYWORD("overlaps", OVERLAPS, TYPE_FUNC_NAME_KEYWORD)
PG_KEYWORD("overlay", OVERLAY, COL_NAME_KEYWORD)
PG_KEYWORD("owned", OWNED, UNRESERVED_KEYWORD)
@@ -291,6 +296,7 @@ PG_KEYWORD("prior", PRIOR, UNRESERVED_KEYWORD)
PG_KEYWORD("privileges", PRIVILEGES, UNRESERVED_KEYWORD)
PG_KEYWORD("procedural", PROCEDURAL, UNRESERVED_KEYWORD)
PG_KEYWORD("procedure", PROCEDURE, UNRESERVED_KEYWORD)
+PG_KEYWORD("program", PROGRAM, UNRESERVED_KEYWORD)
PG_KEYWORD("quote", QUOTE, UNRESERVED_KEYWORD)
PG_KEYWORD("range", RANGE, UNRESERVED_KEYWORD)
PG_KEYWORD("read", READ, UNRESERVED_KEYWORD)
@@ -300,6 +306,7 @@ PG_KEYWORD("recheck", RECHECK, UNRESERVED_KEYWORD)
PG_KEYWORD("recursive", RECURSIVE, UNRESERVED_KEYWORD)
PG_KEYWORD("ref", REF, UNRESERVED_KEYWORD)
PG_KEYWORD("references", REFERENCES, RESERVED_KEYWORD)
+PG_KEYWORD("refresh", REFRESH, UNRESERVED_KEYWORD)
PG_KEYWORD("reindex", REINDEX, UNRESERVED_KEYWORD)
PG_KEYWORD("relative", RELATIVE_P, UNRESERVED_KEYWORD)
PG_KEYWORD("release", RELEASE, UNRESERVED_KEYWORD)
@@ -400,12 +407,14 @@ PG_KEYWORD("varying", VARYING, UNRESERVED_KEYWORD)
PG_KEYWORD("verbose", VERBOSE, TYPE_FUNC_NAME_KEYWORD)
PG_KEYWORD("version", VERSION_P, UNRESERVED_KEYWORD)
PG_KEYWORD("view", VIEW, UNRESERVED_KEYWORD)
+PG_KEYWORD("views", VIEWS, UNRESERVED_KEYWORD)
PG_KEYWORD("volatile", VOLATILE, UNRESERVED_KEYWORD)
PG_KEYWORD("when", WHEN, RESERVED_KEYWORD)
PG_KEYWORD("where", WHERE, RESERVED_KEYWORD)
PG_KEYWORD("whitespace", WHITESPACE_P, UNRESERVED_KEYWORD)
PG_KEYWORD("window", WINDOW, RESERVED_KEYWORD)
PG_KEYWORD("with", WITH, RESERVED_KEYWORD)
+PG_KEYWORD("within", WITHIN, UNRESERVED_KEYWORD)
PG_KEYWORD("without", WITHOUT, UNRESERVED_KEYWORD)
PG_KEYWORD("work", WORK, UNRESERVED_KEYWORD)
PG_KEYWORD("wrapper", WRAPPER, UNRESERVED_KEYWORD)
diff --git a/src/include/parser/nodes.h b/src/include/parser/nodes.h
index ce82521..aa85aa7 100644
--- a/src/include/parser/nodes.h
+++ b/src/include/parser/nodes.h
@@ -4,11 +4,11 @@
* Definitions for tagged nodes.
*
*
- * Portions Copyright (c) 2003-2013, PgPool Global Development Group
- * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
+ * Portions Copyright (c) 2003-2014, PgPool Global Development Group
+ * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * src/include/nodes/parsenodes.h
+ * src/include/nodes/nodes.h
*
*-------------------------------------------------------------------------
*/
@@ -181,6 +181,7 @@ typedef enum NodeTag
*/
T_ExprState = 400,
T_GenericExprState,
+ T_WholeRowVarExprState,
T_AggrefExprState,
T_WindowFuncExprState,
T_ArrayRefExprState,
@@ -205,7 +206,6 @@ typedef enum NodeTag
T_NullTestState,
T_CoerceToDomainState,
T_DomainConstraintState,
- T_WholeRowVarExprState, /* will be in a more natural position in 9.3 */
/*
* TAGS FOR PLANNER NODES (relation.h)
@@ -236,6 +236,7 @@ typedef enum NodeTag
T_RestrictInfo,
T_PlaceHolderVar,
T_SpecialJoinInfo,
+ T_LateralJoinInfo,
T_AppendRelInfo,
T_PlaceHolderInfo,
T_MinMaxAggInfo,
@@ -354,11 +355,17 @@ typedef enum NodeTag
T_AlterUserMappingStmt,
T_DropUserMappingStmt,
T_AlterTableSpaceOptionsStmt,
+ T_AlterTableSpaceMoveStmt,
T_SecLabelStmt,
T_CreateForeignTableStmt,
T_CreateExtensionStmt,
T_AlterExtensionStmt,
T_AlterExtensionContentsStmt,
+ T_CreateEventTrigStmt,
+ T_AlterEventTrigStmt,
+ T_RefreshMatViewStmt,
+ T_ReplicaIdentityStmt,
+ T_AlterSystemStmt,
/*
* TAGS FOR PARSE TREE NODES (parsenodes.h)
@@ -385,6 +392,8 @@ typedef enum NodeTag
T_Constraint,
T_DefElem,
T_RangeTblEntry,
+ T_RangeTblFunction,
+ T_WithCheckOption,
T_SortGroupClause,
T_WindowClause,
T_PrivGrantee,
@@ -404,7 +413,10 @@ typedef enum NodeTag
*/
T_IdentifySystemCmd,
T_BaseBackupCmd,
+ T_CreateReplicationSlotCmd,
+ T_DropReplicationSlotCmd,
T_StartReplicationCmd,
+ T_TimeLineHistoryCmd,
/*
* TAGS FOR RANDOM OTHER STUFF
@@ -415,6 +427,7 @@ typedef enum NodeTag
* pass multiple object types through the same pointer).
*/
T_TriggerData = 950, /* 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 */
@@ -449,14 +462,13 @@ typedef struct Node
#ifdef __GNUC__
/* With GCC, we can use a compound statement within an expression */
-/* XXX AssertMacro was removed */
#define newNode(size, tag) \
({ Node *_result; \
+ AssertMacro((size) >= sizeof(Node)); /* need the tag, at least */ \
_result = (Node *) palloc0fast(size); \
_result->type = (tag); \
_result; \
})
-
#else
/*
@@ -465,7 +477,7 @@ typedef struct Node
* Fortunately, this macro isn't recursive so we just define
* a global variable for this purpose.
*/
-extern Node *newNodeMacroHolder;
+extern Node *newNodeMacroHolder;
#define newNode(size, tag) \
( \
@@ -490,7 +502,7 @@ extern Node *newNodeMacroHolder;
/*
* nodes/{outfuncs.c,print.c}
*/
-extern char *nodeToString(void *obj);
+extern char *nodeToString(const void *obj);
/*
* nodes/{readfuncs.c,read.c}
@@ -564,7 +576,7 @@ typedef enum JoinType
/*
* 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
+ * 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
@@ -588,7 +600,7 @@ typedef enum 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
+ * 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.
*
diff --git a/src/include/parser/parsenodes.h b/src/include/parser/parsenodes.h
index d3b2545..c1ed7a5 100644
--- a/src/include/parser/parsenodes.h
+++ b/src/include/parser/parsenodes.h
@@ -9,9 +9,8 @@
* the node. Access to the original source text is needed to make use of
* the location.
*
- *
- * Portions Copyright (c) 2003-2013, PgPool Global Development Group
- * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
+ * Portions Copyright (c) 2003-2014, PgPool Global Development Group
+ * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/include/nodes/parsenodes.h
@@ -25,7 +24,9 @@
#include "primnodes.h"
#include "value.h"
-/* include/nodes/bitmapset.h start */
+/*
+ * include/nodes/bitmapset.h start
+ */
typedef uint32 bitmapword; /* must be an unsigned type */
typedef struct Bitmapset
@@ -36,7 +37,6 @@ typedef struct Bitmapset
extern Bitmapset *bms_copy(const Bitmapset *a);
/* include/nodes/bitmapset.h end */
-
/* Possible sources of a Query */
typedef enum QuerySource
@@ -88,7 +88,7 @@ typedef uint32 AclMode; /* a bitmask of privilege bits */
#define ACL_CONNECT (1<<11) /* for databases */
#define N_ACL_RIGHTS 12 /* 1 plus the last 1<<x */
#define ACL_NO_RIGHTS 0
-/* Currently, SELECT ... FOR UPDATE/FOR SHARE requires UPDATE privileges */
+/* Currently, SELECT ... FOR [KEY] UPDATE/SHARE requires UPDATE privileges */
#define ACL_SELECT_FOR_UPDATE ACL_UPDATE
@@ -133,7 +133,7 @@ typedef struct Query
bool hasDistinctOn; /* distinctClause is from DISTINCT ON */
bool hasRecursive; /* WITH RECURSIVE was specified */
bool hasModifyingCTE; /* has INSERT/UPDATE/DELETE in WITH */
- bool hasForUpdate; /* FOR UPDATE or FOR SHARE was specified */
+ bool hasForUpdate; /* FOR [KEY] UPDATE/SHARE was specified */
List *cteList; /* WITH list (of CommonTableExpr's) */
@@ -142,6 +142,8 @@ typedef struct Query
List *targetList; /* target list (of TargetEntry) */
+ List *withCheckOptions; /* a list of WithCheckOption's */
+
List *returningList; /* return-values list (of TargetEntry) */
List *groupClause; /* a list of SortGroupClause's */
@@ -171,7 +173,7 @@ typedef struct Query
* Supporting data structures for Parse Trees
*
* Most of these node types appear in raw parsetrees output by the grammar,
- * and get transformed to something else by the analyzer. A few of them
+ * and get transformed to something else by the analyzer. A few of them
* are used as-is in transformed querytrees.
****************************************************************************/
@@ -185,7 +187,7 @@ typedef struct Query
* be prespecified in typemod, otherwise typemod is unused.
*
* If pct_type is TRUE, then names is actually a field name and we look up
- * the type of that field. Otherwise (the normal case), names is a type
+ * the type of that field. Otherwise (the normal case), names is a type
* name possibly qualified with schema and database name.
*/
typedef struct TypeName
@@ -204,7 +206,7 @@ typedef struct TypeName
/*
* ColumnRef - specifies a reference to a column, or possibly a whole tuple
*
- * The "fields" list must be nonempty. It can contain string Value nodes
+ * The "fields" list must be nonempty. It can contain string Value nodes
* (representing names) and A_Star nodes (representing occurrence of a '*').
* Currently, A_Star must appear only as the last list element --- the grammar
* is responsible for enforcing this!
@@ -293,12 +295,16 @@ typedef struct CollateClause
/*
* FuncCall - a function or aggregate invocation
*
- * agg_order (if not NIL) indicates we saw 'foo(... ORDER BY ...)'.
+ * agg_order (if not NIL) indicates we saw 'foo(... ORDER BY ...)', or if
+ * agg_within_group is true, it was 'foo(...) WITHIN GROUP (ORDER BY ...)'.
* agg_star indicates we saw a 'foo(*)' construct, while agg_distinct
* indicates we saw 'foo(DISTINCT ...)'. In any of these cases, the
* construct *must* be an aggregate call. Otherwise, it might be either an
- * aggregate or some other kind of function. However, if OVER is present
- * it had better be an aggregate or window function.
+ * aggregate or some other kind of function. However, if FILTER or OVER is
+ * present it had better be an aggregate or window function.
+ *
+ * Normally, you'd initialize this via makeFuncCall() and then only change the
+ * parts of the struct its defaults don't match afterwards, as needed.
*/
typedef struct FuncCall
{
@@ -306,6 +312,8 @@ typedef struct FuncCall
List *funcname; /* qualified name of function */
List *args; /* the arguments (list of exprs) */
List *agg_order; /* ORDER BY (list of SortBy) */
+ Node *agg_filter; /* FILTER clause, if any */
+ bool agg_within_group; /* ORDER BY appeared in WITHIN GROUP */
bool agg_star; /* argument was really '*' */
bool agg_distinct; /* arguments were labeled DISTINCT */
bool func_variadic; /* last argument was labeled VARIADIC */
@@ -465,17 +473,32 @@ typedef struct WindowDef
typedef struct RangeSubselect
{
NodeTag type;
+ bool lateral; /* does it have LATERAL prefix? */
Node *subquery; /* the untransformed sub-select clause */
Alias *alias; /* table alias & optional column aliases */
} RangeSubselect;
/*
* RangeFunction - function call appearing in a FROM clause
+ *
+ * functions is a List because we use this to represent the construct
+ * ROWS FROM(func1(...), func2(...), ...). Each element of this list is a
+ * two-element sublist, the first element being the untransformed function
+ * call tree, and the second element being a possibly-empty list of ColumnDef
+ * nodes representing any columndef list attached to that function within the
+ * ROWS FROM() syntax.
+ *
+ * alias and coldeflist represent any alias and/or columndef list attached
+ * at the top level. (We disallow coldeflist appearing both here and
+ * per-function, but that's checked in parse analysis, not by the grammar.)
*/
typedef struct RangeFunction
{
NodeTag type;
- Node *funccallnode; /* untransformed function call tree */
+ bool lateral; /* does it have LATERAL prefix? */
+ bool ordinality; /* does it have WITH ORDINALITY suffix? */
+ bool is_rowsfrom; /* is result of ROWS FROM() syntax? */
+ List *functions; /* per-function information, see above */
Alias *alias; /* table alias & optional column aliases */
List *coldeflist; /* list of ColumnDef nodes to describe result
* of function returning RECORD */
@@ -488,7 +511,7 @@ typedef struct RangeFunction
* in either "raw" form (an untransformed parse tree) or "cooked" form
* (a post-parse-analysis, executable expression tree), depending on
* how this ColumnDef node was created (by parsing, or by inheritance
- * from an existing relation). We should never have both in the same node!
+ * from an existing relation). We should never have both in the same node!
*
* Similarly, we may have a COLLATE specification in either raw form
* (represented as a CollateClause with arg==NULL) or cooked form
@@ -515,6 +538,7 @@ typedef struct ColumnDef
Oid collOid; /* collation OID (InvalidOid if not set) */
List *constraints; /* other constraints on column */
List *fdwoptions; /* per-column FDW options */
+ int location; /* parse location, or -1 if none/unknown */
} ColumnDef;
/*
@@ -559,7 +583,7 @@ typedef struct IndexElem
/*
* DefElem - a generic "name = value" option definition
*
- * In some contexts the name can be qualified. Also, certain SQL commands
+ * In some contexts the name can be qualified. Also, certain SQL commands
* allow a SET/ADD/DROP action to be attached to option settings, so it's
* convenient to carry a field for that too. (Note: currently, it is our
* practice that the grammar allows namespace and action only in statements
@@ -584,18 +608,28 @@ typedef struct DefElem
} DefElem;
/*
- * LockingClause - raw representation of FOR UPDATE/SHARE options
+ * LockingClause - raw representation of FOR [NO KEY] UPDATE/[KEY] SHARE
+ * options
*
- * Note: lockedRels == NIL means "all relations in query". Otherwise it
+ * Note: lockedRels == NIL means "all relations in query". Otherwise it
* is a list of RangeVar nodes. (We use RangeVar mainly because it carries
* a location field --- currently, parse analysis insists on unqualified
* names in LockingClause.)
*/
+typedef enum LockClauseStrength
+{
+ /* order is important -- see applyLockingClause */
+ LCS_FORKEYSHARE,
+ LCS_FORSHARE,
+ LCS_FORNOKEYUPDATE,
+ LCS_FORUPDATE
+} LockClauseStrength;
+
typedef struct LockingClause
{
NodeTag type;
- List *lockedRels; /* FOR UPDATE or FOR SHARE relations */
- bool forUpdate; /* true = FOR UPDATE, false = FOR SHARE */
+ List *lockedRels; /* FOR [KEY] UPDATE/SHARE relations */
+ LockClauseStrength strength;
bool noWait; /* NOWAIT option */
} LockingClause;
@@ -641,20 +675,20 @@ typedef struct XmlSerialize
*
* In RELATION RTEs, the colnames in both alias and eref are indexed by
* physical attribute number; this means there must be colname entries for
- * dropped columns. When building an RTE we insert empty strings ("") for
- * dropped columns. Note however that a stored rule may have nonempty
+ * dropped columns. When building an RTE we insert empty strings ("") for
+ * dropped columns. Note however that a stored rule may have nonempty
* colnames for columns dropped since the rule was created (and for that
* matter the colnames might be out of date due to column renamings).
- * The same comments apply to FUNCTION RTEs when the function's return type
+ * The same comments apply to FUNCTION RTEs when a function's return type
* is a named composite type.
*
* In JOIN RTEs, the colnames in both alias and eref are one-to-one with
* joinaliasvars entries. A JOIN RTE will omit columns of its inputs when
- * those columns are known to be dropped at parse time. Again, however,
+ * those columns are known to be dropped at parse time. Again, however,
* a stored rule might contain entries for columns dropped since the rule
- * was created. (This is only possible for columns not actually referenced
+ * was created. (This is only possible for columns not actually referenced
* in the rule.) When loading a stored rule, we replace the joinaliasvars
- * items for any such columns with NULL Consts. (We can't simply delete
+ * items for any such columns with null pointers. (We can't simply delete
* them from the joinaliasvars list, because that would affect the attnums
* of Vars referencing the rest of the list.)
*
@@ -671,7 +705,7 @@ typedef struct XmlSerialize
* decompiled queries.
*
* requiredPerms and checkAsUser specify run-time access permissions
- * checks to be performed at query startup. The user must have *all*
+ * checks to be performed at query startup. The user must have *all*
* of the permissions that are OR'd together in requiredPerms (zero
* indicates no permissions checking). If checkAsUser is not zero,
* then do the permissions checks using the access rights of that user,
@@ -720,34 +754,38 @@ typedef struct RangeTblEntry
* Fields valid for a subquery RTE (else NULL):
*/
Query *subquery; /* the sub-query */
- bool security_barrier; /* subquery from security_barrier view */
+ bool security_barrier; /* is from security_barrier view? */
/*
* Fields valid for a join RTE (else NULL/zero):
*
- * joinaliasvars is a list of Vars or COALESCE expressions corresponding
- * to the columns of the join result. An alias Var referencing column K
- * of the join result can be replaced by the K'th element of joinaliasvars
- * --- but to simplify the task of reverse-listing aliases correctly, we
- * do not do that until planning time. In a Query loaded from a stored
- * rule, it is also possible for joinaliasvars items to be NULL Consts,
- * denoting columns dropped since the rule was made.
+ * joinaliasvars is a list of (usually) Vars corresponding to the columns
+ * of the join result. An alias Var referencing column K of the join
+ * result can be replaced by the K'th element of joinaliasvars --- but to
+ * simplify the task of reverse-listing aliases correctly, we do not do
+ * that until planning time. In detail: an element of joinaliasvars can
+ * be a Var of one of the join's input relations, or such a Var with an
+ * implicit coercion to the join's output column type, or a COALESCE
+ * expression containing the two input column Vars (possibly coerced).
+ * Within a Query loaded from a stored rule, it is also possible for
+ * joinaliasvars items to be null pointers, which are placeholders for
+ * (necessarily unreferenced) columns dropped since the rule was made.
+ * Also, once planning begins, joinaliasvars items can be almost anything,
+ * as a result of subquery-flattening substitutions.
*/
JoinType jointype; /* type of join */
List *joinaliasvars; /* list of alias-var expansions */
/*
- * Fields valid for a function RTE (else NULL):
+ * Fields valid for a function RTE (else NIL/zero):
*
- * If the function returns RECORD, funccoltypes lists the column types
- * declared in the RTE's column type specification, funccoltypmods lists
- * their declared typmods, funccolcollations their collations. Otherwise,
- * those fields are NIL.
+ * When funcordinality is true, the eref->colnames list includes an alias
+ * for the ordinality column. The ordinality column is otherwise
+ * implicit, and must be accounted for "by hand" in places such as
+ * expandRTE().
*/
- Node *funcexpr; /* expression tree for func call */
- List *funccoltypes; /* OID list of column type OIDs */
- List *funccoltypmods; /* integer list of column typmods */
- List *funccolcollations; /* OID list of column collation OIDs */
+ List *functions; /* list of RangeTblFunction nodes */
+ bool funcordinality; /* is this called WITH ORDINALITY? */
/*
* Fields valid for a values RTE (else NIL):
@@ -770,15 +808,61 @@ typedef struct RangeTblEntry
*/
Alias *alias; /* user-written alias clause, if any */
Alias *eref; /* expanded reference names */
+ bool lateral; /* subquery, function, or values is LATERAL? */
bool inh; /* inheritance requested? */
bool inFromCl; /* present in FROM clause? */
AclMode requiredPerms; /* bitmask of required access permissions */
Oid checkAsUser; /* if valid, check access as this role */
Bitmapset *selectedCols; /* columns needing SELECT permission */
Bitmapset *modifiedCols; /* columns needing INSERT/UPDATE permission */
+ List *securityQuals; /* any security barrier quals to apply */
} RangeTblEntry;
/*
+ * RangeTblFunction -
+ * RangeTblEntry subsidiary data for one function in a FUNCTION RTE.
+ *
+ * If the function had a column definition list (required for an
+ * otherwise-unspecified RECORD result), funccolnames lists the names given
+ * in the definition list, funccoltypes lists their declared column types,
+ * funccoltypmods lists their typmods, funccolcollations their collations.
+ * Otherwise, those fields are NIL.
+ *
+ * Notice we don't attempt to store info about the results of functions
+ * returning named composite types, because those can change from time to
+ * time. We do however remember how many columns we thought the type had
+ * (including dropped columns!), so that we can successfully ignore any
+ * columns added after the query was parsed.
+ */
+typedef struct RangeTblFunction
+{
+ NodeTag type;
+
+ Node *funcexpr; /* expression tree for func call */
+ int funccolcount; /* number of columns it contributes to RTE */
+ /* These fields record the contents of a column definition list, if any: */
+ List *funccolnames; /* column names (list of String) */
+ List *funccoltypes; /* OID list of column type OIDs */
+ List *funccoltypmods; /* integer list of column typmods */
+ List *funccolcollations; /* OID list of column collation OIDs */
+ /* This is set during planning for use by the executor: */
+ Bitmapset *funcparams; /* PARAM_EXEC Param IDs affecting this func */
+} RangeTblFunction;
+
+/*
+ * WithCheckOption -
+ * representation of WITH CHECK OPTION checks to be applied to new tuples
+ * when inserting/updating an auto-updatable view.
+ */
+typedef struct WithCheckOption
+{
+ NodeTag type;
+ char *viewname; /* name of view that specified the WCO */
+ Node *qual; /* constraint qual to check */
+ bool cascaded; /* true = WITH CASCADED CHECK OPTION */
+} WithCheckOption;
+
+/*
* SortGroupClause -
* representation of ORDER BY, GROUP BY, PARTITION BY,
* DISTINCT, DISTINCT ON items
@@ -786,7 +870,7 @@ typedef struct RangeTblEntry
* You might think that ORDER BY is only interested in defining ordering,
* and GROUP/DISTINCT are only interested in defining equality. However,
* one way to implement grouping is to sort and then apply a "uniq"-like
- * filter. So it's also interesting to keep track of possible sort operators
+ * filter. So it's also interesting to keep track of possible sort operators
* for GROUP/DISTINCT, and in particular to try to sort for the grouping
* in a way that will also yield a requested ORDER BY ordering. So we need
* to be able to compare ORDER BY and GROUP/DISTINCT lists, which motivates
@@ -806,15 +890,15 @@ typedef struct RangeTblEntry
* here, but it's cheap to get it along with the sortop, and requiring it
* to be valid eases comparisons to grouping items.) Note that this isn't
* actually enough information to determine an ordering: if the sortop is
- * collation-sensitive, a collation OID is needed too. We don't store the
+ * collation-sensitive, a collation OID is needed too. We don't store the
* collation in SortGroupClause because it's not available at the time the
* parser builds the SortGroupClause; instead, consult the exposed collation
* of the referenced targetlist expression to find out what it is.
*
- * In a grouping item, eqop must be valid. If the eqop is a btree equality
+ * In a grouping item, eqop must be valid. If the eqop is a btree equality
* operator, then sortop should be set to a compatible ordering operator.
* We prefer to set eqop/sortop/nulls_first to match any ORDER BY item that
- * the query presents for the same tlist item. If there is none, we just
+ * the query presents for the same tlist item. If there is none, we just
* use the default ordering op for the datatype.
*
* If the tlist item's type has a hash opclass but no btree opclass, then
@@ -876,21 +960,21 @@ typedef struct WindowClause
/*
* RowMarkClause -
- * parser output representation of FOR UPDATE/SHARE clauses
+ * parser output representation of FOR [KEY] UPDATE/SHARE clauses
*
* Query.rowMarks contains a separate RowMarkClause node for each relation
- * identified as a FOR UPDATE/SHARE target. If FOR UPDATE/SHARE is applied
- * to a subquery, we generate RowMarkClauses for all normal and subquery rels
- * in the subquery, but they are marked pushedDown = true to distinguish them
- * from clauses that were explicitly written at this query level. Also,
- * Query.hasForUpdate tells whether there were explicit FOR UPDATE/SHARE
- * clauses in the current query level.
+ * identified as a FOR [KEY] UPDATE/SHARE target. If one of these clauses
+ * is applied to a subquery, we generate RowMarkClauses for all normal and
+ * subquery rels in the subquery, but they are marked pushedDown = true to
+ * distinguish them from clauses that were explicitly written at this query
+ * level. Also, Query.hasForUpdate tells whether there were explicit FOR
+ * UPDATE/SHARE/KEY SHARE clauses in the current query level.
*/
typedef struct RowMarkClause
{
NodeTag type;
Index rti; /* range table index of target relation */
- bool forUpdate; /* true = FOR UPDATE, false = FOR SHARE */
+ LockClauseStrength strength;
bool noWait; /* NOWAIT option */
bool pushedDown; /* pushed down from higher query level? */
} RowMarkClause;
@@ -1030,7 +1114,6 @@ typedef struct SelectStmt
List *groupClause; /* GROUP BY clauses */
Node *havingClause; /* HAVING conditional-expression */
List *windowClause; /* WINDOW window_name AS (...), ... */
- WithClause *withClause; /* WITH clause */
/*
* In a "leaf" node representing a VALUES list, the above fields are all
@@ -1050,6 +1133,7 @@ typedef struct SelectStmt
Node *limitOffset; /* # of result tuples to skip */
Node *limitCount; /* # of result tuples to return */
List *lockingClause; /* FOR UPDATE (list of LockingClause's) */
+ WithClause *withClause; /* WITH clause */
/*
* These fields are used only in upper-level SelectStmts.
@@ -1070,7 +1154,7 @@ typedef struct SelectStmt
* range table. Its setOperations field shows the tree of set operations,
* with leaf SelectStmt nodes replaced by RangeTblRef nodes, and internal
* nodes replaced by SetOperationStmt nodes. Information about the output
- * column types is added, too. (Note that the child nodes do not necessarily
+ * column types is added, too. (Note that the child nodes do not necessarily
* produce these types directly, but we've checked that their output types
* can be coerced to the output column type.) Also, if it's not UNION ALL,
* information about the types' sort/group semantics is provided in the form
@@ -1127,6 +1211,7 @@ typedef enum ObjectType
OBJECT_CONVERSION,
OBJECT_DATABASE,
OBJECT_DOMAIN,
+ OBJECT_EVENT_TRIGGER,
OBJECT_EXTENSION,
OBJECT_FDW,
OBJECT_FOREIGN_SERVER,
@@ -1135,6 +1220,7 @@ typedef enum ObjectType
OBJECT_INDEX,
OBJECT_LANGUAGE,
OBJECT_LARGEOBJECT,
+ OBJECT_MATVIEW,
OBJECT_OPCLASS,
OBJECT_OPERATOR,
OBJECT_OPFAMILY,
@@ -1167,6 +1253,7 @@ typedef struct CreateSchemaStmt
char *schemaname; /* the name of the schema to create */
char *authid; /* the owner of the created schema */
List *schemaElts; /* schema components (list of parsenodes) */
+ bool if_not_exists; /* just do nothing if schema already exists? */
} CreateSchemaStmt;
typedef enum DropBehavior
@@ -1206,6 +1293,8 @@ typedef enum AlterTableType
AT_ReAddIndex, /* internal to commands/tablecmds.c */
AT_AddConstraint, /* add constraint */
AT_AddConstraintRecurse, /* internal to commands/tablecmds.c */
+ AT_ReAddConstraint, /* internal to commands/tablecmds.c */
+ AT_AlterConstraint, /* alter constraint */
AT_ValidateConstraint, /* validate constraint */
AT_ValidateConstraintRecurse, /* internal to commands/tablecmds.c */
AT_ProcessedConstraint, /* pre-processed add constraint (local in
@@ -1241,11 +1330,17 @@ typedef enum AlterTableType
AT_DropInherit, /* NO INHERIT parent */
AT_AddOf, /* OF <type_name> */
AT_DropOf, /* NOT OF */
- AT_GenericOptions, /* OPTIONS (...) */
- /* this will be in a more natural position in 9.3: */
- AT_ReAddConstraint /* internal to commands/tablecmds.c */
+ AT_ReplicaIdentity, /* REPLICA IDENTITY */
+ AT_GenericOptions /* OPTIONS (...) */
} AlterTableType;
+typedef struct ReplicaIdentityStmt
+{
+ NodeTag type;
+ char identity_type;
+ char *name;
+} ReplicaIdentityStmt;
+
typedef struct AlterTableCmd /* one subcommand of an ALTER TABLE */
{
NodeTag type;
@@ -1365,7 +1460,7 @@ typedef struct AccessPriv
*
* Note: because of the parsing ambiguity with the GRANT <privileges>
* statement, granted_roles is a list of AccessPriv; the execution code
- * should complain if any column lists appear. grantee_roles is a list
+ * should complain if any column lists appear. grantee_roles is a list
* of role names, as Value strings.
* ----------------------
*/
@@ -1395,7 +1490,7 @@ typedef struct AlterDefaultPrivilegesStmt
* Copy Statement
*
* We support "COPY relation FROM file", "COPY relation TO file", and
- * "COPY (query) TO file". In any given CopyStmt, exactly one of "relation"
+ * "COPY (query) TO file". In any given CopyStmt, exactly one of "relation"
* and "query" must be non-NULL.
* ----------------------
*/
@@ -1407,6 +1502,7 @@ typedef struct CopyStmt
List *attlist; /* List of column names (as Strings), or NIL
* for all columns */
bool is_from; /* TO or FROM */
+ bool is_program; /* is 'filename' a program to popen? */
char *filename; /* filename, or NULL for STDIN/STDOUT */
List *options; /* List of DefElem nodes */
} CopyStmt;
@@ -1493,7 +1589,7 @@ typedef struct CreateStmt
*
* If skip_validation is true then we skip checking that the existing rows
* in the table satisfy the constraint, and just install the catalog entries
- * for the constraint. A new FK constraint is marked as valid iff
+ * for the constraint. A new FK constraint is marked as valid iff
* initially_valid is true. (Usually skip_validation and initially_valid
* are inverses, but we can set both true if the table is known empty.)
*
@@ -1506,7 +1602,8 @@ typedef struct CreateStmt
typedef enum ConstrType /* types of constraints */
{
- CONSTR_NULL, /* not SQL92, but a lot of people expect it */
+ CONSTR_NULL, /* not standard SQL, but a lot of people
+ * expect it */
CONSTR_NOTNULL,
CONSTR_DEFAULT,
CONSTR_CHECK,
@@ -1530,7 +1627,7 @@ typedef enum ConstrType /* types of constraints */
/* Foreign key matchtype codes */
#define FKCONSTR_MATCH_FULL 'f'
#define FKCONSTR_MATCH_PARTIAL 'p'
-#define FKCONSTR_MATCH_UNSPECIFIED 'u'
+#define FKCONSTR_MATCH_SIMPLE 's'
typedef struct Constraint
{
@@ -1566,10 +1663,11 @@ typedef struct Constraint
RangeVar *pktable; /* Primary key table */
List *fk_attrs; /* Attributes of foreign key */
List *pk_attrs; /* Corresponding attrs in PK table */
- char fk_matchtype; /* FULL, PARTIAL, UNSPECIFIED */
+ char fk_matchtype; /* FULL, PARTIAL, SIMPLE */
char fk_upd_action; /* ON UPDATE action */
char fk_del_action; /* ON DELETE action */
List *old_conpfeqop; /* pg_constraint.conpfeqop of my former self */
+ Oid old_pktable_oid; /* pg_constraint.confrelid of my former self */
/* Fields used for constraints that allow a NOT VALID specification */
bool skip_validation; /* skip validation of existing rows? */
@@ -1587,6 +1685,7 @@ typedef struct CreateTableSpaceStmt
char *tablespacename;
char *owner;
char *location;
+ List *options;
} CreateTableSpaceStmt;
typedef struct DropTableSpaceStmt
@@ -1604,6 +1703,17 @@ typedef struct AlterTableSpaceOptionsStmt
bool isReset;
} AlterTableSpaceOptionsStmt;
+typedef struct AlterTableSpaceMoveStmt
+{
+ NodeTag type;
+ char *orig_tablespacename;
+ ObjectType objtype; /* set to -1 if move_all is true */
+ bool move_all; /* move all, or just objtype objects? */
+ List *roles; /* List of roles to move objects of */
+ char *new_tablespacename;
+ bool nowait;
+} AlterTableSpaceMoveStmt;
+
/* ----------------------
* Create/Alter Extension Statements
* ----------------------
@@ -1747,6 +1857,32 @@ typedef struct CreateTrigStmt
} CreateTrigStmt;
/* ----------------------
+ * Create EVENT TRIGGER Statement
+ * ----------------------
+ */
+typedef struct CreateEventTrigStmt
+{
+ NodeTag type;
+ char *trigname; /* TRIGGER's name */
+ char *eventname; /* event's identifier */
+ List *whenclause; /* list of DefElems indicating filtering */
+ List *funcname; /* qual. name of function to call */
+} CreateEventTrigStmt;
+
+/* ----------------------
+ * Alter EVENT TRIGGER Statement
+ * ----------------------
+ */
+typedef struct AlterEventTrigStmt
+{
+ NodeTag type;
+ char *trigname; /* TRIGGER's name */
+ char tgenabled; /* trigger's firing configuration WRT
+ * session_replication_role */
+} AlterEventTrigStmt;
+
+/* ----------------------
+ * Create/Drop PROCEDURAL LANGUAGE Statements
* Create PROCEDURAL LANGUAGE Statements
* ----------------------
*/
@@ -1972,7 +2108,7 @@ typedef struct SecLabelStmt
* Declare Cursor Statement
*
* Note: the "query" field of DeclareCursorStmt is only used in the raw grammar
- * output. After parse analysis it's set to null, and the Query points to the
+ * output. After parse analysis it's set to null, and the Query points to the
* DeclareCursorStmt, not vice versa.
* ----------------------
*/
@@ -2154,7 +2290,6 @@ typedef struct AlterObjectSchemaStmt
RangeVar *relation; /* in case it's a table */
List *object; /* in case it's some other object */
List *objarg; /* argument types, if applicable */
- char *addname; /* additional name if needed */
char *newschema; /* the new schema */
bool missing_ok; /* skip error if missing? */
} AlterObjectSchemaStmt;
@@ -2170,7 +2305,6 @@ typedef struct AlterOwnerStmt
RangeVar *relation; /* in case it's a table */
List *object; /* in case it's some other object */
List *objarg; /* argument types, if applicable */
- char *addname; /* additional name if needed */
char *newowner; /* the new owner */
} AlterOwnerStmt;
@@ -2292,12 +2426,20 @@ typedef struct AlterEnumStmt
char *newVal; /* new enum value's name */
char *newValNeighbor; /* neighboring enum value, if specified */
bool newValIsAfter; /* place new enum value after neighbor? */
+ bool skipIfExists; /* no error if label already exists */
} AlterEnumStmt;
/* ----------------------
* Create View Statement
* ----------------------
*/
+typedef enum ViewCheckOption
+{
+ NO_CHECK_OPTION,
+ LOCAL_CHECK_OPTION,
+ CASCADED_CHECK_OPTION
+} ViewCheckOption;
+
typedef struct ViewStmt
{
NodeTag type;
@@ -2306,6 +2448,7 @@ typedef struct ViewStmt
Node *query; /* the SELECT query */
bool replace; /* replace an existing view? */
List *options; /* options from WITH clause */
+ ViewCheckOption withCheckOption; /* WITH CHECK OPTION */
} ViewStmt;
/* ----------------------
@@ -2359,6 +2502,16 @@ typedef struct DropdbStmt
} DropdbStmt;
/* ----------------------
+ * Alter System Statement
+ * ----------------------
+ */
+typedef struct AlterSystemStmt
+{
+ NodeTag type;
+ VariableSetStmt *setstmt; /* SET subcommand */
+} AlterSystemStmt;
+
+/* ----------------------
* Cluster Statement (support pbrown's cluster index implementation)
* ----------------------
*/
@@ -2396,6 +2549,10 @@ typedef struct VacuumStmt
int options; /* OR of VacuumOption flags */
int freeze_min_age; /* min freeze age, or -1 to use default */
int freeze_table_age; /* age at which to scan whole table */
+ int multixact_freeze_min_age; /* min multixact freeze age,
+ * or -1 to use default */
+ int multixact_freeze_table_age; /* multixact age at which to
+ * scan whole table */
RangeVar *relation; /* single table to process, or NULL */
List *va_cols; /* list of column names, or NIL for all */
} VacuumStmt;
@@ -2421,6 +2578,8 @@ typedef struct ExplainStmt
* A query written as CREATE TABLE AS will produce this node type natively.
* A query written as SELECT ... INTO will be transformed to this form during
* parse analysis.
+ * A query written as CREATE MATERIALIZED view will produce this node type,
+ * during parse analysis, since it needs all the same data.
*
* The "query" field is handled similarly to EXPLAIN, though note that it
* can be a SELECT or an EXECUTE, but not other DML statements.
@@ -2431,10 +2590,23 @@ typedef struct CreateTableAsStmt
NodeTag type;
Node *query; /* the query (see comments above) */
IntoClause *into; /* destination table */
+ ObjectType relkind; /* OBJECT_TABLE or OBJECT_MATVIEW */
bool is_select_into; /* it was written as SELECT INTO */
} CreateTableAsStmt;
/* ----------------------
+ * REFRESH MATERIALIZED VIEW Statement
+ * ----------------------
+ */
+typedef struct RefreshMatViewStmt
+{
+ NodeTag type;
+ bool concurrent; /* allow concurrent access? */
+ bool skipData; /* true for WITH NO DATA */
+ RangeVar *relation; /* relation to insert into */
+} RefreshMatViewStmt;
+
+/* ----------------------
* Checkpoint Statement
* ----------------------
*/
@@ -2452,6 +2624,7 @@ typedef enum DiscardMode
{
DISCARD_ALL,
DISCARD_PLANS,
+ DISCARD_SEQUENCES,
DISCARD_TEMP
} DiscardMode;
@@ -2491,7 +2664,7 @@ typedef struct ConstraintsSetStmt
typedef struct ReindexStmt
{
NodeTag type;
- ObjectType kind; /* OBJECT_INDEX, OBJECT_TABLE, OBJECT_DATABASE */
+ ObjectType kind; /* OBJECT_INDEX, OBJECT_TABLE, etc. */
RangeVar *relation; /* Table or index to reindex */
const char *name; /* name of database to reindex */
bool do_system; /* include system tables in database case */
diff --git a/src/include/parser/parser.h b/src/include/parser/parser.h
index 5fa00a0..078d41b 100644
--- a/src/include/parser/parser.h
+++ b/src/include/parser/parser.h
@@ -5,8 +5,8 @@
*
* This is the external API for the raw lexing/parsing functions.
*
- * Portions Copyright (c) 2003-2013, PgPool Global Development Group
- * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
+ * Portions Copyright (c) 2003-2014, PgPool Global Development Group
+ * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/include/parser/parser.h
@@ -16,7 +16,6 @@
#ifndef PARSER_H
#define PARSER_H
-#include "pg_list.h"
#include "parsenodes.h"
@@ -35,12 +34,9 @@ extern PGDLLIMPORT bool standard_conforming_strings;
/* Primary entry point for the raw parsing functions */
extern List *raw_parser(const char *str);
-extern void free_parser(void);
/* Utility functions exported by gram.y (perhaps these should be elsewhere) */
extern List *SystemFuncName(char *name);
extern TypeName *SystemTypeName(char *name);
-extern void parser_set_param(const char *name, const char *value);
-
#endif /* PARSER_H */
diff --git a/src/include/parser/primnodes.h b/src/include/parser/primnodes.h
index d1dc158..56802ec 100644
--- a/src/include/parser/primnodes.h
+++ b/src/include/parser/primnodes.h
@@ -6,9 +6,8 @@
* Currently, these are mostly nodes for executable expressions
* and join trees.
*
- *
- * Portions Copyright (c) 2003-2013, PgPool Global Development Group
- * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
+ * Portions Copyright (c) 2003-2013, PgPool Global Development Group *
+ * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/include/nodes/primnodes.h
@@ -33,7 +32,7 @@
*
* Note: colnames is a list of Value nodes (always strings). In Alias structs
* associated with RTEs, there may be entries corresponding to dropped
- * columns; these are normally empty strings (""). See parsenodes.h for info.
+ * columns; these are normally empty strings (""). See parsenodes.h for info.
*/
typedef struct Alias
{
@@ -80,7 +79,12 @@ typedef struct RangeVar
} RangeVar;
/*
- * IntoClause - target information for SELECT INTO and CREATE TABLE AS
+ * IntoClause - target information for SELECT INTO, CREATE TABLE AS, and
+ * CREATE MATERIALIZED VIEW
+ *
+ * For CREATE MATERIALIZED VIEW, viewQuery is the parsed-but-not-rewritten
+ * SELECT Query for the view; otherwise it's NULL. (Although it's actually
+ * Query*, we declare it as Node* to avoid a forward reference.)
*/
typedef struct IntoClause
{
@@ -91,6 +95,7 @@ typedef struct IntoClause
List *options; /* options from WITH clause */
OnCommitAction onCommit; /* what do we do at COMMIT? */
char *tableSpaceName; /* table space to use, or NULL */
+ Node *viewQuery; /* materialized view's SELECT query */
bool skipData; /* true for WITH NO DATA */
} IntoClause;
@@ -219,17 +224,24 @@ typedef struct Param
/*
* Aggref
*
- * The aggregate's args list is a targetlist, ie, a list of TargetEntry nodes
- * (before Postgres 9.0 it was just bare expressions). The non-resjunk TLEs
+ * The aggregate's args list is a targetlist, ie, a list of TargetEntry nodes.
+ *
+ * For a normal (non-ordered-set) aggregate, the non-resjunk TargetEntries
* represent the aggregate's regular arguments (if any) and resjunk TLEs can
* be added at the end to represent ORDER BY expressions that are not also
* arguments. As in a top-level Query, the TLEs can be marked with
* ressortgroupref indexes to let them be referenced by SortGroupClause
* entries in the aggorder and/or aggdistinct lists. This represents ORDER BY
* and DISTINCT operations to be applied to the aggregate input rows before
- * they are passed to the transition function. The grammar only allows a
+ * they are passed to the transition function. The grammar only allows a
* simple "DISTINCT" specifier for the arguments, but we use the full
* query-level representation to allow more code sharing.
+ *
+ * For an ordered-set aggregate, the args list represents the WITHIN GROUP
+ * (aggregated) arguments, all of which will be listed in the aggorder list.
+ * DISTINCT is not supported in this case, so aggdistinct will be NIL.
+ * The direct arguments appear in aggdirectargs (as a list of plain
+ * expressions, not TargetEntry nodes).
*/
typedef struct Aggref
{
@@ -238,10 +250,15 @@ typedef struct Aggref
Oid aggtype; /* type Oid of result of the aggregate */
Oid aggcollid; /* OID of collation of result */
Oid inputcollid; /* OID of collation that function should use */
- List *args; /* arguments and sort expressions */
+ List *aggdirectargs; /* direct arguments, if an ordered-set agg */
+ List *args; /* aggregated arguments and sort expressions */
List *aggorder; /* ORDER BY (list of SortGroupClause) */
List *aggdistinct; /* DISTINCT (list of SortGroupClause) */
+ Expr *aggfilter; /* FILTER expression, if any */
bool aggstar; /* TRUE if argument list was really '*' */
+ bool aggvariadic; /* true if variadic arguments have been
+ * combined into an array last argument */
+ char aggkind; /* aggregate kind (see pg_aggregate.h) */
Index agglevelsup; /* > 0 if agg belongs to outer query */
int location; /* token location, or -1 if unknown */
} Aggref;
@@ -257,6 +274,7 @@ typedef struct WindowFunc
Oid wincollid; /* OID of collation of result */
Oid inputcollid; /* OID of collation that function should use */
List *args; /* arguments to the window function */
+ Expr *aggfilter; /* FILTER expression, if any */
Index winref; /* index of associated WindowClause */
bool winstar; /* TRUE if argument list was really '*' */
bool winagg; /* is function a simple aggregate? */
@@ -274,7 +292,7 @@ typedef struct WindowFunc
* entire new modified array value.
*
* If reflowerindexpr = NIL, then we are fetching or storing a single array
- * element at the subscripts given by refupperindexpr. Otherwise we are
+ * element at the subscripts given by refupperindexpr. Otherwise we are
* fetching or storing an array slice, that is a rectangular subarray
* with lower and upper bounds given by the index expressions.
* reflowerindexpr must be the same length as refupperindexpr when it
@@ -316,7 +334,7 @@ typedef enum CoercionContext
} CoercionContext;
/*
- * CoercionForm - information showing how to display a function-call node
+ * CoercionForm - how to display a node that could have come from a cast
*
* NB: equal() ignores CoercionForm fields, therefore this *must* not carry
* any semantically significant information. We need that behavior so that
@@ -328,8 +346,7 @@ typedef enum CoercionForm
{
COERCE_EXPLICIT_CALL, /* display as a function call */
COERCE_EXPLICIT_CAST, /* display as an explicit cast */
- COERCE_IMPLICIT_CAST, /* implicit cast, so hide it */
- COERCE_DONTCARE /* special case for planner */
+ COERCE_IMPLICIT_CAST /* implicit cast, so hide it */
} CoercionForm;
/*
@@ -341,6 +358,8 @@ typedef struct FuncExpr
Oid funcid; /* PG_PROC OID of the function */
Oid funcresulttype; /* PG_TYPE OID of result value */
bool funcretset; /* true if function returns set */
+ bool funcvariadic; /* true if variadic arguments have been
+ * combined into an array last argument */
CoercionForm funcformat; /* how to display this function call */
Oid funccollid; /* OID of collation of result */
Oid inputcollid; /* OID of collation that function should use */
@@ -439,7 +458,7 @@ typedef struct ScalarArrayOpExpr
*
* Notice the arguments are given as a List. For NOT, of course the list
* must always have exactly one element. For AND and OR, the executor can
- * handle any number of arguments. The parser generally treats AND and OR
+ * handle any number of arguments. The parser generally treats AND and OR
* as binary and so it typically only produces two-element lists, but the
* optimizer will flatten trees of AND and OR nodes to produce longer lists
* when possible. There are also a few special cases where more arguments
@@ -462,7 +481,7 @@ typedef struct BoolExpr
* SubLink
*
* A SubLink represents a subselect appearing in an expression, and in some
- * cases also the combining operator(s) just above it. The subLinkType
+ * cases also the combining operator(s) just above it. The subLinkType
* indicates the form of the expression represented:
* EXISTS_SUBLINK EXISTS(SELECT ...)
* ALL_SUBLINK (lefthand) op ALL (SELECT ...)
@@ -489,7 +508,7 @@ typedef struct BoolExpr
*
* NOTE: in the raw output of gram.y, testexpr contains just the raw form
* of the lefthand expression (if any), and operName is the String name of
- * the combining operator. Also, subselect is a raw parsetree. During parse
+ * the combining operator. Also, subselect is a raw parsetree. During parse
* analysis, the parser transforms testexpr into a complete boolean expression
* that compares the lefthand value(s) to PARAM_SUBLINK nodes representing the
* output columns of the subselect. And subselect is transformed to a Query.
@@ -547,7 +566,7 @@ typedef struct SubLink
* list). In this case testexpr is NULL to avoid duplication.
*
* The planner also derives lists of the values that need to be passed into
- * and out of the subplan. Input values are represented as a list "args" of
+ * and out of the subplan. Input values are represented as a list "args" of
* expressions to be evaluated in the outer-query context (currently these
* args are always just Vars, but in principle they could be any expression).
* The values are assigned to the global PARAM_EXEC params indexed by parParam
@@ -638,7 +657,7 @@ typedef struct FieldSelect
* portion of a column.
*
* A single FieldStore can actually represent updates of several different
- * fields. The parser only generates FieldStores with single-element lists,
+ * fields. The parser only generates FieldStores with single-element lists,
* but the planner will collapse multiple updates of the same base column
* into one FieldStore.
* ----------------
@@ -770,7 +789,7 @@ typedef struct CollateExpr
* and the testexpr in the second case.
*
* In the raw grammar output for the second form, the condition expressions
- * of the WHEN clauses are just the comparison values. Parse analysis
+ * of the WHEN clauses are just the comparison values. Parse analysis
* converts these to valid boolean expressions of the form
* CaseTestExpr '=' compexpr
* where the CaseTestExpr node is a placeholder that emits the correct
@@ -844,22 +863,22 @@ typedef struct ArrayExpr
*
* Note: the list of fields must have a one-for-one correspondence with
* physical fields of the associated rowtype, although it is okay for it
- * to be shorter than the rowtype. That is, the N'th list element must
+ * to be shorter than the rowtype. That is, the N'th list element must
* match up with the N'th physical field. When the N'th physical field
* is a dropped column (attisdropped) then the N'th list element can just
- * be a NULL constant. (This case can only occur for named composite types,
+ * be a NULL constant. (This case can only occur for named composite types,
* not RECORD types, since those are built from the RowExpr itself rather
* than vice versa.) It is important not to assume that length(args) is
* the same as the number of columns logically present in the rowtype.
*
* colnames provides field names in cases where the names can't easily be
- * obtained otherwise. Names *must* be provided if row_typeid is RECORDOID.
+ * obtained otherwise. Names *must* be provided if row_typeid is RECORDOID.
* If row_typeid identifies a known composite type, colnames can be NIL to
* indicate the type's cataloged field names apply. Note that colnames can
* be non-NIL even for a composite type, and typically is when the RowExpr
* was created by expanding a whole-row Var. This is so that we can retain
* the column alias names of the RTE that the Var referenced (which would
- * otherwise be very difficult to extract from the parsetree). Like the
+ * otherwise be very difficult to extract from the parsetree). Like the
* args list, colnames is one-for-one with physical fields of the rowtype.
*/
typedef struct RowExpr
@@ -872,7 +891,7 @@ typedef struct RowExpr
* Note: we deliberately do NOT store a typmod. Although a typmod will be
* associated with specific RECORD types at runtime, it will differ for
* different backends, and so cannot safely be stored in stored
- * parsetrees. We must assume typmod -1 for a RowExpr node.
+ * parsetrees. We must assume typmod -1 for a RowExpr node.
*
* We don't need to store a collation either. The result type is
* necessarily composite, and composite types never have a collation.
@@ -958,7 +977,7 @@ typedef struct MinMaxExpr
* 'args' carries all other arguments.
*
* Note: result type/typmod/collation are not stored, but can be deduced
- * from the XmlExprOp. The type/typmod fields are just used for display
+ * from the XmlExprOp. The type/typmod fields are just used for display
* purposes, and are NOT necessarily the true result type of the node.
* (We also use type == InvalidOid to mark a not-yet-parse-analyzed XmlExpr.)
*/
@@ -1044,8 +1063,8 @@ typedef struct BooleanTest
*
* CoerceToDomain represents the operation of coercing a value to a domain
* type. At runtime (and not before) the precise set of constraints to be
- * checked will be determined. If the value passes, it is returned as the
- * result; if not, an error is raised. Note that this is equivalent to
+ * checked will be determined. If the value passes, it is returned as the
+ * result; if not, an error is raised. Note that this is equivalent to
* RelabelType in the scenario where no constraints are applied.
*/
typedef struct CoerceToDomain
@@ -1061,7 +1080,7 @@ typedef struct CoerceToDomain
/*
* Placeholder node for the value to be processed by a domain's check
- * constraint. This is effectively like a Param, but can be implemented more
+ * constraint. This is effectively like a Param, but can be implemented more
* simply since we need only one replacement value at a time.
*
* Note: the typeId/typeMod/collation will be set from the domain's base type,
@@ -1081,7 +1100,7 @@ typedef struct CoerceToDomainValue
* Placeholder node for a DEFAULT marker in an INSERT or UPDATE command.
*
* This is not an executable expression: it must be replaced by the actual
- * column default expression during rewriting. But it is convenient to
+ * column default expression during rewriting. But it is convenient to
* treat it as an expression node during parsing and rewriting.
*/
typedef struct SetToDefault
@@ -1123,14 +1142,14 @@ typedef struct CurrentOfExpr
* single expression tree.
*
* In a SELECT's targetlist, resno should always be equal to the item's
- * ordinal position (counting from 1). However, in an INSERT or UPDATE
+ * ordinal position (counting from 1). However, in an INSERT or UPDATE
* targetlist, resno represents the attribute number of the destination
* column for the item; so there may be missing or out-of-order resnos.
* It is even legal to have duplicated resnos; consider
* UPDATE table SET arraycol[1] = ..., arraycol[2] = ..., ...
* The two meanings come together in the executor, because the planner
* transforms INSERT/UPDATE tlists into a normalized form with exactly
- * one entry for each column of the destination table. Before that's
+ * one entry for each column of the destination table. Before that's
* happened, however, it is risky to assume that resno == position.
* Generally get_tle_by_resno() should be used rather than list_nth()
* to fetch tlist entries by resno, and only in SELECT should you assume
@@ -1139,25 +1158,25 @@ typedef struct CurrentOfExpr
* resname is required to represent the correct column name in non-resjunk
* entries of top-level SELECT targetlists, since it will be used as the
* column title sent to the frontend. In most other contexts it is only
- * a debugging aid, and may be wrong or even NULL. (In particular, it may
+ * a debugging aid, and may be wrong or even NULL. (In particular, it may
* be wrong in a tlist from a stored rule, if the referenced column has been
- * renamed by ALTER TABLE since the rule was made. Also, the planner tends
+ * renamed by ALTER TABLE since the rule was made. Also, the planner tends
* to store NULL rather than look up a valid name for tlist entries in
* non-toplevel plan nodes.) In resjunk entries, resname should be either
* a specific system-generated name (such as "ctid") or NULL; anything else
* risks confusing ExecGetJunkAttribute!
*
* ressortgroupref is used in the representation of ORDER BY, GROUP BY, and
- * DISTINCT items. Targetlist entries with ressortgroupref=0 are not
+ * DISTINCT items. Targetlist entries with ressortgroupref=0 are not
* sort/group items. If ressortgroupref>0, then this item is an ORDER BY,
- * GROUP BY, and/or DISTINCT target value. No two entries in a targetlist
+ * GROUP BY, and/or DISTINCT target value. No two entries in a targetlist
* may have the same nonzero ressortgroupref --- but there is no particular
* meaning to the nonzero values, except as tags. (For example, one must
* not assume that lower ressortgroupref means a more significant sort key.)
* The order of the associated SortGroupClause lists determine the semantics.
*
* resorigtbl/resorigcol identify the source of the column, if it is a
- * simple reference to a column of a base table (or view). If it is not
+ * simple reference to a column of a base table (or view). If it is not
* a simple reference, these fields are zeroes.
*
* If resjunk is true then the column is a working column (such as a sort key)
@@ -1197,7 +1216,7 @@ typedef struct TargetEntry
*
* NOTE: the qualification expressions present in JoinExpr nodes are
* *in addition to* the query's main WHERE clause, which appears as the
- * qual of the top-level FromExpr. The reason for associating quals with
+ * qual of the top-level FromExpr. The reason for associating quals with
* specific nodes in the jointree is that the position of a qual is critical
* when outer joins are present. (If we enforce a qual too soon or too late,
* that may cause the outer join to produce the wrong set of NULL-extended
@@ -1233,7 +1252,7 @@ typedef struct RangeTblRef
* If he writes NATURAL then parse analysis generates the equivalent USING()
* list, and from that fills in "quals" with the right equality comparisons.
* If he writes USING() then "quals" is filled with equality comparisons.
- * If he writes ON() then only "quals" is set. Note that NATURAL/USING
+ * If he writes ON() then only "quals" is set. Note that NATURAL/USING
* are not equivalent to ON() since they also affect the output column list.
*
* alias is an Alias node representing the AS alias-clause attached to the
@@ -1242,7 +1261,7 @@ typedef struct RangeTblRef
* restricts visibility of the tables/columns inside it.
*
* During parse analysis, an RTE is created for the Join, and its index
- * is filled into rtindex. This RTE is present mainly so that Vars can
+ * is filled into rtindex. This RTE is present mainly so that Vars can
* be created that refer to the outputs of the join. The planner sometimes
* generates JoinExprs internally; these can have rtindex = 0 if there are
* no join alias variables referencing such joins.
diff --git a/src/include/utils/memutils.h b/src/include/utils/memutils.h
index 8153001..a40af1e 100644
--- a/src/include/utils/memutils.h
+++ b/src/include/utils/memutils.h
@@ -73,13 +73,13 @@ typedef struct StandardChunkHeader
* Only TopMemoryContext and ErrorContext are initialized by
* MemoryContextInit() itself.
*/
-extern PGDLLIMPORT MemoryContext TopMemoryContext;
-extern PGDLLIMPORT MemoryContext ErrorContext;
-extern PGDLLIMPORT MemoryContext ProcessLoopContext;
-extern PGDLLIMPORT MemoryContext CacheMemoryContext;
-extern PGDLLIMPORT MemoryContext MessageContext;
-extern PGDLLIMPORT MemoryContext QueryContext;
-extern PGDLLIMPORT MemoryContext CurTransactionContext;
+extern MemoryContext TopMemoryContext;
+extern MemoryContext ErrorContext;
+extern MemoryContext ProcessLoopContext;
+extern MemoryContext CacheMemoryContext;
+extern MemoryContext MessageContext;
+extern MemoryContext QueryContext;
+extern MemoryContext CurTransactionContext;
/* This is a transient link to the active portal's memory context: */
extern PGDLLIMPORT MemoryContext PortalContext;
diff --git a/src/include/utils/palloc.h b/src/include/utils/palloc.h
index 01e7db5..c11d044 100644
--- a/src/include/utils/palloc.h
+++ b/src/include/utils/palloc.h
@@ -101,5 +101,13 @@ extern void *palloc(Size size);
extern void *palloc0(Size size);
extern void pfree(void *pointer);
extern void *repalloc(void *pointer, Size size);
+/* sprintf into a palloc'd buffer --- these are in psprintf.c */
+extern char *
+psprintf(const char *fmt,...)
+__attribute__((format(PG_PRINTF_ATTRIBUTE, 1, 2)));
+extern size_t
+pvsnprintf(char *buf, size_t len, const char *fmt, va_list args)
+__attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 0)));
+
#endif /* PALLOC_H */
diff --git a/src/parallel_query/pool_rewrite_outfuncs.c b/src/parallel_query/pool_rewrite_outfuncs.c
index 90e514e..231a10e 100644
--- a/src/parallel_query/pool_rewrite_outfuncs.c
+++ b/src/parallel_query/pool_rewrite_outfuncs.c
@@ -4271,11 +4271,21 @@ _rewriteLockingClause(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *
{
if (node == NULL)
return;
-
- if (node->forUpdate == TRUE)
- delay_string_append_char(message, str, " FOR UPDATE");
- else
- delay_string_append_char(message, str, " FOR SHARED");
+ switch(node->strength)
+ {
+ case LCS_FORKEYSHARE:
+ delay_string_append_char(message, str, " FOR KEY SHARE");
+ break;
+ case LCS_FORSHARE:
+ delay_string_append_char(message, str, " FOR SHARE");
+ break;
+ case LCS_FORNOKEYUPDATE:
+ delay_string_append_char(message, str, " FOR NO KEY UPDATE");
+ break;
+ case LCS_FORUPDATE:
+ delay_string_append_char(message, str, " FOR UPDATE");
+ break;
+ }
_rewriteNode(BaseSelect, message, dblink, str, node->lockedRels);
@@ -7821,7 +7831,7 @@ _rewriteAlterOwnerStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink
delay_string_append_char(message, str, "OPERATOR CLASS ");
_rewriteFuncName(BaseSelect, message, dblink, str, node->object);
delay_string_append_char(message, str, " USING ");
- delay_string_append_char(message, str, node->addname);
+ delay_string_append_char(message, str, linitial(node->objarg));
delay_string_append_char(message, str, " OWNER TO \"");
delay_string_append_char(message, str, node->newowner);
delay_string_append_char(message, str, "\"");
@@ -8481,7 +8491,7 @@ _rewriteRangeSubselect(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink
static void
_rewriteRangeFunction(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, RangeFunction *node)
{
- _rewriteNode(BaseSelect, message, dblink, str, node->funccallnode);
+ _rewriteNode(BaseSelect, message, dblink, str, node->functions); //TODO
if (node->alias)
{
_rewriteNode(BaseSelect, message, dblink, str, node->alias);
diff --git a/src/parser/copyfuncs.c b/src/parser/copyfuncs.c
index 8697865..0871aa4 100644
--- a/src/parser/copyfuncs.c
+++ b/src/parser/copyfuncs.c
@@ -4,15 +4,15 @@
* Copy functions for Postgres tree nodes.
*
* NOTE: we currently support copying all node types found in parse and
- * plan trees. We do not support copying executor state trees; there
+ * plan trees. We do not support copying executor state trees; there
* is no need for that, and no point in maintaining all the code that
* would be needed. We also do not support copying Path trees, mainly
* because the circular linkages between RelOptInfo and Path nodes can't
* be handled easily in a simple depth-first traversal.
*
*
- * Portions Copyright (c) 2003-2013, PgPool Global Development Group
- * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
+ * Portions Copyright (c) 2003-2014, PgPool Global Development Group
+ * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -26,12 +26,13 @@
#include <string.h>
#include <stddef.h>
#include "utils/palloc.h"
+#include "utils/elog.h"
#include "parsenodes.h"
/*
* Macros to simplify copying of different kinds of fields. Use these
- * wherever possible to reduce the chance for silly typos. Note that these
+ * wherever possible to reduce the chance for silly typos. Note that these
* hard-wire the convention that the local variables in a Copy routine are
* named 'newnode' and 'from'.
*/
@@ -65,6 +66,920 @@
(newnode->fldname = from->fldname)
+/* ****************************************************************
+ * plannodes.h copy functions
+ * ****************************************************************
+ */
+#ifdef NOT_USED_IN_PGPOOL
+/*
+ * _copyPlannedStmt
+ */
+static PlannedStmt *
+_copyPlannedStmt(const PlannedStmt *from)
+{
+ PlannedStmt *newnode = makeNode(PlannedStmt);
+
+ COPY_SCALAR_FIELD(commandType);
+ COPY_SCALAR_FIELD(queryId);
+ COPY_SCALAR_FIELD(hasReturning);
+ COPY_SCALAR_FIELD(hasModifyingCTE);
+ COPY_SCALAR_FIELD(canSetTag);
+ COPY_SCALAR_FIELD(transientPlan);
+ COPY_NODE_FIELD(planTree);
+ COPY_NODE_FIELD(rtable);
+ COPY_NODE_FIELD(resultRelations);
+ COPY_NODE_FIELD(utilityStmt);
+ COPY_NODE_FIELD(subplans);
+ COPY_BITMAPSET_FIELD(rewindPlanIDs);
+ COPY_NODE_FIELD(rowMarks);
+ COPY_NODE_FIELD(relationOids);
+ COPY_NODE_FIELD(invalItems);
+ COPY_SCALAR_FIELD(nParamExec);
+
+ return newnode;
+}
+
+/*
+ * CopyPlanFields
+ *
+ * This function copies the fields of the Plan node. It is used by
+ * all the copy functions for classes which inherit from Plan.
+ */
+static void
+CopyPlanFields(const Plan *from, Plan *newnode)
+{
+ COPY_SCALAR_FIELD(startup_cost);
+ COPY_SCALAR_FIELD(total_cost);
+ COPY_SCALAR_FIELD(plan_rows);
+ COPY_SCALAR_FIELD(plan_width);
+ COPY_NODE_FIELD(targetlist);
+ COPY_NODE_FIELD(qual);
+ COPY_NODE_FIELD(lefttree);
+ COPY_NODE_FIELD(righttree);
+ COPY_NODE_FIELD(initPlan);
+ COPY_BITMAPSET_FIELD(extParam);
+ COPY_BITMAPSET_FIELD(allParam);
+}
+
+/*
+ * _copyPlan
+ */
+static Plan *
+_copyPlan(const Plan *from)
+{
+ Plan *newnode = makeNode(Plan);
+
+ /*
+ * copy node superclass fields
+ */
+ CopyPlanFields(from, newnode);
+
+ return newnode;
+}
+
+/*
+ * _copyResult
+ */
+static Result *
+_copyResult(const Result *from)
+{
+ Result *newnode = makeNode(Result);
+
+ /*
+ * copy node superclass fields
+ */
+ CopyPlanFields((const Plan *) from, (Plan *) newnode);
+
+ /*
+ * copy remainder of node
+ */
+ COPY_NODE_FIELD(resconstantqual);
+
+ return newnode;
+}
+
+/*
+ * _copyModifyTable
+ */
+static ModifyTable *
+_copyModifyTable(const ModifyTable *from)
+{
+ ModifyTable *newnode = makeNode(ModifyTable);
+
+ /*
+ * copy node superclass fields
+ */
+ CopyPlanFields((const Plan *) from, (Plan *) newnode);
+
+ /*
+ * copy remainder of node
+ */
+ COPY_SCALAR_FIELD(operation);
+ COPY_SCALAR_FIELD(canSetTag);
+ COPY_NODE_FIELD(resultRelations);
+ COPY_SCALAR_FIELD(resultRelIndex);
+ COPY_NODE_FIELD(plans);
+ COPY_NODE_FIELD(withCheckOptionLists);
+ COPY_NODE_FIELD(returningLists);
+ COPY_NODE_FIELD(fdwPrivLists);
+ COPY_NODE_FIELD(rowMarks);
+ COPY_SCALAR_FIELD(epqParam);
+
+ return newnode;
+}
+
+/*
+ * _copyAppend
+ */
+static Append *
+_copyAppend(const Append *from)
+{
+ Append *newnode = makeNode(Append);
+
+ /*
+ * copy node superclass fields
+ */
+ CopyPlanFields((const Plan *) from, (Plan *) newnode);
+
+ /*
+ * copy remainder of node
+ */
+ COPY_NODE_FIELD(appendplans);
+
+ return newnode;
+}
+
+/*
+ * _copyMergeAppend
+ */
+static MergeAppend *
+_copyMergeAppend(const MergeAppend *from)
+{
+ MergeAppend *newnode = makeNode(MergeAppend);
+
+ /*
+ * copy node superclass fields
+ */
+ CopyPlanFields((const Plan *) from, (Plan *) newnode);
+
+ /*
+ * copy remainder of node
+ */
+ COPY_NODE_FIELD(mergeplans);
+ COPY_SCALAR_FIELD(numCols);
+ COPY_POINTER_FIELD(sortColIdx, from->numCols * sizeof(AttrNumber));
+ COPY_POINTER_FIELD(sortOperators, from->numCols * sizeof(Oid));
+ COPY_POINTER_FIELD(collations, from->numCols * sizeof(Oid));
+ COPY_POINTER_FIELD(nullsFirst, from->numCols * sizeof(bool));
+
+ return newnode;
+}
+
+/*
+ * _copyRecursiveUnion
+ */
+static RecursiveUnion *
+_copyRecursiveUnion(const RecursiveUnion *from)
+{
+ RecursiveUnion *newnode = makeNode(RecursiveUnion);
+
+ /*
+ * copy node superclass fields
+ */
+ CopyPlanFields((const Plan *) from, (Plan *) newnode);
+
+ /*
+ * copy remainder of node
+ */
+ COPY_SCALAR_FIELD(wtParam);
+ COPY_SCALAR_FIELD(numCols);
+ if (from->numCols > 0)
+ {
+ COPY_POINTER_FIELD(dupColIdx, from->numCols * sizeof(AttrNumber));
+ COPY_POINTER_FIELD(dupOperators, from->numCols * sizeof(Oid));
+ }
+ COPY_SCALAR_FIELD(numGroups);
+
+ return newnode;
+}
+
+/*
+ * _copyBitmapAnd
+ */
+static BitmapAnd *
+_copyBitmapAnd(const BitmapAnd *from)
+{
+ BitmapAnd *newnode = makeNode(BitmapAnd);
+
+ /*
+ * copy node superclass fields
+ */
+ CopyPlanFields((const Plan *) from, (Plan *) newnode);
+
+ /*
+ * copy remainder of node
+ */
+ COPY_NODE_FIELD(bitmapplans);
+
+ return newnode;
+}
+
+/*
+ * _copyBitmapOr
+ */
+static BitmapOr *
+_copyBitmapOr(const BitmapOr *from)
+{
+ BitmapOr *newnode = makeNode(BitmapOr);
+
+ /*
+ * copy node superclass fields
+ */
+ CopyPlanFields((const Plan *) from, (Plan *) newnode);
+
+ /*
+ * copy remainder of node
+ */
+ COPY_NODE_FIELD(bitmapplans);
+
+ return newnode;
+}
+
+
+/*
+ * CopyScanFields
+ *
+ * This function copies the fields of the Scan node. It is used by
+ * all the copy functions for classes which inherit from Scan.
+ */
+static void
+CopyScanFields(const Scan *from, Scan *newnode)
+{
+ CopyPlanFields((const Plan *) from, (Plan *) newnode);
+
+ COPY_SCALAR_FIELD(scanrelid);
+}
+
+/*
+ * _copyScan
+ */
+static Scan *
+_copyScan(const Scan *from)
+{
+ Scan *newnode = makeNode(Scan);
+
+ /*
+ * copy node superclass fields
+ */
+ CopyScanFields((const Scan *) from, (Scan *) newnode);
+
+ return newnode;
+}
+
+/*
+ * _copySeqScan
+ */
+static SeqScan *
+_copySeqScan(const SeqScan *from)
+{
+ SeqScan *newnode = makeNode(SeqScan);
+
+ /*
+ * copy node superclass fields
+ */
+ CopyScanFields((const Scan *) from, (Scan *) newnode);
+
+ return newnode;
+}
+
+/*
+ * _copyIndexScan
+ */
+static IndexScan *
+_copyIndexScan(const IndexScan *from)
+{
+ IndexScan *newnode = makeNode(IndexScan);
+
+ /*
+ * copy node superclass fields
+ */
+ CopyScanFields((const Scan *) from, (Scan *) newnode);
+
+ /*
+ * copy remainder of node
+ */
+ COPY_SCALAR_FIELD(indexid);
+ COPY_NODE_FIELD(indexqual);
+ COPY_NODE_FIELD(indexqualorig);
+ COPY_NODE_FIELD(indexorderby);
+ COPY_NODE_FIELD(indexorderbyorig);
+ COPY_SCALAR_FIELD(indexorderdir);
+
+ return newnode;
+}
+
+/*
+ * _copyIndexOnlyScan
+ */
+static IndexOnlyScan *
+_copyIndexOnlyScan(const IndexOnlyScan *from)
+{
+ IndexOnlyScan *newnode = makeNode(IndexOnlyScan);
+
+ /*
+ * copy node superclass fields
+ */
+ CopyScanFields((const Scan *) from, (Scan *) newnode);
+
+ /*
+ * copy remainder of node
+ */
+ COPY_SCALAR_FIELD(indexid);
+ COPY_NODE_FIELD(indexqual);
+ COPY_NODE_FIELD(indexorderby);
+ COPY_NODE_FIELD(indextlist);
+ COPY_SCALAR_FIELD(indexorderdir);
+
+ return newnode;
+}
+
+/*
+ * _copyBitmapIndexScan
+ */
+static BitmapIndexScan *
+_copyBitmapIndexScan(const BitmapIndexScan *from)
+{
+ BitmapIndexScan *newnode = makeNode(BitmapIndexScan);
+
+ /*
+ * copy node superclass fields
+ */
+ CopyScanFields((const Scan *) from, (Scan *) newnode);
+
+ /*
+ * copy remainder of node
+ */
+ COPY_SCALAR_FIELD(indexid);
+ COPY_NODE_FIELD(indexqual);
+ COPY_NODE_FIELD(indexqualorig);
+
+ return newnode;
+}
+
+/*
+ * _copyBitmapHeapScan
+ */
+static BitmapHeapScan *
+_copyBitmapHeapScan(const BitmapHeapScan *from)
+{
+ BitmapHeapScan *newnode = makeNode(BitmapHeapScan);
+
+ /*
+ * copy node superclass fields
+ */
+ CopyScanFields((const Scan *) from, (Scan *) newnode);
+
+ /*
+ * copy remainder of node
+ */
+ COPY_NODE_FIELD(bitmapqualorig);
+
+ return newnode;
+}
+
+/*
+ * _copyTidScan
+ */
+static TidScan *
+_copyTidScan(const TidScan *from)
+{
+ TidScan *newnode = makeNode(TidScan);
+
+ /*
+ * copy node superclass fields
+ */
+ CopyScanFields((const Scan *) from, (Scan *) newnode);
+
+ /*
+ * copy remainder of node
+ */
+ COPY_NODE_FIELD(tidquals);
+
+ return newnode;
+}
+
+/*
+ * _copySubqueryScan
+ */
+static SubqueryScan *
+_copySubqueryScan(const SubqueryScan *from)
+{
+ SubqueryScan *newnode = makeNode(SubqueryScan);
+
+ /*
+ * copy node superclass fields
+ */
+ CopyScanFields((const Scan *) from, (Scan *) newnode);
+
+ /*
+ * copy remainder of node
+ */
+ COPY_NODE_FIELD(subplan);
+
+ return newnode;
+}
+
+/*
+ * _copyFunctionScan
+ */
+static FunctionScan *
+_copyFunctionScan(const FunctionScan *from)
+{
+ FunctionScan *newnode = makeNode(FunctionScan);
+
+ /*
+ * copy node superclass fields
+ */
+ CopyScanFields((const Scan *) from, (Scan *) newnode);
+
+ /*
+ * copy remainder of node
+ */
+ COPY_NODE_FIELD(functions);
+ COPY_SCALAR_FIELD(funcordinality);
+
+ return newnode;
+}
+
+/*
+ * _copyValuesScan
+ */
+static ValuesScan *
+_copyValuesScan(const ValuesScan *from)
+{
+ ValuesScan *newnode = makeNode(ValuesScan);
+
+ /*
+ * copy node superclass fields
+ */
+ CopyScanFields((const Scan *) from, (Scan *) newnode);
+
+ /*
+ * copy remainder of node
+ */
+ COPY_NODE_FIELD(values_lists);
+
+ return newnode;
+}
+
+/*
+ * _copyCteScan
+ */
+static CteScan *
+_copyCteScan(const CteScan *from)
+{
+ CteScan *newnode = makeNode(CteScan);
+
+ /*
+ * copy node superclass fields
+ */
+ CopyScanFields((const Scan *) from, (Scan *) newnode);
+
+ /*
+ * copy remainder of node
+ */
+ COPY_SCALAR_FIELD(ctePlanId);
+ COPY_SCALAR_FIELD(cteParam);
+
+ return newnode;
+}
+
+/*
+ * _copyWorkTableScan
+ */
+static WorkTableScan *
+_copyWorkTableScan(const WorkTableScan *from)
+{
+ WorkTableScan *newnode = makeNode(WorkTableScan);
+
+ /*
+ * copy node superclass fields
+ */
+ CopyScanFields((const Scan *) from, (Scan *) newnode);
+
+ /*
+ * copy remainder of node
+ */
+ COPY_SCALAR_FIELD(wtParam);
+
+ return newnode;
+}
+
+/*
+ * _copyForeignScan
+ */
+static ForeignScan *
+_copyForeignScan(const ForeignScan *from)
+{
+ ForeignScan *newnode = makeNode(ForeignScan);
+
+ /*
+ * copy node superclass fields
+ */
+ CopyScanFields((const Scan *) from, (Scan *) newnode);
+
+ /*
+ * copy remainder of node
+ */
+ COPY_NODE_FIELD(fdw_exprs);
+ COPY_NODE_FIELD(fdw_private);
+ COPY_SCALAR_FIELD(fsSystemCol);
+
+ return newnode;
+}
+
+/*
+ * CopyJoinFields
+ *
+ * This function copies the fields of the Join node. It is used by
+ * all the copy functions for classes which inherit from Join.
+ */
+static void
+CopyJoinFields(const Join *from, Join *newnode)
+{
+ CopyPlanFields((const Plan *) from, (Plan *) newnode);
+
+ COPY_SCALAR_FIELD(jointype);
+ COPY_NODE_FIELD(joinqual);
+}
+
+
+/*
+ * _copyJoin
+ */
+static Join *
+_copyJoin(const Join *from)
+{
+ Join *newnode = makeNode(Join);
+
+ /*
+ * copy node superclass fields
+ */
+ CopyJoinFields(from, newnode);
+
+ return newnode;
+}
+
+
+/*
+ * _copyNestLoop
+ */
+static NestLoop *
+_copyNestLoop(const NestLoop *from)
+{
+ NestLoop *newnode = makeNode(NestLoop);
+
+ /*
+ * copy node superclass fields
+ */
+ CopyJoinFields((const Join *) from, (Join *) newnode);
+
+ /*
+ * copy remainder of node
+ */
+ COPY_NODE_FIELD(nestParams);
+
+ return newnode;
+}
+
+
+/*
+ * _copyMergeJoin
+ */
+static MergeJoin *
+_copyMergeJoin(const MergeJoin *from)
+{
+ MergeJoin *newnode = makeNode(MergeJoin);
+ int numCols;
+
+ /*
+ * copy node superclass fields
+ */
+ CopyJoinFields((const Join *) from, (Join *) newnode);
+
+ /*
+ * copy remainder of node
+ */
+ COPY_NODE_FIELD(mergeclauses);
+ numCols = list_length(from->mergeclauses);
+ if (numCols > 0)
+ {
+ COPY_POINTER_FIELD(mergeFamilies, numCols * sizeof(Oid));
+ COPY_POINTER_FIELD(mergeCollations, numCols * sizeof(Oid));
+ COPY_POINTER_FIELD(mergeStrategies, numCols * sizeof(int));
+ COPY_POINTER_FIELD(mergeNullsFirst, numCols * sizeof(bool));
+ }
+
+ return newnode;
+}
+
+/*
+ * _copyHashJoin
+ */
+static HashJoin *
+_copyHashJoin(const HashJoin *from)
+{
+ HashJoin *newnode = makeNode(HashJoin);
+
+ /*
+ * copy node superclass fields
+ */
+ CopyJoinFields((const Join *) from, (Join *) newnode);
+
+ /*
+ * copy remainder of node
+ */
+ COPY_NODE_FIELD(hashclauses);
+
+ return newnode;
+}
+
+
+/*
+ * _copyMaterial
+ */
+static Material *
+_copyMaterial(const Material *from)
+{
+ Material *newnode = makeNode(Material);
+
+ /*
+ * copy node superclass fields
+ */
+ CopyPlanFields((const Plan *) from, (Plan *) newnode);
+
+ return newnode;
+}
+
+
+/*
+ * _copySort
+ */
+static Sort *
+_copySort(const Sort *from)
+{
+ Sort *newnode = makeNode(Sort);
+
+ /*
+ * copy node superclass fields
+ */
+ CopyPlanFields((const Plan *) from, (Plan *) newnode);
+
+ COPY_SCALAR_FIELD(numCols);
+ COPY_POINTER_FIELD(sortColIdx, from->numCols * sizeof(AttrNumber));
+ COPY_POINTER_FIELD(sortOperators, from->numCols * sizeof(Oid));
+ COPY_POINTER_FIELD(collations, from->numCols * sizeof(Oid));
+ COPY_POINTER_FIELD(nullsFirst, from->numCols * sizeof(bool));
+
+ return newnode;
+}
+
+
+/*
+ * _copyGroup
+ */
+static Group *
+_copyGroup(const Group *from)
+{
+ Group *newnode = makeNode(Group);
+
+ CopyPlanFields((const Plan *) from, (Plan *) newnode);
+
+ COPY_SCALAR_FIELD(numCols);
+ COPY_POINTER_FIELD(grpColIdx, from->numCols * sizeof(AttrNumber));
+ COPY_POINTER_FIELD(grpOperators, from->numCols * sizeof(Oid));
+
+ return newnode;
+}
+
+/*
+ * _copyAgg
+ */
+static Agg *
+_copyAgg(const Agg *from)
+{
+ Agg *newnode = makeNode(Agg);
+
+ CopyPlanFields((const Plan *) from, (Plan *) newnode);
+
+ COPY_SCALAR_FIELD(aggstrategy);
+ COPY_SCALAR_FIELD(numCols);
+ if (from->numCols > 0)
+ {
+ COPY_POINTER_FIELD(grpColIdx, from->numCols * sizeof(AttrNumber));
+ COPY_POINTER_FIELD(grpOperators, from->numCols * sizeof(Oid));
+ }
+ COPY_SCALAR_FIELD(numGroups);
+
+ return newnode;
+}
+
+/*
+ * _copyWindowAgg
+ */
+static WindowAgg *
+_copyWindowAgg(const WindowAgg *from)
+{
+ WindowAgg *newnode = makeNode(WindowAgg);
+
+ CopyPlanFields((const Plan *) from, (Plan *) newnode);
+
+ COPY_SCALAR_FIELD(winref);
+ COPY_SCALAR_FIELD(partNumCols);
+ if (from->partNumCols > 0)
+ {
+ COPY_POINTER_FIELD(partColIdx, from->partNumCols * sizeof(AttrNumber));
+ COPY_POINTER_FIELD(partOperators, from->partNumCols * sizeof(Oid));
+ }
+ COPY_SCALAR_FIELD(ordNumCols);
+ if (from->ordNumCols > 0)
+ {
+ COPY_POINTER_FIELD(ordColIdx, from->ordNumCols * sizeof(AttrNumber));
+ COPY_POINTER_FIELD(ordOperators, from->ordNumCols * sizeof(Oid));
+ }
+ COPY_SCALAR_FIELD(frameOptions);
+ COPY_NODE_FIELD(startOffset);
+ COPY_NODE_FIELD(endOffset);
+
+ return newnode;
+}
+
+/*
+ * _copyUnique
+ */
+static Unique *
+_copyUnique(const Unique *from)
+{
+ Unique *newnode = makeNode(Unique);
+
+ /*
+ * copy node superclass fields
+ */
+ CopyPlanFields((const Plan *) from, (Plan *) newnode);
+
+ /*
+ * copy remainder of node
+ */
+ COPY_SCALAR_FIELD(numCols);
+ COPY_POINTER_FIELD(uniqColIdx, from->numCols * sizeof(AttrNumber));
+ COPY_POINTER_FIELD(uniqOperators, from->numCols * sizeof(Oid));
+
+ return newnode;
+}
+
+/*
+ * _copyHash
+ */
+static Hash *
+_copyHash(const Hash *from)
+{
+ Hash *newnode = makeNode(Hash);
+
+ /*
+ * copy node superclass fields
+ */
+ CopyPlanFields((const Plan *) from, (Plan *) newnode);
+
+ /*
+ * copy remainder of node
+ */
+ COPY_SCALAR_FIELD(skewTable);
+ COPY_SCALAR_FIELD(skewColumn);
+ COPY_SCALAR_FIELD(skewInherit);
+ COPY_SCALAR_FIELD(skewColType);
+ COPY_SCALAR_FIELD(skewColTypmod);
+
+ return newnode;
+}
+
+/*
+ * _copySetOp
+ */
+static SetOp *
+_copySetOp(const SetOp *from)
+{
+ SetOp *newnode = makeNode(SetOp);
+
+ /*
+ * copy node superclass fields
+ */
+ CopyPlanFields((const Plan *) from, (Plan *) newnode);
+
+ /*
+ * copy remainder of node
+ */
+ COPY_SCALAR_FIELD(cmd);
+ COPY_SCALAR_FIELD(strategy);
+ COPY_SCALAR_FIELD(numCols);
+ COPY_POINTER_FIELD(dupColIdx, from->numCols * sizeof(AttrNumber));
+ COPY_POINTER_FIELD(dupOperators, from->numCols * sizeof(Oid));
+ COPY_SCALAR_FIELD(flagColIdx);
+ COPY_SCALAR_FIELD(firstFlag);
+ COPY_SCALAR_FIELD(numGroups);
+
+ return newnode;
+}
+
+/*
+ * _copyLockRows
+ */
+static LockRows *
+_copyLockRows(const LockRows *from)
+{
+ LockRows *newnode = makeNode(LockRows);
+
+ /*
+ * copy node superclass fields
+ */
+ CopyPlanFields((const Plan *) from, (Plan *) newnode);
+
+ /*
+ * copy remainder of node
+ */
+ COPY_NODE_FIELD(rowMarks);
+ COPY_SCALAR_FIELD(epqParam);
+
+ return newnode;
+}
+
+/*
+ * _copyLimit
+ */
+static Limit *
+_copyLimit(const Limit *from)
+{
+ Limit *newnode = makeNode(Limit);
+
+ /*
+ * copy node superclass fields
+ */
+ CopyPlanFields((const Plan *) from, (Plan *) newnode);
+
+ /*
+ * copy remainder of node
+ */
+ COPY_NODE_FIELD(limitOffset);
+ COPY_NODE_FIELD(limitCount);
+
+ return newnode;
+}
+
+/*
+ * _copyNestLoopParam
+ */
+static NestLoopParam *
+_copyNestLoopParam(const NestLoopParam *from)
+{
+ NestLoopParam *newnode = makeNode(NestLoopParam);
+
+ COPY_SCALAR_FIELD(paramno);
+ COPY_NODE_FIELD(paramval);
+
+ return newnode;
+}
+
+/*
+ * _copyPlanRowMark
+ */
+static PlanRowMark *
+_copyPlanRowMark(const PlanRowMark *from)
+{
+ PlanRowMark *newnode = makeNode(PlanRowMark);
+
+ COPY_SCALAR_FIELD(rti);
+ COPY_SCALAR_FIELD(prti);
+ COPY_SCALAR_FIELD(rowmarkId);
+ COPY_SCALAR_FIELD(markType);
+ COPY_SCALAR_FIELD(noWait);
+ COPY_SCALAR_FIELD(isParent);
+
+ return newnode;
+}
+
+/*
+ * _copyPlanInvalItem
+ */
+static PlanInvalItem *
+_copyPlanInvalItem(const PlanInvalItem *from)
+{
+ PlanInvalItem *newnode = makeNode(PlanInvalItem);
+
+ COPY_SCALAR_FIELD(cacheId);
+ COPY_SCALAR_FIELD(hashValue);
+
+ return newnode;
+}
+#endif
/* ****************************************************************
* primnodes.h copy functions
@@ -117,6 +1032,7 @@ _copyIntoClause(const IntoClause *from)
COPY_NODE_FIELD(options);
COPY_SCALAR_FIELD(onCommit);
COPY_STRING_FIELD(tableSpaceName);
+ COPY_NODE_FIELD(viewQuery);
COPY_SCALAR_FIELD(skipData);
return newnode;
@@ -124,7 +1040,7 @@ _copyIntoClause(const IntoClause *from)
/*
* We don't need a _copyExpr because Expr is an abstract supertype which
- * should never actually get instantiated. Also, since it has no common
+ * should never actually get instantiated. Also, since it has no common
* fields except NodeTag, there's no need for a helper routine to factor
* out copying the common fields...
*/
@@ -150,10 +1066,10 @@ _copyVar(const Var *from)
return newnode;
}
+#ifdef NOT_USED_IN_PGPOOL
/*
* _copyConst
*/
-#if 0
static Const *
_copyConst(const Const *from)
{
@@ -184,11 +1100,11 @@ _copyConst(const Const *from)
COPY_SCALAR_FIELD(constisnull);
COPY_SCALAR_FIELD(constbyval);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
#endif
-
/*
* _copyParam
*/
@@ -219,10 +1135,14 @@ _copyAggref(const Aggref *from)
COPY_SCALAR_FIELD(aggtype);
COPY_SCALAR_FIELD(aggcollid);
COPY_SCALAR_FIELD(inputcollid);
+ COPY_NODE_FIELD(aggdirectargs);
COPY_NODE_FIELD(args);
COPY_NODE_FIELD(aggorder);
COPY_NODE_FIELD(aggdistinct);
+ COPY_NODE_FIELD(aggfilter);
COPY_SCALAR_FIELD(aggstar);
+ COPY_SCALAR_FIELD(aggvariadic);
+ COPY_SCALAR_FIELD(aggkind);
COPY_SCALAR_FIELD(agglevelsup);
COPY_LOCATION_FIELD(location);
@@ -242,6 +1162,7 @@ _copyWindowFunc(const WindowFunc *from)
COPY_SCALAR_FIELD(wincollid);
COPY_SCALAR_FIELD(inputcollid);
COPY_NODE_FIELD(args);
+ COPY_NODE_FIELD(aggfilter);
COPY_SCALAR_FIELD(winref);
COPY_SCALAR_FIELD(winstar);
COPY_SCALAR_FIELD(winagg);
@@ -281,6 +1202,7 @@ _copyFuncExpr(const FuncExpr *from)
COPY_SCALAR_FIELD(funcid);
COPY_SCALAR_FIELD(funcresulttype);
COPY_SCALAR_FIELD(funcretset);
+ COPY_SCALAR_FIELD(funcvariadic);
COPY_SCALAR_FIELD(funcformat);
COPY_SCALAR_FIELD(funccollid);
COPY_SCALAR_FIELD(inputcollid);
@@ -891,6 +1813,159 @@ _copyFromExpr(const FromExpr *from)
return newnode;
}
+/* ****************************************************************
+ * relation.h copy functions
+ *
+ * We don't support copying RelOptInfo, IndexOptInfo, or Path nodes.
+ * There are some subsidiary structs that are useful to copy, though.
+ * ****************************************************************
+ */
+
+#ifdef NOT_USED_IN_PGPOOL
+/*
+ * _copyPathKey
+ */
+static PathKey *
+_copyPathKey(const PathKey *from)
+{
+ PathKey *newnode = makeNode(PathKey);
+
+ /* EquivalenceClasses are never moved, so just shallow-copy the pointer */
+ COPY_SCALAR_FIELD(pk_eclass);
+ COPY_SCALAR_FIELD(pk_opfamily);
+ COPY_SCALAR_FIELD(pk_strategy);
+ COPY_SCALAR_FIELD(pk_nulls_first);
+
+ return newnode;
+}
+
+/*
+ * _copyRestrictInfo
+ */
+static RestrictInfo *
+_copyRestrictInfo(const RestrictInfo *from)
+{
+ RestrictInfo *newnode = makeNode(RestrictInfo);
+
+ COPY_NODE_FIELD(clause);
+ COPY_SCALAR_FIELD(is_pushed_down);
+ COPY_SCALAR_FIELD(outerjoin_delayed);
+ COPY_SCALAR_FIELD(can_join);
+ COPY_SCALAR_FIELD(pseudoconstant);
+ COPY_BITMAPSET_FIELD(clause_relids);
+ COPY_BITMAPSET_FIELD(required_relids);
+ COPY_BITMAPSET_FIELD(outer_relids);
+ COPY_BITMAPSET_FIELD(nullable_relids);
+ COPY_BITMAPSET_FIELD(left_relids);
+ COPY_BITMAPSET_FIELD(right_relids);
+ COPY_NODE_FIELD(orclause);
+ /* EquivalenceClasses are never copied, so shallow-copy the pointers */
+ COPY_SCALAR_FIELD(parent_ec);
+ COPY_SCALAR_FIELD(eval_cost);
+ COPY_SCALAR_FIELD(norm_selec);
+ COPY_SCALAR_FIELD(outer_selec);
+ COPY_NODE_FIELD(mergeopfamilies);
+ /* EquivalenceClasses are never copied, so shallow-copy the pointers */
+ COPY_SCALAR_FIELD(left_ec);
+ COPY_SCALAR_FIELD(right_ec);
+ COPY_SCALAR_FIELD(left_em);
+ COPY_SCALAR_FIELD(right_em);
+ /* MergeScanSelCache isn't a Node, so hard to copy; just reset cache */
+ newnode->scansel_cache = NIL;
+ COPY_SCALAR_FIELD(outer_is_left);
+ COPY_SCALAR_FIELD(hashjoinoperator);
+ COPY_SCALAR_FIELD(left_bucketsize);
+ COPY_SCALAR_FIELD(right_bucketsize);
+
+ return newnode;
+}
+
+/*
+ * _copyPlaceHolderVar
+ */
+static PlaceHolderVar *
+_copyPlaceHolderVar(const PlaceHolderVar *from)
+{
+ PlaceHolderVar *newnode = makeNode(PlaceHolderVar);
+
+ COPY_NODE_FIELD(phexpr);
+ COPY_BITMAPSET_FIELD(phrels);
+ COPY_SCALAR_FIELD(phid);
+ COPY_SCALAR_FIELD(phlevelsup);
+
+ return newnode;
+}
+
+/*
+ * _copySpecialJoinInfo
+ */
+static SpecialJoinInfo *
+_copySpecialJoinInfo(const SpecialJoinInfo *from)
+{
+ SpecialJoinInfo *newnode = makeNode(SpecialJoinInfo);
+
+ COPY_BITMAPSET_FIELD(min_lefthand);
+ COPY_BITMAPSET_FIELD(min_righthand);
+ COPY_BITMAPSET_FIELD(syn_lefthand);
+ COPY_BITMAPSET_FIELD(syn_righthand);
+ COPY_SCALAR_FIELD(jointype);
+ COPY_SCALAR_FIELD(lhs_strict);
+ COPY_SCALAR_FIELD(delay_upper_joins);
+ COPY_NODE_FIELD(join_quals);
+
+ return newnode;
+}
+
+/*
+ * _copyLateralJoinInfo
+ */
+static LateralJoinInfo *
+_copyLateralJoinInfo(const LateralJoinInfo *from)
+{
+ LateralJoinInfo *newnode = makeNode(LateralJoinInfo);
+
+ COPY_BITMAPSET_FIELD(lateral_lhs);
+ COPY_BITMAPSET_FIELD(lateral_rhs);
+
+ return newnode;
+}
+
+/*
+ * _copyAppendRelInfo
+ */
+static AppendRelInfo *
+_copyAppendRelInfo(const AppendRelInfo *from)
+{
+ AppendRelInfo *newnode = makeNode(AppendRelInfo);
+
+ COPY_SCALAR_FIELD(parent_relid);
+ COPY_SCALAR_FIELD(child_relid);
+ COPY_SCALAR_FIELD(parent_reltype);
+ COPY_SCALAR_FIELD(child_reltype);
+ COPY_NODE_FIELD(translated_vars);
+ COPY_SCALAR_FIELD(parent_reloid);
+
+ return newnode;
+}
+
+/*
+ * _copyPlaceHolderInfo
+ */
+static PlaceHolderInfo *
+_copyPlaceHolderInfo(const PlaceHolderInfo *from)
+{
+ PlaceHolderInfo *newnode = makeNode(PlaceHolderInfo);
+
+ COPY_SCALAR_FIELD(phid);
+ COPY_NODE_FIELD(ph_var);
+ COPY_BITMAPSET_FIELD(ph_eval_at);
+ COPY_BITMAPSET_FIELD(ph_lateral);
+ COPY_BITMAPSET_FIELD(ph_needed);
+ COPY_SCALAR_FIELD(ph_width);
+
+ return newnode;
+}
+#endif
/* ****************************************************************
* parsenodes.h copy functions
@@ -909,10 +1984,8 @@ _copyRangeTblEntry(const RangeTblEntry *from)
COPY_SCALAR_FIELD(security_barrier);
COPY_SCALAR_FIELD(jointype);
COPY_NODE_FIELD(joinaliasvars);
- COPY_NODE_FIELD(funcexpr);
- COPY_NODE_FIELD(funccoltypes);
- COPY_NODE_FIELD(funccoltypmods);
- COPY_NODE_FIELD(funccolcollations);
+ COPY_NODE_FIELD(functions);
+ COPY_SCALAR_FIELD(funcordinality);
COPY_NODE_FIELD(values_lists);
COPY_NODE_FIELD(values_collations);
COPY_STRING_FIELD(ctename);
@@ -923,12 +1996,42 @@ _copyRangeTblEntry(const RangeTblEntry *from)
COPY_NODE_FIELD(ctecolcollations);
COPY_NODE_FIELD(alias);
COPY_NODE_FIELD(eref);
+ COPY_SCALAR_FIELD(lateral);
COPY_SCALAR_FIELD(inh);
COPY_SCALAR_FIELD(inFromCl);
COPY_SCALAR_FIELD(requiredPerms);
COPY_SCALAR_FIELD(checkAsUser);
COPY_BITMAPSET_FIELD(selectedCols);
COPY_BITMAPSET_FIELD(modifiedCols);
+ COPY_NODE_FIELD(securityQuals);
+
+ return newnode;
+}
+
+static RangeTblFunction *
+_copyRangeTblFunction(const RangeTblFunction *from)
+{
+ RangeTblFunction *newnode = makeNode(RangeTblFunction);
+
+ COPY_NODE_FIELD(funcexpr);
+ COPY_SCALAR_FIELD(funccolcount);
+ COPY_NODE_FIELD(funccolnames);
+ COPY_NODE_FIELD(funccoltypes);
+ COPY_NODE_FIELD(funccoltypmods);
+ COPY_NODE_FIELD(funccolcollations);
+ COPY_BITMAPSET_FIELD(funcparams);
+
+ return newnode;
+}
+
+static WithCheckOption *
+_copyWithCheckOption(const WithCheckOption *from)
+{
+ WithCheckOption *newnode = makeNode(WithCheckOption);
+
+ COPY_STRING_FIELD(viewname);
+ COPY_NODE_FIELD(qual);
+ COPY_SCALAR_FIELD(cascaded);
return newnode;
}
@@ -971,7 +2074,7 @@ _copyRowMarkClause(const RowMarkClause *from)
RowMarkClause *newnode = makeNode(RowMarkClause);
COPY_SCALAR_FIELD(rti);
- COPY_SCALAR_FIELD(forUpdate);
+ COPY_SCALAR_FIELD(strength);
COPY_SCALAR_FIELD(noWait);
COPY_SCALAR_FIELD(pushedDown);
@@ -1066,7 +2169,7 @@ _copyAConst(const A_Const *from)
/* nothing to do */
break;
default:
- pool_error("unrecognized node type: %d",
+ elog(ERROR, "unrecognized node type: %d",
(int) from->val.type);
break;
}
@@ -1084,6 +2187,8 @@ _copyFuncCall(const FuncCall *from)
COPY_NODE_FIELD(funcname);
COPY_NODE_FIELD(args);
COPY_NODE_FIELD(agg_order);
+ COPY_NODE_FIELD(agg_filter);
+ COPY_SCALAR_FIELD(agg_within_group);
COPY_SCALAR_FIELD(agg_star);
COPY_SCALAR_FIELD(agg_distinct);
COPY_SCALAR_FIELD(func_variadic);
@@ -1200,6 +2305,7 @@ _copyRangeSubselect(const RangeSubselect *from)
{
RangeSubselect *newnode = makeNode(RangeSubselect);
+ COPY_SCALAR_FIELD(lateral);
COPY_NODE_FIELD(subquery);
COPY_NODE_FIELD(alias);
@@ -1211,7 +2317,10 @@ _copyRangeFunction(const RangeFunction *from)
{
RangeFunction *newnode = makeNode(RangeFunction);
- COPY_NODE_FIELD(funccallnode);
+ COPY_SCALAR_FIELD(lateral);
+ COPY_SCALAR_FIELD(ordinality);
+ COPY_SCALAR_FIELD(is_rowsfrom);
+ COPY_NODE_FIELD(functions);
COPY_NODE_FIELD(alias);
COPY_NODE_FIELD(coldeflist);
@@ -1276,6 +2385,7 @@ _copyColumnDef(const ColumnDef *from)
COPY_SCALAR_FIELD(collOid);
COPY_NODE_FIELD(constraints);
COPY_NODE_FIELD(fdwoptions);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
@@ -1307,6 +2417,7 @@ _copyConstraint(const Constraint *from)
COPY_SCALAR_FIELD(fk_upd_action);
COPY_SCALAR_FIELD(fk_del_action);
COPY_NODE_FIELD(old_conpfeqop);
+ COPY_SCALAR_FIELD(old_pktable_oid);
COPY_SCALAR_FIELD(skip_validation);
COPY_SCALAR_FIELD(initially_valid);
@@ -1332,7 +2443,7 @@ _copyLockingClause(const LockingClause *from)
LockingClause *newnode = makeNode(LockingClause);
COPY_NODE_FIELD(lockedRels);
- COPY_SCALAR_FIELD(forUpdate);
+ COPY_SCALAR_FIELD(strength);
COPY_SCALAR_FIELD(noWait);
return newnode;
@@ -1373,6 +2484,7 @@ _copyQuery(const Query *from)
COPY_NODE_FIELD(rtable);
COPY_NODE_FIELD(jointree);
COPY_NODE_FIELD(targetList);
+ COPY_NODE_FIELD(withCheckOptions);
COPY_NODE_FIELD(returningList);
COPY_NODE_FIELD(groupClause);
COPY_NODE_FIELD(havingQual);
@@ -1444,12 +2556,12 @@ _copySelectStmt(const SelectStmt *from)
COPY_NODE_FIELD(groupClause);
COPY_NODE_FIELD(havingClause);
COPY_NODE_FIELD(windowClause);
- COPY_NODE_FIELD(withClause);
COPY_NODE_FIELD(valuesLists);
COPY_NODE_FIELD(sortClause);
COPY_NODE_FIELD(limitOffset);
COPY_NODE_FIELD(limitCount);
COPY_NODE_FIELD(lockingClause);
+ COPY_NODE_FIELD(withClause);
COPY_SCALAR_FIELD(op);
COPY_SCALAR_FIELD(all);
COPY_NODE_FIELD(larg);
@@ -1635,6 +2747,7 @@ _copyCopyStmt(const CopyStmt *from)
COPY_NODE_FIELD(query);
COPY_NODE_FIELD(attlist);
COPY_SCALAR_FIELD(is_from);
+ COPY_SCALAR_FIELD(is_program);
COPY_STRING_FIELD(filename);
COPY_NODE_FIELD(options);
@@ -1865,7 +2978,6 @@ _copyAlterObjectSchemaStmt(const AlterObjectSchemaStmt *from)
COPY_NODE_FIELD(relation);
COPY_NODE_FIELD(object);
COPY_NODE_FIELD(objarg);
- COPY_STRING_FIELD(addname);
COPY_STRING_FIELD(newschema);
COPY_SCALAR_FIELD(missing_ok);
@@ -1881,7 +2993,6 @@ _copyAlterOwnerStmt(const AlterOwnerStmt *from)
COPY_NODE_FIELD(relation);
COPY_NODE_FIELD(object);
COPY_NODE_FIELD(objarg);
- COPY_STRING_FIELD(addname);
COPY_STRING_FIELD(newowner);
return newnode;
@@ -1988,6 +3099,7 @@ _copyAlterEnumStmt(const AlterEnumStmt *from)
COPY_STRING_FIELD(newVal);
COPY_STRING_FIELD(newValNeighbor);
COPY_SCALAR_FIELD(newValIsAfter);
+ COPY_SCALAR_FIELD(skipIfExists);
return newnode;
}
@@ -2002,6 +3114,7 @@ _copyViewStmt(const ViewStmt *from)
COPY_NODE_FIELD(query);
COPY_SCALAR_FIELD(replace);
COPY_NODE_FIELD(options);
+ COPY_SCALAR_FIELD(withCheckOption);
return newnode;
}
@@ -2136,6 +3249,8 @@ _copyVacuumStmt(const VacuumStmt *from)
COPY_SCALAR_FIELD(options);
COPY_SCALAR_FIELD(freeze_min_age);
COPY_SCALAR_FIELD(freeze_table_age);
+ COPY_SCALAR_FIELD(multixact_freeze_min_age);
+ COPY_SCALAR_FIELD(multixact_freeze_table_age);
COPY_NODE_FIELD(relation);
COPY_NODE_FIELD(va_cols);
@@ -2160,11 +3275,45 @@ _copyCreateTableAsStmt(const CreateTableAsStmt *from)
COPY_NODE_FIELD(query);
COPY_NODE_FIELD(into);
+ COPY_SCALAR_FIELD(relkind);
COPY_SCALAR_FIELD(is_select_into);
return newnode;
}
+static RefreshMatViewStmt *
+_copyRefreshMatViewStmt(const RefreshMatViewStmt *from)
+{
+ RefreshMatViewStmt *newnode = makeNode(RefreshMatViewStmt);
+
+ COPY_SCALAR_FIELD(concurrent);
+ COPY_SCALAR_FIELD(skipData);
+ COPY_NODE_FIELD(relation);
+
+ return newnode;
+}
+
+static ReplicaIdentityStmt *
+_copyReplicaIdentityStmt(const ReplicaIdentityStmt *from)
+{
+ ReplicaIdentityStmt *newnode = makeNode(ReplicaIdentityStmt);
+
+ COPY_SCALAR_FIELD(identity_type);
+ COPY_STRING_FIELD(name);
+
+ return newnode;
+}
+
+static AlterSystemStmt *
+_copyAlterSystemStmt(const AlterSystemStmt *from)
+{
+ AlterSystemStmt *newnode = makeNode(AlterSystemStmt);
+
+ COPY_NODE_FIELD(setstmt);
+
+ return newnode;
+}
+
static CreateSeqStmt *
_copyCreateSeqStmt(const CreateSeqStmt *from)
{
@@ -2230,6 +3379,7 @@ _copyCreateTableSpaceStmt(const CreateTableSpaceStmt *from)
COPY_STRING_FIELD(tablespacename);
COPY_STRING_FIELD(owner);
COPY_STRING_FIELD(location);
+ COPY_NODE_FIELD(options);
return newnode;
}
@@ -2257,6 +3407,21 @@ _copyAlterTableSpaceOptionsStmt(const AlterTableSpaceOptionsStmt *from)
return newnode;
}
+static AlterTableSpaceMoveStmt *
+_copyAlterTableSpaceMoveStmt(const AlterTableSpaceMoveStmt *from)
+{
+ AlterTableSpaceMoveStmt *newnode = makeNode(AlterTableSpaceMoveStmt);
+
+ COPY_STRING_FIELD(orig_tablespacename);
+ COPY_SCALAR_FIELD(objtype);
+ COPY_SCALAR_FIELD(move_all);
+ COPY_NODE_FIELD(roles);
+ COPY_STRING_FIELD(new_tablespacename);
+ COPY_SCALAR_FIELD(nowait);
+
+ return newnode;
+}
+
static CreateExtensionStmt *
_copyCreateExtensionStmt(const CreateExtensionStmt *from)
{
@@ -2416,6 +3581,30 @@ _copyCreateTrigStmt(const CreateTrigStmt *from)
return newnode;
}
+static CreateEventTrigStmt *
+_copyCreateEventTrigStmt(const CreateEventTrigStmt *from)
+{
+ CreateEventTrigStmt *newnode = makeNode(CreateEventTrigStmt);
+
+ COPY_STRING_FIELD(trigname);
+ COPY_SCALAR_FIELD(eventname);
+ COPY_NODE_FIELD(whenclause);
+ COPY_NODE_FIELD(funcname);
+
+ return newnode;
+}
+
+static AlterEventTrigStmt *
+_copyAlterEventTrigStmt(const AlterEventTrigStmt *from)
+{
+ AlterEventTrigStmt *newnode = makeNode(AlterEventTrigStmt);
+
+ COPY_STRING_FIELD(trigname);
+ COPY_SCALAR_FIELD(tgenabled);
+
+ return newnode;
+}
+
static CreatePLangStmt *
_copyCreatePLangStmt(const CreatePLangStmt *from)
{
@@ -2523,6 +3712,7 @@ _copyCreateSchemaStmt(const CreateSchemaStmt *from)
COPY_STRING_FIELD(schemaname);
COPY_STRING_FIELD(authid);
COPY_NODE_FIELD(schemaElts);
+ COPY_SCALAR_FIELD(if_not_exists);
return newnode;
}
@@ -2704,7 +3894,7 @@ _copyValue(const Value *from)
/* nothing to do */
break;
default:
- pool_error("unrecognized node type: %d",
+ elog(ERROR, "unrecognized node type: %d",
(int) from->type);
break;
}
@@ -2725,13 +3915,134 @@ copyObject(const void *from)
if (from == NULL)
return NULL;
-#if 0
/* Guard against stack overflow due to overly complex expressions */
+#ifdef NOT_USED_IN_PGPOOL
check_stack_depth();
#endif
-
switch (nodeTag(from))
{
+#ifdef NOT_USED_IN_PGPOOL
+ /*
+ * PLAN NODES
+ */
+ case T_PlannedStmt:
+ retval = _copyPlannedStmt(from);
+ break;
+ case T_Plan:
+ retval = _copyPlan(from);
+ break;
+ case T_Result:
+ retval = _copyResult(from);
+ break;
+ case T_ModifyTable:
+ retval = _copyModifyTable(from);
+ break;
+ case T_Append:
+ retval = _copyAppend(from);
+ break;
+ case T_MergeAppend:
+ retval = _copyMergeAppend(from);
+ break;
+ case T_RecursiveUnion:
+ retval = _copyRecursiveUnion(from);
+ break;
+ case T_BitmapAnd:
+ retval = _copyBitmapAnd(from);
+ break;
+ case T_BitmapOr:
+ retval = _copyBitmapOr(from);
+ break;
+ case T_Scan:
+ retval = _copyScan(from);
+ break;
+ case T_SeqScan:
+ retval = _copySeqScan(from);
+ break;
+ case T_IndexScan:
+ retval = _copyIndexScan(from);
+ break;
+ case T_IndexOnlyScan:
+ retval = _copyIndexOnlyScan(from);
+ break;
+ case T_BitmapIndexScan:
+ retval = _copyBitmapIndexScan(from);
+ break;
+ case T_BitmapHeapScan:
+ retval = _copyBitmapHeapScan(from);
+ break;
+ case T_TidScan:
+ retval = _copyTidScan(from);
+ break;
+ case T_SubqueryScan:
+ retval = _copySubqueryScan(from);
+ break;
+ case T_FunctionScan:
+ retval = _copyFunctionScan(from);
+ break;
+ case T_ValuesScan:
+ retval = _copyValuesScan(from);
+ break;
+ case T_CteScan:
+ retval = _copyCteScan(from);
+ break;
+ case T_WorkTableScan:
+ retval = _copyWorkTableScan(from);
+ break;
+ case T_ForeignScan:
+ retval = _copyForeignScan(from);
+ break;
+ case T_Join:
+ retval = _copyJoin(from);
+ break;
+ case T_NestLoop:
+ retval = _copyNestLoop(from);
+ break;
+ case T_MergeJoin:
+ retval = _copyMergeJoin(from);
+ break;
+ case T_HashJoin:
+ retval = _copyHashJoin(from);
+ break;
+ case T_Material:
+ retval = _copyMaterial(from);
+ break;
+ case T_Sort:
+ retval = _copySort(from);
+ break;
+ case T_Group:
+ retval = _copyGroup(from);
+ break;
+ case T_Agg:
+ retval = _copyAgg(from);
+ break;
+ case T_WindowAgg:
+ retval = _copyWindowAgg(from);
+ break;
+ case T_Unique:
+ retval = _copyUnique(from);
+ break;
+ case T_Hash:
+ retval = _copyHash(from);
+ break;
+ case T_SetOp:
+ retval = _copySetOp(from);
+ break;
+ case T_LockRows:
+ retval = _copyLockRows(from);
+ break;
+ case T_Limit:
+ retval = _copyLimit(from);
+ break;
+ case T_NestLoopParam:
+ retval = _copyNestLoopParam(from);
+ break;
+ case T_PlanRowMark:
+ retval = _copyPlanRowMark(from);
+ break;
+ case T_PlanInvalItem:
+ retval = _copyPlanInvalItem(from);
+ break;
+#endif
/*
* PRIMITIVE NODES
*/
@@ -2747,6 +4058,11 @@ copyObject(const void *from)
case T_Var:
retval = _copyVar(from);
break;
+#ifdef NOT_USED_IN_PGPOOL
+ case T_Const:
+ retval = _copyConst(from);
+ break;
+#endif
case T_Param:
retval = _copyParam(from);
break;
@@ -2867,7 +4183,32 @@ copyObject(const void *from)
case T_FromExpr:
retval = _copyFromExpr(from);
break;
-
+#ifdef NOT_USED_IN_PGPOOL
+ /*
+ * RELATION NODES
+ */
+ case T_PathKey:
+ retval = _copyPathKey(from);
+ break;
+ case T_RestrictInfo:
+ retval = _copyRestrictInfo(from);
+ break;
+ case T_PlaceHolderVar:
+ retval = _copyPlaceHolderVar(from);
+ break;
+ case T_SpecialJoinInfo:
+ retval = _copySpecialJoinInfo(from);
+ break;
+ case T_LateralJoinInfo:
+ retval = _copyLateralJoinInfo(from);
+ break;
+ case T_AppendRelInfo:
+ retval = _copyAppendRelInfo(from);
+ break;
+ case T_PlaceHolderInfo:
+ retval = _copyPlaceHolderInfo(from);
+ break;
+#endif
/*
* VALUE NODES
*/
@@ -3063,6 +4404,15 @@ copyObject(const void *from)
case T_CreateTableAsStmt:
retval = _copyCreateTableAsStmt(from);
break;
+ case T_RefreshMatViewStmt:
+ retval = _copyRefreshMatViewStmt(from);
+ break;
+ case T_ReplicaIdentityStmt:
+ retval = _copyReplicaIdentityStmt(from);
+ break;
+ case T_AlterSystemStmt:
+ retval = _copyAlterSystemStmt(from);
+ break;
case T_CreateSeqStmt:
retval = _copyCreateSeqStmt(from);
break;
@@ -3087,6 +4437,9 @@ copyObject(const void *from)
case T_AlterTableSpaceOptionsStmt:
retval = _copyAlterTableSpaceOptionsStmt(from);
break;
+ case T_AlterTableSpaceMoveStmt:
+ retval = _copyAlterTableSpaceMoveStmt(from);
+ break;
case T_CreateExtensionStmt:
retval = _copyCreateExtensionStmt(from);
break;
@@ -3123,6 +4476,12 @@ copyObject(const void *from)
case T_CreateTrigStmt:
retval = _copyCreateTrigStmt(from);
break;
+ case T_CreateEventTrigStmt:
+ retval = _copyCreateEventTrigStmt(from);
+ break;
+ case T_AlterEventTrigStmt:
+ retval = _copyAlterEventTrigStmt(from);
+ break;
case T_CreatePLangStmt:
retval = _copyCreatePLangStmt(from);
break;
@@ -3250,6 +4609,12 @@ copyObject(const void *from)
case T_RangeTblEntry:
retval = _copyRangeTblEntry(from);
break;
+ case T_RangeTblFunction:
+ retval = _copyRangeTblFunction(from);
+ break;
+ case T_WithCheckOption:
+ retval = _copyWithCheckOption(from);
+ break;
case T_SortGroupClause:
retval = _copySortGroupClause(from);
break;
@@ -3279,32 +4644,33 @@ copyObject(const void *from)
break;
default:
- pool_error("unrecognized node type: %d", (int) nodeTag(from));
- retval = (char*)from; /* keep compiler quiet */
+ elog(ERROR, "unrecognized node type: %d", (int) nodeTag(from));
+ retval = 0; /* keep compiler quiet */
break;
}
return retval;
}
-/* from backend/nodes/bitmapset.c start */
-#define BITMAPSET_SIZE(nwords) \
- (offsetof(Bitmapset, words) + (nwords) * sizeof(bitmapword))
-
/*
+ * from src/backend/nodes/bitmapset.c
* bms_copy - make a palloc'd copy of a bitmapset
*/
+
+#define BITMAPSET_SIZE(nwords) \
+(offsetof(Bitmapset, words) + (nwords) * sizeof(bitmapword))
+
+
Bitmapset *
bms_copy(const Bitmapset *a)
{
- Bitmapset *result;
- size_t size;
-
- if (a == NULL)
- return NULL;
- size = BITMAPSET_SIZE(a->nwords);
- result = (Bitmapset *) palloc(size);
- memcpy(result, a, size);
- return result;
+ Bitmapset *result;
+ size_t size;
+
+ if (a == NULL)
+ return NULL;
+ size = BITMAPSET_SIZE(a->nwords);
+ result = (Bitmapset *) palloc(size);
+ memcpy(result, a, size);
+ return result;
}
-/* from backend/nodes/bitmapset.c end */
diff --git a/src/parser/gram.y b/src/parser/gram.y
index 0147e01..23a73b0 100644
--- a/src/parser/gram.y
+++ b/src/parser/gram.y
@@ -6,8 +6,8 @@
* gram.y
* POSTGRESQL BISON rules/actions
*
- * Portions Copyright (c) 2003-2013, PgPool Global Development Group
- * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
+ * Portions Copyright (c) 2003-2014, PgPool Global Development Group
+ * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -22,8 +22,6 @@
* NOTES
* CAPITALS are used to represent terminal symbols.
* non-capitals are used to represent non-terminals.
- * SQL92-specific syntax is separated from plain SQL/Postgres syntax
- * to help isolate the non-extensible portions of the parser.
*
* In general, nothing in this file should initiate database accesses
* nor depend on changeable state (such as SET variables). If you do
@@ -47,6 +45,7 @@
*
*-------------------------------------------------------------------------
*/
+
#include "pool_parser.h"
#include "utils/elog.h"
#include "utils/palloc.h"
@@ -66,27 +65,66 @@
#include "pg_trigger.h"
-/* for XML data type */
+/*
+ * Definition taken from
+ * postgreSQL source code file: src/include/commands/trigger.h
+ */
+#define TRIGGER_FIRES_ON_ORIGIN 'O'
+#define TRIGGER_FIRES_ALWAYS 'A'
+#define TRIGGER_FIRES_ON_REPLICA 'R'
+#define TRIGGER_DISABLED 'D'
+
+/*
+ * Definition taken from
+ * postgreSQL source code file: src/include/catalog/pg_class.h
+ */
+
+#define REPLICA_IDENTITY_DEFAULT 'd'
+#define REPLICA_IDENTITY_NOTHING 'n'
+#define REPLICA_IDENTITY_FULL 'f'
+#define REPLICA_IDENTITY_INDEX 'i'
+
+/*
+ * Definition taken from
+ * postgreSQL source code file: src/include/utils/xml.h
+ */
typedef enum
{
- XML_STANDALONE_YES,
- XML_STANDALONE_NO,
- XML_STANDALONE_NO_VALUE,
- XML_STANDALONE_OMITTED
+ XML_STANDALONE_YES,
+ XML_STANDALONE_NO,
+ XML_STANDALONE_NO_VALUE,
+ XML_STANDALONE_OMITTED
} XmlStandaloneType;
static DefElem *defWithOids(bool value);
-
-/* Location tracking support --- simpler than bison's default */
+/*
+ * Location tracking support --- simpler than bison's default, since we only
+ * want to track the start position not the end position of each nonterminal.
+ */
#define YYLLOC_DEFAULT(Current, Rhs, N) \
do { \
- if (N) \
+ if ((N) > 0) \
(Current) = (Rhs)[1]; \
else \
- (Current) = (Rhs)[0]; \
+ (Current) = (-1); \
} while (0)
/*
+ * The above macro assigns -1 (unknown) as the parse location of any
+ * nonterminal that was reduced from an empty rule. This is problematic
+ * for nonterminals defined like
+ * OptFooList: / * EMPTY * / { ... } | OptFooList Foo { ... } ;
+ * because we'll set -1 as the location during the first reduction and then
+ * copy it during each subsequent reduction, leaving us with -1 for the
+ * location even when the list is not empty. To fix that, do this in the
+ * action for the nonempty rule(s):
+ * if (@$ < 0) @$ = @2;
+ * (Although we have many nonterminals that follow this pattern, we only
+ * bother with fixing @$ like this when the nonterminal's parse location
+ * is actually referenced in some rule.)
+ */
+
+/*
* Bison doesn't allocate anything that needs to live across parser calls,
* so we can easily have it use palloc instead of malloc. This prevents
* memory leaks if we error out during parsing. Note this only works with
@@ -130,12 +168,13 @@ static Node *makeBitStringConst(char *str, int location);
static Node *makeNullAConst(int location);
static Node *makeAConst(Value *v, int location);
static Node *makeBoolAConst(bool state, int location);
-static FuncCall *makeOverlaps(List *largs, List *rargs,
- int location, core_yyscan_t yyscanner);
static void check_qualified_name(List *names, core_yyscan_t yyscanner);
static List *check_func_name(List *names, core_yyscan_t yyscanner);
static List *check_indirection(List *indirection, core_yyscan_t yyscanner);
static List *extractArgTypes(List *parameters);
+static List *extractAggrArgTypes(List *aggrargs);
+static List *makeOrderedSetArgs(List *directargs, List *orderedargs,
+ core_yyscan_t yyscanner);
static void insertSelectOptions(SelectStmt *stmt,
List *sortClause, List *lockingClause,
Node *limitOffset, Node *limitCount,
@@ -156,6 +195,7 @@ static void SplitColQualList(List *qualList,
static void processCASbits(int cas_bits, int location, const char *constrType,
bool *deferrable, bool *initdeferred, bool *not_valid,
bool *no_inherit, core_yyscan_t yyscanner);
+static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%}
@@ -206,10 +246,11 @@ static void processCASbits(int cas_bits, int location, const char *constrType,
}
%type <node> stmt schema_stmt
+ AlterEventTrigStmt
AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterEnumStmt
AlterFdwStmt AlterForeignServerStmt AlterGroupStmt
- AlterObjectSchemaStmt AlterOwnerStmt AlterSeqStmt AlterTableStmt
- AlterExtensionStmt AlterExtensionContentsStmt AlterForeignTableStmt
+ AlterObjectSchemaStmt AlterOwnerStmt AlterSeqStmt AlterSystemStmt AlterTableStmt
+ AlterTblSpcStmt AlterExtensionStmt AlterExtensionContentsStmt AlterForeignTableStmt
AlterCompositeTypeStmt AlterUserStmt AlterUserMappingStmt AlterUserSetStmt
AlterRoleStmt AlterRoleSetStmt
AlterDefaultPrivilegesStmt DefACLAction
@@ -219,7 +260,7 @@ static void processCASbits(int cas_bits, int location, const char *constrType,
CreateOpFamilyStmt AlterOpFamilyStmt CreatePLangStmt
CreateSchemaStmt CreateSeqStmt CreateStmt CreateTableSpaceStmt
CreateFdwStmt CreateForeignServerStmt CreateForeignTableStmt
- CreateAssertStmt CreateTrigStmt
+ CreateAssertStmt CreateTrigStmt CreateEventTrigStmt
CreateUserStmt CreateUserMappingStmt CreateRoleStmt
CreatedbStmt DeclareCursorStmt DefineStmt DeleteStmt DiscardStmt DoStmt
DropGroupStmt DropOpClassStmt DropOpFamilyStmt DropPLangStmt DropStmt
@@ -238,6 +279,7 @@ static void processCASbits(int cas_bits, int location, const char *constrType,
DeallocateStmt PrepareStmt ExecuteStmt
DropOwnedStmt ReassignOwnedStmt
AlterTSConfigurationStmt AlterTSDictionaryStmt
+ CreateMatViewStmt RefreshMatViewStmt
%type <node> select_no_parens select_with_parens select_clause
simple_select values_clause
@@ -246,6 +288,7 @@ static void processCASbits(int cas_bits, int location, const char *constrType,
%type <ival> add_drop opt_asc_desc opt_nulls_order
%type <node> alter_table_cmd alter_type_cmd opt_collate_clause
+ replica_identity
%type <list> alter_table_cmds alter_type_cmds
%type <dbehavior> opt_drop_behavior
@@ -280,6 +323,10 @@ static void processCASbits(int cas_bits, int location, const char *constrType,
%type <value> TriggerFuncArg
%type <node> TriggerWhen
+%type <list> event_trigger_when_list event_trigger_value_list
+%type <defelt> event_trigger_when_item
+%type <chr> enable_trigger
+
%type <str> copy_file_name
database_name access_method_clause access_method attr_name
name cursor_name file_name
@@ -308,19 +355,19 @@ static void processCASbits(int cas_bits, int location, const char *constrType,
%type <list> stmtblock stmtmulti
OptTableElementList TableElementList OptInherit definition
OptTypedTableElementList TypedTableElementList
- OptForeignTableElementList ForeignTableElementList
reloptions opt_reloptions
OptWith opt_distinct opt_definition func_args func_args_list
func_args_with_defaults func_args_with_defaults_list
+ aggr_args aggr_args_list
func_as createfunc_opt_list alterfunc_opt_list
- aggr_args old_aggr_definition old_aggr_list
+ old_aggr_definition old_aggr_list
oper_argtypes RuleActionList RuleActionMulti
opt_column_list columnList opt_name_list
sort_clause opt_sort_clause sortby_list index_params
- name_list from_clause from_list opt_array_bounds
+ name_list role_list from_clause from_list opt_array_bounds
qualified_name_list any_name any_name_list
any_operator expr_list attrs
- target_list insert_column_list set_target_list
+ target_list opt_target_list insert_column_list set_target_list
set_clause_list set_clause multiple_set_clause
ctext_expr_list ctext_row def_list indirection opt_indirection
reloption_list group_clause TriggerFuncArgs select_limit
@@ -337,17 +384,19 @@ static void processCASbits(int cas_bits, int location, const char *constrType,
%type <defelt> fdw_option
%type <range> OptTempTableName
-%type <into> into_clause create_as_target
+%type <into> into_clause create_as_target create_mv_target
%type <defelt> createfunc_opt_item common_func_opt_item dostmt_opt_item
-%type <fun_param> func_arg func_arg_with_default table_func_column
+%type <fun_param> func_arg func_arg_with_default table_func_column aggr_arg
%type <fun_param_mode> arg_class
%type <typnam> func_return func_type
%type <boolean> opt_trusted opt_restart_seqs
%type <ival> OptTemp
+%type <ival> OptNoLog
%type <oncommit> OnCommitOption
+%type <ival> for_locking_strength
%type <node> for_locking_item
%type <list> for_locking_clause opt_for_locking_clause for_locking_items
%type <list> locked_rels_list
@@ -366,7 +415,7 @@ static void processCASbits(int cas_bits, int location, const char *constrType,
%type <boolean> opt_freeze opt_default opt_recheck
%type <defelt> opt_binary opt_oids copy_delimiter
-%type <boolean> copy_from
+%type <boolean> copy_from opt_program
%type <ival> opt_column event cursor_options opt_hold opt_set_data
%type <objtype> reindex_type drop_type comment_type security_label_type
@@ -381,16 +430,17 @@ static void processCASbits(int cas_bits, int location, const char *constrType,
%type <istmt> insert_rest
-%type <vsetstmt> set_rest set_rest_more SetResetClause FunctionSetResetClause
+%type <vsetstmt> generic_set set_rest set_rest_more SetResetClause FunctionSetResetClause
%type <node> TableElement TypedTableElement ConstraintElem TableFuncElement
- ForeignTableElement
%type <node> columnDef columnOptions
%type <defelt> def_elem reloption_elem old_aggr_elem
%type <node> def_arg columnElem where_clause where_or_current_clause
- a_expr b_expr c_expr func_expr AexprConst indirection_el
+ a_expr b_expr c_expr AexprConst indirection_el
columnref in_expr having_clause func_table array_expr
ExclusionWhereClause
+%type <list> rowsfrom_item rowsfrom_list opt_col_def_list
+%type <boolean> opt_ordinality
%type <list> ExclusionConstraintList ExclusionConstraintElem
%type <list> func_arg_list
%type <node> func_arg_expr
@@ -401,7 +451,8 @@ static void processCASbits(int cas_bits, int location, const char *constrType,
%type <node> ctext_expr
%type <value> NumericOnly
%type <list> NumericOnly_list
-%type <alias> alias_clause
+%type <alias> alias_clause opt_alias_clause
+%type <list> func_alias_clause
%type <sortby> sortby
%type <ielem> index_elem
%type <node> table_ref
@@ -436,9 +487,10 @@ static void processCASbits(int cas_bits, int location, const char *constrType,
%type <ival> Iconst SignedIconst
%type <str> Sconst comment_text notify_payload
-%type <str> RoleId opt_granted_by opt_boolean_or_string ColId_or_Sconst
+%type <str> RoleId opt_granted_by opt_boolean_or_string
%type <list> var_list
%type <str> ColId ColLabel var_name type_function_name param_name
+%type <str> NonReservedWord NonReservedWord_or_Sconst
%type <node> var_value zone_value
%type <keyword> unreserved_keyword type_func_name_keyword
@@ -455,7 +507,7 @@ static void processCASbits(int cas_bits, int location, const char *constrType,
%type <list> constraints_set_list
%type <boolean> constraints_set_mode
%type <str> OptTableSpace OptConsTableSpace OptTableSpaceOwner
-%type <list> opt_check_option
+%type <ival> opt_check_option
%type <str> opt_provider security_label
@@ -466,15 +518,19 @@ static void processCASbits(int cas_bits, int location, const char *constrType,
%type <ival> document_or_content
%type <boolean> xml_whitespace_option
+%type <node> func_application func_expr_common_subexpr
+%type <node> func_expr func_expr_windowless
%type <node> common_table_expr
%type <with> with_clause opt_with_clause
%type <list> cte_list
+%type <list> within_group_clause
+%type <node> filter_clause
%type <list> window_clause window_definition_list opt_partition_clause
%type <windef> window_definition over_clause window_specification
opt_frame_clause frame_extent frame_bound
%type <str> opt_existing_window_name
-
+%type <boolean> opt_if_not_exists
/*
* Non-keyword token types. These are hard-wired into the "flex" lexer.
@@ -517,12 +573,12 @@ static void processCASbits(int cas_bits, int location, const char *constrType,
DEFERRABLE DEFERRED DEFINER DELETE_P DELIMITER DELIMITERS DESC
DICTIONARY DISABLE_P DISCARD DISTINCT DO DOCUMENT_P DOMAIN_P DOUBLE_P DROP
- EACH ELSE ENABLE_P ENCODING ENCRYPTED END_P ENUM_P ESCAPE EXCEPT
+ EACH ELSE ENABLE_P ENCODING ENCRYPTED END_P ENUM_P ESCAPE EVENT EXCEPT
EXCLUDE EXCLUDING EXCLUSIVE EXECUTE EXISTS EXPLAIN
EXTENSION EXTERNAL EXTRACT
- FALSE_P FAMILY FETCH FIRST_P FLOAT_P FOLLOWING FOR FORCE FOREIGN FORWARD
- FREEZE FROM FULL FUNCTION FUNCTIONS
+ FALSE_P FAMILY FETCH FILTER FIRST_P FLOAT_P FOLLOWING FOR
+ FORCE FOREIGN FORWARD FREEZE FROM FULL FUNCTION FUNCTIONS
GLOBAL GRANT GRANTED GREATEST GROUP_P
@@ -537,26 +593,26 @@ static void processCASbits(int cas_bits, int location, const char *constrType,
KEY
- LABEL LANGUAGE LARGE_P LAST_P LC_COLLATE_P LC_CTYPE_P LEADING LEAKPROOF
- LEAST LEFT LEVEL LIKE LIMIT LISTEN LOAD LOCAL LOCALTIME LOCALTIMESTAMP
- LOCATION LOCK_P
+ LABEL LANGUAGE LARGE_P LAST_P LATERAL_P LC_COLLATE_P LC_CTYPE_P
+ LEADING LEAKPROOF LEAST LEFT LEVEL LIKE LIMIT LISTEN LOAD LOCAL
+ LOCALTIME LOCALTIMESTAMP LOCATION LOCK_P
- MAPPING MATCH MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE
+ MAPPING MATCH MATERIALIZED MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE
NAME_P NAMES NATIONAL NATURAL NCHAR NEXT NO NONE
NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF
NULLS_P NUMERIC
OBJECT_P OF OFF OFFSET OIDS ON ONLY OPERATOR OPTION OPTIONS OR
- ORDER OUT_P OUTER_P OVER OVERLAPS OVERLAY OWNED OWNER
+ ORDER ORDINALITY OUT_P OUTER_P OVER OVERLAPS OVERLAY OWNED OWNER
PARSER PARTIAL PARTITION PASSING PASSWORD PLACING PLANS POSITION
PRECEDING PRECISION PRESERVE PREPARE PREPARED PRIMARY
- PRIOR PRIVILEGES PROCEDURAL PROCEDURE
+ PRIOR PRIVILEGES PROCEDURAL PROCEDURE PROGRAM
QUOTE
- RANGE READ REAL REASSIGN RECHECK RECURSIVE REF REFERENCES REINDEX
+ RANGE READ REAL REASSIGN RECHECK RECURSIVE REF REFERENCES REFRESH REINDEX
RELATIVE_P RELEASE RENAME REPEATABLE REPLACE REPLICA
RESET RESTART RESTRICT RETURNING RETURNS REVOKE RIGHT ROLE ROLLBACK
ROW ROWS RULE
@@ -575,9 +631,9 @@ static void processCASbits(int cas_bits, int location, const char *constrType,
UNTIL UPDATE USER USING
VACUUM VALID VALIDATE VALIDATOR VALUE_P VALUES VARCHAR VARIADIC VARYING
- VERBOSE VERSION_P VIEW VOLATILE
+ VERBOSE VERSION_P VIEW VIEWS VOLATILE
- WHEN WHERE WHITESPACE_P WINDOW WITH WITHOUT WORK WRAPPER WRITE
+ WHEN WHERE WHITESPACE_P WINDOW WITH WITHIN WITHOUT WORK WRAPPER WRITE
XML_P XMLATTRIBUTES XMLCONCAT XMLELEMENT XMLEXISTS XMLFOREST XMLPARSE
XMLPI XMLROOT XMLSERIALIZE
@@ -591,7 +647,7 @@ static void processCASbits(int cas_bits, int location, const char *constrType,
* list and so can never be entered directly. The filter in parser.c
* creates these tokens when required.
*/
-%token NULLS_FIRST NULLS_LAST WITH_TIME
+%token NULLS_FIRST NULLS_LAST WITH_ORDINALITY WITH_TIME
/* Precedence: lowest to highest */
@@ -686,7 +742,8 @@ stmtmulti: stmtmulti ';' stmt
;
stmt :
- AlterDatabaseStmt
+ AlterEventTrigStmt
+ | AlterDatabaseStmt
| AlterDatabaseSetStmt
| AlterDefaultPrivilegesStmt
| AlterDomainStmt
@@ -701,7 +758,9 @@ stmt :
| AlterObjectSchemaStmt
| AlterOwnerStmt
| AlterSeqStmt
+ | AlterSystemStmt
| AlterTableStmt
+ | AlterTblSpcStmt
| AlterCompositeTypeStmt
| AlterRoleSetStmt
| AlterRoleStmt
@@ -728,6 +787,7 @@ stmt :
| CreateForeignTableStmt
| CreateFunctionStmt
| CreateGroupStmt
+ | CreateMatViewStmt
| CreateOpClassStmt
| CreateOpFamilyStmt
| AlterOpFamilyStmt
@@ -737,6 +797,7 @@ stmt :
| CreateStmt
| CreateTableSpaceStmt
| CreateTrigStmt
+ | CreateEventTrigStmt
| CreateRoleStmt
| CreateUserStmt
| CreateUserMappingStmt
@@ -772,6 +833,7 @@ stmt :
| IndexStmt
| InsertStmt
| ListenStmt
+ | RefreshMatViewStmt
| LoadStmt
| LockStmt
| NotifyStmt
@@ -870,7 +932,7 @@ AlterOptRoleElem:
$$ = makeDefElem("validUntil", (Node *)makeString($3));
}
/* Supported but not documented for roles, for use by ALTER GROUP. */
- | USER name_list
+ | USER role_list
{
$$ = makeDefElem("rolemembers", (Node *)$2);
}
@@ -934,19 +996,19 @@ CreateOptRoleElem:
{
$$ = makeDefElem("sysid", (Node *)makeInteger($2));
}
- | ADMIN name_list
+ | ADMIN role_list
{
$$ = makeDefElem("adminmembers", (Node *)$2);
}
- | ROLE name_list
+ | ROLE role_list
{
$$ = makeDefElem("rolemembers", (Node *)$2);
}
- | IN_P ROLE name_list
+ | IN_P ROLE role_list
{
$$ = makeDefElem("addroleto", (Node *)$3);
}
- | IN_P GROUP_P name_list
+ | IN_P GROUP_P role_list
{
$$ = makeDefElem("addroleto", (Node *)$3);
}
@@ -1002,6 +1064,14 @@ AlterRoleSetStmt:
n->setstmt = $5;
$$ = (Node *)n;
}
+ | ALTER ROLE ALL opt_in_database SetResetClause
+ {
+ AlterRoleSetStmt *n = makeNode(AlterRoleSetStmt);
+ n->role = NULL;
+ n->database = $4;
+ n->setstmt = $5;
+ $$ = (Node *)n;
+ }
;
@@ -1045,14 +1115,14 @@ AlterUserSetStmt:
*****************************************************************************/
DropRoleStmt:
- DROP ROLE name_list
+ DROP ROLE role_list
{
DropRoleStmt *n = makeNode(DropRoleStmt);
n->missing_ok = FALSE;
n->roles = $3;
$$ = (Node *)n;
}
- | DROP ROLE IF_P EXISTS name_list
+ | DROP ROLE IF_P EXISTS role_list
{
DropRoleStmt *n = makeNode(DropRoleStmt);
n->missing_ok = TRUE;
@@ -1071,14 +1141,14 @@ DropRoleStmt:
*****************************************************************************/
DropUserStmt:
- DROP USER name_list
+ DROP USER role_list
{
DropRoleStmt *n = makeNode(DropRoleStmt);
n->missing_ok = FALSE;
n->roles = $3;
$$ = (Node *)n;
}
- | DROP USER IF_P EXISTS name_list
+ | DROP USER IF_P EXISTS role_list
{
DropRoleStmt *n = makeNode(DropRoleStmt);
n->roles = $5;
@@ -1113,7 +1183,7 @@ CreateGroupStmt:
*****************************************************************************/
AlterGroupStmt:
- ALTER GROUP_P RoleId add_drop USER name_list
+ ALTER GROUP_P RoleId add_drop USER role_list
{
AlterRoleStmt *n = makeNode(AlterRoleStmt);
n->role = $3;
@@ -1137,14 +1207,14 @@ add_drop: ADD_P { $$ = +1; }
*****************************************************************************/
DropGroupStmt:
- DROP GROUP_P name_list
+ DROP GROUP_P role_list
{
DropRoleStmt *n = makeNode(DropRoleStmt);
n->missing_ok = FALSE;
n->roles = $3;
$$ = (Node *)n;
}
- | DROP GROUP_P IF_P EXISTS name_list
+ | DROP GROUP_P IF_P EXISTS role_list
{
DropRoleStmt *n = makeNode(DropRoleStmt);
n->missing_ok = TRUE;
@@ -1171,6 +1241,7 @@ CreateSchemaStmt:
n->schemaname = $5;
n->authid = $5;
n->schemaElts = $6;
+ n->if_not_exists = false;
$$ = (Node *)n;
}
| CREATE SCHEMA ColId OptSchemaEltList
@@ -1180,6 +1251,40 @@ CreateSchemaStmt:
n->schemaname = $3;
n->authid = NULL;
n->schemaElts = $4;
+ n->if_not_exists = false;
+ $$ = (Node *)n;
+ }
+ | CREATE SCHEMA IF_P NOT EXISTS OptSchemaName AUTHORIZATION RoleId OptSchemaEltList
+ {
+ CreateSchemaStmt *n = makeNode(CreateSchemaStmt);
+ /* One can omit the schema name or the authorization id. */
+ if ($6 != NULL)
+ n->schemaname = $6;
+ else
+ n->schemaname = $8;
+ n->authid = $8;
+ if ($9 != NIL)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("CREATE SCHEMA IF NOT EXISTS cannot include schema elements"),
+ parser_errposition(@9)));
+ n->schemaElts = $9;
+ n->if_not_exists = true;
+ $$ = (Node *)n;
+ }
+ | CREATE SCHEMA IF_P NOT EXISTS ColId OptSchemaEltList
+ {
+ CreateSchemaStmt *n = makeNode(CreateSchemaStmt);
+ /* ...but not both */
+ n->schemaname = $6;
+ n->authid = NULL;
+ if ($7 != NIL)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("CREATE SCHEMA IF NOT EXISTS cannot include schema elements"),
+ parser_errposition(@7)));
+ n->schemaElts = $7;
+ n->if_not_exists = true;
$$ = (Node *)n;
}
;
@@ -1190,8 +1295,14 @@ OptSchemaName:
;
OptSchemaEltList:
- OptSchemaEltList schema_stmt { $$ = lappend($1, $2); }
- | /* EMPTY */ { $$ = NIL; }
+ OptSchemaEltList schema_stmt
+ {
+ if (@$ < 0) /* see comments for YYLLOC_DEFAULT */
+ @$ = @2;
+ $$ = lappend($1, $2);
+ }
+ | /* EMPTY */
+ { $$ = NIL; }
;
/*
@@ -1212,7 +1323,7 @@ schema_stmt:
*
* Set PG internal variable
* SET name TO 'var_value'
- * Include SQL92 syntax (thomas 1997-10-22):
+ * Include SQL syntax (thomas 1997-10-22):
* SET TIME ZONE 'var_value'
*
*****************************************************************************/
@@ -1258,7 +1369,7 @@ set_rest:
| set_rest_more
;
-set_rest_more: /* Generic SET syntaxes: */
+generic_set:
var_name TO var_list
{
VariableSetStmt *n = makeNode(VariableSetStmt);
@@ -1289,6 +1400,9 @@ set_rest_more: /* Generic SET syntaxes: */
n->name = $1;
$$ = n;
}
+
+set_rest_more: /* Generic SET syntaxes: */
+ generic_set {$$ = $1;}
| var_name FROM CURRENT_P
{
VariableSetStmt *n = makeNode(VariableSetStmt);
@@ -1335,7 +1449,7 @@ set_rest_more: /* Generic SET syntaxes: */
n->kind = VAR_SET_DEFAULT;
$$ = n;
}
- | ROLE ColId_or_Sconst
+ | ROLE NonReservedWord_or_Sconst
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_SET_VALUE;
@@ -1343,7 +1457,7 @@ set_rest_more: /* Generic SET syntaxes: */
n->args = list_make1(makeStringConst($2, @2));
$$ = n;
}
- | SESSION AUTHORIZATION ColId_or_Sconst
+ | SESSION AUTHORIZATION NonReservedWord_or_Sconst
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_SET_VALUE;
@@ -1379,10 +1493,7 @@ set_rest_more: /* Generic SET syntaxes: */
var_name: ColId { $$ = $1; }
| var_name '.' ColId
- {
- $$ = palloc(strlen($1) + strlen($3) + 2);
- sprintf($$, "%s.%s", $1, $3);
- }
+ { $$ = psprintf("%s.%s", $1, $3); }
;
var_list: var_value { $$ = list_make1($1); }
@@ -1406,11 +1517,11 @@ opt_boolean_or_string:
| FALSE_P { $$ = "false"; }
| ON { $$ = "on"; }
/*
- * OFF is also accepted as a boolean value, but is handled
- * by the ColId rule below. The action for booleans and strings
+ * OFF is also accepted as a boolean value, but is handled by
+ * the NonReservedWord rule. The action for booleans and strings
* is the same, so we don't need to distinguish them here.
*/
- | ColId_or_Sconst { $$ = $1; }
+ | NonReservedWord_or_Sconst { $$ = $1; }
;
/* Timezone values can be:
@@ -1479,8 +1590,8 @@ opt_encoding:
| /*EMPTY*/ { $$ = NULL; }
;
-ColId_or_Sconst:
- ColId { $$ = $1; }
+NonReservedWord_or_Sconst:
+ NonReservedWord { $$ = $1; }
| Sconst { $$ = $1; }
;
@@ -1603,7 +1714,7 @@ CheckPointStmt:
/*****************************************************************************
*
- * DISCARD { ALL | TEMP | PLANS }
+ * DISCARD { ALL | TEMP | PLANS | SEQUENCES }
*
*****************************************************************************/
@@ -1632,14 +1743,21 @@ DiscardStmt:
n->target = DISCARD_PLANS;
$$ = (Node *) n;
}
+ | DISCARD SEQUENCES
+ {
+ DiscardStmt *n = makeNode(DiscardStmt);
+ n->target = DISCARD_SEQUENCES;
+ $$ = (Node *) n;
+ }
+
;
/*****************************************************************************
*
- * ALTER [ TABLE | INDEX | SEQUENCE | VIEW ] variations
+ * ALTER [ TABLE | INDEX | SEQUENCE | VIEW | MATERIALIZED VIEW ] variations
*
- * Note: we accept all subcommands for each of the four variants, and sort
+ * Note: we accept all subcommands for each of the five variants, and sort
* out what's really legal at execution time.
*****************************************************************************/
@@ -1716,6 +1834,24 @@ AlterTableStmt:
n->missing_ok = true;
$$ = (Node *)n;
}
+ | ALTER MATERIALIZED VIEW qualified_name alter_table_cmds
+ {
+ AlterTableStmt *n = makeNode(AlterTableStmt);
+ n->relation = $4;
+ n->cmds = $5;
+ n->relkind = OBJECT_MATVIEW;
+ n->missing_ok = false;
+ $$ = (Node *)n;
+ }
+ | ALTER MATERIALIZED VIEW IF_P EXISTS qualified_name alter_table_cmds
+ {
+ AlterTableStmt *n = makeNode(AlterTableStmt);
+ n->relation = $6;
+ n->cmds = $7;
+ n->relkind = OBJECT_MATVIEW;
+ n->missing_ok = true;
+ $$ = (Node *)n;
+ }
;
alter_table_cmds:
@@ -1832,10 +1968,11 @@ alter_table_cmd:
n->subtype = AT_AlterColumnType;
n->name = $3;
n->def = (Node *) def;
- /* We only use these three fields of the ColumnDef node */
+ /* We only use these fields of the ColumnDef node */
def->typeName = $6;
def->collClause = (CollateClause *) $7;
def->raw_default = $8;
+ def->location = @3;
$$ = (Node *)n;
}
/* ALTER FOREIGN TABLE <name> ALTER [COLUMN] <colname> OPTIONS */
@@ -1855,6 +1992,21 @@ alter_table_cmd:
n->def = $2;
$$ = (Node *)n;
}
+ /* ALTER TABLE <name> ALTER CONSTRAINT ... */
+ | ALTER CONSTRAINT name ConstraintAttributeSpec
+ {
+ AlterTableCmd *n = makeNode(AlterTableCmd);
+ Constraint *c = makeNode(Constraint);
+ n->subtype = AT_AlterConstraint;
+ n->def = (Node *) c;
+ c->contype = CONSTR_FOREIGN; /* others not supported, yet */
+ c->conname = $3;
+ processCASbits($4, @4, "ALTER CONSTRAINT statement",
+ &c->deferrable,
+ &c->initdeferred,
+ NULL, NULL, yyscanner);
+ $$ = (Node *)n;
+ }
/* ALTER TABLE <name> VALIDATE CONSTRAINT ... */
| VALIDATE CONSTRAINT name
{
@@ -2070,6 +2222,14 @@ alter_table_cmd:
n->def = (Node *)$2;
$$ = (Node *)n;
}
+ /* ALTER TABLE <name> REPLICA IDENTITY */
+ | REPLICA IDENTITY_P replica_identity
+ {
+ AlterTableCmd *n = makeNode(AlterTableCmd);
+ n->subtype = AT_ReplicaIdentity;
+ n->def = $3;
+ $$ = (Node *)n;
+ }
| alter_generic_options
{
AlterTableCmd *n = makeNode(AlterTableCmd);
@@ -2107,6 +2267,37 @@ alter_using:
| /* EMPTY */ { $$ = NULL; }
;
+replica_identity:
+ NOTHING
+ {
+ ReplicaIdentityStmt *n = makeNode(ReplicaIdentityStmt);
+ n->identity_type = REPLICA_IDENTITY_NOTHING;
+ n->name = NULL;
+ $$ = (Node *) n;
+ }
+ | FULL
+ {
+ ReplicaIdentityStmt *n = makeNode(ReplicaIdentityStmt);
+ n->identity_type = REPLICA_IDENTITY_FULL;
+ n->name = NULL;
+ $$ = (Node *) n;
+ }
+ | DEFAULT
+ {
+ ReplicaIdentityStmt *n = makeNode(ReplicaIdentityStmt);
+ n->identity_type = REPLICA_IDENTITY_DEFAULT;
+ n->name = NULL;
+ $$ = (Node *) n;
+ }
+ | USING INDEX name
+ {
+ ReplicaIdentityStmt *n = makeNode(ReplicaIdentityStmt);
+ n->identity_type = REPLICA_IDENTITY_INDEX;
+ n->name = $3;
+ $$ = (Node *) n;
+ }
+;
+
reloptions:
'(' reloption_list ')' { $$ = $2; }
;
@@ -2206,10 +2397,11 @@ alter_type_cmd:
n->name = $3;
n->def = (Node *) def;
n->behavior = $8;
- /* We only use these three fields of the ColumnDef node */
+ /* We only use these fields of the ColumnDef node */
def->typeName = $6;
def->collClause = (CollateClause *) $7;
def->raw_default = NULL;
+ def->location = @3;
$$ = (Node *)n;
}
;
@@ -2242,7 +2434,10 @@ ClosePortalStmt:
*
* QUERY :
* COPY relname [(columnList)] FROM/TO file [WITH] [(options)]
- * COPY ( SELECT ... ) TO file [WITH] [(options)]
+ * COPY ( SELECT ... ) TO file [WITH] [(options)]
+ *
+ * where 'file' can be one of:
+ * { PROGRAM 'command' | STDIN | STDOUT | 'filename' }
*
* In the preferred syntax the options are comma-separated
* and use generic identifiers instead of keywords. The pre-9.0
@@ -2257,14 +2452,21 @@ ClosePortalStmt:
*****************************************************************************/
CopyStmt: COPY opt_binary qualified_name opt_column_list opt_oids
- copy_from copy_file_name copy_delimiter opt_with copy_options
+ copy_from opt_program copy_file_name copy_delimiter opt_with copy_options
{
CopyStmt *n = makeNode(CopyStmt);
n->relation = $3;
n->query = NULL;
n->attlist = $4;
n->is_from = $6;
- n->filename = $7;
+ n->is_program = $7;
+ n->filename = $8;
+
+ if (n->is_program && n->filename == NULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("STDIN/STDOUT not allowed with PROGRAM"),
+ parser_errposition(@8)));
n->options = NIL;
/* Concatenate user-supplied flags */
@@ -2272,21 +2474,29 @@ CopyStmt: COPY opt_binary qualified_name opt_column_list opt_oids
n->options = lappend(n->options, $2);
if ($5)
n->options = lappend(n->options, $5);
- if ($8)
- n->options = lappend(n->options, $8);
- if ($10)
- n->options = list_concat(n->options, $10);
+ if ($9)
+ n->options = lappend(n->options, $9);
+ if ($11)
+ n->options = list_concat(n->options, $11);
$$ = (Node *)n;
}
- | COPY select_with_parens TO copy_file_name opt_with copy_options
+ | COPY select_with_parens TO opt_program copy_file_name opt_with copy_options
{
CopyStmt *n = makeNode(CopyStmt);
n->relation = NULL;
n->query = $2;
n->attlist = NIL;
n->is_from = false;
- n->filename = $4;
- n->options = $6;
+ n->is_program = $4;
+ n->filename = $5;
+ n->options = $7;
+
+ if (n->is_program && n->filename == NULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("STDIN/STDOUT not allowed with PROGRAM"),
+ parser_errposition(@5)));
+
$$ = (Node *)n;
}
;
@@ -2296,6 +2506,11 @@ copy_from:
| TO { $$ = FALSE; }
;
+opt_program:
+ PROGRAM { $$ = TRUE; }
+ | /* EMPTY */ { $$ = FALSE; }
+ ;
+
/*
* copy_file_name NULL indicates stdio is used. Whether stdin or stdout is
* used depends on the direction. (It really doesn't make sense to copy from
@@ -2326,6 +2541,10 @@ copy_opt_item:
{
$$ = makeDefElem("oids", (Node *)makeInteger(TRUE));
}
+ | FREEZE
+ {
+ $$ = makeDefElem("freeze", (Node *)makeInteger(TRUE));
+ }
| DELIMITER opt_as Sconst
{
$$ = makeDefElem("delimiter", (Node *)makeString($3));
@@ -2362,6 +2581,10 @@ copy_opt_item:
{
$$ = makeDefElem("force_not_null", (Node *)$4);
}
+ | FORCE NULL_P columnList
+ {
+ $$ = makeDefElem("force_null", (Node *)$3);
+ }
| ENCODING Sconst
{
$$ = makeDefElem("encoding", (Node *)makeString($2));
@@ -2607,6 +2830,7 @@ columnDef: ColId Typename create_generic_options ColQualList
n->fdwoptions = $3;
SplitColQualList($4, &n->constraints, &n->collClause,
yyscanner);
+ n->location = @1;
$$ = (Node *)n;
}
;
@@ -2626,6 +2850,7 @@ columnOptions: ColId WITH OPTIONS ColQualList
n->collOid = InvalidOid;
SplitColQualList($4, &n->constraints, &n->collClause,
yyscanner);
+ n->location = @1;
$$ = (Node *)n;
}
;
@@ -2666,7 +2891,7 @@ ColConstraint:
* to make it explicit.
* - thomas 1998-09-13
*
- * WITH NULL and NULL are not SQL92-standard syntax elements,
+ * WITH NULL and NULL are not SQL-standard syntax elements,
* so leave them out. Use DEFAULT NULL to explicitly indicate
* that a column may have that value. WITH NULL leads to
* shift/reduce conflicts with WITH TIME ZONE anyway.
@@ -2983,11 +3208,11 @@ key_match: MATCH FULL
}
| MATCH SIMPLE
{
- $$ = FKCONSTR_MATCH_UNSPECIFIED;
+ $$ = FKCONSTR_MATCH_SIMPLE;
}
| /*EMPTY*/
{
- $$ = FKCONSTR_MATCH_UNSPECIFIED;
+ $$ = FKCONSTR_MATCH_SIMPLE;
}
;
@@ -3092,6 +3317,7 @@ CreateAsStmt:
CreateTableAsStmt *ctas = makeNode(CreateTableAsStmt);
ctas->query = $6;
ctas->into = $4;
+ ctas->relkind = OBJECT_TABLE;
ctas->is_select_into = false;
/* cram additional flags into the IntoClause */
$4->rel->relpersistence = $2;
@@ -3109,6 +3335,7 @@ create_as_target:
$$->options = $3;
$$->onCommit = $4;
$$->tableSpaceName = $5;
+ $$->viewQuery = NULL;
$$->skipData = false; /* might get changed later */
}
;
@@ -3123,6 +3350,66 @@ opt_with_data:
/*****************************************************************************
*
* QUERY :
+ * CREATE MATERIALIZED VIEW relname AS SelectStmt
+ *
+ *****************************************************************************/
+
+CreateMatViewStmt:
+ CREATE OptNoLog MATERIALIZED VIEW create_mv_target AS SelectStmt opt_with_data
+ {
+ CreateTableAsStmt *ctas = makeNode(CreateTableAsStmt);
+ ctas->query = $7;
+ ctas->into = $5;
+ ctas->relkind = OBJECT_MATVIEW;
+ ctas->is_select_into = false;
+ /* cram additional flags into the IntoClause */
+ $5->rel->relpersistence = $2;
+ $5->skipData = !($8);
+ $$ = (Node *) ctas;
+ }
+ ;
+
+create_mv_target:
+ qualified_name opt_column_list opt_reloptions OptTableSpace
+ {
+ $$ = makeNode(IntoClause);
+ $$->rel = $1;
+ $$->colNames = $2;
+ $$->options = $3;
+ $$->onCommit = ONCOMMIT_NOOP;
+ $$->tableSpaceName = $4;
+ $$->viewQuery = NULL; /* filled at analysis time */
+ $$->skipData = false; /* might get changed later */
+ }
+ ;
+
+OptNoLog: UNLOGGED { $$ = RELPERSISTENCE_UNLOGGED; }
+ | /*EMPTY*/ { $$ = RELPERSISTENCE_PERMANENT; }
+ ;
+
+
+/*****************************************************************************
+ *
+ * QUERY :
+ * REFRESH MATERIALIZED VIEW qualified_name
+ *
+ *****************************************************************************/
+
+RefreshMatViewStmt:
+ REFRESH MATERIALIZED VIEW opt_concurrently qualified_name opt_with_data
+ {
+ RefreshMatViewStmt *n = makeNode(RefreshMatViewStmt);
+ n->concurrent = $4;
+ n->relation = $5;
+ n->skipData = !($6);
+ $$ = (Node *) n;
+ }
+ ;
+
+
+/*****************************************************************************
+ *
+ * QUERY :
* CREATE SEQUENCE seqname
* ALTER SEQUENCE seqname
*
@@ -3245,7 +3532,7 @@ NumericOnly_list: NumericOnly { $$ = list_make1($1); }
*****************************************************************************/
CreatePLangStmt:
- CREATE opt_or_replace opt_trusted opt_procedural LANGUAGE ColId_or_Sconst
+ CREATE opt_or_replace opt_trusted opt_procedural LANGUAGE NonReservedWord_or_Sconst
{
CreatePLangStmt *n = makeNode(CreatePLangStmt);
n->replace = $2;
@@ -3257,7 +3544,7 @@ CreatePLangStmt:
n->pltrusted = false;
$$ = (Node *)n;
}
- | CREATE opt_or_replace opt_trusted opt_procedural LANGUAGE ColId_or_Sconst
+ | CREATE opt_or_replace opt_trusted opt_procedural LANGUAGE NonReservedWord_or_Sconst
HANDLER handler_name opt_inline_handler opt_validator
{
CreatePLangStmt *n = makeNode(CreatePLangStmt);
@@ -3301,7 +3588,7 @@ opt_validator:
;
DropPLangStmt:
- DROP opt_procedural LANGUAGE ColId_or_Sconst opt_drop_behavior
+ DROP opt_procedural LANGUAGE NonReservedWord_or_Sconst opt_drop_behavior
{
DropStmt *n = makeNode(DropStmt);
n->removeType = OBJECT_LANGUAGE;
@@ -3312,7 +3599,7 @@ DropPLangStmt:
n->concurrent = false;
$$ = (Node *)n;
}
- | DROP opt_procedural LANGUAGE IF_P EXISTS ColId_or_Sconst opt_drop_behavior
+ | DROP opt_procedural LANGUAGE IF_P EXISTS NonReservedWord_or_Sconst opt_drop_behavior
{
DropStmt *n = makeNode(DropStmt);
n->removeType = OBJECT_LANGUAGE;
@@ -3336,12 +3623,13 @@ opt_procedural:
*
*****************************************************************************/
-CreateTableSpaceStmt: CREATE TABLESPACE name OptTableSpaceOwner LOCATION Sconst
+CreateTableSpaceStmt: CREATE TABLESPACE name OptTableSpaceOwner LOCATION Sconst opt_reloptions
{
CreateTableSpaceStmt *n = makeNode(CreateTableSpaceStmt);
n->tablespacename = $3;
n->owner = $4;
n->location = $6;
+ n->options = $7;
$$ = (Node *) n;
}
;
@@ -3414,11 +3702,11 @@ create_extension_opt_item:
{
$$ = makeDefElem("schema", (Node *)makeString($2));
}
- | VERSION_P ColId_or_Sconst
+ | VERSION_P NonReservedWord_or_Sconst
{
$$ = makeDefElem("new_version", (Node *)makeString($2));
}
- | FROM ColId_or_Sconst
+ | FROM NonReservedWord_or_Sconst
{
$$ = makeDefElem("old_version", (Node *)makeString($2));
}
@@ -3447,7 +3735,7 @@ alter_extension_opt_list:
;
alter_extension_opt_item:
- TO ColId_or_Sconst
+ TO NonReservedWord_or_Sconst
{
$$ = makeDefElem("new_version", (Node *)makeString($2));
}
@@ -3467,7 +3755,7 @@ AlterExtensionContentsStmt:
n->action = $4;
n->objtype = OBJECT_AGGREGATE;
n->objname = $6;
- n->objargs = $7;
+ n->objargs = extractAggrArgTypes($7);
$$ = (Node *)n;
}
| ALTER EXTENSION name add_drop CAST '(' Typename AS Typename ')'
@@ -3565,6 +3853,15 @@ AlterExtensionContentsStmt:
n->objname = list_make1(makeString($6));
$$ = (Node *)n;
}
+ | ALTER EXTENSION name add_drop EVENT TRIGGER name
+ {
+ AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt);
+ n->extname = $3;
+ n->action = $4;
+ n->objtype = OBJECT_EVENT_TRIGGER;
+ n->objname = list_make1(makeString($7));
+ $$ = (Node *)n;
+ }
| ALTER EXTENSION name add_drop TABLE any_name
{
AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt);
@@ -3628,6 +3925,15 @@ AlterExtensionContentsStmt:
n->objname = $6;
$$ = (Node *)n;
}
+ | ALTER EXTENSION name add_drop MATERIALIZED VIEW any_name
+ {
+ AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt);
+ n->extname = $3;
+ n->action = $4;
+ n->objtype = OBJECT_MATVIEW;
+ n->objname = $7;
+ $$ = (Node *)n;
+ }
| ALTER EXTENSION name add_drop FOREIGN TABLE any_name
{
AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt);
@@ -3719,7 +4025,7 @@ DropFdwStmt: DROP FOREIGN DATA_P WRAPPER name opt_drop_behavior
$$ = (Node *) n;
}
| DROP FOREIGN DATA_P WRAPPER IF_P EXISTS name opt_drop_behavior
- {
+ {
DropStmt *n = makeNode(DropStmt);
n->removeType = OBJECT_FDW;
n->objects = list_make1(list_make1(makeString($7)));
@@ -3881,7 +4187,7 @@ DropForeignServerStmt: DROP SERVER name opt_drop_behavior
$$ = (Node *) n;
}
| DROP SERVER IF_P EXISTS name opt_drop_behavior
- {
+ {
DropStmt *n = makeNode(DropStmt);
n->removeType = OBJECT_FOREIGN_SERVER;
n->objects = list_make1(list_make1(makeString($5)));
@@ -3935,57 +4241,37 @@ AlterForeignServerStmt: ALTER SERVER name foreign_server_version alter_generic_o
CreateForeignTableStmt:
CREATE FOREIGN TABLE qualified_name
- OptForeignTableElementList
+ '(' OptTableElementList ')'
SERVER name create_generic_options
{
CreateForeignTableStmt *n = makeNode(CreateForeignTableStmt);
$4->relpersistence = RELPERSISTENCE_PERMANENT;
n->base.relation = $4;
- n->base.tableElts = $5;
+ n->base.tableElts = $6;
n->base.inhRelations = NIL;
n->base.if_not_exists = false;
/* FDW-specific data */
- n->servername = $7;
- n->options = $8;
+ n->servername = $9;
+ n->options = $10;
$$ = (Node *) n;
}
| CREATE FOREIGN TABLE IF_P NOT EXISTS qualified_name
- OptForeignTableElementList
+ '(' OptTableElementList ')'
SERVER name create_generic_options
{
CreateForeignTableStmt *n = makeNode(CreateForeignTableStmt);
$7->relpersistence = RELPERSISTENCE_PERMANENT;
n->base.relation = $7;
- n->base.tableElts = $8;
+ n->base.tableElts = $9;
n->base.inhRelations = NIL;
n->base.if_not_exists = true;
/* FDW-specific data */
- n->servername = $10;
- n->options = $11;
+ n->servername = $12;
+ n->options = $13;
$$ = (Node *) n;
}
;
-OptForeignTableElementList:
- '(' ForeignTableElementList ')' { $$ = $2; }
- | '(' ')' { $$ = NIL; }
- ;
-
-ForeignTableElementList:
- ForeignTableElement
- {
- $$ = list_make1($1);
- }
- | ForeignTableElementList ',' ForeignTableElement
- {
- $$ = lappend($1, $3);
- }
- ;
-
-ForeignTableElement:
- columnDef { $$ = $1; }
- ;
-
/*****************************************************************************
*
* QUERY:
@@ -4297,6 +4583,74 @@ DropTrigStmt:
/*****************************************************************************
*
* QUERIES :
+ * CREATE EVENT TRIGGER ...
+ * ALTER EVENT TRIGGER ...
+ *
+ *****************************************************************************/
+
+CreateEventTrigStmt:
+ CREATE EVENT TRIGGER name ON ColLabel
+ EXECUTE PROCEDURE func_name '(' ')'
+ {
+ CreateEventTrigStmt *n = makeNode(CreateEventTrigStmt);
+ n->trigname = $4;
+ n->eventname = $6;
+ n->whenclause = NULL;
+ n->funcname = $9;
+ $$ = (Node *)n;
+ }
+ | CREATE EVENT TRIGGER name ON ColLabel
+ WHEN event_trigger_when_list
+ EXECUTE PROCEDURE func_name '(' ')'
+ {
+ CreateEventTrigStmt *n = makeNode(CreateEventTrigStmt);
+ n->trigname = $4;
+ n->eventname = $6;
+ n->whenclause = $8;
+ n->funcname = $11;
+ $$ = (Node *)n;
+ }
+ ;
+
+event_trigger_when_list:
+ event_trigger_when_item
+ { $$ = list_make1($1); }
+ | event_trigger_when_list AND event_trigger_when_item
+ { $$ = lappend($1, $3); }
+ ;
+
+event_trigger_when_item:
+ ColId IN_P '(' event_trigger_value_list ')'
+ { $$ = makeDefElem($1, (Node *) $4); }
+ ;
+
+event_trigger_value_list:
+ SCONST
+ { $$ = list_make1(makeString($1)); }
+ | event_trigger_value_list ',' SCONST
+ { $$ = lappend($1, makeString($3)); }
+ ;
+
+AlterEventTrigStmt:
+ ALTER EVENT TRIGGER name enable_trigger
+ {
+ AlterEventTrigStmt *n = makeNode(AlterEventTrigStmt);
+ n->trigname = $4;
+ n->tgenabled = $5;
+ $$ = (Node *) n;
+ }
+ ;
+
+enable_trigger:
+ ENABLE_P { $$ = TRIGGER_FIRES_ON_ORIGIN; }
+ | ENABLE_P REPLICA { $$ = TRIGGER_FIRES_ON_REPLICA; }
+ | ENABLE_P ALWAYS { $$ = TRIGGER_FIRES_ALWAYS; }
+ | DISABLE_P { $$ = TRIGGER_DISABLED; }
+ ;
+
+/*****************************************************************************
+ *
+ * QUERIES :
* CREATE ASSERTION ...
* DROP ASSERTION ...
*
@@ -4502,10 +4856,6 @@ def_arg: func_type { $$ = (Node *)$1; }
| Sconst { $$ = (Node *)makeString($1); }
;
-aggr_args: '(' type_list ')' { $$ = $2; }
- | '(' '*' ')' { $$ = NIL; }
- ;
-
old_aggr_definition: '(' old_aggr_list ')' { $$ = $2; }
;
@@ -4542,35 +4892,42 @@ enum_val_list: Sconst
*****************************************************************************/
AlterEnumStmt:
- ALTER TYPE_P any_name ADD_P VALUE_P Sconst
+ ALTER TYPE_P any_name ADD_P VALUE_P opt_if_not_exists Sconst
{
AlterEnumStmt *n = makeNode(AlterEnumStmt);
n->typeName = $3;
- n->newVal = $6;
+ n->newVal = $7;
n->newValNeighbor = NULL;
n->newValIsAfter = true;
+ n->skipIfExists = $6;
$$ = (Node *) n;
}
- | ALTER TYPE_P any_name ADD_P VALUE_P Sconst BEFORE Sconst
+ | ALTER TYPE_P any_name ADD_P VALUE_P opt_if_not_exists Sconst BEFORE Sconst
{
AlterEnumStmt *n = makeNode(AlterEnumStmt);
n->typeName = $3;
- n->newVal = $6;
- n->newValNeighbor = $8;
+ n->newVal = $7;
+ n->newValNeighbor = $9;
n->newValIsAfter = false;
+ n->skipIfExists = $6;
$$ = (Node *) n;
}
- | ALTER TYPE_P any_name ADD_P VALUE_P Sconst AFTER Sconst
+ | ALTER TYPE_P any_name ADD_P VALUE_P opt_if_not_exists Sconst AFTER Sconst
{
AlterEnumStmt *n = makeNode(AlterEnumStmt);
n->typeName = $3;
- n->newVal = $6;
- n->newValNeighbor = $8;
+ n->newVal = $7;
+ n->newValNeighbor = $9;
n->newValIsAfter = true;
+ n->skipIfExists = $6;
$$ = (Node *) n;
}
;
+opt_if_not_exists: IF_P NOT EXISTS { $$ = true; }
+ | /* empty */ { $$ = false; }
+ ;
+
/*****************************************************************************
*
@@ -4800,7 +5157,7 @@ DropOpFamilyStmt:
*
*****************************************************************************/
DropOwnedStmt:
- DROP OWNED BY name_list opt_drop_behavior
+ DROP OWNED BY role_list opt_drop_behavior
{
DropOwnedStmt *n = makeNode(DropOwnedStmt);
n->roles = $4;
@@ -4810,7 +5167,7 @@ DropOwnedStmt:
;
ReassignOwnedStmt:
- REASSIGN OWNED BY name_list TO name
+ REASSIGN OWNED BY role_list TO name
{
ReassignOwnedStmt *n = makeNode(ReassignOwnedStmt);
n->roles = $4;
@@ -4878,8 +5235,10 @@ DropStmt: DROP drop_type IF_P EXISTS any_name_list opt_drop_behavior
drop_type: TABLE { $$ = OBJECT_TABLE; }
| SEQUENCE { $$ = OBJECT_SEQUENCE; }
| VIEW { $$ = OBJECT_VIEW; }
+ | MATERIALIZED VIEW { $$ = OBJECT_MATVIEW; }
| INDEX { $$ = OBJECT_INDEX; }
| FOREIGN TABLE { $$ = OBJECT_FOREIGN_TABLE; }
+ | EVENT TRIGGER { $$ = OBJECT_EVENT_TRIGGER; }
| TYPE_P { $$ = OBJECT_TYPE; }
| DOMAIN_P { $$ = OBJECT_DOMAIN; }
| COLLATION { $$ = OBJECT_COLLATION; }
@@ -4937,19 +5296,25 @@ opt_restart_seqs:
* The COMMENT ON statement can take different forms based upon the type of
* the object associated with the comment. The form of the statement is:
*
- * COMMENT ON [ [ DATABASE | DOMAIN | INDEX | SEQUENCE | TABLE | TYPE | VIEW |
- * COLLATION | CONVERSION | LANGUAGE | OPERATOR CLASS |
- * LARGE OBJECT | CAST | COLUMN | SCHEMA | TABLESPACE |
- * EXTENSION | ROLE | TEXT SEARCH PARSER |
- * TEXT SEARCH DICTIONARY | TEXT SEARCH TEMPLATE |
- * TEXT SEARCH CONFIGURATION | FOREIGN TABLE |
- * FOREIGN DATA WRAPPER | SERVER ] <objname> |
+ * COMMENT ON [ [ CONVERSION | COLLATION | DATABASE | DOMAIN |
+ * EXTENSION | EVENT TRIGGER | FOREIGN DATA WRAPPER |
+ * FOREIGN TABLE | INDEX | [PROCEDURAL] LANGUAGE |
+ * MATERIALIZED VIEW | ROLE | SCHEMA | SEQUENCE |
+ * SERVER | TABLE | TABLESPACE |
+ * TEXT SEARCH CONFIGURATION | TEXT SEARCH DICTIONARY |
+ * TEXT SEARCH PARSER | TEXT SEARCH TEMPLATE | TYPE |
+ * VIEW] <objname> |
* AGGREGATE <aggname> (arg1, ...) |
+ * CAST (<src type> AS <dst type>) |
+ * COLUMN <relname>.<colname> |
+ * CONSTRAINT <constraintname> ON <relname> |
* FUNCTION <funcname> (arg1, arg2, ...) |
+ * LARGE OBJECT <oid> |
* OPERATOR <op> (leftoperand_typ, rightoperand_typ) |
- * TRIGGER <triggername> ON <relname> |
- * CONSTRAINT <constraintname> ON <relname> |
- * RULE <rulename> ON <relname> ]
+ * OPERATOR CLASS <name> USING <access-method> |
+ * OPERATOR FAMILY <name> USING <access-method> |
+ * RULE <rulename> ON <relname> |
+ * TRIGGER <triggername> ON <relname> ]
* IS 'text'
*
*****************************************************************************/
@@ -4969,7 +5334,7 @@ CommentStmt:
CommentStmt *n = makeNode(CommentStmt);
n->objtype = OBJECT_AGGREGATE;
n->objname = $4;
- n->objargs = $5;
+ n->objargs = extractAggrArgTypes($5);
n->comment = $7;
$$ = (Node *) n;
}
@@ -5073,38 +5438,6 @@ CommentStmt:
n->comment = $7;
$$ = (Node *) n;
}
- | COMMENT ON TEXT_P SEARCH PARSER any_name IS comment_text
- {
- CommentStmt *n = makeNode(CommentStmt);
- n->objtype = OBJECT_TSPARSER;
- n->objname = $6;
- n->comment = $8;
- $$ = (Node *) n;
- }
- | COMMENT ON TEXT_P SEARCH DICTIONARY any_name IS comment_text
- {
- CommentStmt *n = makeNode(CommentStmt);
- n->objtype = OBJECT_TSDICTIONARY;
- n->objname = $6;
- n->comment = $8;
- $$ = (Node *) n;
- }
- | COMMENT ON TEXT_P SEARCH TEMPLATE any_name IS comment_text
- {
- CommentStmt *n = makeNode(CommentStmt);
- n->objtype = OBJECT_TSTEMPLATE;
- n->objname = $6;
- n->comment = $8;
- $$ = (Node *) n;
- }
- | COMMENT ON TEXT_P SEARCH CONFIGURATION any_name IS comment_text
- {
- CommentStmt *n = makeNode(CommentStmt);
- n->objtype = OBJECT_TSCONFIGURATION;
- n->objname = $6;
- n->comment = $8;
- $$ = (Node *) n;
- }
;
comment_type:
@@ -5117,6 +5450,7 @@ comment_type:
| DOMAIN_P { $$ = OBJECT_DOMAIN; }
| TYPE_P { $$ = OBJECT_TYPE; }
| VIEW { $$ = OBJECT_VIEW; }
+ | MATERIALIZED VIEW { $$ = OBJECT_MATVIEW; }
| COLLATION { $$ = OBJECT_COLLATION; }
| CONVERSION_P { $$ = OBJECT_CONVERSION; }
| TABLESPACE { $$ = OBJECT_TABLESPACE; }
@@ -5125,6 +5459,11 @@ comment_type:
| FOREIGN TABLE { $$ = OBJECT_FOREIGN_TABLE; }
| SERVER { $$ = OBJECT_FOREIGN_SERVER; }
| FOREIGN DATA_P WRAPPER { $$ = OBJECT_FDW; }
+ | EVENT TRIGGER { $$ = OBJECT_EVENT_TRIGGER; }
+ | TEXT_P SEARCH CONFIGURATION { $$ = OBJECT_TSCONFIGURATION; }
+ | TEXT_P SEARCH DICTIONARY { $$ = OBJECT_TSDICTIONARY; }
+ | TEXT_P SEARCH PARSER { $$ = OBJECT_TSPARSER; }
+ | TEXT_P SEARCH TEMPLATE { $$ = OBJECT_TSTEMPLATE; }
;
comment_text:
@@ -5161,7 +5500,7 @@ SecLabelStmt:
n->provider = $3;
n->objtype = OBJECT_AGGREGATE;
n->objname = $6;
- n->objargs = $7;
+ n->objargs = extractAggrArgTypes($7);
n->label = $9;
$$ = (Node *) n;
}
@@ -5200,13 +5539,14 @@ SecLabelStmt:
}
;
-opt_provider: FOR ColId_or_Sconst { $$ = $2; }
- | /* empty */ { $$ = NULL; }
+opt_provider: FOR NonReservedWord_or_Sconst { $$ = $2; }
+ | /* empty */ { $$ = NULL; }
;
security_label_type:
COLUMN { $$ = OBJECT_COLUMN; }
| DATABASE { $$ = OBJECT_DATABASE; }
+ | EVENT TRIGGER { $$ = OBJECT_EVENT_TRIGGER; }
| FOREIGN TABLE { $$ = OBJECT_FOREIGN_TABLE; }
| SCHEMA { $$ = OBJECT_SCHEMA; }
| SEQUENCE { $$ = OBJECT_SEQUENCE; }
@@ -5216,6 +5556,7 @@ security_label_type:
| TABLESPACE { $$ = OBJECT_TABLESPACE; }
| TYPE_P { $$ = OBJECT_TYPE; }
| VIEW { $$ = OBJECT_VIEW; }
+ | MATERIALIZED VIEW { $$ = OBJECT_MATVIEW; }
;
security_label: Sconst { $$ = $1; }
@@ -5692,7 +6033,7 @@ function_with_argtypes:
*****************************************************************************/
GrantRoleStmt:
- GRANT privilege_list TO name_list opt_grant_admin_option opt_granted_by
+ GRANT privilege_list TO role_list opt_grant_admin_option opt_granted_by
{
GrantRoleStmt *n = makeNode(GrantRoleStmt);
n->is_grant = true;
@@ -5705,7 +6046,7 @@ GrantRoleStmt:
;
RevokeRoleStmt:
- REVOKE privilege_list FROM name_list opt_granted_by opt_drop_behavior
+ REVOKE privilege_list FROM role_list opt_granted_by opt_drop_behavior
{
GrantRoleStmt *n = makeNode(GrantRoleStmt);
n->is_grant = false;
@@ -5715,7 +6056,7 @@ RevokeRoleStmt:
n->behavior = $6;
$$ = (Node*)n;
}
- | REVOKE ADMIN OPTION FOR privilege_list FROM name_list opt_granted_by opt_drop_behavior
+ | REVOKE ADMIN OPTION FOR privilege_list FROM role_list opt_granted_by opt_drop_behavior
{
GrantRoleStmt *n = makeNode(GrantRoleStmt);
n->is_grant = false;
@@ -5761,11 +6102,11 @@ DefACLOption:
{
$$ = makeDefElem("schemas", (Node *)$3);
}
- | FOR ROLE name_list
+ | FOR ROLE role_list
{
$$ = makeDefElem("roles", (Node *)$3);
}
- | FOR USER name_list
+ | FOR USER role_list
{
$$ = makeDefElem("roles", (Node *)$3);
}
@@ -5901,7 +6242,7 @@ index_elem: ColId opt_collate opt_class opt_asc_desc opt_nulls_order
$$->ordering = $4;
$$->nulls_ordering = $5;
}
- | func_expr opt_collate opt_class opt_asc_desc opt_nulls_order
+ | func_expr_windowless opt_collate opt_class opt_asc_desc opt_nulls_order
{
$$ = makeNode(IndexElem);
$$->name = NULL;
@@ -6146,6 +6487,71 @@ func_arg_with_default:
}
;
+/* Aggregate args can be most things that function args can be */
+aggr_arg: func_arg
+ {
+ if (!($1->mode == FUNC_PARAM_IN ||
+ $1->mode == FUNC_PARAM_VARIADIC))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("aggregates cannot have output arguments"),
+ parser_errposition(@1)));
+ $$ = $1;
+ }
+ ;
+
+/*
+ * The SQL standard offers no guidance on how to declare aggregate argument
+ * lists, since it doesn't have CREATE AGGREGATE etc. We accept these cases:
+ *
+ * (*) - normal agg with no args
+ * (aggr_arg,...) - normal agg with args
+ * (ORDER BY aggr_arg,...) - ordered-set agg with no direct args
+ * (aggr_arg,... ORDER BY aggr_arg,...) - ordered-set agg with direct args
+ *
+ * The zero-argument case is spelled with '*' for consistency with COUNT(*).
+ *
+ * An additional restriction is that if the direct-args list ends in a
+ * VARIADIC item, the ordered-args list must contain exactly one item that
+ * is also VARIADIC with the same type. This allows us to collapse the two
+ * VARIADIC items into one, which is necessary to represent the aggregate in
+ * pg_proc. We check this at the grammar stage so that we can return a list
+ * in which the second VARIADIC item is already discarded, avoiding extra work
+ * in cases such as DROP AGGREGATE.
+ *
+ * The return value of this production is a two-element list, in which the
+ * first item is a sublist of FunctionParameter nodes (with any duplicate
+ * VARIADIC item already dropped, as per above) and the second is an integer
+ * Value node, containing -1 if there was no ORDER BY and otherwise the number
+ * of argument declarations before the ORDER BY. (If this number is equal
+ * to the first sublist's length, then we dropped a duplicate VARIADIC item.)
+ * This representation is passed as-is to CREATE AGGREGATE; for operations
+ * on existing aggregates, we can just apply extractArgTypes to the first
+ * sublist.
+ */
+aggr_args: '(' '*' ')'
+ {
+ $$ = list_make2(NIL, makeInteger(-1));
+ }
+ | '(' aggr_args_list ')'
+ {
+ $$ = list_make2($2, makeInteger(-1));
+ }
+ | '(' ORDER BY aggr_args_list ')'
+ {
+ $$ = list_make2($4, makeInteger(0));
+ }
+ | '(' aggr_args_list ORDER BY aggr_args_list ')'
+ {
+ /* this is the only case requiring consistency checking */
+ $$ = makeOrderedSetArgs($2, $5, yyscanner);
+ }
+ ;
+
+aggr_args_list:
+ aggr_arg { $$ = list_make1($1); }
+ | aggr_args_list ',' aggr_arg { $$ = lappend($1, $3); }
+ ;
createfunc_opt_list:
/* Must be at least one to prevent conflict */
@@ -6225,7 +6631,7 @@ createfunc_opt_item:
{
$$ = makeDefElem("as", (Node *)$2);
}
- | LANGUAGE ColId_or_Sconst
+ | LANGUAGE NonReservedWord_or_Sconst
{
$$ = makeDefElem("language", (Node *)makeString($2));
}
@@ -6345,7 +6751,7 @@ RemoveAggrStmt:
DropStmt *n = makeNode(DropStmt);
n->removeType = OBJECT_AGGREGATE;
n->objects = list_make1($3);
- n->arguments = list_make1($4);
+ n->arguments = list_make1(extractAggrArgTypes($4));
n->behavior = $5;
n->missing_ok = false;
n->concurrent = false;
@@ -6356,7 +6762,7 @@ RemoveAggrStmt:
DropStmt *n = makeNode(DropStmt);
n->removeType = OBJECT_AGGREGATE;
n->objects = list_make1($5);
- n->arguments = list_make1($6);
+ n->arguments = list_make1(extractAggrArgTypes($6));
n->behavior = $7;
n->missing_ok = true;
n->concurrent = false;
@@ -6440,7 +6846,7 @@ dostmt_opt_item:
{
$$ = makeDefElem("as", (Node *)makeString($1));
}
- | LANGUAGE ColId_or_Sconst
+ | LANGUAGE NonReservedWord_or_Sconst
{
$$ = makeDefElem("language", (Node *)makeString($2));
}
@@ -6563,6 +6969,128 @@ opt_force: FORCE { $$ = TRUE; }
/*****************************************************************************
*
+ * ALTER TABLESPACE
+ *
+ *****************************************************************************/
+
+AlterTblSpcStmt: ALTER TABLESPACE name MOVE ALL TO name opt_nowait
+ {
+ AlterTableSpaceMoveStmt *n =
+ makeNode(AlterTableSpaceMoveStmt);
+ n->orig_tablespacename = $3;
+ n->objtype = -1;
+ n->move_all = true;
+ n->roles = NIL;
+ n->new_tablespacename = $7;
+ n->nowait = $8;
+ $$ = (Node *)n;
+ }
+ | ALTER TABLESPACE name MOVE TABLES TO name opt_nowait
+ {
+ AlterTableSpaceMoveStmt *n =
+ makeNode(AlterTableSpaceMoveStmt);
+ n->orig_tablespacename = $3;
+ n->objtype = OBJECT_TABLE;
+ n->move_all = false;
+ n->roles = NIL;
+ n->new_tablespacename = $7;
+ n->nowait = $8;
+ $$ = (Node *)n;
+ }
+ | ALTER TABLESPACE name MOVE INDEXES TO name opt_nowait
+ {
+ AlterTableSpaceMoveStmt *n =
+ makeNode(AlterTableSpaceMoveStmt);
+ n->orig_tablespacename = $3;
+ n->objtype = OBJECT_INDEX;
+ n->move_all = false;
+ n->roles = NIL;
+ n->new_tablespacename = $7;
+ n->nowait = $8;
+ $$ = (Node *)n;
+ }
+ | ALTER TABLESPACE name MOVE MATERIALIZED VIEWS TO name opt_nowait
+ {
+ AlterTableSpaceMoveStmt *n =
+ makeNode(AlterTableSpaceMoveStmt);
+ n->orig_tablespacename = $3;
+ n->objtype = OBJECT_MATVIEW;
+ n->move_all = false;
+ n->roles = NIL;
+ n->new_tablespacename = $8;
+ n->nowait = $9;
+ $$ = (Node *)n;
+ }
+ | ALTER TABLESPACE name MOVE ALL OWNED BY role_list TO name opt_nowait
+ {
+ AlterTableSpaceMoveStmt *n =
+ makeNode(AlterTableSpaceMoveStmt);
+ n->orig_tablespacename = $3;
+ n->objtype = -1;
+ n->move_all = true;
+ n->roles = $8;
+ n->new_tablespacename = $10;
+ n->nowait = $11;
+ $$ = (Node *)n;
+ }
+ | ALTER TABLESPACE name MOVE TABLES OWNED BY role_list TO name opt_nowait
+ {
+ AlterTableSpaceMoveStmt *n =
+ makeNode(AlterTableSpaceMoveStmt);
+ n->orig_tablespacename = $3;
+ n->objtype = OBJECT_TABLE;
+ n->move_all = false;
+ n->roles = $8;
+ n->new_tablespacename = $10;
+ n->nowait = $11;
+ $$ = (Node *)n;
+ }
+ | ALTER TABLESPACE name MOVE INDEXES OWNED BY role_list TO name opt_nowait
+ {
+ AlterTableSpaceMoveStmt *n =
+ makeNode(AlterTableSpaceMoveStmt);
+ n->orig_tablespacename = $3;
+ n->objtype = OBJECT_INDEX;
+ n->move_all = false;
+ n->roles = $8;
+ n->new_tablespacename = $10;
+ n->nowait = $11;
+ $$ = (Node *)n;
+ }
+ | ALTER TABLESPACE name MOVE MATERIALIZED VIEWS OWNED BY role_list TO name opt_nowait
+ {
+ AlterTableSpaceMoveStmt *n =
+ makeNode(AlterTableSpaceMoveStmt);
+ n->orig_tablespacename = $3;
+ n->objtype = OBJECT_MATVIEW;
+ n->move_all = false;
+ n->roles = $9;
+ n->new_tablespacename = $11;
+ n->nowait = $12;
+ $$ = (Node *)n;
+ }
+ | ALTER TABLESPACE name SET reloptions
+ {
+ AlterTableSpaceOptionsStmt *n =
+ makeNode(AlterTableSpaceOptionsStmt);
+ n->tablespacename = $3;
+ n->options = $5;
+ n->isReset = FALSE;
+ $$ = (Node *)n;
+ }
+ | ALTER TABLESPACE name RESET reloptions
+ {
+ AlterTableSpaceOptionsStmt *n =
+ makeNode(AlterTableSpaceOptionsStmt);
+ n->tablespacename = $3;
+ n->options = $5;
+ n->isReset = TRUE;
+ $$ = (Node *)n;
+ }
+ ;
+
+/*****************************************************************************
+ *
* ALTER THING name RENAME TO newname
*
*****************************************************************************/
@@ -6572,7 +7100,7 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_AGGREGATE;
n->object = $3;
- n->objarg = $4;
+ n->objarg = extractAggrArgTypes($4);
n->newname = $7;
n->missing_ok = false;
$$ = (Node *)n;
@@ -6627,7 +7155,7 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_FDW;
- n->subname = $5;
+ n->object = list_make1(makeString($5));
n->newname = $8;
n->missing_ok = false;
$$ = (Node *)n;
@@ -6655,7 +7183,7 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_LANGUAGE;
- n->subname = $4;
+ n->object = list_make1(makeString($4));
n->newname = $7;
n->missing_ok = false;
$$ = (Node *)n;
@@ -6665,7 +7193,7 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_OPCLASS;
n->object = $4;
- n->subname = $6;
+ n->objarg = list_make1(makeString($6));
n->newname = $9;
n->missing_ok = false;
$$ = (Node *)n;
@@ -6675,7 +7203,7 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_OPFAMILY;
n->object = $4;
- n->subname = $6;
+ n->objarg = list_make1(makeString($6));
n->newname = $9;
n->missing_ok = false;
$$ = (Node *)n;
@@ -6693,7 +7221,7 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_FOREIGN_SERVER;
- n->subname = $3;
+ n->object = list_make1(makeString($3));
n->newname = $6;
n->missing_ok = false;
$$ = (Node *)n;
@@ -6758,6 +7286,26 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
n->missing_ok = true;
$$ = (Node *)n;
}
+ | ALTER MATERIALIZED VIEW qualified_name RENAME TO name
+ {
+ RenameStmt *n = makeNode(RenameStmt);
+ n->renameType = OBJECT_MATVIEW;
+ n->relation = $4;
+ n->subname = NULL;
+ n->newname = $7;
+ n->missing_ok = false;
+ $$ = (Node *)n;
+ }
+ | ALTER MATERIALIZED VIEW IF_P EXISTS qualified_name RENAME TO name
+ {
+ RenameStmt *n = makeNode(RenameStmt);
+ n->renameType = OBJECT_MATVIEW;
+ n->relation = $6;
+ n->subname = NULL;
+ n->newname = $9;
+ n->missing_ok = true;
+ $$ = (Node *)n;
+ }
| ALTER INDEX qualified_name RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
@@ -6820,6 +7368,28 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
n->missing_ok = true;
$$ = (Node *)n;
}
+ | ALTER MATERIALIZED VIEW qualified_name RENAME opt_column name TO name
+ {
+ RenameStmt *n = makeNode(RenameStmt);
+ n->renameType = OBJECT_COLUMN;
+ n->relationType = OBJECT_MATVIEW;
+ n->relation = $4;
+ n->subname = $7;
+ n->newname = $9;
+ n->missing_ok = false;
+ $$ = (Node *)n;
+ }
+ | ALTER MATERIALIZED VIEW IF_P EXISTS qualified_name RENAME opt_column name TO name
+ {
+ RenameStmt *n = makeNode(RenameStmt);
+ n->renameType = OBJECT_COLUMN;
+ n->relationType = OBJECT_MATVIEW;
+ n->relation = $6;
+ n->subname = $9;
+ n->newname = $11;
+ n->missing_ok = true;
+ $$ = (Node *)n;
+ }
| ALTER TABLE relation_expr RENAME CONSTRAINT name TO name
{
RenameStmt *n = makeNode(RenameStmt);
@@ -6852,6 +7422,16 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
n->missing_ok = true;
$$ = (Node *)n;
}
+ | ALTER RULE name ON qualified_name RENAME TO name
+ {
+ RenameStmt *n = makeNode(RenameStmt);
+ n->renameType = OBJECT_RULE;
+ n->relation = $5;
+ n->subname = $3;
+ n->newname = $8;
+ n->missing_ok = false;
+ $$ = (Node *)n;
+ }
| ALTER TRIGGER name ON qualified_name RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
@@ -6862,6 +7442,14 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
n->missing_ok = false;
$$ = (Node *)n;
}
+ | ALTER EVENT TRIGGER name RENAME TO name
+ {
+ RenameStmt *n = makeNode(RenameStmt);
+ n->renameType = OBJECT_EVENT_TRIGGER;
+ n->object = list_make1(makeString($4));
+ n->newname = $7;
+ $$ = (Node *)n;
+ }
| ALTER ROLE RoleId RENAME TO RoleId
{
RenameStmt *n = makeNode(RenameStmt);
@@ -6889,24 +7477,6 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
n->missing_ok = false;
$$ = (Node *)n;
}
- | ALTER TABLESPACE name SET reloptions
- {
- AlterTableSpaceOptionsStmt *n =
- makeNode(AlterTableSpaceOptionsStmt);
- n->tablespacename = $3;
- n->options = $5;
- n->isReset = FALSE;
- $$ = (Node *)n;
- }
- | ALTER TABLESPACE name RESET reloptions
- {
- AlterTableSpaceOptionsStmt *n =
- makeNode(AlterTableSpaceOptionsStmt);
- n->tablespacename = $3;
- n->options = $5;
- n->isReset = TRUE;
- $$ = (Node *)n;
- }
| ALTER TEXT_P SEARCH PARSER any_name RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
@@ -6986,7 +7556,7 @@ AlterObjectSchemaStmt:
AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
n->objectType = OBJECT_AGGREGATE;
n->object = $3;
- n->objarg = $4;
+ n->objarg = extractAggrArgTypes($4);
n->newschema = $7;
n->missing_ok = false;
$$ = (Node *)n;
@@ -7052,7 +7622,7 @@ AlterObjectSchemaStmt:
AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
n->objectType = OBJECT_OPCLASS;
n->object = $4;
- n->addname = $6;
+ n->objarg = list_make1(makeString($6));
n->newschema = $9;
n->missing_ok = false;
$$ = (Node *)n;
@@ -7062,7 +7632,7 @@ AlterObjectSchemaStmt:
AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
n->objectType = OBJECT_OPFAMILY;
n->object = $4;
- n->addname = $6;
+ n->objarg = list_make1(makeString($6));
n->newschema = $9;
n->missing_ok = false;
$$ = (Node *)n;
@@ -7157,6 +7727,24 @@ AlterObjectSchemaStmt:
n->missing_ok = true;
$$ = (Node *)n;
}
+ | ALTER MATERIALIZED VIEW qualified_name SET SCHEMA name
+ {
+ AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
+ n->objectType = OBJECT_MATVIEW;
+ n->relation = $4;
+ n->newschema = $7;
+ n->missing_ok = false;
+ $$ = (Node *)n;
+ }
+ | ALTER MATERIALIZED VIEW IF_P EXISTS qualified_name SET SCHEMA name
+ {
+ AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
+ n->objectType = OBJECT_MATVIEW;
+ n->relation = $6;
+ n->newschema = $9;
+ n->missing_ok = true;
+ $$ = (Node *)n;
+ }
| ALTER FOREIGN TABLE relation_expr SET SCHEMA name
{
AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
@@ -7197,7 +7785,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId
AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
n->objectType = OBJECT_AGGREGATE;
n->object = $3;
- n->objarg = $4;
+ n->objarg = extractAggrArgTypes($4);
n->newowner = $7;
$$ = (Node *)n;
}
@@ -7272,7 +7860,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId
AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
n->objectType = OBJECT_OPCLASS;
n->object = $4;
- n->addname = $6;
+ n->objarg = list_make1(makeString($6));
n->newowner = $9;
$$ = (Node *)n;
}
@@ -7281,7 +7869,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId
AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
n->objectType = OBJECT_OPFAMILY;
n->object = $4;
- n->addname = $6;
+ n->objarg = list_make1(makeString($6));
n->newowner = $9;
$$ = (Node *)n;
}
@@ -7341,6 +7929,14 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId
n->newowner = $6;
$$ = (Node *)n;
}
+ | ALTER EVENT TRIGGER name OWNER TO RoleId
+ {
+ AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
+ n->objectType = OBJECT_EVENT_TRIGGER;
+ n->object = list_make1(makeString($4));
+ n->newowner = $7;
+ $$ = (Node *)n;
+ }
;
@@ -7659,6 +8255,7 @@ ViewStmt: CREATE OptTemp VIEW qualified_name opt_column_list opt_reloptions
n->query = $8;
n->replace = false;
n->options = $6;
+ n->withCheckOption = $9;
$$ = (Node *) n;
}
| CREATE OR REPLACE OptTemp VIEW qualified_name opt_column_list opt_reloptions
@@ -7671,30 +8268,52 @@ ViewStmt: CREATE OptTemp VIEW qualified_name opt_column_list opt_reloptions
n->query = $10;
n->replace = true;
n->options = $8;
+ n->withCheckOption = $11;
$$ = (Node *) n;
}
- ;
-
-opt_check_option:
- WITH CHECK OPTION
- {
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("WITH CHECK OPTION is not implemented")));
- }
- | WITH CASCADED CHECK OPTION
+ | CREATE OptTemp RECURSIVE VIEW qualified_name '(' columnList ')' opt_reloptions
+ AS SelectStmt opt_check_option
{
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("WITH CHECK OPTION is not implemented")));
+ ViewStmt *n = makeNode(ViewStmt);
+ n->view = $5;
+ n->view->relpersistence = $2;
+ n->aliases = $7;
+ n->query = makeRecursiveViewSelect(n->view->relname, n->aliases, $11);
+ n->replace = false;
+ n->options = $9;
+ n->withCheckOption = $12;
+ if (n->withCheckOption != NO_CHECK_OPTION)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("WITH CHECK OPTION not supported on recursive views"),
+ parser_errposition(@12)));
+ $$ = (Node *) n;
}
- | WITH LOCAL CHECK OPTION
+ | CREATE OR REPLACE OptTemp RECURSIVE VIEW qualified_name '(' columnList ')' opt_reloptions
+ AS SelectStmt opt_check_option
{
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("WITH CHECK OPTION is not implemented")));
+ ViewStmt *n = makeNode(ViewStmt);
+ n->view = $7;
+ n->view->relpersistence = $4;
+ n->aliases = $9;
+ n->query = makeRecursiveViewSelect(n->view->relname, n->aliases, $13);
+ n->replace = true;
+ n->options = $11;
+ n->withCheckOption = $14;
+ if (n->withCheckOption != NO_CHECK_OPTION)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("WITH CHECK OPTION not supported on recursive views"),
+ parser_errposition(@14)));
+ $$ = (Node *) n;
}
- | /* EMPTY */ { $$ = NIL; }
+ ;
+
+opt_check_option:
+ WITH CHECK OPTION { $$ = CASCADED_CHECK_OPTION; }
+ | WITH CASCADED CHECK OPTION { $$ = CASCADED_CHECK_OPTION; }
+ | WITH LOCAL CHECK OPTION { $$ = LOCAL_CHECK_OPTION; }
+ | /* EMPTY */ { $$ = NO_CHECK_OPTION; }
;
/*****************************************************************************
@@ -7884,6 +8503,23 @@ DropdbStmt: DROP DATABASE database_name
/*****************************************************************************
*
+ * ALTER SYSTEM SET
+ *
+ * This is used to change configuration parameters persistently.
+ *****************************************************************************/
+
+AlterSystemStmt:
+ ALTER SYSTEM_P SET generic_set
+ {
+ AlterSystemStmt *n = makeNode(AlterSystemStmt);
+ n->setstmt = $4;
+ $$ = (Node *)n;
+ }
+ ;
+
+
+/*****************************************************************************
+ *
* Manipulate a domain
*
*****************************************************************************/
@@ -8133,6 +8769,8 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
n->options |= VACOPT_VERBOSE;
n->freeze_min_age = $3 ? 0 : -1;
n->freeze_table_age = $3 ? 0 : -1;
+ n->multixact_freeze_min_age = $3 ? 0 : -1;
+ n->multixact_freeze_table_age = $3 ? 0 : -1;
n->relation = NULL;
n->va_cols = NIL;
$$ = (Node *)n;
@@ -8147,6 +8785,8 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
n->options |= VACOPT_VERBOSE;
n->freeze_min_age = $3 ? 0 : -1;
n->freeze_table_age = $3 ? 0 : -1;
+ n->multixact_freeze_min_age = $3 ? 0 : -1;
+ n->multixact_freeze_table_age = $3 ? 0 : -1;
n->relation = $5;
n->va_cols = NIL;
$$ = (Node *)n;
@@ -8161,6 +8801,8 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
n->options |= VACOPT_VERBOSE;
n->freeze_min_age = $3 ? 0 : -1;
n->freeze_table_age = $3 ? 0 : -1;
+ n->multixact_freeze_min_age = $3 ? 0 : -1;
+ n->multixact_freeze_table_age = $3 ? 0 : -1;
$$ = (Node *)n;
}
| VACUUM '(' vacuum_option_list ')'
@@ -8168,9 +8810,17 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
VacuumStmt *n = makeNode(VacuumStmt);
n->options = VACOPT_VACUUM | $3;
if (n->options & VACOPT_FREEZE)
+ {
n->freeze_min_age = n->freeze_table_age = 0;
+ n->multixact_freeze_min_age = 0;
+ n->multixact_freeze_table_age = 0;
+ }
else
+ {
n->freeze_min_age = n->freeze_table_age = -1;
+ n->multixact_freeze_min_age = -1;
+ n->multixact_freeze_table_age = -1;
+ }
n->relation = NULL;
n->va_cols = NIL;
$$ = (Node *) n;
@@ -8180,9 +8830,17 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
VacuumStmt *n = makeNode(VacuumStmt);
n->options = VACOPT_VACUUM | $3;
if (n->options & VACOPT_FREEZE)
+ {
n->freeze_min_age = n->freeze_table_age = 0;
+ n->multixact_freeze_min_age = 0;
+ n->multixact_freeze_table_age = 0;
+ }
else
+ {
n->freeze_min_age = n->freeze_table_age = -1;
+ n->multixact_freeze_min_age = -1;
+ n->multixact_freeze_table_age = -1;
+ }
n->relation = $5;
n->va_cols = $6;
if (n->va_cols != NIL) /* implies analyze */
@@ -8212,6 +8870,8 @@ AnalyzeStmt:
n->options |= VACOPT_VERBOSE;
n->freeze_min_age = -1;
n->freeze_table_age = -1;
+ n->multixact_freeze_min_age = -1;
+ n->multixact_freeze_table_age = -1;
n->relation = NULL;
n->va_cols = NIL;
$$ = (Node *)n;
@@ -8224,6 +8884,8 @@ AnalyzeStmt:
n->options |= VACOPT_VERBOSE;
n->freeze_min_age = -1;
n->freeze_table_age = -1;
+ n->multixact_freeze_min_age = -1;
+ n->multixact_freeze_table_age = -1;
n->relation = $3;
n->va_cols = $4;
$$ = (Node *)n;
@@ -8303,6 +8965,8 @@ ExplainableStmt:
| DeleteStmt
| DeclareCursorStmt
| CreateAsStmt
+ | CreateMatViewStmt
+ | RefreshMatViewStmt
| ExecuteStmt /* by default all are $$=$1 */
;
@@ -8325,9 +8989,8 @@ explain_option_elem:
;
explain_option_name:
- ColId { $$ = $1; }
+ NonReservedWord { $$ = $1; }
| analyze_keyword { $$ = "analyze"; }
- | VERBOSE { $$ = "verbose"; }
;
explain_option_arg:
@@ -8387,6 +9050,7 @@ ExecuteStmt: EXECUTE name execute_param_clause
n->params = $8;
ctas->query = (Node *) n;
ctas->into = $4;
+ ctas->relkind = OBJECT_TABLE;
ctas->is_select_into = false;
/* cram additional flags into the IntoClause */
$4->rel->relpersistence = $2;
@@ -8735,9 +9399,10 @@ select_with_parens:
* The duplicative productions are annoying, but hard to get rid of without
* creating shift/reduce conflicts.
*
- * FOR UPDATE/SHARE may be before or after LIMIT/OFFSET.
+ * The locking clause (FOR UPDATE etc) may be before or after LIMIT/OFFSET.
* In <=7.2.X, LIMIT/OFFSET had to be after FOR UPDATE
- * We now support both orderings, but prefer LIMIT/OFFSET before FOR UPDATE/SHARE
+ * We now support both orderings, but prefer LIMIT/OFFSET before the locking
+ * clause.
* 2002-08-28 bjm
*/
select_no_parens:
@@ -8813,7 +9478,7 @@ select_clause:
* As with select_no_parens, simple_select cannot have outer parentheses,
* but can have parenthesized subclauses.
*
- * Note that sort clauses cannot be included at this level --- SQL92 requires
+ * Note that sort clauses cannot be included at this level --- SQL requires
* SELECT foo UNION SELECT bar ORDER BY baz
* to be parsed as
* (SELECT foo UNION SELECT bar) ORDER BY baz
@@ -8828,7 +9493,7 @@ select_clause:
* However, this is not checked by the grammar; parse analysis must check it.
*/
simple_select:
- SELECT opt_distinct target_list
+ SELECT opt_distinct opt_target_list
into_clause from_clause where_clause
group_clause having_clause window_clause
{
@@ -8932,6 +9597,7 @@ into_clause:
$$->options = NIL;
$$->onCommit = ONCOMMIT_NOOP;
$$->tableSpaceName = NULL;
+ $$->viewQuery = NULL;
$$->skipData = false;
}
| /*EMPTY*/
@@ -9156,24 +9822,23 @@ for_locking_items:
;
for_locking_item:
- FOR UPDATE locked_rels_list opt_nowait
- {
- LockingClause *n = makeNode(LockingClause);
- n->lockedRels = $3;
- n->forUpdate = TRUE;
- n->noWait = $4;
- $$ = (Node *) n;
- }
- | FOR SHARE locked_rels_list opt_nowait
+ for_locking_strength locked_rels_list opt_nowait
{
LockingClause *n = makeNode(LockingClause);
- n->lockedRels = $3;
- n->forUpdate = FALSE;
- n->noWait = $4;
+ n->lockedRels = $2;
+ n->strength = $1;
+ n->noWait = $3;
$$ = (Node *) n;
}
;
+for_locking_strength:
+ FOR UPDATE { $$ = LCS_FORUPDATE; }
+ | FOR NO KEY UPDATE { $$ = LCS_FORNOKEYUPDATE; }
+ | FOR SHARE { $$ = LCS_FORSHARE; }
+ | FOR KEY SHARE { $$ = LCS_FORKEYSHARE; }
+ ;
+
locked_rels_list:
OF qualified_name_list { $$ = $2; }
| /* EMPTY */ { $$ = NIL; }
@@ -9215,65 +9880,34 @@ from_list:
;
/*
- * table_ref is where an alias clause can be attached. Note we cannot make
- * alias_clause have an empty production because that causes parse conflicts
- * between table_ref := '(' joined_table ')' alias_clause
- * and joined_table := '(' joined_table ')'. So, we must have the
- * redundant-looking productions here instead.
+ * table_ref is where an alias clause can be attached.
*/
-table_ref: relation_expr
- {
- $$ = (Node *) $1;
- }
- | relation_expr alias_clause
+table_ref: relation_expr opt_alias_clause
{
$1->alias = $2;
$$ = (Node *) $1;
}
- | func_table
- {
- RangeFunction *n = makeNode(RangeFunction);
- n->funccallnode = $1;
- n->coldeflist = NIL;
- $$ = (Node *) n;
- }
- | func_table alias_clause
- {
- RangeFunction *n = makeNode(RangeFunction);
- n->funccallnode = $1;
- n->alias = $2;
- n->coldeflist = NIL;
- $$ = (Node *) n;
- }
- | func_table AS '(' TableFuncElementList ')'
+ | func_table func_alias_clause
{
- RangeFunction *n = makeNode(RangeFunction);
- n->funccallnode = $1;
- n->coldeflist = $4;
+ RangeFunction *n = (RangeFunction *) $1;
+ n->alias = linitial($2);
+ n->coldeflist = lsecond($2);
$$ = (Node *) n;
}
- | func_table AS ColId '(' TableFuncElementList ')'
+ | LATERAL_P func_table func_alias_clause
{
- RangeFunction *n = makeNode(RangeFunction);
- Alias *a = makeNode(Alias);
- n->funccallnode = $1;
- a->aliasname = $3;
- n->alias = a;
- n->coldeflist = $5;
+ RangeFunction *n = (RangeFunction *) $2;
+ n->lateral = true;
+ n->alias = linitial($3);
+ n->coldeflist = lsecond($3);
$$ = (Node *) n;
}
- | func_table ColId '(' TableFuncElementList ')'
- {
- RangeFunction *n = makeNode(RangeFunction);
- Alias *a = makeNode(Alias);
- n->funccallnode = $1;
- a->aliasname = $2;
- n->alias = a;
- n->coldeflist = $4;
- $$ = (Node *) n;
- }
- | select_with_parens
+ | select_with_parens opt_alias_clause
{
+ RangeSubselect *n = makeNode(RangeSubselect);
+ n->lateral = false;
+ n->subquery = $1;
+ n->alias = $2;
/*
* The SQL spec does not permit a subselect
* (<derived_table>) without an alias clause,
@@ -9285,26 +9919,47 @@ table_ref: relation_expr
* However, it does seem like a good idea to emit
* an error message that's better than "syntax error".
*/
- if (IsA($1, SelectStmt) &&
- ((SelectStmt *) $1)->valuesLists)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("VALUES in FROM must have an alias"),
- errhint("For example, FROM (VALUES ...) [AS] foo."),
- parser_errposition(@1)));
- else
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("subquery in FROM must have an alias"),
- errhint("For example, FROM (SELECT ...) [AS] foo."),
- parser_errposition(@1)));
- $$ = NULL;
+ if ($2 == NULL)
+ {
+ if (IsA($1, SelectStmt) &&
+ ((SelectStmt *) $1)->valuesLists)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("VALUES in FROM must have an alias"),
+ errhint("For example, FROM (VALUES ...) [AS] foo."),
+ parser_errposition(@1)));
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("subquery in FROM must have an alias"),
+ errhint("For example, FROM (SELECT ...) [AS] foo."),
+ parser_errposition(@1)));
+ }
+ $$ = (Node *) n;
}
- | select_with_parens alias_clause
+ | LATERAL_P select_with_parens opt_alias_clause
{
RangeSubselect *n = makeNode(RangeSubselect);
- n->subquery = $1;
- n->alias = $2;
+ n->lateral = true;
+ n->subquery = $2;
+ n->alias = $3;
+ /* same coment as above */
+ if ($3 == NULL)
+ {
+ if (IsA($2, SelectStmt) &&
+ ((SelectStmt *) $2)->valuesLists)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("VALUES in FROM must have an alias"),
+ errhint("For example, FROM (VALUES ...) [AS] foo."),
+ parser_errposition(@2)));
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("subquery in FROM must have an alias"),
+ errhint("For example, FROM (SELECT ...) [AS] foo."),
+ parser_errposition(@2)));
+ }
$$ = (Node *) n;
}
| joined_table
@@ -9321,7 +9976,7 @@ table_ref: relation_expr
/*
* It may seem silly to separate joined_table from table_ref, but there is
- * method in SQL92's madness: if you don't do it this way you get reduce-
+ * method in SQL's madness: if you don't do it this way you get reduce-
* reduce conflicts, because it's not clear to the parser generator whether
* to expect alias_clause after ')' or not. For the same reason we must
* treat 'JOIN' and 'join_type JOIN' separately, rather than allowing
@@ -9430,6 +10085,41 @@ alias_clause:
}
;
+opt_alias_clause: alias_clause { $$ = $1; }
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
+
+/*
+ * func_alias_clause can include both an Alias and a coldeflist, so we make it
+ * return a 2-element list that gets disassembled by calling production.
+ */
+func_alias_clause:
+ alias_clause
+ {
+ $$ = list_make2($1, NIL);
+ }
+ | AS '(' TableFuncElementList ')'
+ {
+ $$ = list_make2(NULL, $3);
+ }
+ | AS ColId '(' TableFuncElementList ')'
+ {
+ Alias *a = makeNode(Alias);
+ a->aliasname = $2;
+ $$ = list_make2(a, $4);
+ }
+ | ColId '(' TableFuncElementList ')'
+ {
+ Alias *a = makeNode(Alias);
+ a->aliasname = $1;
+ $$ = list_make2(a, $3);
+ }
+ | /*EMPTY*/
+ {
+ $$ = list_make2(NULL, NIL);
+ }
+ ;
+
join_type: FULL join_outer { $$ = JOIN_FULL; }
| LEFT join_outer { $$ = JOIN_LEFT; }
| RIGHT join_outer { $$ = JOIN_RIGHT; }
@@ -9522,8 +10212,55 @@ relation_expr_opt_alias: relation_expr %prec UMINUS
}
;
+/*
+ * func_table represents a function invocation in a FROM list. It can be
+ * a plain function call, like "foo(...)", or a ROWS FROM expression with
+ * one or more function calls, "ROWS FROM (foo(...), bar(...))",
+ * optionally with WITH ORDINALITY attached.
+ * In the ROWS FROM syntax, a column definition list can be given for each
+ * function, for example:
+ * ROWS FROM (foo() AS (foo_res_a text, foo_res_b text),
+ * bar() AS (bar_res_a text, bar_res_b text))
+ * It's also possible to attach a column definition list to the RangeFunction
+ * as a whole, but that's handled by the table_ref production.
+ */
+func_table: func_expr_windowless opt_ordinality
+ {
+ RangeFunction *n = makeNode(RangeFunction);
+ n->lateral = false;
+ n->ordinality = $2;
+ n->is_rowsfrom = false;
+ n->functions = list_make1(list_make2($1, NIL));
+ /* alias and coldeflist are set by table_ref production */
+ $$ = (Node *) n;
+ }
+ | ROWS FROM '(' rowsfrom_list ')' opt_ordinality
+ {
+ RangeFunction *n = makeNode(RangeFunction);
+ n->lateral = false;
+ n->ordinality = $6;
+ n->is_rowsfrom = true;
+ n->functions = $4;
+ /* alias and coldeflist are set by table_ref production */
+ $$ = (Node *) n;
+ }
+ ;
+
+rowsfrom_item: func_expr_windowless opt_col_def_list
+ { $$ = list_make2($1, $2); }
+ ;
+
+rowsfrom_list:
+ rowsfrom_item { $$ = list_make1($1); }
+ | rowsfrom_list ',' rowsfrom_item { $$ = lappend($1, $3); }
+ ;
-func_table: func_expr { $$ = $1; }
+opt_col_def_list: AS '(' TableFuncElementList ')' { $$ = $3; }
+ | /*EMPTY*/ { $$ = NIL; }
+ ;
+
+opt_ordinality: WITH_ORDINALITY { $$ = true; }
+ | /*EMPTY*/ { $$ = false; }
;
@@ -9578,6 +10315,7 @@ TableFuncElement: ColId Typename opt_collate_clause
n->collClause = (CollateClause *) $3;
n->collOid = InvalidOid;
n->constraints = NIL;
+ n->location = @1;
$$ = (Node *)n;
}
;
@@ -9585,7 +10323,7 @@ TableFuncElement: ColId Typename opt_collate_clause
/*****************************************************************************
*
* Type syntax
- * SQL92 introduces a large amount of type-specific syntax.
+ * SQL introduces a large amount of type-specific syntax.
* Define individual clauses to handle these cases, and use
* the generic case to handle regular type-extensible Postgres syntax.
* - thomas 1997-10-10
@@ -9711,7 +10449,7 @@ opt_type_modifiers: '(' expr_list ')' { $$ = $2; }
;
/*
- * SQL92 numeric data types
+ * SQL numeric data types
*/
Numeric: INT_P
{
@@ -9801,7 +10539,7 @@ opt_float: '(' Iconst ')'
;
/*
- * SQL92 bit-field data types
+ * SQL bit-field data types
* The following implements BIT() and BIT VARYING().
*/
Bit: BitWithLength
@@ -9858,7 +10596,7 @@ BitWithoutLength:
/*
- * SQL92 character data types
+ * SQL character data types
* The following implements CHAR() and VARCHAR().
*/
Character: CharacterWithLength
@@ -9878,7 +10616,7 @@ ConstCharacter: CharacterWithLength
| CharacterWithoutLength
{
/* Length was not specified so allow to be unrestricted.
- * This handles problems with fixed-length (char) strings
+ * This handles problems with fixed-length (bpchar) strings
* which in column definitions must default to a length
* of one, but should not be constrained if the length
* was not specified.
@@ -9891,15 +10629,7 @@ ConstCharacter: CharacterWithLength
CharacterWithLength: character '(' Iconst ')' opt_charset
{
if (($5 != NULL) && (strcmp($5, "sql_text") != 0))
- {
- char *type;
-
- type = palloc(strlen($1) + 1 + strlen($5) + 1);
- strcpy(type, $1);
- strcat(type, "_");
- strcat(type, $5);
- $1 = type;
- }
+ $1 = psprintf("%s_%s", $1, $5);
$$ = SystemTypeName($1);
$$->typmods = list_make1(makeIntConst($3, @3));
@@ -9910,20 +10640,12 @@ CharacterWithLength: character '(' Iconst ')' opt_charset
CharacterWithoutLength: character opt_charset
{
if (($2 != NULL) && (strcmp($2, "sql_text") != 0))
- {
- char *type;
-
- type = palloc(strlen($1) + 1 + strlen($2) + 1);
- strcpy(type, $1);
- strcat(type, "_");
- strcat(type, $2);
- $1 = type;
- }
+ $1 = psprintf("%s_%s", $1, $2);
$$ = SystemTypeName($1);
/* char defaults to char(1), varchar to no limit */
- if (strcmp($1, "char") == 0)
+ if (strcmp($1, "bpchar") == 0)
$$->typmods = list_make1(makeIntConst(1, -1));
$$->location = @1;
@@ -9931,17 +10653,17 @@ CharacterWithoutLength: character opt_charset
;
character: CHARACTER opt_varying
- { $$ = $2 ? "varchar": "char"; }
+ { $$ = $2 ? "varchar": "bpchar"; }
| CHAR_P opt_varying
- { $$ = $2 ? "varchar": "char"; }
+ { $$ = $2 ? "varchar": "bpchar"; }
| VARCHAR
{ $$ = "varchar"; }
| NATIONAL CHARACTER opt_varying
- { $$ = $3 ? "varchar": "char"; }
+ { $$ = $3 ? "varchar": "bpchar"; }
| NATIONAL CHAR_P opt_varying
- { $$ = $3 ? "varchar": "char"; }
+ { $$ = $3 ? "varchar": "bpchar"; }
| NCHAR opt_varying
- { $$ = $2 ? "varchar": "char"; }
+ { $$ = $2 ? "varchar": "bpchar"; }
;
opt_varying:
@@ -9955,7 +10677,7 @@ opt_charset:
;
/*
- * SQL92 date/time types
+ * SQL date/time types
*/
ConstDatetime:
TIMESTAMP '(' Iconst ')' opt_timezone
@@ -10115,16 +10837,9 @@ a_expr: c_expr { $$ = $1; }
}
| a_expr AT TIME ZONE a_expr %prec AT
{
- FuncCall *n = makeNode(FuncCall);
- n->funcname = SystemFuncName("timezone");
- n->args = list_make2($5, $1);
- n->agg_order = NIL;
- n->agg_star = FALSE;
- n->agg_distinct = FALSE;
- n->func_variadic = FALSE;
- n->over = NULL;
- n->location = @2;
- $$ = (Node *) n;
+ $$ = (Node *) makeFuncCall(SystemFuncName("timezone"),
+ list_make2($5, $1),
+ @2);
}
/*
* These operators must be called out explicitly in order to make use
@@ -10176,118 +10891,70 @@ a_expr: c_expr { $$ = $1; }
{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~~", $1, $3, @2); }
| a_expr LIKE a_expr ESCAPE a_expr
{
- FuncCall *n = makeNode(FuncCall);
- n->funcname = SystemFuncName("like_escape");
- n->args = list_make2($3, $5);
- n->agg_order = NIL;
- n->agg_star = FALSE;
- n->agg_distinct = FALSE;
- n->func_variadic = FALSE;
- n->over = NULL;
- n->location = @2;
+ FuncCall *n = makeFuncCall(SystemFuncName("like_escape"),
+ list_make2($3, $5),
+ @2);
$$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~~", $1, (Node *) n, @2);
}
| a_expr NOT LIKE a_expr
{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~~", $1, $4, @2); }
| a_expr NOT LIKE a_expr ESCAPE a_expr
{
- FuncCall *n = makeNode(FuncCall);
- n->funcname = SystemFuncName("like_escape");
- n->args = list_make2($4, $6);
- n->agg_order = NIL;
- n->agg_star = FALSE;
- n->agg_distinct = FALSE;
- n->func_variadic = FALSE;
- n->over = NULL;
- n->location = @2;
+ FuncCall *n = makeFuncCall(SystemFuncName("like_escape"),
+ list_make2($4, $6),
+ @2);
$$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~~", $1, (Node *) n, @2);
}
| a_expr ILIKE a_expr
{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~~*", $1, $3, @2); }
| a_expr ILIKE a_expr ESCAPE a_expr
{
- FuncCall *n = makeNode(FuncCall);
- n->funcname = SystemFuncName("like_escape");
- n->args = list_make2($3, $5);
- n->agg_order = NIL;
- n->agg_star = FALSE;
- n->agg_distinct = FALSE;
- n->func_variadic = FALSE;
- n->over = NULL;
- n->location = @2;
+ FuncCall *n = makeFuncCall(SystemFuncName("like_escape"),
+ list_make2($3, $5),
+ @2);
$$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~~*", $1, (Node *) n, @2);
}
| a_expr NOT ILIKE a_expr
{ $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~~*", $1, $4, @2); }
| a_expr NOT ILIKE a_expr ESCAPE a_expr
{
- FuncCall *n = makeNode(FuncCall);
- n->funcname = SystemFuncName("like_escape");
- n->args = list_make2($4, $6);
- n->agg_order = NIL;
- n->agg_star = FALSE;
- n->agg_distinct = FALSE;
- n->func_variadic = FALSE;
- n->over = NULL;
- n->location = @2;
+ FuncCall *n = makeFuncCall(SystemFuncName("like_escape"),
+ list_make2($4, $6),
+ @2);
$$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~~*", $1, (Node *) n, @2);
}
| a_expr SIMILAR TO a_expr %prec SIMILAR
{
- FuncCall *n = makeNode(FuncCall);
- n->funcname = SystemFuncName("similar_escape");
- n->args = list_make2($4, makeNullAConst(-1));
- n->agg_order = NIL;
- n->agg_star = FALSE;
- n->agg_distinct = FALSE;
- n->func_variadic = FALSE;
- n->over = NULL;
- n->location = @2;
+ FuncCall *n = makeFuncCall(SystemFuncName("similar_escape"),
+ list_make2($4, makeNullAConst(-1)),
+ @2);
$$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~", $1, (Node *) n, @2);
}
| a_expr SIMILAR TO a_expr ESCAPE a_expr
{
- FuncCall *n = makeNode(FuncCall);
- n->funcname = SystemFuncName("similar_escape");
- n->args = list_make2($4, $6);
- n->agg_order = NIL;
- n->agg_star = FALSE;
- n->agg_distinct = FALSE;
- n->func_variadic = FALSE;
- n->over = NULL;
- n->location = @2;
+ FuncCall *n = makeFuncCall(SystemFuncName("similar_escape"),
+ list_make2($4, $6),
+ @2);
$$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~", $1, (Node *) n, @2);
}
| a_expr NOT SIMILAR TO a_expr %prec SIMILAR
{
- FuncCall *n = makeNode(FuncCall);
- n->funcname = SystemFuncName("similar_escape");
- n->args = list_make2($5, makeNullAConst(-1));
- n->agg_order = NIL;
- n->agg_star = FALSE;
- n->agg_distinct = FALSE;
- n->func_variadic = FALSE;
- n->over = NULL;
- n->location = @2;
+ FuncCall *n = makeFuncCall(SystemFuncName("similar_escape"),
+ list_make2($5, makeNullAConst(-1)),
+ @2);
$$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~", $1, (Node *) n, @2);
}
| a_expr NOT SIMILAR TO a_expr ESCAPE a_expr
{
- FuncCall *n = makeNode(FuncCall);
- n->funcname = SystemFuncName("similar_escape");
- n->args = list_make2($5, $7);
- n->agg_order = NIL;
- n->agg_star = FALSE;
- n->agg_distinct = FALSE;
- n->func_variadic = FALSE;
- n->over = NULL;
- n->location = @2;
+ FuncCall *n = makeFuncCall(SystemFuncName("similar_escape"),
+ list_make2($5, $7),
+ @2);
$$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~", $1, (Node *) n, @2);
}
/* NullTest clause
- * Define SQL92-style Null test clause.
+ * Define SQL-style Null test clause.
* Allow two forms described in the standard:
* a IS NULL
* a IS NOT NULL
@@ -10325,7 +10992,19 @@ a_expr: c_expr { $$ = $1; }
}
| row OVERLAPS row
{
- $$ = (Node *)makeOverlaps($1, $3, @2, yyscanner);
+ if (list_length($1) != 2)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("wrong number of parameters on left side of OVERLAPS expression"),
+ parser_errposition(@1)));
+ if (list_length($3) != 2)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("wrong number of parameters on right side of OVERLAPS expression"),
+ parser_errposition(@3)));
+ $$ = (Node *) makeFuncCall(SystemFuncName("overlaps"),
+ list_concat($1, $3),
+ @2);
}
| a_expr IS TRUE_P %prec IS
{
@@ -10707,144 +11386,134 @@ c_expr: columnref { $$ = $1; }
}
;
-/*
- * func_expr is split out from c_expr just so that we have a classification
- * for "everything that is a function call or looks like one". This isn't
- * very important, but it saves us having to document which variants are
- * legal in the backwards-compatible functional-index syntax for CREATE INDEX.
- * (Note that many of the special SQL functions wouldn't actually make any
- * sense as functional index entries, but we ignore that consideration here.)
- */
-func_expr: func_name '(' ')' over_clause
+func_application: func_name '(' ')'
{
- FuncCall *n = makeNode(FuncCall);
- n->funcname = $1;
- n->args = NIL;
- n->agg_order = NIL;
- n->agg_star = FALSE;
- n->agg_distinct = FALSE;
- n->func_variadic = FALSE;
- n->over = $4;
- n->location = @1;
- $$ = (Node *)n;
+ $$ = (Node *) makeFuncCall($1, NIL, @1);
}
- | func_name '(' func_arg_list ')' over_clause
+ | func_name '(' func_arg_list opt_sort_clause ')'
{
- FuncCall *n = makeNode(FuncCall);
- n->funcname = $1;
- n->args = $3;
- n->agg_order = NIL;
- n->agg_star = FALSE;
- n->agg_distinct = FALSE;
- n->func_variadic = FALSE;
- n->over = $5;
- n->location = @1;
+ FuncCall *n = makeFuncCall($1, $3, @1);
+ n->agg_order = $4;
$$ = (Node *)n;
}
- | func_name '(' VARIADIC func_arg_expr ')' over_clause
+ | func_name '(' VARIADIC func_arg_expr opt_sort_clause ')'
{
- FuncCall *n = makeNode(FuncCall);
- n->funcname = $1;
- n->args = list_make1($4);
- n->agg_order = NIL;
- n->agg_star = FALSE;
- n->agg_distinct = FALSE;
+ FuncCall *n = makeFuncCall($1, list_make1($4), @1);
n->func_variadic = TRUE;
- n->over = $6;
- n->location = @1;
+ n->agg_order = $5;
$$ = (Node *)n;
}
- | func_name '(' func_arg_list ',' VARIADIC func_arg_expr ')' over_clause
+ | func_name '(' func_arg_list ',' VARIADIC func_arg_expr opt_sort_clause ')'
{
- FuncCall *n = makeNode(FuncCall);
- n->funcname = $1;
- n->args = lappend($3, $6);
- n->agg_order = NIL;
- n->agg_star = FALSE;
- n->agg_distinct = FALSE;
+ FuncCall *n = makeFuncCall($1, lappend($3, $6), @1);
n->func_variadic = TRUE;
- n->over = $8;
- n->location = @1;
- $$ = (Node *)n;
- }
- | func_name '(' func_arg_list sort_clause ')' over_clause
- {
- FuncCall *n = makeNode(FuncCall);
- n->funcname = $1;
- n->args = $3;
- n->agg_order = $4;
- n->agg_star = FALSE;
- n->agg_distinct = FALSE;
- n->func_variadic = FALSE;
- n->over = $6;
- n->location = @1;
+ n->agg_order = $7;
$$ = (Node *)n;
}
- | func_name '(' ALL func_arg_list opt_sort_clause ')' over_clause
+ | func_name '(' ALL func_arg_list opt_sort_clause ')'
{
- FuncCall *n = makeNode(FuncCall);
- n->funcname = $1;
- n->args = $4;
+ FuncCall *n = makeFuncCall($1, $4, @1);
n->agg_order = $5;
- n->agg_star = FALSE;
- n->agg_distinct = FALSE;
/* Ideally we'd mark the FuncCall node to indicate
* "must be an aggregate", but there's no provision
* for that in FuncCall at the moment.
*/
- n->func_variadic = FALSE;
- n->over = $7;
- n->location = @1;
$$ = (Node *)n;
}
- | func_name '(' DISTINCT func_arg_list opt_sort_clause ')' over_clause
+ | func_name '(' DISTINCT func_arg_list opt_sort_clause ')'
{
- FuncCall *n = makeNode(FuncCall);
- n->funcname = $1;
- n->args = $4;
+ FuncCall *n = makeFuncCall($1, $4, @1);
n->agg_order = $5;
- n->agg_star = FALSE;
n->agg_distinct = TRUE;
- n->func_variadic = FALSE;
- n->over = $7;
- n->location = @1;
$$ = (Node *)n;
}
- | func_name '(' '*' ')' over_clause
+ | func_name '(' '*' ')'
{
/*
* We consider AGGREGATE(*) to invoke a parameterless
* aggregate. This does the right thing for COUNT(*),
- * and there are no other aggregates in SQL92 that accept
+ * and there are no other aggregates in SQL that accept
* '*' as parameter.
*
* The FuncCall node is also marked agg_star = true,
* so that later processing can detect what the argument
* really was.
*/
- FuncCall *n = makeNode(FuncCall);
- n->funcname = $1;
- n->args = NIL;
- n->agg_order = NIL;
+ FuncCall *n = makeFuncCall($1, NIL, @1);
n->agg_star = TRUE;
- n->agg_distinct = FALSE;
- n->func_variadic = FALSE;
- n->over = $5;
- n->location = @1;
$$ = (Node *)n;
}
- | COLLATION FOR '(' a_expr ')'
+ ;
+
+
+/*
+ * func_expr and its cousin func_expr_windowless are split out from c_expr just
+ * so that we have classifications for "everything that is a function call or
+ * looks like one". This isn't very important, but it saves us having to
+ * document which variants are legal in places like "FROM function()" or the
+ * backwards-compatible functional-index syntax for CREATE INDEX.
+ * (Note that many of the special SQL functions wouldn't actually make any
+ * sense as functional index entries, but we ignore that consideration here.)
+ */
+func_expr: func_application within_group_clause filter_clause over_clause
{
- FuncCall *n = makeNode(FuncCall);
- n->funcname = SystemFuncName("pg_collation_for");
- n->args = list_make1($4);
- n->agg_order = NIL;
- n->agg_star = FALSE;
- n->agg_distinct = FALSE;
- n->func_variadic = FALSE;
- n->over = NULL;
- n->location = @1;
- $$ = (Node *)n;
+ FuncCall *n = (FuncCall *) $1;
+ /*
+ * The order clause for WITHIN GROUP and the one for
+ * plain-aggregate ORDER BY share a field, so we have to
+ * check here that at most one is present. We also check
+ * for DISTINCT and VARIADIC here to give a better error
+ * location. Other consistency checks are deferred to
+ * parse analysis.
+ */
+ if ($2 != NIL)
+ {
+ if (n->agg_order != NIL)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("cannot use multiple ORDER BY clauses with WITHIN GROUP"),
+ parser_errposition(@2)));
+ if (n->agg_distinct)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("cannot use DISTINCT with WITHIN GROUP"),
+ parser_errposition(@2)));
+ if (n->func_variadic)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("cannot use VARIADIC with WITHIN GROUP"),
+ parser_errposition(@2)));
+ n->agg_order = $2;
+ n->agg_within_group = TRUE;
+ }
+ n->agg_filter = $3;
+ n->over = $4;
+ $$ = (Node *) n;
+ }
+ | func_expr_common_subexpr
+ { $$ = $1; }
+ ;
+
+/*
+ * As func_expr but does not accept WINDOW functions directly
+ * (but they can still be contained in arguments for functions etc).
+ * Use this when window expressions are not allowed, where needed to
+ * disambiguate the grammar (e.g. in CREATE INDEX).
+ */
+func_expr_windowless:
+ func_application { $$ = $1; }
+ | func_expr_common_subexpr { $$ = $1; }
+ ;
+
+/*
+ * Special expressions that are considered to be functions.
+ */
+func_expr_common_subexpr:
+ COLLATION FOR '(' a_expr ')'
+ {
+ $$ = (Node *) makeFuncCall(SystemFuncName("pg_collation_for"),
+ list_make1($4),
+ @1);
}
| CURRENT_DATE
{
@@ -10862,10 +11531,15 @@ func_expr: func_name '(' ')' over_clause
* of type-input conversion functions. (As of PG 7.3
* that is actually possible, but not clear that we want
* to rely on it.)
+ *
+ * The token location is attached to the run-time
+ * typecast, not to the Const, for the convenience of
+ * pg_stat_statements (which doesn't want these constructs
+ * to appear to be replaceable constants).
*/
Node *n;
- n = makeStringConstCast("now", @1, SystemTypeName("text"));
- $$ = makeTypeCast(n, SystemTypeName("date"), -1);
+ n = makeStringConstCast("now", -1, SystemTypeName("text"));
+ $$ = makeTypeCast(n, SystemTypeName("date"), @1);
}
| CURRENT_TIME
{
@@ -10874,8 +11548,8 @@ func_expr: func_name '(' ')' over_clause
* See comments for CURRENT_DATE.
*/
Node *n;
- n = makeStringConstCast("now", @1, SystemTypeName("text"));
- $$ = makeTypeCast(n, SystemTypeName("timetz"), -1);
+ n = makeStringConstCast("now", -1, SystemTypeName("text"));
+ $$ = makeTypeCast(n, SystemTypeName("timetz"), @1);
}
| CURRENT_TIME '(' Iconst ')'
{
@@ -10885,10 +11559,10 @@ func_expr: func_name '(' ')' over_clause
*/
Node *n;
TypeName *d;
- n = makeStringConstCast("now", @1, SystemTypeName("text"));
+ n = makeStringConstCast("now", -1, SystemTypeName("text"));
d = SystemTypeName("timetz");
d->typmods = list_make1(makeIntConst($3, @3));
- $$ = makeTypeCast(n, d, -1);
+ $$ = makeTypeCast(n, d, @1);
}
| CURRENT_TIMESTAMP
{
@@ -10896,16 +11570,7 @@ func_expr: func_name '(' ')' over_clause
* Translate as "now()", since we have a function that
* does exactly what is needed.
*/
- FuncCall *n = makeNode(FuncCall);
- n->funcname = SystemFuncName("now");
- n->args = NIL;
- n->agg_order = NIL;
- n->agg_star = FALSE;
- n->agg_distinct = FALSE;
- n->func_variadic = FALSE;
- n->over = NULL;
- n->location = @1;
- $$ = (Node *)n;
+ $$ = (Node *) makeFuncCall(SystemFuncName("now"), NIL, @1);
}
| CURRENT_TIMESTAMP '(' Iconst ')'
{
@@ -10915,10 +11580,10 @@ func_expr: func_name '(' ')' over_clause
*/
Node *n;
TypeName *d;
- n = makeStringConstCast("now", @1, SystemTypeName("text"));
+ n = makeStringConstCast("now", -1, SystemTypeName("text"));
d = SystemTypeName("timestamptz");
d->typmods = list_make1(makeIntConst($3, @3));
- $$ = makeTypeCast(n, d, -1);
+ $$ = makeTypeCast(n, d, @1);
}
| LOCALTIME
{
@@ -10927,8 +11592,8 @@ func_expr: func_name '(' ')' over_clause
* See comments for CURRENT_DATE.
*/
Node *n;
- n = makeStringConstCast("now", @1, SystemTypeName("text"));
- $$ = makeTypeCast((Node *)n, SystemTypeName("time"), -1);
+ n = makeStringConstCast("now", -1, SystemTypeName("text"));
+ $$ = makeTypeCast((Node *)n, SystemTypeName("time"), @1);
}
| LOCALTIME '(' Iconst ')'
{
@@ -10938,10 +11603,10 @@ func_expr: func_name '(' ')' over_clause
*/
Node *n;
TypeName *d;
- n = makeStringConstCast("now", @1, SystemTypeName("text"));
+ n = makeStringConstCast("now", -1, SystemTypeName("text"));
d = SystemTypeName("time");
d->typmods = list_make1(makeIntConst($3, @3));
- $$ = makeTypeCast((Node *)n, d, -1);
+ $$ = makeTypeCast((Node *)n, d, @1);
}
| LOCALTIMESTAMP
{
@@ -10950,8 +11615,8 @@ func_expr: func_name '(' ')' over_clause
* See comments for CURRENT_DATE.
*/
Node *n;
- n = makeStringConstCast("now", @1, SystemTypeName("text"));
- $$ = makeTypeCast(n, SystemTypeName("timestamp"), -1);
+ n = makeStringConstCast("now", -1, SystemTypeName("text"));
+ $$ = makeTypeCast(n, SystemTypeName("timestamp"), @1);
}
| LOCALTIMESTAMP '(' Iconst ')'
{
@@ -10961,103 +11626,40 @@ func_expr: func_name '(' ')' over_clause
*/
Node *n;
TypeName *d;
- n = makeStringConstCast("now", @1, SystemTypeName("text"));
+ n = makeStringConstCast("now", -1, SystemTypeName("text"));
d = SystemTypeName("timestamp");
d->typmods = list_make1(makeIntConst($3, @3));
- $$ = makeTypeCast(n, d, -1);
+ $$ = makeTypeCast(n, d, @1);
}
| CURRENT_ROLE
{
- FuncCall *n = makeNode(FuncCall);
- n->funcname = SystemFuncName("current_user");
- n->args = NIL;
- n->agg_order = NIL;
- n->agg_star = FALSE;
- n->agg_distinct = FALSE;
- n->func_variadic = FALSE;
- n->over = NULL;
- n->location = @1;
- $$ = (Node *)n;
+ $$ = (Node *) makeFuncCall(SystemFuncName("current_user"), NIL, @1);
}
| CURRENT_USER
{
- FuncCall *n = makeNode(FuncCall);
- n->funcname = SystemFuncName("current_user");
- n->args = NIL;
- n->agg_order = NIL;
- n->agg_star = FALSE;
- n->agg_distinct = FALSE;
- n->func_variadic = FALSE;
- n->over = NULL;
- n->location = @1;
- $$ = (Node *)n;
+ $$ = (Node *) makeFuncCall(SystemFuncName("current_user"), NIL, @1);
}
| SESSION_USER
{
- FuncCall *n = makeNode(FuncCall);
- n->funcname = SystemFuncName("session_user");
- n->args = NIL;
- n->agg_order = NIL;
- n->agg_star = FALSE;
- n->agg_distinct = FALSE;
- n->func_variadic = FALSE;
- n->over = NULL;
- n->location = @1;
- $$ = (Node *)n;
+ $$ = (Node *) makeFuncCall(SystemFuncName("session_user"), NIL, @1);
}
| USER
{
- FuncCall *n = makeNode(FuncCall);
- n->funcname = SystemFuncName("current_user");
- n->args = NIL;
- n->agg_order = NIL;
- n->agg_star = FALSE;
- n->agg_distinct = FALSE;
- n->func_variadic = FALSE;
- n->over = NULL;
- n->location = @1;
- $$ = (Node *)n;
+ $$ = (Node *) makeFuncCall(SystemFuncName("current_user"), NIL, @1);
}
| CURRENT_CATALOG
{
- FuncCall *n = makeNode(FuncCall);
- n->funcname = SystemFuncName("current_database");
- n->args = NIL;
- n->agg_order = NIL;
- n->agg_star = FALSE;
- n->agg_distinct = FALSE;
- n->func_variadic = FALSE;
- n->over = NULL;
- n->location = @1;
- $$ = (Node *)n;
+ $$ = (Node *) makeFuncCall(SystemFuncName("current_database"), NIL, @1);
}
| CURRENT_SCHEMA
{
- FuncCall *n = makeNode(FuncCall);
- n->funcname = SystemFuncName("current_schema");
- n->args = NIL;
- n->agg_order = NIL;
- n->agg_star = FALSE;
- n->agg_distinct = FALSE;
- n->func_variadic = FALSE;
- n->over = NULL;
- n->location = @1;
- $$ = (Node *)n;
+ $$ = (Node *) makeFuncCall(SystemFuncName("current_schema"), NIL, @1);
}
| CAST '(' a_expr AS Typename ')'
{ $$ = makeTypeCast($3, $5, @1); }
| EXTRACT '(' extract_list ')'
{
- FuncCall *n = makeNode(FuncCall);
- n->funcname = SystemFuncName("date_part");
- n->args = $3;
- n->agg_order = NIL;
- n->agg_star = FALSE;
- n->agg_distinct = FALSE;
- n->func_variadic = FALSE;
- n->over = NULL;
- n->location = @1;
- $$ = (Node *)n;
+ $$ = (Node *) makeFuncCall(SystemFuncName("date_part"), $3, @1);
}
| OVERLAY '(' overlay_list ')'
{
@@ -11066,46 +11668,19 @@ func_expr: func_name '(' ')' over_clause
* overlay(A PLACING B FROM C) is converted to
* overlay(A, B, C)
*/
- FuncCall *n = makeNode(FuncCall);
- n->funcname = SystemFuncName("overlay");
- n->args = $3;
- n->agg_order = NIL;
- n->agg_star = FALSE;
- n->agg_distinct = FALSE;
- n->func_variadic = FALSE;
- n->over = NULL;
- n->location = @1;
- $$ = (Node *)n;
+ $$ = (Node *) makeFuncCall(SystemFuncName("overlay"), $3, @1);
}
| POSITION '(' position_list ')'
{
/* position(A in B) is converted to position(B, A) */
- FuncCall *n = makeNode(FuncCall);
- n->funcname = SystemFuncName("position");
- n->args = $3;
- n->agg_order = NIL;
- n->agg_star = FALSE;
- n->agg_distinct = FALSE;
- n->func_variadic = FALSE;
- n->over = NULL;
- n->location = @1;
- $$ = (Node *)n;
+ $$ = (Node *) makeFuncCall(SystemFuncName("position"), $3, @1);
}
| SUBSTRING '(' substr_list ')'
{
/* substring(A from B for C) is converted to
* substring(A, B, C) - thomas 2000-11-28
*/
- FuncCall *n = makeNode(FuncCall);
- n->funcname = SystemFuncName("substring");
- n->args = $3;
- n->agg_order = NIL;
- n->agg_star = FALSE;
- n->agg_distinct = FALSE;
- n->func_variadic = FALSE;
- n->over = NULL;
- n->location = @1;
- $$ = (Node *)n;
+ $$ = (Node *) makeFuncCall(SystemFuncName("substring"), $3, @1);
}
| TREAT '(' a_expr AS Typename ')'
{
@@ -11114,75 +11689,32 @@ func_expr: func_name '(' ')' over_clause
* In SQL99, this is intended for use with structured UDTs,
* but let's make this a generally useful form allowing stronger
* coercions than are handled by implicit casting.
- */
- FuncCall *n = makeNode(FuncCall);
- /* Convert SystemTypeName() to SystemFuncName() even though
+ *
+ * Convert SystemTypeName() to SystemFuncName() even though
* at the moment they result in the same thing.
*/
- n->funcname = SystemFuncName(((Value *)llast($5->names))->val.str);
- n->args = list_make1($3);
- n->agg_order = NIL;
- n->agg_star = FALSE;
- n->agg_distinct = FALSE;
- n->func_variadic = FALSE;
- n->over = NULL;
- n->location = @1;
- $$ = (Node *)n;
+ $$ = (Node *) makeFuncCall(SystemFuncName(((Value *)llast($5->names))->val.str),
+ list_make1($3),
+ @1);
}
| TRIM '(' BOTH trim_list ')'
{
- /* various trim expressions are defined in SQL92
+ /* various trim expressions are defined in SQL
* - thomas 1997-07-19
*/
- FuncCall *n = makeNode(FuncCall);
- n->funcname = SystemFuncName("btrim");
- n->args = $4;
- n->agg_order = NIL;
- n->agg_star = FALSE;
- n->agg_distinct = FALSE;
- n->func_variadic = FALSE;
- n->over = NULL;
- n->location = @1;
- $$ = (Node *)n;
+ $$ = (Node *) makeFuncCall(SystemFuncName("btrim"), $4, @1);
}
| TRIM '(' LEADING trim_list ')'
{
- FuncCall *n = makeNode(FuncCall);
- n->funcname = SystemFuncName("ltrim");
- n->args = $4;
- n->agg_order = NIL;
- n->agg_star = FALSE;
- n->agg_distinct = FALSE;
- n->func_variadic = FALSE;
- n->over = NULL;
- n->location = @1;
- $$ = (Node *)n;
+ $$ = (Node *) makeFuncCall(SystemFuncName("ltrim"), $4, @1);
}
| TRIM '(' TRAILING trim_list ')'
{
- FuncCall *n = makeNode(FuncCall);
- n->funcname = SystemFuncName("rtrim");
- n->args = $4;
- n->agg_order = NIL;
- n->agg_star = FALSE;
- n->agg_distinct = FALSE;
- n->func_variadic = FALSE;
- n->over = NULL;
- n->location = @1;
- $$ = (Node *)n;
+ $$ = (Node *) makeFuncCall(SystemFuncName("rtrim"), $4, @1);
}
| TRIM '(' trim_list ')'
{
- FuncCall *n = makeNode(FuncCall);
- n->funcname = SystemFuncName("btrim");
- n->args = $3;
- n->agg_order = NIL;
- n->agg_star = FALSE;
- n->agg_distinct = FALSE;
- n->func_variadic = FALSE;
- n->over = NULL;
- n->location = @1;
- $$ = (Node *)n;
+ $$ = (Node *) makeFuncCall(SystemFuncName("btrim"), $3, @1);
}
| NULLIF '(' a_expr ',' a_expr ')'
{
@@ -11235,16 +11767,7 @@ func_expr: func_name '(' ')' over_clause
{
/* xmlexists(A PASSING [BY REF] B [BY REF]) is
* converted to xmlexists(A, B)*/
- FuncCall *n = makeNode(FuncCall);
- n->funcname = SystemFuncName("xmlexists");
- n->args = list_make2($3, $4);
- n->agg_order = NIL;
- n->agg_star = FALSE;
- n->agg_distinct = FALSE;
- n->func_variadic = FALSE;
- n->over = NULL;
- n->location = @1;
- $$ = (Node *)n;
+ $$ = (Node *) makeFuncCall(SystemFuncName("xmlexists"), list_make2($3, $4), @1);
}
| XMLFOREST '(' xml_attribute_list ')'
{
@@ -11358,6 +11881,20 @@ xmlexists_argument:
/*
+ * Aggregate decoration clauses
+ */
+within_group_clause:
+ WITHIN GROUP_P '(' sort_clause ')' { $$ = $4; }
+ | /*EMPTY*/ { $$ = NIL; }
+ ;
+
+filter_clause:
+ FILTER '(' WHERE a_expr ')' { $$ = $4; }
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
+
+
+/*
* Window Definitions
*/
window_clause:
@@ -11834,7 +12371,7 @@ in_expr: select_with_parens
;
/*
- * Define SQL92-style case clause.
+ * Define SQL-style CASE clause.
* - Full specification
* CASE WHEN a = b THEN c ... ELSE d END
* - Implicit argument
@@ -11964,6 +12501,10 @@ ctext_row: '(' ctext_expr_list ')' { $$ = $2; }
*
*****************************************************************************/
+opt_target_list: target_list { $$ = $1; }
+ | /* EMPTY */ { $$ = NIL; }
+ ;
+
target_list:
target_el { $$ = list_make1($1); }
| target_list ',' target_el { $$ = lappend($1, $3); }
@@ -12140,16 +12681,17 @@ AexprConst: Iconst
t->location = @1;
$$ = makeStringConstCast($2, @2, t);
}
- | func_name '(' func_arg_list ')' Sconst
+ | func_name '(' func_arg_list opt_sort_clause ')' Sconst
{
/* generic syntax with a type modifier */
TypeName *t = makeTypeNameFromNameList($1);
ListCell *lc;
/*
- * We must use func_arg_list in the production to avoid
- * reduce/reduce conflicts, but we don't actually wish
- * to allow NamedArgExpr in this context.
+ * We must use func_arg_list and opt_sort_clause in the
+ * production to avoid reduce/reduce conflicts, but we
+ * don't actually wish to allow NamedArgExpr in this
+ * context, nor ORDER BY.
*/
foreach(lc, $3)
{
@@ -12161,9 +12703,15 @@ AexprConst: Iconst
errmsg("type modifier cannot have parameter name"),
parser_errposition(arg->location)));
}
+ if ($4 != NIL)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("type modifier cannot have ORDER BY"),
+ parser_errposition(@4)));
+
t->typmods = $3;
t->location = @1;
- $$ = makeStringConstCast($5, @5, t);
+ $$ = makeStringConstCast($6, @6, t);
}
| ConstTypename Sconst
{
@@ -12208,7 +12756,13 @@ AexprConst: Iconst
Iconst: ICONST { $$ = $1; };
Sconst: SCONST { $$ = $1; };
-RoleId: ColId { $$ = $1; };
+RoleId: NonReservedWord { $$ = $1; };
+
+role_list: RoleId
+ { $$ = list_make1(makeString($1)); }
+ | role_list ',' RoleId
+ { $$ = lappend($1, makeString($3)); }
+ ;
SignedIconst: Iconst { $$ = $1; }
| '+' Iconst { $$ = + $2; }
@@ -12240,6 +12794,14 @@ type_function_name: IDENT { $$ = $1; }
| type_func_name_keyword { $$ = pstrdup($1); }
;
+/* Any not-fully-reserved word --- these names can be, eg, role names.
+ */
+NonReservedWord: IDENT { $$ = $1; }
+ | unreserved_keyword { $$ = pstrdup($1); }
+ | col_name_keyword { $$ = pstrdup($1); }
+ | type_func_name_keyword { $$ = pstrdup($1); }
+ ;
+
/* Column label --- allowed labels in "AS" clauses.
* This presently includes *all* Postgres keywords.
*/
@@ -12337,6 +12899,7 @@ unreserved_keyword:
| ENCRYPTED
| ENUM_P
| ESCAPE
+ | EVENT
| EXCLUDE
| EXCLUDING
| EXCLUSIVE
@@ -12345,6 +12908,7 @@ unreserved_keyword:
| EXTENSION
| EXTERNAL
| FAMILY
+ | FILTER
| FIRST_P
| FOLLOWING
| FORCE
@@ -12391,6 +12955,7 @@ unreserved_keyword:
| LOCK_P
| MAPPING
| MATCH
+ | MATERIALIZED
| MAXVALUE
| MINUTE_P
| MINVALUE
@@ -12412,6 +12977,8 @@ unreserved_keyword:
| OPERATOR
| OPTION
| OPTIONS
+ | ORDINALITY
+ | OVER
| OWNED
| OWNER
| PARSER
@@ -12428,6 +12995,7 @@ unreserved_keyword:
| PRIVILEGES
| PROCEDURAL
| PROCEDURE
+ | PROGRAM
| QUOTE
| RANGE
| READ
@@ -12435,6 +13003,7 @@ unreserved_keyword:
| RECHECK
| RECURSIVE
| REF
+ | REFRESH
| REINDEX
| RELATIVE_P
| RELEASE
@@ -12507,8 +13076,10 @@ unreserved_keyword:
| VARYING
| VERSION_P
| VIEW
+ | VIEWS
| VOLATILE
| WHITESPACE_P
+ | WITHIN
| WITHOUT
| WORK
| WRAPPER
@@ -12608,7 +13179,6 @@ type_func_name_keyword:
| NATURAL
| NOTNULL
| OUTER_P
- | OVER
| OVERLAPS
| RIGHT
| SIMILAR
@@ -12665,6 +13235,7 @@ reserved_keyword:
| INITIALLY
| INTERSECT
| INTO
+ | LATERAL_P
| LEADING
| LIMIT
| LOCALTIME
@@ -12881,39 +13452,6 @@ makeBoolAConst(bool state, int location)
return makeTypeCast((Node *)n, SystemTypeName("bool"), -1);
}
-/* makeOverlaps()
- * Create and populate a FuncCall node to support the OVERLAPS operator.
- */
-static FuncCall *
-makeOverlaps(List *largs, List *rargs, int location, core_yyscan_t yyscanner)
-{
- FuncCall *n = makeNode(FuncCall);
-
- n->funcname = SystemFuncName("overlaps");
- if (list_length(largs) == 1)
- largs = lappend(largs, largs);
- else if (list_length(largs) != 2)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("wrong number of parameters on left side of OVERLAPS expression"),
- parser_errposition(location)));
- if (list_length(rargs) == 1)
- rargs = lappend(rargs, rargs);
- else if (list_length(rargs) != 2)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("wrong number of parameters on right side of OVERLAPS expression"),
- parser_errposition(location)));
- n->args = list_concat(largs, rargs);
- n->agg_order = NIL;
- n->agg_star = FALSE;
- n->agg_distinct = FALSE;
- n->func_variadic = FALSE;
- n->over = NULL;
- n->location = location;
- return n;
-}
-
/* check_qualified_name --- check the result of qualified_name production
*
* It's easiest to let the grammar production for qualified_name allow
@@ -12992,6 +13530,55 @@ extractArgTypes(List *parameters)
return result;
}
+/* extractAggrArgTypes()
+ * As above, but work from the output of the aggr_args production.
+ */
+static List *
+extractAggrArgTypes(List *aggrargs)
+{
+ Assert(list_length(aggrargs) == 2);
+ return extractArgTypes((List *) linitial(aggrargs));
+}
+
+/* makeOrderedSetArgs()
+ * Build the result of the aggr_args production (which see the comments for).
+ * This handles only the case where both given lists are nonempty, so that
+ * we have to deal with multiple VARIADIC arguments.
+ */
+static List *
+makeOrderedSetArgs(List *directargs, List *orderedargs,
+ core_yyscan_t yyscanner)
+{
+ FunctionParameter *lastd = (FunctionParameter *) llast(directargs);
+ int ndirectargs;
+
+ /* No restriction unless last direct arg is VARIADIC */
+ if (lastd->mode == FUNC_PARAM_VARIADIC)
+ {
+ FunctionParameter *firsto = (FunctionParameter *) linitial(orderedargs);
+
+ /*
+ * We ignore the names, though the aggr_arg production allows them;
+ * it doesn't allow default values, so those need not be checked.
+ */
+ if (list_length(orderedargs) != 1 ||
+ firsto->mode != FUNC_PARAM_VARIADIC)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("an ordered-set aggregate with a VARIADIC direct argument must have one VARIADIC aggregated argument of the same data type"),
+ parser_errposition(exprLocation((Node *) firsto))));
+
+ /* OK, drop the duplicate VARIADIC argument from the internal form */
+ orderedargs = NIL;
+ }
+
+ /* don't merge into the next line, as list_concat changes directargs */
+ ndirectargs = list_length(directargs);
+
+ return list_make2(list_concat(directargs, orderedargs),
+ makeInteger(ndirectargs));
+}
+
/* insertSelectOptions()
* Insert ORDER BY, etc into an already-constructed SelectStmt.
*
@@ -13133,13 +13720,7 @@ doNegateFloat(Value *v)
if (*oldval == '-')
v->val.str = oldval+1; /* just strip the '-' */
else
- {
- char *newval = (char *) palloc(strlen(oldval) + 2);
-
- *newval = '-';
- strcpy(newval+1, oldval);
- v->val.str = newval;
- }
+ v->val.str = psprintf("-%s", oldval);
}
static Node *
@@ -13374,6 +13955,66 @@ processCASbits(int cas_bits, int location, const char *constrType,
}
}
+/*----------
+ * Recursive view transformation
+ *
+ * Convert
+ *
+ * CREATE RECURSIVE VIEW relname (aliases) AS query
+ *
+ * to
+ *
+ * CREATE VIEW relname (aliases) AS
+ * WITH RECURSIVE relname (aliases) AS (query)
+ * SELECT aliases FROM relname
+ *
+ * Actually, just the WITH ... part, which is then inserted into the original
+ * view definition as the query.
+ * ----------
+ */
+static Node *
+makeRecursiveViewSelect(char *relname, List *aliases, Node *query)
+{
+ SelectStmt *s = makeNode(SelectStmt);
+ WithClause *w = makeNode(WithClause);
+ CommonTableExpr *cte = makeNode(CommonTableExpr);
+ List *tl = NIL;
+ ListCell *lc;
+
+ /* create common table expression */
+ cte->ctename = relname;
+ cte->aliascolnames = aliases;
+ cte->ctequery = query;
+ cte->location = -1;
+
+ /* create WITH clause and attach CTE */
+ w->recursive = true;
+ w->ctes = list_make1(cte);
+ w->location = -1;
+
+ /* create target list for the new SELECT from the alias list of the
+ * recursive view specification */
+ foreach (lc, aliases)
+ {
+ ResTarget *rt = makeNode(ResTarget);
+
+ rt->name = NULL;
+ rt->indirection = NIL;
+ rt->val = makeColumnRef(strVal(lfirst(lc)), NIL, -1, 0);
+ rt->location = -1;
+
+ tl = lappend(tl, rt);
+ }
+
+ /* create new SELECT combining WITH clause, target list, and fake FROM
+ * clause */
+ s->withClause = w;
+ s->targetList = tl;
+ s->fromClause = list_make1(makeRangeVar(NULL, relname, -1));
+
+ return (Node *) s;
+}
+
/* parser_init()
* Initialize to parse one query string
*/
@@ -13383,18 +14024,17 @@ parser_init(base_yy_extra_type *yyext)
yyext->parsetree = NIL; /* in case grammar forgets to set it */
}
-
/*
* Create a DefElem setting "oids" to the specified value.
*/
static DefElem *
defWithOids(bool value)
{
- DefElem *f = makeNode(DefElem);
-
- f->defname = "oids";
- f->arg = (Node *) makeInteger(value);
- return f;
+ DefElem *f = makeNode(DefElem);
+
+ f->defname = "oids";
+ f->arg = (Node *) makeInteger(value);
+ return f;
}
/*
diff --git a/src/parser/makefuncs.c b/src/parser/makefuncs.c
index 69ff203..0f15e0b 100644
--- a/src/parser/makefuncs.c
+++ b/src/parser/makefuncs.c
@@ -4,8 +4,8 @@
* creator functions for primitive nodes. The functions here are for
* the most frequently created nodes.
*
- * Portions Copyright (c) 2003-2013, PgPool Global Development Group
- * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
+ * Portions Copyright (c) 2003-2014, PgPool Global Development Group
+ * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
@@ -25,6 +25,8 @@
#define BOOLOID 16 /* XXX */
+
+
/*
* makeA_Expr -
* makes an A_Expr node
@@ -126,7 +128,7 @@ makeVarFromTargetEntry(Index varno,
* a rowtype; either a named composite type, or RECORD. This function
* encapsulates the logic for determining the correct rowtype OID to use.
*
- * If allowScalar is true, then for the case where the RTE is a function
+ * If allowScalar is true, then for the case where the RTE is a single function
* returning a non-composite result type, we produce a normal Var referencing
* the function's result directly, instead of the single-column composite
* value that the whole-row notation might otherwise suggest.
@@ -139,6 +141,7 @@ makeWholeRowVar(RangeTblEntry *rte,
{
Var *result;
Oid toid;
+ Node *fexpr;
switch (rte->rtekind)
{
@@ -155,8 +158,28 @@ makeWholeRowVar(RangeTblEntry *rte,
InvalidOid,
varlevelsup);
break;
+
case RTE_FUNCTION:
- toid = exprType(rte->funcexpr);
+
+ /*
+ * If there's more than one function, or ordinality is requested,
+ * force a RECORD result, since there's certainly more than one
+ * column involved and it can't be a known named type.
+ */
+ if (rte->funcordinality || list_length(rte->functions) != 1)
+ {
+ /* always produces an anonymous RECORD result */
+ result = makeVar(varno,
+ InvalidAttrNumber,
+ RECORDOID,
+ -1,
+ InvalidOid,
+ varlevelsup);
+ break;
+ }
+
+ fexpr = ((RangeTblFunction *) linitial(rte->functions))->funcexpr;
+ toid = exprType(fexpr);
if (type_is_rowtype(toid))
{
/* func returns composite; same as relation case */
@@ -174,7 +197,7 @@ makeWholeRowVar(RangeTblEntry *rte,
1,
toid,
-1,
- exprCollation(rte->funcexpr),
+ exprCollation(fexpr),
varlevelsup);
}
else
@@ -188,6 +211,7 @@ makeWholeRowVar(RangeTblEntry *rte,
varlevelsup);
}
break;
+
default:
/*
@@ -207,6 +231,7 @@ makeWholeRowVar(RangeTblEntry *rte,
return result;
}
+
#endif
/*
@@ -320,9 +345,7 @@ makeNullConst(Oid consttype, int32 consttypmod, Oid constcollid)
true,
typByVal);
}
-#endif
-#if 0
/*
* makeBoolConst -
* creates a Const node representing a boolean value (can be NULL too)
@@ -334,6 +357,7 @@ makeBoolConst(bool value, bool isnull)
return (Node *) makeConst(BOOLOID, -1, InvalidOid, 1,
BoolGetDatum(value), isnull, true);
}
+
#endif
/*
@@ -470,6 +494,7 @@ makeFuncExpr(Oid funcid, Oid rettype, List *args,
funcexpr->funcid = funcid;
funcexpr->funcresulttype = rettype;
funcexpr->funcretset = false; /* only allowed case here */
+ funcexpr->funcvariadic = false; /* only allowed case here */
funcexpr->funcformat = fformat;
funcexpr->funccollid = funccollid;
funcexpr->inputcollid = inputcollid;
@@ -516,3 +541,27 @@ makeDefElemExtended(char *nameSpace, char *name, Node *arg,
return res;
}
+
+/*
+ * makeFuncCall -
+ *
+ * Initialize a FuncCall struct with the information every caller must
+ * supply. Any non-default parameters have to be inserted by the caller.
+ */
+FuncCall *
+makeFuncCall(List *name, List *args, int location)
+{
+ FuncCall *n = makeNode(FuncCall);
+
+ n->funcname = name;
+ n->args = args;
+ n->agg_order = NIL;
+ n->agg_filter = NULL;
+ n->agg_within_group = false;
+ n->agg_star = false;
+ n->agg_distinct = false;
+ n->func_variadic = false;
+ n->over = NULL;
+ n->location = location;
+ return n;
+}
diff --git a/src/parser/outfuncs.c b/src/parser/outfuncs.c
index 3b72f92..1cc89ef 100644
--- a/src/parser/outfuncs.c
+++ b/src/parser/outfuncs.c
@@ -1137,10 +1137,21 @@ _outLockingClause(String *str, LockingClause *node)
if (node == NULL)
return;
- if (node->forUpdate == TRUE)
- string_append_char(str, " FOR UPDATE");
- else
- string_append_char(str, " FOR SHARED");
+ switch(node->strength)
+ {
+ case LCS_FORKEYSHARE:
+ string_append_char(str, " FOR KEY SHARE");
+ break;
+ case LCS_FORSHARE:
+ string_append_char(str, " FOR SHARE");
+ break;
+ case LCS_FORNOKEYUPDATE:
+ string_append_char(str, " FOR NO KEY UPDATE");
+ break;
+ case LCS_FORUPDATE:
+ string_append_char(str, " FOR UPDATE");
+ break;
+ }
_outNode(str, node->lockedRels);
@@ -4265,7 +4276,7 @@ _outAlterOwnerStmt(String *str, AlterOwnerStmt *node)
string_append_char(str, "OPERATOR CLASS ");
_outFuncName(str, node->object);
string_append_char(str, " USING ");
- string_append_char(str, node->addname);
+ string_append_char(str, strVal(linitial(node->objarg)));
string_append_char(str, " OWNER TO \"");
string_append_char(str, node->newowner);
string_append_char(str, "\"");
@@ -4275,7 +4286,7 @@ _outAlterOwnerStmt(String *str, AlterOwnerStmt *node)
string_append_char(str, "OPERATOR FAMILY ");
_outFuncName(str, node->object);
string_append_char(str, " USING ");
- string_append_char(str, node->addname);
+ string_append_char(str, strVal(linitial(node->objarg)));
string_append_char(str, " OWNER TO \"");
string_append_char(str, node->newowner);
string_append_char(str, "\"");
@@ -4872,10 +4883,11 @@ _outRangeSubselect(String *str, RangeSubselect *node)
_outNode(str, node->alias);
}
+/*TODO*/
static void
_outRangeFunction(String *str, RangeFunction *node)
{
- _outNode(str, node->funccallnode);
+ _outNode(str, node->functions); //TODO
if (node->alias)
{
_outNode(str, node->alias);
@@ -5772,13 +5784,12 @@ _outNode(String *str, void *obj)
}
}
-
/*
* nodeToString -
* returns the ascii representation of the Node as a palloc'd string
*/
char *
-nodeToString(void *obj)
+nodeToString(const void *obj)
{
String *str;
char *p;
diff --git a/src/parser/parser.c b/src/parser/parser.c
index b6b10de..806490b 100644
--- a/src/parser/parser.c
+++ b/src/parser/parser.c
@@ -10,8 +10,8 @@
* analyze.c and related files.
*
*
- * Portions Copyright (c) 2003-2009, PgPool Global Development Group
- * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
+ * Portions Copyright (c) 2003-2014, PgPool Global Development Group
+ * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -38,6 +38,7 @@ static bool in_parser_context = false;
static int
parse_version(const char *versionString);
+
/*
* raw_parser
* Given a query in string form, do lexical and grammatical analysis.
@@ -51,16 +52,16 @@ raw_parser(const char *str)
base_yy_extra_type yyextra;
int yyresult;
MemoryContext oldContext = CurrentMemoryContext;
-
+
parsetree = NIL; /* in case grammar forgets to set it */
-
+
/* initialize the flex scanner */
yyscanner = scanner_init(str, &yyextra.core_yy_extra,
ScanKeywords, NumScanKeywords);
-
+
/* base_yylex() only needs this much initialization */
yyextra.have_lookahead = false;
-
+
/* initialize the bison parser */
parser_init(&yyextra);
in_parser_context = true;
@@ -84,15 +85,13 @@ raw_parser(const char *str)
return yyextra.parsetree;
}
-void free_parser(void)
-{
-}
+
/*
- * Intermediate filter between parser and base lexer (base_yylex in scan.l).
+ * Intermediate filter between parser and core lexer (core_yylex in scan.l).
*
* The filter is needed because in some cases the standard SQL grammar
- * requires more than one token lookahead. We reduce these cases to one-token
+ * requires more than one token lookahead. We reduce these cases to one-token
* lookahead by combining tokens here, in order to keep the grammar LALR(1).
*
* Using a filter is simpler than trying to recognize multiword tokens
@@ -160,7 +159,7 @@ base_yylex(YYSTYPE *lvalp, YYLTYPE *llocp, core_yyscan_t yyscanner)
case WITH:
/*
- * WITH TIME must be reduced to one token
+ * WITH TIME and WITH ORDINALITY must each be reduced to one token
*/
cur_yylval = lvalp->core_yystype;
cur_yylloc = *llocp;
@@ -170,6 +169,9 @@ base_yylex(YYSTYPE *lvalp, YYLTYPE *llocp, core_yyscan_t yyscanner)
case TIME:
cur_token = WITH_TIME;
break;
+ case ORDINALITY:
+ cur_token = WITH_ORDINALITY;
+ break;
default:
/* save the lookahead token for next time */
yyextra->lookahead_token = next_token;
@@ -190,23 +192,22 @@ base_yylex(YYSTYPE *lvalp, YYLTYPE *llocp, core_yyscan_t yyscanner)
return cur_token;
}
-
static int
parse_version(const char *versionString)
{
int cnt;
int vmaj,
- vmin,
- vrev;
-
+ vmin,
+ vrev;
+
cnt = sscanf(versionString, "%d.%d.%d", &vmaj, &vmin, &vrev);
-
+
if (cnt < 2)
return -1;
-
+
if (cnt == 2)
vrev = 0;
-
+
return (100 * vmaj + vmin) * 100 + vrev;
}
@@ -244,3 +245,4 @@ pg_mblen(const char *mbstr)
{
return pg_utf_mblen((const unsigned char *) mbstr);
}
+
diff --git a/src/parser/scan.l b/src/parser/scan.l
index 3495542..f2779a1 100644
--- a/src/parser/scan.l
+++ b/src/parser/scan.l
@@ -17,11 +17,12 @@
* for handling float numbers and continued string literals. If you change
* the lexical rules, verify that you haven't broken the no-backtrack
* property by running flex with the "-b" option and checking that the
- * resulting "lex.backup" file says that no backing up is needed.
+ * resulting "lex.backup" file says that no backing up is needed. (As of
+ * Postgres 9.2, this check is made automatically by the Makefile.)
*
*
- * Portions Copyright (c) 2003-2013, PgPool Global Development Group
- * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
+ * Portions Copyright (c) 2003-2014, PgPool Global Development Group
+ * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
@@ -33,26 +34,25 @@
#include <ctype.h>
#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-/* Not needed now that this file is compiled as part of gram.y */
-/* #include "parser/parse.h" */
-#include "parser.h"
-#include "gram.h"
+#include "parser.h" /* only needed for GUC variables */
#include "scanner.h"
#include "scansup.h"
-
-#include "utils/palloc.h"
#include "pg_wchar.h"
+#include "gram.h"
+#include "utils/palloc.h"
-
-#ifdef nouse
/* Avoid exit() on fatal scanner errors (a bit ugly -- see yy_fatal_error) */
#undef fprintf
-#define fprintf(file, fmt, msg) ereport(ERROR, (errmsg_internal("%s", msg)))
-#endif
+#define fprintf(file, fmt, msg) fprintf_to_ereport(fmt, msg)
+
+static void
+fprintf_to_ereport(const char *fmt, const char *msg)
+{
+ ereport(ERROR, (errmsg_internal("%s", msg)));
+}
+
/*
* GUC variables. This is a DIRECT violation of the warning given at the
* head of gram.y, ie flex/bison code must not depend on any GUC variables;
@@ -62,7 +62,7 @@
*/
int backslash_quote = BACKSLASH_QUOTE_SAFE_ENCODING;
bool escape_string_warning = true;
-bool standard_conforming_strings = false;
+bool standard_conforming_strings = true;
/*
* Set the type of YYSTYPE.
@@ -100,6 +100,7 @@ static bool is_utf16_surrogate_first(pg_wchar c);
static bool is_utf16_surrogate_second(pg_wchar c);
static pg_wchar surrogate_pair_to_codepoint(pg_wchar first, pg_wchar second);
static void addunicode(pg_wchar c, yyscan_t yyscanner);
+static bool check_uescapechar(unsigned char escape);
#define yyerror(msg) scanner_yyerror(msg, yyscanner)
@@ -153,8 +154,13 @@ extern void core_yyset_column(int column_no, yyscan_t yyscanner);
* <xe> extended quoted strings (support backslash escape sequences)
* <xdolq> $foo$ quoted strings
* <xui> quoted identifier with Unicode escapes
+ * <xuiend> end of a quoted identifier with Unicode escapes, UESCAPE can follow
* <xus> quoted string with Unicode escapes
+ * <xusend> end of a quoted string with Unicode escapes, UESCAPE can follow
* <xeu> Unicode surrogate pair in extended quoted string
+ *
+ * Remember to add an <<EOF>> case whenever you add a new exclusive state!
+ * The default one is probably not the right thing.
*/
%x xb
@@ -165,7 +171,9 @@ extern void core_yyset_column(int column_no, yyscan_t yyscanner);
%x xq
%x xdolq
%x xui
+%x xuiend
%x xus
+%x xusend
%x xeu
/*
@@ -282,17 +290,17 @@ xdinside [^"]+
/* Unicode escapes */
uescape [uU][eE][sS][cC][aA][pP][eE]{whitespace}*{quote}[^']{quote}
/* error rule to avoid backup */
-uescapefail ("-"|[uU][eE][sS][cC][aA][pP][eE]{whitespace}*"-"|[uU][eE][sS][cC][aA][pP][eE]{whitespace}*{quote}[^']|[uU][eE][sS][cC][aA][pP][eE]{whitespace}*{quote}|[uU][eE][sS][cC][aA][pP][eE]{whitespace}*|[uU][eE][sS][cC][aA][pP]|[uU][eE][sS][cC][aA]|[uU][eE][sS][cC]|[uU][eE][sS]|[uU][eE]|[uU])
+uescapefail [uU][eE][sS][cC][aA][pP][eE]{whitespace}*"-"|[uU][eE][sS][cC][aA][pP][eE]{whitespace}*{quote}[^']|[uU][eE][sS][cC][aA][pP][eE]{whitespace}*{quote}|[uU][eE][sS][cC][aA][pP][eE]{whitespace}*|[uU][eE][sS][cC][aA][pP]|[uU][eE][sS][cC][aA]|[uU][eE][sS][cC]|[uU][eE][sS]|[uU][eE]|[uU]
/* Quoted identifier with Unicode escapes */
xuistart [uU]&{dquote}
-xuistop1 {dquote}{whitespace}*{uescapefail}?
-xuistop2 {dquote}{whitespace}*{uescape}
/* Quoted string with Unicode escapes */
xusstart [uU]&{quote}
-xusstop1 {quote}{whitespace}*{uescapefail}?
-xusstop2 {quote}{whitespace}*{uescape}
+
+/* Optional UESCAPE after a quoted string or identifier with Unicode escapes. */
+xustop1 {uescapefail}?
+xustop2 {uescape}
/* error rule to avoid backup */
xufailed [uU]&
@@ -539,15 +547,32 @@ other .
yylval->str = litbufdup(yyscanner);
return SCONST;
}
-<xus>{xusstop1} {
+<xus>{quotestop} |
+<xus>{quotefail} {
/* throw back all but the quote */
yyless(1);
+ /* xusend state looks for possible UESCAPE */
+ BEGIN(xusend);
+ }
+<xusend>{whitespace} { /* stay in xusend state over whitespace */ }
+<xusend>{other} |
+<xusend>{xustop1} |
+<xusend><<EOF>> {
+ /* no UESCAPE after the quote, throw back everything */
+ yyless(0);
BEGIN(INITIAL);
yylval->str = litbuf_udeescape('\\', yyscanner);
return SCONST;
}
-<xus>{xusstop2} {
+<xusend>{xustop2} {
+ /* found UESCAPE after the end quote */
BEGIN(INITIAL);
+ if (!check_uescapechar(yytext[yyleng-2]))
+ {
+ SET_YYLLOC();
+ ADVANCE_YYLLOC(yyleng-2);
+ yyerror("invalid Unicode escape character");
+ }
yylval->str = litbuf_udeescape(yytext[yyleng-2], yyscanner);
return SCONST;
}
@@ -707,29 +732,49 @@ other .
yylval->str = ident;
return IDENT;
}
-<xui>{xuistop1} {
- char *ident;
+<xui>{dquote} {
+ yyless(1);
+ /* xuiend state looks for possible UESCAPE */
+ BEGIN(xuiend);
+ }
+<xuiend>{whitespace} { /* stay in xuiend state over whitespace */ }
+<xuiend>{other} |
+<xuiend>{xustop1} |
+<xuiend><<EOF>> {
+ /* no UESCAPE after the quote, throw back everything */
+ char *ident;
+ int identlen;
+
+ yyless(0);
BEGIN(INITIAL);
if (yyextra->literallen == 0)
yyerror("zero-length delimited identifier");
ident = litbuf_udeescape('\\', yyscanner);
- if (yyextra->literallen >= NAMEDATALEN)
- truncate_identifier(ident, yyextra->literallen, true);
+ identlen = strlen(ident);
+ if (identlen >= NAMEDATALEN)
+ truncate_identifier(ident, identlen, true);
yylval->str = ident;
- /* throw back all but the quote */
- yyless(1);
return IDENT;
}
-<xui>{xuistop2} {
- char *ident;
+<xuiend>{xustop2} {
+ /* found UESCAPE after the end quote */
+ char *ident;
+ int identlen;
BEGIN(INITIAL);
if (yyextra->literallen == 0)
yyerror("zero-length delimited identifier");
+ if (!check_uescapechar(yytext[yyleng-2]))
+ {
+ SET_YYLLOC();
+ ADVANCE_YYLLOC(yyleng-2);
+ yyerror("invalid Unicode escape character");
+ }
ident = litbuf_udeescape(yytext[yyleng - 2], yyscanner);
- if (yyextra->literallen >= NAMEDATALEN)
- truncate_identifier(ident, yyextra->literallen, true);
+ identlen = strlen(ident);
+ if (identlen >= NAMEDATALEN)
+ truncate_identifier(ident, identlen, true);
yylval->str = ident;
return IDENT;
}
@@ -1211,22 +1256,29 @@ addunicode(pg_wchar c, core_yyscan_t yyscanner)
addlit(buf, pg_mblen(buf), yyscanner);
}
-static char *
-litbuf_udeescape(unsigned char escape, core_yyscan_t yyscanner)
+/* is 'escape' acceptable as Unicode escape character (UESCAPE syntax) ? */
+static bool
+check_uescapechar(unsigned char escape)
{
- char *new;
- char *litbuf, *in, *out;
- pg_wchar pair_first = 0;
-
if (isxdigit(escape)
|| escape == '+'
|| escape == '\''
|| escape == '"'
|| scanner_isspace(escape))
{
- ADVANCE_YYLLOC(yyextra->literallen + yyleng + 1);
- yyerror("invalid Unicode escape character");
+ return false;
}
+ else
+ return true;
+}
+
+/* like litbufdup, but handle unicode escapes */
+static char *
+litbuf_udeescape(unsigned char escape, core_yyscan_t yyscanner)
+{
+ char *new;
+ char *litbuf, *in, *out;
+ pg_wchar pair_first = 0;
/* Make literalbuf null-terminated to simplify the scanning loop */
litbuf = yyextra->literalbuf;
diff --git a/src/rewrite/pool_timestamp.c b/src/rewrite/pool_timestamp.c
index f1e8104..aa99fc8 100644
--- a/src/rewrite/pool_timestamp.c
+++ b/src/rewrite/pool_timestamp.c
@@ -1180,7 +1180,7 @@ bool
{
RangeFunction *rf = (RangeFunction *) node;
- if (walker(rf->funccallnode, context))
+ if (walker(rf->functions, context))
return true;
if (walker(rf->alias, context))
return true;
diff --git a/src/utils/psprintf.c b/src/utils/psprintf.c
new file mode 100644
index 0000000..9df8f72
--- /dev/null
+++ b/src/utils/psprintf.c
@@ -0,0 +1,194 @@
+/*-------------------------------------------------------------------------
+ *
+ * psprintf.c
+ * sprintf into an allocated-on-demand buffer
+ *
+ *
+ * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/common/psprintf.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+//#ifndef FRONTEND
+
+//#include "postgres.h"
+#include <errno.h>
+#include <stdarg.h>
+#include "pool.h"
+#include "utils/elog.h"
+#include "utils/palloc.h"
+#include "utils/memutils.h"
+
+//#else
+
+//#include "postgres_fe.h"
+
+/* It's possible we could use a different value for this in frontend code */
+//#define MaxAllocSize ((Size) 0x3fffffff) /* 1 gigabyte - 1 */
+
+//#endif
+
+
+/*
+ * psprintf
+ *
+ * Format text data under the control of fmt (an sprintf-style format string)
+ * and return it in an allocated-on-demand buffer. The buffer is allocated
+ * with palloc in the backend, or malloc in frontend builds. Caller is
+ * responsible to free the buffer when no longer needed, if appropriate.
+ *
+ * Errors are not returned to the caller, but are reported via elog(ERROR)
+ * in the backend, or printf-to-stderr-and-exit() in frontend builds.
+ * One should therefore think twice about using this in libpq.
+ */
+char *
+psprintf(const char *fmt,...)
+{
+ size_t len = 128; /* initial assumption about buffer size */
+
+ for (;;)
+ {
+ char *result;
+ va_list args;
+ size_t newlen;
+
+ /*
+ * Allocate result buffer. Note that in frontend this maps to malloc
+ * with exit-on-error.
+ */
+ result = (char *) palloc(len);
+
+ /* Try to format the data. */
+ va_start(args, fmt);
+ newlen = pvsnprintf(result, len, fmt, args);
+ va_end(args);
+
+ if (newlen < len)
+ return result; /* success */
+
+ /* Release buffer and loop around to try again with larger len. */
+ pfree(result);
+ len = newlen;
+ }
+}
+
+/*
+ * pvsnprintf
+ *
+ * Attempt to format text data under the control of fmt (an sprintf-style
+ * format string) and insert it into buf (which has length len, len > 0).
+ *
+ * If successful, return the number of bytes emitted, not counting the
+ * trailing zero byte. This will always be strictly less than len.
+ *
+ * If there's not enough space in buf, return an estimate of the buffer size
+ * needed to succeed (this *must* be more than the given len, else callers
+ * might loop infinitely).
+ *
+ * Other error cases do not return, but exit via elog(ERROR) or exit().
+ * Hence, this shouldn't be used inside libpq.
+ *
+ * This function exists mainly to centralize our workarounds for
+ * non-C99-compliant vsnprintf implementations. Generally, any call that
+ * pays any attention to the return value should go through here rather
+ * than calling snprintf or vsnprintf directly.
+ *
+ * Note that the semantics of the return value are not exactly C99's.
+ * First, we don't promise that the estimated buffer size is exactly right;
+ * callers must be prepared to loop multiple times to get the right size.
+ * Second, we return the recommended buffer size, not one less than that;
+ * this lets overflow concerns be handled here rather than in the callers.
+ */
+size_t
+pvsnprintf(char *buf, size_t len, const char *fmt, va_list args)
+{
+ int nprinted;
+
+ Assert(len > 0);
+
+ errno = 0;
+
+ /*
+ * Assert check here is to catch buggy vsnprintf that overruns the
+ * specified buffer length. Solaris 7 in 64-bit mode is an example of a
+ * platform with such a bug.
+ */
+#ifdef USE_ASSERT_CHECKING
+ buf[len - 1] = '\0';
+#endif
+
+ nprinted = vsnprintf(buf, len, fmt, args);
+
+ Assert(buf[len - 1] == '\0');
+
+ /*
+ * If vsnprintf reports an error other than ENOMEM, fail. The possible
+ * causes of this are not user-facing errors, so elog should be enough.
+ */
+ if (nprinted < 0 && errno != 0 && errno != ENOMEM)
+ {
+#ifndef FRONTEND
+ elog(ERROR, "vsnprintf failed: %m");
+#else
+ fprintf(stderr, "vsnprintf failed: %s\n", strerror(errno));
+ exit(EXIT_FAILURE);
+#endif
+ }
+
+ /*
+ * Note: some versions of vsnprintf return the number of chars actually
+ * stored, not the total space needed as C99 specifies. And at least one
+ * returns -1 on failure. Be conservative about believing whether the
+ * print worked.
+ */
+ if (nprinted >= 0 && (size_t) nprinted < len - 1)
+ {
+ /* Success. Note nprinted does not include trailing null. */
+ return (size_t) nprinted;
+ }
+
+ if (nprinted >= 0 && (size_t) nprinted > len)
+ {
+ /*
+ * This appears to be a C99-compliant vsnprintf, so believe its
+ * estimate of the required space. (If it's wrong, the logic will
+ * still work, but we may loop multiple times.) Note that the space
+ * needed should be only nprinted+1 bytes, but we'd better allocate
+ * one more than that so that the test above will succeed next time.
+ *
+ * In the corner case where the required space just barely overflows,
+ * fall through so that we'll error out below (possibly after
+ * looping).
+ */
+ if ((size_t) nprinted <= MaxAllocSize - 2)
+ return nprinted + 2;
+ }
+
+ /*
+ * Buffer overrun, and we don't know how much space is needed. Estimate
+ * twice the previous buffer size, but not more than MaxAllocSize; if we
+ * are already at MaxAllocSize, choke. Note we use this palloc-oriented
+ * overflow limit even when in frontend.
+ */
+ if (len >= MaxAllocSize)
+ {
+#ifndef FRONTEND
+ ereport(ERROR,
+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+ errmsg("out of memory")));
+#else
+ fprintf(stderr, _("out of memory\n"));
+ exit(EXIT_FAILURE);
+#endif
+ }
+
+ if (len >= MaxAllocSize / 2)
+ return MaxAllocSize;
+
+ return len * 2;
+}
More information about the pgpool-hackers
mailing list