should be it

This commit is contained in:
2025-10-24 19:21:19 -05:00
parent a4b23fc57c
commit f09560c7b1
14047 changed files with 3161551 additions and 1 deletions

View File

@@ -0,0 +1,33 @@
cmake_minimum_required(VERSION 3.5...3.29)
project(duckdb_pg_query CXX C)
if(POLICY CMP0063)
cmake_policy(SET CMP0063 NEW)
endif()
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
add_library(duckdb_pg_query STATIC
postgres_parser.cpp
pg_functions.cpp
src_backend_parser_parser.cpp
src_backend_parser_gram.cpp
src_backend_nodes_list.cpp
src_backend_parser_scansup.cpp
src_backend_nodes_makefuncs.cpp
src_backend_nodes_value.cpp
src_backend_parser_scan.cpp
src_common_keywords.cpp)
target_include_directories(
duckdb_pg_query
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
set_target_properties(duckdb_pg_query PROPERTIES EXPORT_NAME duckdb_duckdb_pg_query)
install(TARGETS duckdb_pg_query
EXPORT "${DUCKDB_EXPORT_SET}"
LIBRARY DESTINATION "${INSTALL_LIB_DIR}"
ARCHIVE DESTINATION "${INSTALL_LIB_DIR}")
disable_target_warnings(duckdb_pg_query)
set_target_properties(duckdb_pg_query PROPERTIES POSITION_INDEPENDENT_CODE ON)

View File

@@ -0,0 +1,28 @@
Copyright (c) 2015, Lukas Fittl <lukas@fittl.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of pg_query nor the names of its contributors may be used
to endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,133 @@
# Modified Postgres Parser
This directory holds the core parser that is used by DuckDB. It is based on the [Postgres parser](https://github.com/pganalyze/libpg_query), but has been stripped down and generally cleaned up to make it easier to modify and extend.
The most important changes made are listed here:
* The output format has been changed to C++
* The parser and all its auxiliary structures are wrapped in the `duckdb_libpgquery` namespace.
* The parser has been split up into multiple different files instead of living in one big file.
* Duplication is reduced and code is simplified by e.g. not requiring the same keyword or statement to be declared in multiple different places.
# Compiling the Parser
The parser is converted to C++ using flex/bison. It is usually run on a Macbook, and has been tested with the following versions of flex/bison:
```bash
yac --flex 2.5.35 Apple(flex-32)
bison (GNU Bison) 2.3
```
In order to compile the grammar, run the following command:
```bash
python3 scripts/generate_grammar.py
```
Depending on how you installed bison, you may need to pass `--bison=/usr/bin/bison` to the above command.
In order to compile the lexer, run the following command:
```bash
python3 scripts/generate_flex.py
```
# Modifying the Grammar
In order to modify the grammar, you will generally need to change files in the `third_party/libpg_query/grammar` directory.
The grammar is divided in separate files in the `statements` directory. The bulk of the grammar (expressions, types, etc) are found in the `select.y` file. This is likely the file you will want to edit.
### Short Bison Intro
Bison is defined in terms of rules. Each rule defines a *return type*. The return types of the rules should be defined in the corresponding `.yh` file (for example, for the `select.y`, the return types are defined in `third_party/libpg_query/grammar/types/select.yh`).
Rules generally reference other rules using the grammar. Each rule contains inline C code. The C code describes how to compose the result objects from the grammar.
The result objects are primarily defined in `third_party/libpg_query/include/nodes/parsenodes.hpp`, and are mostly taken over from Postgres. The parse nodes are converted into DuckDB's internal representation in the Transformer phase.
As an example, let's look at a rule:
### Rule Example
```yacc
from_list:
table_ref { $$ = list_make1($1); }
| from_list ',' table_ref { $$ = lappend($1, $3); }
;
```
We see here the rule with the name `from_list`. This describes the list of tables found in the FROM clause of a SELECT statement.
Rules can be composed using a chain of one or more OR statements (`|`). The rule can be satisfied using either section of the OR statement.
As we see, the rules can also be recursive. In this case, we can have as many table references as we like. For example, the following are all valid SQL:
```sql
SELECT * FROM a;
SELECT * FROM a, b;
SELECT * FROM a, b, c, d, e, f;
```
Recursive statements are generally used to generate lists. The recursion happens on the left side, and a new list is created in the left-most element.
Note that in the generated C code we see two special symbols: `$$` and `$1`. `$$` is the *return value* of the rule. The `$1, $2, $3, etc` symbols refer to the sub-rules.
For example, in this part of the statement:
```yacc
from_list ',' table_ref { $$ = lappend($1, $3); }
```
We are really saying: take the return value of `from_list` (a list) and the return value of `table_ref` (a node) and append it to the list. That list then becomes the return value. Note that we use `$3` to refer to `table_ref`. That is because the second rule (`$2`) is actually the comma in the middle.
`list_make1` and `lappend` are regular C functions defined by Postgres (see `third_party/libpg_query/include/nodes/pg_list.hpp`).
### Return Values
As stated before, rules have return values. The return values must be defined in the corresponding `.yh` files. For example, for `select.y`, the corresponding `.yh` file is `third_party/libpg_query/grammar/types/select.yh`.
We can find the following type definitions there for our previous example:
```yacc
%type <list> from_list
%type <node> table_ref
```
The names given here correspond to C objects and are defined in `third_party/libpg_query/grammar/grammar.y`.
```c
%union
{
...
PGList *list;
PGNode *node;
...
};
```
Most rules return either a `PGNode` (which is the parent class of almost all parse nodes), or a `PGList` (generally a list of nodes). Other common return values are `ival`, `str`, `boolean` and `value`.
### Adding a Keyword
Keywords are defined in the various keyword lists in `third_party/libpg_query/grammar/keywords`.
```
unreserved_keywords.list
column_name_keywords.list
func_name_keywords.list
type_name_keywords.list
reserved_keywords.list
```
The list in which you add a keyword determines where the keyword can be used.
It is heavily preferred that keywords are added to the `unreserved_keywords.list`. Keywords added to this list can still be used as column names, type names and function names by users of the system.
The `reserved_keywords.list` on the other hand heavily restricts the usage of the specific keyword. It should only be used if there is no other option, as reserved keywords can break people's code.
The other lists exist for keywords that are not *entirely* reserved, but are partially reserved.
* A keyword in `column_name_keywords.list` can be used as a column name.
* A keyword in `func_name_keywords.list` can be used as a function name.
* A keyword in `type_name_keywords.list` can be used as a type name.
Note that these lists are not mutually exclusive. A keyword can be added to *both* `column_name_keywords.list` and `func_name_keywords.list`.
Adding a keyword to all three of these lists is equivalent to adding an unreserved keyword (and hence the keyword should just be added there).
### Adding a Statement Type
A new statement type can be defined by creating two new files (`new_statement.y` and `new_statement.yh`), and adding the top-level statement to the list of statements (`third_party/libpg_query/grammar/statements.list`).
As an example, it is recommended to look at the PragmaStmt (`pragma.y`).
# Modifying the Lexer
The lexer file is provided in `third_party/libpg_query/scan.l`. After changing the lexer, run `python3 scripts/generate_flex.py`.

View File

@@ -0,0 +1,756 @@
/*
* The signature of this function is required by bison. However, we
* ignore the passed yylloc and instead use the last token position
* available from the scanner.
*/
static void
base_yyerror(YYLTYPE *yylloc, core_yyscan_t yyscanner, const char *msg)
{
parser_yyerror(msg);
}
static PGRawStmt *
makeRawStmt(PGNode *stmt, int stmt_location)
{
PGRawStmt *rs = makeNode(PGRawStmt);
rs->stmt = stmt;
rs->stmt_location = stmt_location;
rs->stmt_len = 0; /* might get changed later */
return rs;
}
/* Adjust a PGRawStmt to reflect that it doesn't run to the end of the string */
static void
updateRawStmtEnd(PGRawStmt *rs, int end_location)
{
/*
* If we already set the length, don't change it. This is for situations
* like "select foo ;; select bar" where the same statement will be last
* in the string for more than one semicolon.
*/
if (rs->stmt_len > 0)
return;
/* OK, update length of PGRawStmt */
rs->stmt_len = end_location - rs->stmt_location;
}
static PGNode *
makeColumnRef(char *colname, PGList *indirection,
int location, core_yyscan_t yyscanner)
{
/*
* Generate a PGColumnRef node, with an PGAIndirection node added if there
* is any subscripting in the specified indirection list. However,
* any field selection at the start of the indirection list must be
* transposed into the "fields" part of the PGColumnRef node.
*/
PGColumnRef *c = makeNode(PGColumnRef);
int nfields = 0;
PGListCell *l;
c->location = location;
foreach(l, indirection)
{
if (IsA(lfirst(l), PGAIndices))
{
PGAIndirection *i = makeNode(PGAIndirection);
if (nfields == 0)
{
/* easy case - all indirection goes to PGAIndirection */
c->fields = list_make1(makeString(colname));
i->indirection = check_indirection(indirection, yyscanner);
}
else
{
/* got to split the list in two */
i->indirection = check_indirection(list_copy_tail(indirection,
nfields),
yyscanner);
indirection = list_truncate(indirection, nfields);
c->fields = lcons(makeString(colname), indirection);
}
i->arg = (PGNode *) c;
return (PGNode *) i;
}
else if (IsA(lfirst(l), PGAStar))
{
/* We only allow '*' at the end of a PGColumnRef */
if (lnext(l) != NULL)
parser_yyerror("improper use of \"*\"");
}
nfields++;
}
/* No subscripting, so all indirection gets added to field list */
c->fields = lcons(makeString(colname), indirection);
return (PGNode *) c;
}
static PGNode *
makeTypeCast(PGNode *arg, PGTypeName *tpname, int trycast, int location)
{
PGTypeCast *n = makeNode(PGTypeCast);
n->arg = arg;
n->typeName = tpname;
n->tryCast = trycast;
n->location = location;
return (PGNode *) n;
}
static PGNode *
makeStringConst(const char *str, int location)
{
PGAConst *n = makeNode(PGAConst);
n->val.type = T_PGString;
n->val.val.str = (char *) str;
n->location = location;
return (PGNode *)n;
}
static PGNode *
makeStringConstCast(const char *str, int location, PGTypeName *tpname)
{
PGNode *s = makeStringConst(str, location);
return makeTypeCast(s, tpname, 0, -1);
}
static PGNode *
makeIntervalNode(char *str, int location, PGList *typmods) {
PGIntervalConstant *n = makeNode(PGIntervalConstant);
n->val_type = T_PGString;
n->sval = str;
n->location = location;
n->typmods = typmods;
return (PGNode *)n;
}
static PGNode *
makeIntervalNode(int val, int location, PGList *typmods) {
PGIntervalConstant *n = makeNode(PGIntervalConstant);
n->val_type = T_PGInteger;
n->ival = val;
n->location = location;
n->typmods = typmods;
return (PGNode *)n;
}
static PGNode *
makeIntervalNode(PGNode *arg, int location, PGList *typmods) {
PGIntervalConstant *n = makeNode(PGIntervalConstant);
n->val_type = T_PGAExpr;
n->eval = arg;
n->location = location;
n->typmods = typmods;
return (PGNode *)n;
}
static PGNode *
makeSampleSize(PGNode *sample_size, bool is_percentage) {
PGSampleSize *n = makeNode(PGSampleSize);
n->sample_size = sample_size;
n->is_percentage = is_percentage;
return (PGNode *)n;
}
static PGNode *
makeSampleOptions(PGNode *sample_size, char *method, int *seed, int location) {
PGSampleOptions *n = makeNode(PGSampleOptions);
n->sample_size = sample_size;
n->method = method;
if (seed) {
n->has_seed = true;
n->seed = *seed;
}
n->location = location;
return (PGNode *)n;
}
/* makeLimitPercent()
* Make limit percent node
*/
static PGNode *
makeLimitPercent(PGNode *limit_percent) {
PGLimitPercent *n = makeNode(PGLimitPercent);
n->limit_percent = limit_percent;
return (PGNode *)n;
}
static PGNode *
makeIntConst(int val, int location)
{
PGAConst *n = makeNode(PGAConst);
n->val.type = T_PGInteger;
n->val.val.ival = val;
n->location = location;
return (PGNode *)n;
}
static PGNode *
makeFloatConst(char *str, int location)
{
PGAConst *n = makeNode(PGAConst);
n->val.type = T_PGFloat;
n->val.val.str = str;
n->location = location;
return (PGNode *)n;
}
static PGNode *
makeBitStringConst(char *str, int location)
{
PGAConst *n = makeNode(PGAConst);
n->val.type = T_PGBitString;
n->val.val.str = str;
n->location = location;
return (PGNode *)n;
}
static PGNode *
makeNullAConst(int location)
{
PGAConst *n = makeNode(PGAConst);
n->val.type = T_PGNull;
n->location = location;
return (PGNode *)n;
}
static PGNode *
makeAConst(PGValue *v, int location)
{
PGNode *n;
switch (v->type)
{
case T_PGFloat:
n = makeFloatConst(v->val.str, location);
break;
case T_PGInteger:
n = makeIntConst(v->val.ival, location);
break;
case T_PGString:
default:
n = makeStringConst(v->val.str, location);
break;
}
return n;
}
/* makeBoolAConst()
* Create an PGAConst string node and put it inside a boolean cast.
*/
static PGNode *
makeBoolAConst(bool state, int location)
{
PGAConst *n = makeNode(PGAConst);
n->val.type = T_PGString;
n->val.val.str = (state ? (char*) "t" : (char*) "f");
n->location = location;
return makeTypeCast((PGNode *)n, SystemTypeName("bool"), 0, -1);
}
/* check_qualified_name --- check the result of qualified_name production
*
* It's easiest to let the grammar production for qualified_name allow
* subscripts and '*', which we then must reject here.
*/
static void
check_qualified_name(PGList *names, core_yyscan_t yyscanner)
{
PGListCell *i;
foreach(i, names)
{
if (!IsA(lfirst(i), PGString))
parser_yyerror("syntax error");
}
}
/* check_func_name --- check the result of func_name production
*
* It's easiest to let the grammar production for func_name allow subscripts
* and '*', which we then must reject here.
*/
static PGList *
check_func_name(PGList *names, core_yyscan_t yyscanner)
{
PGListCell *i;
foreach(i, names)
{
if (!IsA(lfirst(i), PGString))
parser_yyerror("syntax error");
}
return names;
}
/* check_indirection --- check the result of indirection production
*
* We only allow '*' at the end of the list, but it's hard to enforce that
* in the grammar, so do it here.
*/
static PGList *
check_indirection(PGList *indirection, core_yyscan_t yyscanner)
{
PGListCell *l;
foreach(l, indirection)
{
if (IsA(lfirst(l), PGAStar))
{
if (lnext(l) != NULL)
parser_yyerror("improper use of \"*\"");
}
}
return indirection;
}
/* makeParamRef
* Creates a new PGParamRef node
*/
static PGNode* makeParamRef(int number, int location)
{
PGParamRef *p = makeNode(PGParamRef);
p->number = number;
p->location = location;
p->name = NULL;
return (PGNode *) p;
}
/* makeNamedParamRef
* Creates a new PGParamRef node
*/
static PGNode* makeNamedParamRef(char *name, int location)
{
PGParamRef *p = (PGParamRef *)makeParamRef(0, location);
p->name = name;
return (PGNode *) p;
}
/* insertSelectOptions()
* Insert ORDER BY, etc into an already-constructed SelectStmt.
*
* This routine is just to avoid duplicating code in PGSelectStmt productions.
*/
static void
insertSelectOptions(PGSelectStmt *stmt,
PGList *sortClause, PGList *lockingClause,
PGNode *limitOffset, PGNode *limitCount, PGNode *isLimitOffsetFirst,
PGWithClause *withClause,
core_yyscan_t yyscanner)
{
if (stmt->type != T_PGSelectStmt) {
ereport(ERROR,
(errcode(PG_ERRCODE_SYNTAX_ERROR),
errmsg("DESCRIBE/SHOW/SUMMARIZE with CTE/ORDER BY/... not allowed - wrap the statement in a subquery instead"),
parser_errposition(exprLocation((PGNode *) stmt))));
}
Assert(IsA(stmt, PGSelectStmt));
/*
* Tests here are to reject constructs like
* (SELECT foo ORDER BY bar) ORDER BY baz
*/
if (sortClause)
{
if (stmt->sortClause)
ereport(ERROR,
(errcode(PG_ERRCODE_SYNTAX_ERROR),
errmsg("multiple ORDER BY clauses not allowed"),
parser_errposition(exprLocation((PGNode *) sortClause))));
stmt->sortClause = sortClause;
}
/* We can handle multiple locking clauses, though */
stmt->lockingClause = list_concat(stmt->lockingClause, lockingClause);
if (limitOffset)
{
if (stmt->limitOffset)
ereport(ERROR,
(errcode(PG_ERRCODE_SYNTAX_ERROR),
errmsg("multiple OFFSET clauses not allowed"),
parser_errposition(exprLocation(limitOffset))));
stmt->limitOffset = limitOffset;
}
if (limitCount)
{
if (stmt->limitCount)
ereport(ERROR,
(errcode(PG_ERRCODE_SYNTAX_ERROR),
errmsg("multiple LIMIT clauses not allowed"),
parser_errposition(exprLocation(limitCount))));
stmt->limitCount = limitCount;
}
if (limitOffset == isLimitOffsetFirst) {
stmt->offset_first = true;
}
if (withClause)
{
if (stmt->withClause)
ereport(ERROR,
(errcode(PG_ERRCODE_SYNTAX_ERROR),
errmsg("multiple WITH clauses not allowed"),
parser_errposition(exprLocation((PGNode *) withClause))));
stmt->withClause = withClause;
}
}
static PGNode *
makeSetOp(PGSetOperation op, bool all, PGNode *larg, PGNode *rarg)
{
PGSelectStmt *n = makeNode(PGSelectStmt);
n->op = op;
n->all = all;
n->larg = larg;
n->rarg = rarg;
return (PGNode *) n;
}
/* SystemFuncName()
* Build a properly-qualified reference to a built-in function.
*/
PGList *
SystemFuncName(const char *name)
{
return list_make2(makeString(DEFAULT_SCHEMA), makeString(name));
}
/* SystemTypeName()
* Build a properly-qualified reference to a built-in type.
*
* typmod is defaulted, but may be changed afterwards by caller.
* Likewise for the location.
*/
PGTypeName *
SystemTypeName(const char *name)
{
return makeTypeNameFromNameList(list_make1(makeString(name)));
}
/* doNegate()
* Handle negation of a numeric constant.
*
* Formerly, we did this here because the optimizer couldn't cope with
* indexquals that looked like "var = -4" --- it wants "var = const"
* and a unary minus operator applied to a constant didn't qualify.
* As of Postgres 7.0, that problem doesn't exist anymore because there
* is a constant-subexpression simplifier in the optimizer. However,
* there's still a good reason for doing this here, which is that we can
* postpone committing to a particular internal representation for simple
* negative constants. It's better to leave "-123.456" in string form
* until we know what the desired type is.
*/
static PGNode *
doNegate(PGNode *n, int location)
{
if (IsA(n, PGAConst))
{
PGAConst *con = (PGAConst *)n;
/* report the constant's location as that of the '-' sign */
con->location = location;
if (con->val.type == T_PGInteger)
{
con->val.val.ival = -con->val.val.ival;
return n;
}
if (con->val.type == T_PGFloat)
{
doNegateFloat(&con->val);
return n;
}
}
return (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "-", NULL, n, location);
}
static void
doNegateFloat(PGValue *v)
{
char *oldval = v->val.str;
Assert(IsA(v, PGFloat));
if (*oldval == '+')
oldval++;
if (*oldval == '-')
v->val.str = oldval+1; /* just strip the '-' */
else
v->val.str = psprintf("-%s", oldval);
}
static PGNode *
makeAndExpr(PGNode *lexpr, PGNode *rexpr, int location)
{
PGNode *lexp = lexpr;
/* Look through AEXPR_PAREN nodes so they don't affect flattening */
while (IsA(lexp, PGAExpr) &&
((PGAExpr *) lexp)->kind == AEXPR_PAREN)
lexp = ((PGAExpr *) lexp)->lexpr;
/* Flatten "a AND b AND c ..." to a single PGBoolExpr on sight */
if (IsA(lexp, PGBoolExpr))
{
PGBoolExpr *blexpr = (PGBoolExpr *) lexp;
if (blexpr->boolop == PG_AND_EXPR)
{
blexpr->args = lappend(blexpr->args, rexpr);
return (PGNode *) blexpr;
}
}
return (PGNode *) makeBoolExpr(PG_AND_EXPR, list_make2(lexpr, rexpr), location);
}
static PGNode *
makeOrExpr(PGNode *lexpr, PGNode *rexpr, int location)
{
PGNode *lexp = lexpr;
/* Look through AEXPR_PAREN nodes so they don't affect flattening */
while (IsA(lexp, PGAExpr) &&
((PGAExpr *) lexp)->kind == AEXPR_PAREN)
lexp = ((PGAExpr *) lexp)->lexpr;
/* Flatten "a OR b OR c ..." to a single PGBoolExpr on sight */
if (IsA(lexp, PGBoolExpr))
{
PGBoolExpr *blexpr = (PGBoolExpr *) lexp;
if (blexpr->boolop == PG_OR_EXPR)
{
blexpr->args = lappend(blexpr->args, rexpr);
return (PGNode *) blexpr;
}
}
return (PGNode *) makeBoolExpr(PG_OR_EXPR, list_make2(lexpr, rexpr), location);
}
static PGNode *
makeNotExpr(PGNode *expr, int location)
{
return (PGNode *) makeBoolExpr(PG_NOT_EXPR, list_make1(expr), location);
}
/* Separate PGConstraint nodes from COLLATE clauses in a */
static void
SplitColQualList(PGList *qualList,
PGList **constraintList, PGCollateClause **collClause,
core_yyscan_t yyscanner)
{
PGListCell *cell;
PGListCell *prev;
PGListCell *next;
*collClause = NULL;
prev = NULL;
for (cell = list_head(qualList); cell; cell = next)
{
PGNode *n = (PGNode *) lfirst(cell);
next = lnext(cell);
if (IsA(n, PGConstraint))
{
/* keep it in list */
prev = cell;
continue;
}
if (IsA(n, PGCollateClause))
{
PGCollateClause *c = (PGCollateClause *) n;
if (*collClause)
ereport(ERROR,
(errcode(PG_ERRCODE_SYNTAX_ERROR),
errmsg("multiple COLLATE clauses not allowed"),
parser_errposition(c->location)));
*collClause = c;
}
else
elog(ERROR, "unexpected node type %d", (int) n->type);
/* remove non-Constraint nodes from qualList */
qualList = list_delete_cell(qualList, cell, prev);
}
*constraintList = qualList;
}
/*
* Process result of ConstraintAttributeSpec, and set appropriate bool flags
* in the output command node. Pass NULL for any flags the particular
* command doesn't support.
*/
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)
{
/* defaults */
if (deferrable)
*deferrable = false;
if (initdeferred)
*initdeferred = false;
if (not_valid)
*not_valid = false;
if (cas_bits & (CAS_DEFERRABLE | CAS_INITIALLY_DEFERRED))
{
if (deferrable)
*deferrable = true;
else
ereport(ERROR,
(errcode(PG_ERRCODE_FEATURE_NOT_SUPPORTED),
/* translator: %s is CHECK, UNIQUE, or similar */
errmsg("%s constraints cannot be marked DEFERRABLE",
constrType),
parser_errposition(location)));
}
if (cas_bits & CAS_INITIALLY_DEFERRED)
{
if (initdeferred)
*initdeferred = true;
else
ereport(ERROR,
(errcode(PG_ERRCODE_FEATURE_NOT_SUPPORTED),
/* translator: %s is CHECK, UNIQUE, or similar */
errmsg("%s constraints cannot be marked DEFERRABLE",
constrType),
parser_errposition(location)));
}
if (cas_bits & CAS_NOT_VALID)
{
if (not_valid)
*not_valid = true;
else
ereport(ERROR,
(errcode(PG_ERRCODE_FEATURE_NOT_SUPPORTED),
/* translator: %s is CHECK, UNIQUE, or similar */
errmsg("%s constraints cannot be marked NOT VALID",
constrType),
parser_errposition(location)));
}
if (cas_bits & CAS_NO_INHERIT)
{
if (no_inherit)
*no_inherit = true;
else
ereport(ERROR,
(errcode(PG_ERRCODE_FEATURE_NOT_SUPPORTED),
/* translator: %s is CHECK, UNIQUE, or similar */
errmsg("%s constraints cannot be marked NO INHERIT",
constrType),
parser_errposition(location)));
}
}
/*----------
* 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 as the query.
* ----------
*/
static PGNode *
makeRecursiveViewSelect(char *relname, PGList *aliases, PGNode *query)
{
PGSelectStmt *s = makeNode(PGSelectStmt);
PGWithClause *w = makeNode(PGWithClause);
PGCommonTableExpr *cte = makeNode(PGCommonTableExpr);
PGList *tl = NIL;
PGListCell *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)
{
PGResTarget *rt = makeNode(PGResTarget);
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 (PGNode *) s;
}
/* parser_init()
* Initialize to parse one query string
*/
void
parser_init(base_yy_extra_type *yyext)
{
yyext->parsetree = NIL; /* in case grammar forgets to set it */
}
#undef yyparse
#undef yylex
#undef yyerror
#undef yylval
#undef yychar
#undef yydebug
#undef yynerrs
#undef yylloc
} // namespace duckdb_libpgquery

View File

@@ -0,0 +1,216 @@
/*#define YYDEBUG 1*/
/*-------------------------------------------------------------------------
*
* gram.y
* POSTGRESQL BISON rules/actions
*
* Portions Copyright (c) 1996-2017, PostgreSQL Global Development PGGroup
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* src/backend/parser/gram.y
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
* Andrew Yu Sept, 1994 POSTQUEL to SQL conversion
* Andrew Yu Oct, 1994 lispy code conversion
*
* NOTES
* CAPITALS are used to represent terminal symbols.
* non-capitals are used to represent non-terminals.
*
* In general, nothing in this file should initiate database accesses
* nor depend on changeable state (such as SET variables). If you do
* database accesses, your code will fail when we have aborted the
* current transaction and are just parsing commands to find the next
* ROLLBACK or COMMIT. If you make use of SET variables, then you
* will do the wrong thing in multi-query strings like this:
* SET constraint_exclusion TO off; SELECT * FROM foo;
* because the entire string is parsed by gram.y before the SET gets
* executed. Anything that depends on the database or changeable state
* should be handled during parse analysis so that it happens at the
* right time not the wrong time.
*
* WARNINGS
* If you use a list, make sure the datum is a node so that the printing
* routines work.
*
* Sometimes we assign constants to makeStrings. Make sure we don't free
* those.
*
*-------------------------------------------------------------------------
*/
#include "pg_functions.hpp"
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include "nodes/makefuncs.hpp"
#include "nodes/nodeFuncs.hpp"
#include "parser/gramparse.hpp"
#include "parser/parser.hpp"
#include "utils/datetime.hpp"
namespace duckdb_libpgquery {
#define DEFAULT_SCHEMA "main"
/*
* 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) > 0) \
(Current) = (Rhs)[1]; \
else \
(Current) = (-1); \
} while (0)
/*
* The above macro assigns -1 (unknown) as the parse location of any
* nonterminal that was reduced from an empty rule, or whose leftmost
* component 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.)
*
* A cleaner answer would be to make YYLLOC_DEFAULT scan all the Rhs
* locations until it's found one that's not -1. Then we'd get a correct
* location for any nonterminal that isn't entirely empty. But this way
* would add overhead to every rule reduction, and so far there's not been
* a compelling reason to pay that overhead.
*/
/*
* 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
* bison >= 2.0. However, in bison 1.875 the default is to use alloca()
* if possible, so there's not really much problem anyhow, at least if
* you're building with gcc.
*/
#define YYMALLOC palloc
#define YYFREE pfree
#define YYINITDEPTH 1000
/* yields an integer bitmask of these flags: */
#define CAS_NOT_DEFERRABLE 0x01
#define CAS_DEFERRABLE 0x02
#define CAS_INITIALLY_IMMEDIATE 0x04
#define CAS_INITIALLY_DEFERRED 0x08
#define CAS_NOT_VALID 0x10
#define CAS_NO_INHERIT 0x20
#define parser_yyerror(msg) scanner_yyerror(msg, yyscanner)
#define parser_errposition(pos) scanner_errposition(pos, yyscanner)
#if YYBISON == 1
// explicitly define stack growing support
// yacc cannot handle stack growing by default YYLTYPE is overriden - which the Postgres parser overrides with an `int`
// so we need to copy these definitions here explicitly
/* A type that is properly aligned for any stack member. */
union yyalloc
{
short int yyss;
YYSTYPE yyvs;
YYLTYPE yyls;
};
/* The size of the maximum gap between one aligned stack and the next. */
# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
/* The size of an array large to enough to hold all stacks, each with
N elements. */
# define YYSTACK_BYTES(N) \
((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \
+ 2 * YYSTACK_GAP_MAXIMUM)
/* Copy COUNT objects from FROM to TO. The source and destination do
not overlap. */
# ifndef YYCOPY
# if defined __GNUC__ && 1 < __GNUC__
# define YYCOPY(To, From, Count) \
__builtin_memcpy (To, From, (Count) * sizeof (*(From)))
# else
# define YYCOPY(To, From, Count) \
do \
{ \
YYSIZE_T yyi; \
for (yyi = 0; yyi < (Count); yyi++) \
(To)[yyi] = (From)[yyi]; \
} \
while (YYID (0))
# endif
# endif
/* Relocate STACK from its old location to the new one. The
local variables YYSIZE and YYSTACKSIZE give the old and new number of
elements in the stack, and YYPTR gives the new location of the
stack. Advance YYPTR to a properly aligned location for the next
stack. */
# define YYSTACK_RELOCATE(Stack) \
do \
{ \
YYSIZE_T yynewbytes; \
YYCOPY (&yyptr->Stack, Stack, yysize); \
Stack = &yyptr->Stack; \
yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
yyptr += yynewbytes / sizeof (*yyptr); \
} \
while (YYID (0))
#endif
static void base_yyerror(YYLTYPE *yylloc, core_yyscan_t yyscanner,
const char *msg);
static PGRawStmt *makeRawStmt(PGNode *stmt, int stmt_location);
static void updateRawStmtEnd(PGRawStmt *rs, int end_location);
static PGNode *makeColumnRef(char *colname, PGList *indirection,
int location, core_yyscan_t yyscanner);
static PGNode *makeTypeCast(PGNode *arg, PGTypeName *tpname, int trycast, int location);
static PGNode *makeStringConst(const char *str, int location);
static PGNode *makeStringConstCast(const char *str, int location, PGTypeName *tpname);
static PGNode *makeIntervalNode(char *str, int location, PGList *typmods);
static PGNode *makeIntervalNode(int val, int location, PGList *typmods);
static PGNode *makeIntervalNode(PGNode *arg, int location, PGList *typmods);
static PGNode *makeSampleSize(PGNode *sample_size, bool is_percentage);
static PGNode *makeSampleOptions(PGNode *sample_size, char *method, int *seed, int location);
static PGNode *makeIntConst(int val, int location);
static PGNode *makeFloatConst(char *str, int location);
static PGNode *makeBitStringConst(char *str, int location);
static PGNode *makeNullAConst(int location);
static PGNode *makeAConst(PGValue *v, int location);
static PGNode *makeBoolAConst(bool state, int location);
static PGNode *makeParamRef(int number, int location);
static PGNode *makeNamedParamRef(char* name, int location);
static void check_qualified_name(PGList *names, core_yyscan_t yyscanner);
static PGList *check_func_name(PGList *names, core_yyscan_t yyscanner);
static PGList *check_indirection(PGList *indirection, core_yyscan_t yyscanner);
static void insertSelectOptions(PGSelectStmt *stmt,
PGList *sortClause, PGList *lockingClause,
PGNode *limitOffset, PGNode *limitCount, PGNode *isLimitOffsetFirst,
PGWithClause *withClause,
core_yyscan_t yyscanner);
static PGNode *makeSetOp(PGSetOperation op, bool all, PGNode *larg, PGNode *rarg);
static PGNode *doNegate(PGNode *n, int location);
static void doNegateFloat(PGValue *v);
static PGNode *makeAndExpr(PGNode *lexpr, PGNode *rexpr, int location);
static PGNode *makeOrExpr(PGNode *lexpr, PGNode *rexpr, int location);
static PGNode *makeNotExpr(PGNode *expr, int location);
static void SplitColQualList(PGList *qualList,
PGList **constraintList, PGCollateClause **collClause,
core_yyscan_t yyscanner);
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 PGNode *makeRecursiveViewSelect(char *relname, PGList *aliases, PGNode *query);
static PGNode *makeLimitPercent(PGNode *limit_percent);

View File

@@ -0,0 +1,223 @@
%{
{{{ GRAMMAR_HEADER }}}
%}
#line 5 "third_party/libpg_query/grammar/grammar.y"
%pure-parser
%expect 0
%name-prefix="base_yy"
%locations
%parse-param {core_yyscan_t yyscanner}
%lex-param {core_yyscan_t yyscanner}
%union
{
core_YYSTYPE core_yystype;
/* these fields must match core_YYSTYPE: */
int ival;
char *str;
const char *keyword;
const char *conststr;
char chr;
bool boolean;
PGJoinType jtype;
PGDropBehavior dbehavior;
PGOnCommitAction oncommit;
PGOnCreateConflict oncreateconflict;
PGList *list;
PGNode *node;
PGValue *value;
PGObjectType objtype;
PGTypeName *typnam;
PGObjectWithArgs *objwithargs;
PGDefElem *defelt;
PGSortBy *sortby;
PGWindowDef *windef;
PGJoinExpr *jexpr;
PGIndexElem *ielem;
PGAlias *alias;
PGRangeVar *range;
PGIntoClause *into;
PGCTEMaterialize ctematerialize;
PGWithClause *with;
PGInferClause *infer;
PGOnConflictClause *onconflict;
PGOnConflictActionAlias onconflictshorthand;
PGAIndices *aind;
PGResTarget *target;
PGInsertStmt *istmt;
PGVariableSetStmt *vsetstmt;
PGOverridingKind override;
PGSortByDir sortorder;
PGSortByNulls nullorder;
PGIgnoreNulls ignorenulls;
PGConstrType constr;
PGLockClauseStrength lockstrength;
PGLockWaitPolicy lockwaitpolicy;
PGSubLinkType subquerytype;
PGViewCheckOption viewcheckoption;
PGInsertColumnOrder bynameorposition;
PGLoadInstallType loadinstalltype;
PGTransactionStmtType transactiontype;
PGMergeAction mergeaction;
}
%type <node> stmt
%type <list> stmtblock
%type <list> stmtmulti
{{{ TYPES }}}
/*
* Non-keyword token types. These are hard-wired into the "flex" lexer.
* They must be listed first so that their numeric codes do not depend on
* the set of keywords. PL/pgSQL depends on this so that it can share the
* same lexer. If you add/change tokens here, fix PL/pgSQL to match!
*
* DOT_DOT is unused in the core SQL grammar, and so will always provoke
* parse errors. It is needed by PL/pgSQL.
*/
%token <str> IDENT FCONST SCONST BCONST XCONST Op
%token <ival> ICONST PARAM
%token TYPECAST DOT_DOT COLON_EQUALS EQUALS_GREATER INTEGER_DIVISION POWER_OF SINGLE_ARROW DOUBLE_ARROW SINGLE_COLON
%token LESS_EQUALS GREATER_EQUALS NOT_EQUALS
/*
* If you want to make any keyword changes, update the keyword table in
* src/include/parser/kwlist.h and add new keywords to the appropriate one
* of the reserved-or-not-so-reserved keyword lists, below; search
* this file for "Keyword category lists".
*/
/* ordinary key words in alphabetical order */
{{{ KEYWORDS }}}
/*
* The grammar thinks these are keywords, but they are not in the kwlist.h
* list and so can never be entered directly. The filter in parser.c
* creates these tokens when required (based on looking one token ahead).
*
* NOT_LA exists so that productions such as NOT LIKE can be given the same
* precedence as LIKE; otherwise they'd effectively have the same precedence
* as NOT, at least with respect to their left-hand subexpression.
* NULLS_LA and WITH_LA are needed to make the grammar LALR(1).
*/
%token NOT_LA NULLS_LA WITH_LA
/* Precedence: lowest to highest */
%left SINGLE_COLON
%nonassoc SET /* see */
%left UNION EXCEPT
%left INTERSECT
%left SINGLE_ARROW DOUBLE_ARROW
%left OR
%left AND
%right NOT
%nonassoc IS ISNULL NOTNULL /* IS sets precedence for IS NULL, etc */
%nonassoc '<' '>' '=' LESS_EQUALS GREATER_EQUALS NOT_EQUALS
%nonassoc BETWEEN IN_P GLOB LIKE ILIKE SIMILAR NOT_LA
%nonassoc ESCAPE /* ESCAPE must be just above LIKE/ILIKE/SIMILAR */
%left POSTFIXOP /* dummy for postfix Op rules */
/*
* To support target_el without AS, we must give IDENT an explicit priority
* between POSTFIXOP and Op. We can safely assign the same priority to
* various unreserved keywords as needed to resolve ambiguities (this can't
* have any bad effects since obviously the keywords will still behave the
* same as if they weren't keywords). We need to do this for PARTITION,
* RANGE, ROWS to support opt_existing_window_name; and for RANGE, ROWS
* so that they can follow a_expr without creating postfix-operator problems;
* for GENERATED so that it can follow b_expr;
* and for NULL so that it can follow b_expr in without creating
* postfix-operator problems.
*
* To support CUBE and ROLLUP in GROUP BY without reserving them, we give them
* an explicit priority lower than '(', so that a rule with CUBE '(' will shift
* rather than reducing a conflicting rule that takes CUBE as a function name.
* Using the same precedence as IDENT seems right for the reasons given above.
*
* The frame_bound productions UNBOUNDED PRECEDING and UNBOUNDED FOLLOWING
* are even messier: since UNBOUNDED is an unreserved keyword (per spec!),
* there is no principled way to distinguish these from the productions
* a_expr PRECEDING/FOLLOWING. We hack this up by giving UNBOUNDED slightly
* lower precedence than PRECEDING and FOLLOWING. At present this doesn't
* appear to cause UNBOUNDED to be treated differently from other unreserved
* keywords anywhere else in the grammar, but it's definitely risky. We can
* blame any funny behavior of UNBOUNDED on the SQL standard, though.
*/
%nonassoc UNBOUNDED /* ideally should have same precedence as IDENT */
%nonassoc IDENT GENERATED NULL_P PARTITION RANGE ROWS GROUPS PRECEDING FOLLOWING CUBE ROLLUP ENUM_P
%left Op OPERATOR /* multi-character ops and user-defined operators */
%left '+' '-'
%left '*' '/' '%' INTEGER_DIVISION
%left '^' POWER_OF
/* Unary Operators */
%left AT /* sets precedence for AT TIME ZONE */
%left COLLATE
%right UMINUS
%left '[' ']'
%left '(' ')'
%left TYPECAST
%left '.'
/*
* These might seem to be low-precedence, but actually they are not part
* of the arithmetic hierarchy at all in their use as JOIN operators.
* We make them high-precedence to support their use as function names.
* They wouldn't be given a precedence at all, were it not that we need
* left-associativity among the JOIN rules themselves.
*/
%left JOIN CROSS LEFT FULL RIGHT INNER_P NATURAL POSITIONAL PIVOT UNPIVOT ANTI SEMI ASOF
/* kluge to keep from causing shift/reduce conflicts */
%right PRESERVE STRIP_P IGNORE_P RESPECT_P
%%
/*
* The target production for the whole parse.
*/
stmtblock: stmtmulti
{
pg_yyget_extra(yyscanner)->parsetree = $1;
}
;
/*
* At top level, we wrap each stmt with a PGRawStmt node carrying start location
* and length of the stmt's text. Notice that the start loc/len are driven
* entirely from semicolon locations (@2). It would seem natural to use
* @1 or @3 to get the true start location of a stmt, but that doesn't work
* for statements that can start with empty nonterminals (opt_with_clause is
* the main offender here); as noted in the comments for YYLLOC_DEFAULT,
* we'd get -1 for the location in such cases.
* We also take care to discard empty statements entirely.
*/
stmtmulti: stmtmulti ';' stmt
{
if ($1 != NIL)
{
/* update length of previous stmt */
updateRawStmtEnd(llast_node(PGRawStmt, $1), @2);
}
if ($3 != NULL)
$$ = lappend($1, makeRawStmt($3, @2 + 1));
else
$$ = $1;
}
| stmt
{
if ($1 != NULL)
$$ = list_make1(makeRawStmt($1, 0));
else
$$ = NIL;
}
;
{{{ STATEMENTS }}}
{{{ GRAMMAR RULES }}}
{{{ KEYWORD_DEFINITIONS }}}
%%
{{{ GRAMMAR_SOURCE }}}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,54 @@
BETWEEN
BIGINT
BIT
BOOLEAN_P
CHAR_P
CHARACTER
COALESCE
COLUMNS
DEC
DECIMAL_P
EXISTS
EXTRACT
FLOAT_P
GENERATED
GROUPING
GROUPING_ID
INOUT
INT_P
INTEGER
INTERVAL
MAP
NATIONAL
NCHAR
NONE
NULLIF
NUMERIC
OUT_P
OVERLAY
POSITION
PRECISION
REAL
ROW
SETOF
SMALLINT
SUBSTRING
STRUCT
TIME
TIMESTAMP
TREAT
TRIM
TRY_CAST
VALUES
VARCHAR
XMLATTRIBUTES
XMLCONCAT
XMLELEMENT
XMLEXISTS
XMLFOREST
XMLNAMESPACES
XMLPARSE
XMLPI
XMLROOT
XMLSERIALIZE
XMLTABLE

View File

@@ -0,0 +1,29 @@
ASOF
AT
AUTHORIZATION
BINARY
COLLATION
CONCURRENTLY
CROSS
FREEZE
FULL
GENERATED
GLOB
ILIKE
INNER_P
IS
ISNULL
JOIN
LEFT
LIKE
MAP
NATURAL
NOTNULL
OUTER_P
OVERLAPS
POSITIONAL
RIGHT
SIMILAR
STRUCT
TABLESAMPLE
VERBOSE

View File

@@ -0,0 +1,75 @@
ALL
ANALYSE
ANALYZE
AND
ANY
ARRAY
AS
ASC_P
ASYMMETRIC
BOTH
CASE
CAST
CHECK_P
COLLATE
COLUMN
CONSTRAINT
CREATE_P
DEFAULT
DEFERRABLE
DESC_P
DESCRIBE
DISTINCT
DO
ELSE
END_P
EXCEPT
FALSE_P
FETCH
FOR
FOREIGN
FROM
GROUP_P
HAVING
QUALIFY
IN_P
INITIALLY
INTERSECT
INTO
LAMBDA
LATERAL_P
LEADING
LIMIT
NOT
NULL_P
OFFSET
ON
ONLY
OR
ORDER
PIVOT
PIVOT_WIDER
PIVOT_LONGER
PLACING
PRIMARY
REFERENCES
RETURNING
SELECT
SHOW
SOME
SUMMARIZE
SYMMETRIC
TABLE
THEN
TO
TRAILING
TRUE_P
UNION
UNIQUE
UNPIVOT
USING
VARIADIC
WHEN
WHERE
WINDOW
WITH

View File

@@ -0,0 +1,32 @@
ASOF
AT
AUTHORIZATION
BINARY
BY
COLLATION
COLUMNS
CONCURRENTLY
CROSS
FREEZE
FULL
GLOB
ILIKE
INNER_P
IS
ISNULL
JOIN
LEFT
LIKE
NATURAL
NOTNULL
OUTER_P
OVERLAPS
POSITIONAL
RIGHT
UNPACK
SIMILAR
TABLESAMPLE
TRY_CAST
VERBOSE
SEMI
ANTI

View File

@@ -0,0 +1,330 @@
ABORT_P
ABSOLUTE_P
ACCESS
ACTION
ADD_P
ADMIN
AFTER
AGGREGATE
ALSO
ALTER
ALWAYS
ASSERTION
ASSIGNMENT
ATTACH
ATTRIBUTE
BACKWARD
BEFORE
BEGIN_P
CACHE
CALL_P
CALLED
CASCADE
CASCADED
CATALOG_P
CENTURY_P
CENTURIES_P
CHAIN
CHARACTERISTICS
CHECKPOINT
CLASS
CLOSE
CLUSTER
COMMENT
COMMENTS
COMMIT
COMMITTED
COMPRESSION
CONFIGURATION
CONFLICT
CONNECTION
CONSTRAINTS
CONTENT_P
CONTINUE_P
CONVERSION_P
COPY
COST
CSV
CUBE
CURRENT_P
CURSOR
CYCLE
DATA_P
DATABASE
DAY_P
DAYS_P
DEALLOCATE
DECADE_P
DECADES_P
DECLARE
DEFAULTS
DEFERRED
DEFINER
DELETE_P
DELIMITER
DELIMITERS
DEPENDS
DETACH
DICTIONARY
DISABLE_P
DISCARD
DOCUMENT_P
DOMAIN_P
DOUBLE_P
DROP
EACH
ENABLE_P
ENCODING
ENCRYPTED
ENUM_P
ERROR_P
ESCAPE
EVENT
EXCLUDE
EXCLUDING
EXCLUSIVE
EXECUTE
EXPLAIN
EXPORT_P
EXPORT_STATE
EXTENSION
EXTENSIONS
EXTERNAL
FAMILY
FILTER
FIRST_P
FOLLOWING
FORCE
FORWARD
FUNCTION
FUNCTIONS
GLOBAL
GRANT
GRANTED
GROUPS
HANDLER
HEADER_P
HOLD
HOUR_P
HOURS_P
IDENTITY_P
IF_P
IGNORE_P
IMMEDIATE
IMMUTABLE
IMPLICIT_P
IMPORT_P
INCLUDE_P
INCLUDING
INCREMENT
INDEX
INDEXES
INHERIT
INHERITS
INLINE_P
INPUT_P
INSENSITIVE
INSERT
INSTALL
INSTEAD
INVOKER
JSON
ISOLATION
KEY
LABEL
LANGUAGE
LARGE_P
LAST_P
LEAKPROOF
LEVEL
LISTEN
LOAD
LOCAL
LOCATION
LOCK_P
LOCKED
LOGGED
MACRO
MAPPING
MATCH
MATCHED
MATERIALIZED
MAXVALUE
MERGE
METHOD
MICROSECOND_P
MICROSECONDS_P
MILLENNIUM_P
MILLENNIA_P
MILLISECOND_P
MILLISECONDS_P
MINUTE_P
MINUTES_P
MINVALUE
MODE
MONTH_P
MONTHS_P
MOVE
NAME_P
NAMES
NEW
NEXT
NO
NOTHING
NOTIFY
NOWAIT
NULLS_P
OBJECT_P
OF
OFF
OIDS
OLD
OPERATOR
OPTION
OPTIONS
ORDINALITY
OTHERS
OVER
OVERRIDING
OWNED
OWNER
PARALLEL
PARSER
PARTIAL
PARTITION
PARTITIONED
PASSING
PASSWORD
PERCENT
PERSISTENT
PLANS
POLICY
PRAGMA_P
PRECEDING
PREPARE
PREPARED
PRESERVE
PRIOR
PRIVILEGES
PROCEDURAL
PROCEDURE
PROGRAM
PUBLICATION
QUARTER_P
QUARTERS_P
QUOTE
RANGE
READ_P
REASSIGN
RECHECK
RECURSIVE
REF
REFERENCING
REFRESH
REINDEX
RELATIVE_P
RELEASE
RENAME
REPEATABLE
REPLACE
REPLICA
RESET
RESPECT_P
RESTART
RESTRICT
RETURNS
REVOKE
ROLE
ROLLBACK
ROLLUP
ROWS
RULE
SAMPLE
SAVEPOINT
SCHEMA
SCHEMAS
SCOPE
SCROLL
SEARCH
SECRET
SECOND_P
SECONDS_P
SECURITY
SEQUENCE
SEQUENCES
SERIALIZABLE
SERVER
SESSION
SET
SETS
SHARE
SIMPLE
SKIP
SNAPSHOT
SORTED
SOURCE_P
SQL_P
STABLE
STANDALONE_P
START
STATEMENT
STATISTICS
STDIN
STDOUT
STORAGE
STORED
STRICT_P
STRIP_P
SUBSCRIPTION
SYSID
SYSTEM_P
TABLES
TABLESPACE
TARGET_P
TEMP
TEMPLATE
TEMPORARY
TEXT_P
TIES
TRANSACTION
TRANSFORM
TRIGGER
TRUNCATE
TRUSTED
TYPE_P
TYPES_P
UNBOUNDED
UNCOMMITTED
UNENCRYPTED
UNKNOWN
UNLISTEN
UNLOGGED
UNTIL
UPDATE
USE_P
USER
VACUUM
VALID
VALIDATE
VALIDATOR
VALUE_P
VARIABLE_P
VARYING
VERSION_P
VIEW
VIEWS
VIRTUAL
VOLATILE
WEEK_P
WEEKS_P
WHITESPACE_P
WITHIN
WITHOUT
WORK
WRAPPER
WRITE_P
XML_P
YEAR_P
YEARS_P
YES_P
ZONE

View File

@@ -0,0 +1,43 @@
AlterDatabaseStmt
AlterObjectSchemaStmt
AlterSeqStmt
AlterTableStmt
AnalyzeStmt
AttachStmt
CallStmt
CheckPointStmt
CopyStmt
CreateAsStmt
CreateSecretStmt
CreateTypeStmt
CreateFunctionStmt
CreateSchemaStmt
CreateSeqStmt
CreateStmt
CommentOnStmt
DeallocateStmt
DeleteStmt
DetachStmt
DropSecretStmt
DropStmt
ExecuteStmt
ExplainStmt
ExportStmt
ImportStmt
IndexStmt
InsertStmt
LoadStmt
MergeIntoStmt
PragmaStmt
PrepareStmt
RenameStmt
SelectStmt
TransactionStmt
UpdateStmt
UpdateExtensionsStmt
UseStmt
VacuumStmt
VariableResetStmt
VariableSetStmt
VariableShowStmt
ViewStmt

View File

@@ -0,0 +1,25 @@
/*****************************************************************************
*
* Alter Database Statement
*
*****************************************************************************/
AlterDatabaseStmt:
ALTER DATABASE ColId RENAME TO ColId
{
PGAlterDatabaseStmt *n = makeNode(PGAlterDatabaseStmt);
n->dbname = $3;
n->new_name = $6;
n->alter_type = PG_ALTER_DATABASE_RENAME;
n->missing_ok = false;
$$ = (PGNode *)n;
}
| ALTER DATABASE IF_P EXISTS ColId RENAME TO ColId
{
PGAlterDatabaseStmt *n = makeNode(PGAlterDatabaseStmt);
n->dbname = $5;
n->new_name = $8;
n->alter_type = PG_ALTER_DATABASE_RENAME;
n->missing_ok = true;
$$ = (PGNode *)n;
}
;

View File

@@ -0,0 +1,61 @@
/*****************************************************************************
*
* ALTER THING name SET SCHEMA name
*
*****************************************************************************/
AlterObjectSchemaStmt:
ALTER TABLE relation_expr SET SCHEMA name
{
PGAlterObjectSchemaStmt *n = makeNode(PGAlterObjectSchemaStmt);
n->objectType = PG_OBJECT_TABLE;
n->relation = $3;
n->newschema = $6;
n->missing_ok = false;
$$ = (PGNode *)n;
}
| ALTER TABLE IF_P EXISTS relation_expr SET SCHEMA name
{
PGAlterObjectSchemaStmt *n = makeNode(PGAlterObjectSchemaStmt);
n->objectType = PG_OBJECT_TABLE;
n->relation = $5;
n->newschema = $8;
n->missing_ok = true;
$$ = (PGNode *)n;
}
| ALTER SEQUENCE qualified_name SET SCHEMA name
{
PGAlterObjectSchemaStmt *n = makeNode(PGAlterObjectSchemaStmt);
n->objectType = PG_OBJECT_SEQUENCE;
n->relation = $3;
n->newschema = $6;
n->missing_ok = false;
$$ = (PGNode *)n;
}
| ALTER SEQUENCE IF_P EXISTS qualified_name SET SCHEMA name
{
PGAlterObjectSchemaStmt *n = makeNode(PGAlterObjectSchemaStmt);
n->objectType = PG_OBJECT_SEQUENCE;
n->relation = $5;
n->newschema = $8;
n->missing_ok = true;
$$ = (PGNode *)n;
}
| ALTER VIEW qualified_name SET SCHEMA name
{
PGAlterObjectSchemaStmt *n = makeNode(PGAlterObjectSchemaStmt);
n->objectType = PG_OBJECT_VIEW;
n->relation = $3;
n->newschema = $6;
n->missing_ok = false;
$$ = (PGNode *)n;
}
| ALTER VIEW IF_P EXISTS qualified_name SET SCHEMA name
{
PGAlterObjectSchemaStmt *n = makeNode(PGAlterObjectSchemaStmt);
n->objectType = PG_OBJECT_VIEW;
n->relation = $5;
n->newschema = $8;
n->missing_ok = true;
$$ = (PGNode *)n;
}
;

View File

@@ -0,0 +1,120 @@
/*****************************************************************************
*
* QUERY :
* CREATE SEQUENCE seqname
* ALTER SEQUENCE seqname
*
*****************************************************************************/
AlterSeqStmt:
ALTER SEQUENCE qualified_name SeqOptList
{
PGAlterSeqStmt *n = makeNode(PGAlterSeqStmt);
n->sequence = $3;
n->options = $4;
n->missing_ok = false;
$$ = (PGNode *)n;
}
| ALTER SEQUENCE IF_P EXISTS qualified_name SeqOptList
{
PGAlterSeqStmt *n = makeNode(PGAlterSeqStmt);
n->sequence = $5;
n->options = $6;
n->missing_ok = true;
$$ = (PGNode *)n;
}
;
SeqOptList: SeqOptElem { $$ = list_make1($1); }
| SeqOptList SeqOptElem { $$ = lappend($1, $2); }
;
opt_with: WITH {}
| WITH_LA {}
| /*EMPTY*/ {}
;
NumericOnly:
FCONST { $$ = makeFloat($1); }
| '+' FCONST { $$ = makeFloat($2); }
| '-' FCONST
{
$$ = makeFloat($2);
doNegateFloat($$);
}
| SignedIconst { $$ = makeInteger($1); }
;
SeqOptElem: AS SimpleTypename
{
$$ = makeDefElem("as", (PGNode *)$2, @1);
}
| CACHE NumericOnly
{
$$ = makeDefElem("cache", (PGNode *)$2, @1);
}
| CYCLE
{
$$ = makeDefElem("cycle", (PGNode *)makeInteger(true), @1);
}
| NO CYCLE
{
$$ = makeDefElem("cycle", (PGNode *)makeInteger(false), @1);
}
| INCREMENT opt_by NumericOnly
{
$$ = makeDefElem("increment", (PGNode *)$3, @1);
}
| MAXVALUE NumericOnly
{
$$ = makeDefElem("maxvalue", (PGNode *)$2, @1);
}
| MINVALUE NumericOnly
{
$$ = makeDefElem("minvalue", (PGNode *)$2, @1);
}
| NO MAXVALUE
{
$$ = makeDefElem("maxvalue", NULL, @1);
}
| NO MINVALUE
{
$$ = makeDefElem("minvalue", NULL, @1);
}
| OWNED BY any_name
{
$$ = makeDefElem("owned_by", (PGNode *)$3, @1);
}
| SEQUENCE NAME_P any_name
{
/* not documented, only used by pg_dump */
$$ = makeDefElem("sequence_name", (PGNode *)$3, @1);
}
| START opt_with NumericOnly
{
$$ = makeDefElem("start", (PGNode *)$3, @1);
}
| RESTART
{
$$ = makeDefElem("restart", NULL, @1);
}
| RESTART opt_with NumericOnly
{
$$ = makeDefElem("restart", (PGNode *)$3, @1);
}
;
opt_by: BY {}
| /* empty */ {}
;
SignedIconst: Iconst { $$ = $1; }
| '+' Iconst { $$ = + $2; }
| '-' Iconst { $$ = - $2; }
;

View File

@@ -0,0 +1,525 @@
/*****************************************************************************
*
* ALTER [ TABLE | INDEX | SEQUENCE | VIEW | MATERIALIZED VIEW ] variations
*
* Note: we accept all subcommands for each of the five variants, and sort
* out what's really legal at execution time.
*****************************************************************************/
AlterTableStmt:
ALTER TABLE relation_expr alter_table_cmds
{
PGAlterTableStmt *n = makeNode(PGAlterTableStmt);
n->relation = $3;
n->cmds = $4;
n->relkind = PG_OBJECT_TABLE;
n->missing_ok = false;
$$ = (PGNode *)n;
}
| ALTER TABLE IF_P EXISTS relation_expr alter_table_cmds
{
PGAlterTableStmt *n = makeNode(PGAlterTableStmt);
n->relation = $5;
n->cmds = $6;
n->relkind = PG_OBJECT_TABLE;
n->missing_ok = true;
$$ = (PGNode *)n;
}
| ALTER INDEX qualified_name alter_table_cmds
{
PGAlterTableStmt *n = makeNode(PGAlterTableStmt);
n->relation = $3;
n->cmds = $4;
n->relkind = PG_OBJECT_INDEX;
n->missing_ok = false;
$$ = (PGNode *)n;
}
| ALTER INDEX IF_P EXISTS qualified_name alter_table_cmds
{
PGAlterTableStmt *n = makeNode(PGAlterTableStmt);
n->relation = $5;
n->cmds = $6;
n->relkind = PG_OBJECT_INDEX;
n->missing_ok = true;
$$ = (PGNode *)n;
}
| ALTER SEQUENCE qualified_name alter_table_cmds
{
PGAlterTableStmt *n = makeNode(PGAlterTableStmt);
n->relation = $3;
n->cmds = $4;
n->relkind = PG_OBJECT_SEQUENCE;
n->missing_ok = false;
$$ = (PGNode *)n;
}
| ALTER SEQUENCE IF_P EXISTS qualified_name alter_table_cmds
{
PGAlterTableStmt *n = makeNode(PGAlterTableStmt);
n->relation = $5;
n->cmds = $6;
n->relkind = PG_OBJECT_SEQUENCE;
n->missing_ok = true;
$$ = (PGNode *)n;
}
| ALTER VIEW qualified_name alter_table_cmds
{
PGAlterTableStmt *n = makeNode(PGAlterTableStmt);
n->relation = $3;
n->cmds = $4;
n->relkind = PG_OBJECT_VIEW;
n->missing_ok = false;
$$ = (PGNode *)n;
}
| ALTER VIEW IF_P EXISTS qualified_name alter_table_cmds
{
PGAlterTableStmt *n = makeNode(PGAlterTableStmt);
n->relation = $5;
n->cmds = $6;
n->relkind = PG_OBJECT_VIEW;
n->missing_ok = true;
$$ = (PGNode *)n;
}
;
alter_identity_column_option_list:
alter_identity_column_option
{ $$ = list_make1($1); }
| alter_identity_column_option_list alter_identity_column_option
{ $$ = lappend($1, $2); }
;
alter_column_default:
SET DEFAULT a_expr { $$ = $3; }
| DROP DEFAULT { $$ = NULL; }
;
alter_identity_column_option:
RESTART
{
$$ = makeDefElem("restart", NULL, @1);
}
| RESTART opt_with NumericOnly
{
$$ = makeDefElem("restart", (PGNode *)$3, @1);
}
| SET SeqOptElem
{
if (strcmp($2->defname, "as") == 0 ||
strcmp($2->defname, "restart") == 0 ||
strcmp($2->defname, "owned_by") == 0)
ereport(ERROR,
(errcode(PG_ERRCODE_SYNTAX_ERROR),
errmsg("sequence option \"%s\" not supported here", $2->defname),
parser_errposition(@2)));
$$ = $2;
}
| SET GENERATED generated_when
{
$$ = makeDefElem("generated", (PGNode *) makeInteger($3), @1);
}
;
alter_generic_option_list:
alter_generic_option_elem
{
$$ = list_make1($1);
}
| alter_generic_option_list ',' alter_generic_option_elem
{
$$ = lappend($1, $3);
}
;
qualify_list:
qualify_el { $$ = list_make1($1); }
| qualify_list qualify_el { $$ = lappend($1, $2); }
;
qualify_el:
'.' attr_name
{
$$ = $2;
}
;
qualified_column:
ColId { $$ = list_make1($1); }
| ColId qualify_list { $$ = list_concat(list_make1($1), $2); }
;
qualifiedColumnDef:
qualified_column regularColumnDef
{
PGColumnDef *n = (PGColumnDef *) $2;
n->location = @1;
$$ = list_make2($1, n);
}
|
qualified_column generatedColumnDef
{
PGColumnDef *n = (PGColumnDef *) $2;
n->location = @1;
$$ = list_make2($1, n);
}
;
alter_table_cmd:
/* ALTER TABLE <name> ADD <coldef> */
ADD_P qualifiedColumnDef
{
PGAlterTableCmd *n = makeNode(PGAlterTableCmd);
n->subtype = PG_AT_AddColumn;
n->def_list = $2;
n->missing_ok = false;
$$ = (PGNode *)n;
}
/* ALTER TABLE <name> ADD IF NOT EXISTS <coldef> */
| ADD_P IF_P NOT EXISTS qualifiedColumnDef
{
PGAlterTableCmd *n = makeNode(PGAlterTableCmd);
n->subtype = PG_AT_AddColumn;
n->def_list = $5;
n->missing_ok = true;
$$ = (PGNode *)n;
}
/* ALTER TABLE <name> ADD COLUMN <coldef> */
| ADD_P COLUMN qualifiedColumnDef
{
PGAlterTableCmd *n = makeNode(PGAlterTableCmd);
n->subtype = PG_AT_AddColumn;
n->def_list = $3;
n->missing_ok = false;
$$ = (PGNode *)n;
}
/* ALTER TABLE <name> ADD COLUMN IF NOT EXISTS <coldef> */
| ADD_P COLUMN IF_P NOT EXISTS qualifiedColumnDef
{
PGAlterTableCmd *n = makeNode(PGAlterTableCmd);
n->subtype = PG_AT_AddColumn;
n->def_list = $6;
n->missing_ok = true;
$$ = (PGNode *)n;
}
/* ALTER TABLE <name> SET PARTITIONED BY ( <partition_key_list> ) */
| SET PARTITIONED BY '(' expr_list_opt_comma ')'
{
PGAlterTableCmd *n = makeNode(PGAlterTableCmd);
n->subtype = PG_AT_SetPartitionedBy;
n->def_list = $5;
$$ = (PGNode *)n;
}
/* ALTER TABLE <name> RESET PARTITIONED BY */
| RESET PARTITIONED BY
{
PGAlterTableCmd *n = makeNode(PGAlterTableCmd);
n->subtype = PG_AT_SetPartitionedBy;
n->def_list = NULL;
$$ = (PGNode *)n;
}
/* ALTER TABLE <name> SET SORTED BY ( <order_key_list> ) */
| SET SORTED BY '(' sortby_list ')'
{
PGAlterTableCmd *n = makeNode(PGAlterTableCmd);
n->subtype = PG_AT_SetSortedBy;
n->def_list = $5;
$$ = (PGNode *)n;
}
/* ALTER TABLE <name> RESET SORTED BY */
| RESET SORTED BY
{
PGAlterTableCmd *n = makeNode(PGAlterTableCmd);
n->subtype = PG_AT_SetSortedBy;
n->def_list = NULL;
$$ = (PGNode *)n;
}
/* ALTER TABLE <name> ALTER [COLUMN] <colname> {SET DEFAULT <expr>|DROP DEFAULT} */
| ALTER opt_column ColId alter_column_default
{
PGAlterTableCmd *n = makeNode(PGAlterTableCmd);
n->subtype = PG_AT_ColumnDefault;
n->name = $3;
n->def = $4;
$$ = (PGNode *)n;
}
/* ALTER TABLE <name> ALTER [COLUMN] <colname> DROP NOT NULL */
| ALTER opt_column ColId DROP NOT NULL_P
{
PGAlterTableCmd *n = makeNode(PGAlterTableCmd);
n->subtype = PG_AT_DropNotNull;
n->name = $3;
$$ = (PGNode *)n;
}
/* ALTER TABLE <name> ALTER [COLUMN] <colname> SET NOT NULL */
| ALTER opt_column ColId SET NOT NULL_P
{
PGAlterTableCmd *n = makeNode(PGAlterTableCmd);
n->subtype = PG_AT_SetNotNull;
n->name = $3;
$$ = (PGNode *)n;
}
/* ALTER TABLE <name> ALTER [COLUMN] <colname> SET STATISTICS <SignedIconst> */
| ALTER opt_column ColId SET STATISTICS SignedIconst
{
PGAlterTableCmd *n = makeNode(PGAlterTableCmd);
n->subtype = PG_AT_SetStatistics;
n->name = $3;
n->def = (PGNode *) makeInteger($6);
$$ = (PGNode *)n;
}
/* ALTER TABLE <name> ALTER [COLUMN] <colname> SET ( column_parameter = value [, ... ] ) */
| ALTER opt_column ColId SET reloptions
{
PGAlterTableCmd *n = makeNode(PGAlterTableCmd);
n->subtype = PG_AT_SetOptions;
n->name = $3;
n->def = (PGNode *) $5;
$$ = (PGNode *)n;
}
/* ALTER TABLE <name> ALTER [COLUMN] <colname> RESET ( column_parameter = value [, ... ] ) */
| ALTER opt_column ColId RESET reloptions
{
PGAlterTableCmd *n = makeNode(PGAlterTableCmd);
n->subtype = PG_AT_ResetOptions;
n->name = $3;
n->def = (PGNode *) $5;
$$ = (PGNode *)n;
}
/* ALTER TABLE <name> ALTER [COLUMN] <colname> SET STORAGE <storagemode> */
| ALTER opt_column ColId SET STORAGE ColId
{
PGAlterTableCmd *n = makeNode(PGAlterTableCmd);
n->subtype = PG_AT_SetStorage;
n->name = $3;
n->def = (PGNode *) makeString($6);
$$ = (PGNode *)n;
}
/* ALTER TABLE <name> ALTER [COLUMN] <colname> ADD GENERATED ... AS IDENTITY ... */
| ALTER opt_column ColId ADD_P GENERATED generated_when AS IDENTITY_P OptParenthesizedSeqOptList
{
PGAlterTableCmd *n = makeNode(PGAlterTableCmd);
PGConstraint *c = makeNode(PGConstraint);
c->contype = PG_CONSTR_IDENTITY;
c->generated_when = $6;
c->options = $9;
c->location = @5;
n->subtype = PG_AT_AddIdentity;
n->name = $3;
n->def = (PGNode *) c;
$$ = (PGNode *)n;
}
/* ALTER TABLE <name> ALTER [COLUMN] <colname> SET <sequence options>/RESET */
| ALTER opt_column ColId alter_identity_column_option_list
{
PGAlterTableCmd *n = makeNode(PGAlterTableCmd);
n->subtype = PG_AT_SetIdentity;
n->name = $3;
n->def = (PGNode *) $4;
$$ = (PGNode *)n;
}
/* ALTER TABLE <name> ALTER [COLUMN] <colname> DROP IDENTITY */
| ALTER opt_column ColId DROP IDENTITY_P
{
PGAlterTableCmd *n = makeNode(PGAlterTableCmd);
n->subtype = AT_DropIdentity;
n->name = $3;
n->missing_ok = false;
$$ = (PGNode *)n;
}
/* ALTER TABLE <name> ALTER [COLUMN] <colname> DROP IDENTITY IF EXISTS */
| ALTER opt_column ColId DROP IDENTITY_P IF_P EXISTS
{
PGAlterTableCmd *n = makeNode(PGAlterTableCmd);
n->subtype = AT_DropIdentity;
n->name = $3;
n->missing_ok = true;
$$ = (PGNode *)n;
}
/* ALTER TABLE <name> DROP [COLUMN] IF EXISTS <colname> [RESTRICT|CASCADE] */
| DROP opt_column IF_P EXISTS qualified_column opt_drop_behavior
{
PGAlterTableCmd *n = makeNode(PGAlterTableCmd);
n->subtype = PG_AT_DropColumn;
n->def_list = $5;
n->behavior = $6;
n->missing_ok = true;
$$ = (PGNode *)n;
}
/* ALTER TABLE <name> DROP [COLUMN] <colname> [RESTRICT|CASCADE] */
| DROP opt_column qualified_column opt_drop_behavior
{
PGAlterTableCmd *n = makeNode(PGAlterTableCmd);
n->subtype = PG_AT_DropColumn;
n->def_list = $3;
n->behavior = $4;
n->missing_ok = false;
$$ = (PGNode *)n;
}
/*
* ALTER TABLE <name> ALTER [COLUMN] <colname> [SET DATA] TYPE <typename>
* [ USING <expression> ] [RESTRICT|CASCADE]
*/
| ALTER opt_column ColId opt_set_data TYPE_P opt_Typename opt_collate_clause alter_using
{
PGAlterTableCmd *n = makeNode(PGAlterTableCmd);
PGColumnDef *def = makeNode(PGColumnDef);
n->subtype = PG_AT_AlterColumnType;
n->name = $3;
n->def = (PGNode *) def;
/* We only use these fields of the PGColumnDef node */
def->typeName = $6;
def->collClause = (PGCollateClause *) $7;
def->raw_default = $8;
def->location = @3;
$$ = (PGNode *)n;
}
/* ALTER FOREIGN TABLE <name> ALTER [COLUMN] <colname> OPTIONS */
| ALTER opt_column ColId alter_generic_options
{
PGAlterTableCmd *n = makeNode(PGAlterTableCmd);
n->subtype = PG_AT_AlterColumnGenericOptions;
n->name = $3;
n->def = (PGNode *) $4;
$$ = (PGNode *)n;
}
/* ALTER TABLE <name> ADD CONSTRAINT ... */
| ADD_P TableConstraint
{
PGAlterTableCmd *n = makeNode(PGAlterTableCmd);
n->subtype = PG_AT_AddConstraint;
n->def = $2;
$$ = (PGNode *)n;
}
/* ALTER TABLE <name> ALTER CONSTRAINT ... */
| ALTER CONSTRAINT name ConstraintAttributeSpec
{
PGAlterTableCmd *n = makeNode(PGAlterTableCmd);
PGConstraint *c = makeNode(PGConstraint);
n->subtype = PG_AT_AlterConstraint;
n->def = (PGNode *) c;
c->contype = PG_CONSTR_FOREIGN; /* others not supported, yet */
c->conname = $3;
processCASbits($4, @4, "ALTER CONSTRAINT statement",
&c->deferrable,
&c->initdeferred,
NULL, NULL, yyscanner);
$$ = (PGNode *)n;
}
/* ALTER TABLE <name> VALIDATE CONSTRAINT ... */
| VALIDATE CONSTRAINT name
{
PGAlterTableCmd *n = makeNode(PGAlterTableCmd);
n->subtype = PG_AT_ValidateConstraint;
n->name = $3;
$$ = (PGNode *)n;
}
/* ALTER TABLE <name> DROP CONSTRAINT IF EXISTS <name> [RESTRICT|CASCADE] */
| DROP CONSTRAINT IF_P EXISTS name opt_drop_behavior
{
PGAlterTableCmd *n = makeNode(PGAlterTableCmd);
n->subtype = PG_AT_DropConstraint;
n->name = $5;
n->behavior = $6;
n->missing_ok = true;
$$ = (PGNode *)n;
}
/* ALTER TABLE <name> DROP CONSTRAINT <name> [RESTRICT|CASCADE] */
| DROP CONSTRAINT name opt_drop_behavior
{
PGAlterTableCmd *n = makeNode(PGAlterTableCmd);
n->subtype = PG_AT_DropConstraint;
n->name = $3;
n->behavior = $4;
n->missing_ok = false;
$$ = (PGNode *)n;
}
/* ALTER TABLE <name> SET LOGGED */
| SET LOGGED
{
PGAlterTableCmd *n = makeNode(PGAlterTableCmd);
n->subtype = PG_AT_SetLogged;
$$ = (PGNode *)n;
}
/* ALTER TABLE <name> SET UNLOGGED */
| SET UNLOGGED
{
PGAlterTableCmd *n = makeNode(PGAlterTableCmd);
n->subtype = PG_AT_SetUnLogged;
$$ = (PGNode *)n;
}
/* ALTER TABLE <name> SET (...) */
| SET reloptions
{
PGAlterTableCmd *n = makeNode(PGAlterTableCmd);
n->subtype = PG_AT_SetRelOptions;
n->def = (PGNode *)$2;
$$ = (PGNode *)n;
}
/* ALTER TABLE <name> RESET (...) */
| RESET reloptions
{
PGAlterTableCmd *n = makeNode(PGAlterTableCmd);
n->subtype = PG_AT_ResetRelOptions;
n->def = (PGNode *)$2;
$$ = (PGNode *)n;
}
| alter_generic_options
{
PGAlterTableCmd *n = makeNode(PGAlterTableCmd);
n->subtype = PG_AT_GenericOptions;
n->def = (PGNode *)$1;
$$ = (PGNode *) n;
}
;
alter_using:
USING a_expr { $$ = $2; }
| /* EMPTY */ { $$ = NULL; }
;
alter_generic_option_elem:
generic_option_elem
{
$$ = $1;
}
| SET generic_option_elem
{
$$ = $2;
$$->defaction = PG_DEFELEM_SET;
}
| ADD_P generic_option_elem
{
$$ = $2;
$$->defaction = PG_DEFELEM_ADD;
}
| DROP generic_option_name
{
$$ = makeDefElemExtended(NULL, $2, NULL, DEFELEM_DROP, @2);
}
;
alter_table_cmds:
alter_table_cmd { $$ = list_make1($1); }
| alter_table_cmds ',' alter_table_cmd { $$ = lappend($1, $3); }
;
alter_generic_options:
OPTIONS '(' alter_generic_option_list ')' { $$ = $3; }
;
opt_set_data: SET DATA_P { $$ = 1; }
| SET { $$ = 0; }
| /*EMPTY*/ { $$ = 0; }
;

View File

@@ -0,0 +1,29 @@
/*****************************************************************************
*
* QUERY:
* VACUUM
* ANALYZE
*
*****************************************************************************/
AnalyzeStmt:
analyze_keyword opt_verbose
{
PGVacuumStmt *n = makeNode(PGVacuumStmt);
n->options = PG_VACOPT_ANALYZE;
if ($2)
n->options |= PG_VACOPT_VERBOSE;
n->relation = NULL;
n->va_cols = NIL;
$$ = (PGNode *)n;
}
| analyze_keyword opt_verbose qualified_name opt_name_list
{
PGVacuumStmt *n = makeNode(PGVacuumStmt);
n->options = PG_VACOPT_ANALYZE;
if ($2)
n->options |= PG_VACOPT_VERBOSE;
n->relation = $3;
n->va_cols = $4;
$$ = (PGNode *)n;
}
;

View File

@@ -0,0 +1,108 @@
/*****************************************************************************
*
* Attach Statement
*
*****************************************************************************/
AttachStmt:
ATTACH opt_database Sconst opt_database_alias opt_attach_options
{
PGAttachStmt *n = makeNode(PGAttachStmt);
n->path = $3;
n->name = $4;
n->options = $5;
n->onconflict = PG_ERROR_ON_CONFLICT;
$$ = (PGNode *)n;
}
| ATTACH IF_P NOT EXISTS opt_database Sconst opt_database_alias opt_attach_options
{
PGAttachStmt *n = makeNode(PGAttachStmt);
n->path = $6;
n->name = $7;
n->options = $8;
n->onconflict = PG_IGNORE_ON_CONFLICT;
$$ = (PGNode *)n;
}
| ATTACH OR REPLACE opt_database Sconst opt_database_alias opt_attach_options
{
PGAttachStmt *n = makeNode(PGAttachStmt);
n->path = $5;
n->name = $6;
n->options = $7;
n->onconflict = PG_REPLACE_ON_CONFLICT;
$$ = (PGNode *)n;
}
;
DetachStmt:
DETACH ColLabel
{
PGDetachStmt *n = makeNode(PGDetachStmt);
n->missing_ok = false;
n->db_name = $2;
$$ = (PGNode *)n;
}
| DETACH DATABASE ColLabel
{
PGDetachStmt *n = makeNode(PGDetachStmt);
n->missing_ok = false;
n->db_name = $3;
$$ = (PGNode *)n;
}
| DETACH DATABASE IF_P EXISTS ColLabel
{
PGDetachStmt *n = makeNode(PGDetachStmt);
n->missing_ok = true;
n->db_name = $5;
$$ = (PGNode *)n;
}
;
opt_database: DATABASE {}
| /*EMPTY*/ {}
;
opt_database_alias:
AS ColId { $$ = $2; }
| /*EMPTY*/ { $$ = NULL; }
;
ident_name: IDENT { $$ = list_make1(makeString($1)); }
ident_list:
ident_name { $$ = list_make1($1); }
| ident_list ',' ident_name { $$ = lappend($1, $3); }
;
generic_opt_arg:
a_expr { $$ = (PGNode *) $1; }
| /* EMPTY */ { $$ = NULL; }
;
generic_opt_elem:
ColLabel generic_opt_arg
{
$$ = makeDefElem($1, $2, @1);
}
;
generic_opt_list:
generic_opt_elem
{
$$ = list_make1($1);
}
| generic_opt_list ',' generic_opt_elem
{
$$ = lappend($1, $3);
}
;
opt_attach_options:
'(' generic_opt_list ')'
{
$$ = $2;
}
| /* EMPTY */
{
$$ = NULL;
}
;

View File

@@ -0,0 +1,12 @@
/*****************************************************************************
*
* CALL <proc_name> [(params, ...)]
*
*****************************************************************************/
CallStmt: CALL_P func_application
{
PGCallStmt *n = makeNode(PGCallStmt);
n->func = $2;
$$ = (PGNode *) n;
}
;

View File

@@ -0,0 +1,23 @@
/*
* Checkpoint statement
*/
CheckPointStmt:
FORCE CHECKPOINT opt_col_id
{
PGCheckPointStmt *n = makeNode(PGCheckPointStmt);
n->force = true;
n->name = $3;
$$ = (PGNode *)n;
}
| CHECKPOINT opt_col_id
{
PGCheckPointStmt *n = makeNode(PGCheckPointStmt);
n->force = false;
n->name = $2;
$$ = (PGNode *)n;
}
;
opt_col_id:
ColId { $$ = $1; }
| /* empty */ { $$ = NULL; }

View File

@@ -0,0 +1,40 @@
/*****************************************************************************
*
* Create a Comment
*
*****************************************************************************/
CommentOnStmt:
COMMENT ON comment_on_type_any_name qualified_name IS comment_value
{
PGCommentOnStmt *n = makeNode(PGCommentOnStmt);
n->object_type = $3;
n->name = $4;
n->value = $6;
$$ = (PGNode *)n;
}
| COMMENT ON COLUMN a_expr IS comment_value
{
PGCommentOnStmt *n = makeNode(PGCommentOnStmt);
n->object_type = PG_OBJECT_COLUMN;
n->column_expr = $4;
n->value = $6;
$$ = (PGNode *)n;
}
;
comment_value:
Sconst { $$ = makeStringConst($1, @1); }
| NULL_P { $$ = makeNullAConst(@1); }
comment_on_type_any_name:
TABLE { $$ = PG_OBJECT_TABLE; }
| SEQUENCE { $$ = PG_OBJECT_SEQUENCE; }
| FUNCTION { $$ = PG_OBJECT_FUNCTION; }
| MACRO { $$ = PG_OBJECT_FUNCTION; }
| MACRO TABLE { $$ = PG_OBJECT_TABLE_MACRO; }
| VIEW { $$ = PG_OBJECT_VIEW; }
| DATABASE { $$ = PG_OBJECT_DATABASE; }
| INDEX { $$ = PG_OBJECT_INDEX; }
| SCHEMA { $$ = PG_OBJECT_SCHEMA; }
| TYPE_P { $$ = PG_OBJECT_TYPE; }
;

View File

@@ -0,0 +1,80 @@
/*
* The production for a qualified relation name has to exactly match the
* production for a qualified func_name, because in a FROM clause we cannot
* tell which we are parsing until we see what comes after it ('(' for a
* func_name, something else for a relation). Therefore we allow 'indirection'
* which may contain subscripts, and reject that case in the C code.
*/
qualified_name:
ColIdOrString
{
$$ = makeRangeVar(NULL, $1, @1);
}
| ColId indirection
{
check_qualified_name($2, yyscanner);
$$ = makeRangeVar(NULL, NULL, @1);
switch (list_length($2))
{
case 1:
$$->catalogname = NULL;
$$->schemaname = $1;
$$->relname = strVal(linitial($2));
break;
case 2:
$$->catalogname = $1;
$$->schemaname = strVal(linitial($2));
$$->relname = strVal(lsecond($2));
break;
case 3:
default:
ereport(ERROR,
(errcode(PG_ERRCODE_SYNTAX_ERROR),
errmsg("improper qualified name (too many dotted names): %s",
NameListToString(lcons(makeString($1), $2))),
parser_errposition(@1)));
break;
}
}
;
/* Column identifier --- names that can be column, table, etc names.
*/
ColId: IDENT { $$ = $1; }
| unreserved_keyword { $$ = pstrdup($1); }
| col_name_keyword { $$ = pstrdup($1); }
;
ColIdOrString: ColId { $$ = $1; }
| SCONST { $$ = $1; }
;
Sconst: SCONST { $$ = $1; };
indirection:
indirection_el { $$ = list_make1($1); }
| indirection indirection_el { $$ = lappend($1, $2); }
;
indirection_el:
'.' attr_name
{
$$ = (PGNode *) makeString($2);
}
;
attr_name: ColLabel { $$ = $1; };
/* Column label --- allowed labels in "AS" clauses.
* This presently includes *all* Postgres keywords.
*/
ColLabel: IDENT { $$ = $1; }
| other_keyword { $$ = pstrdup($1); }
| unreserved_keyword { $$ = pstrdup($1); }
| reserved_keyword { $$ = pstrdup($1); }
;

View File

@@ -0,0 +1,218 @@
CopyStmt: COPY opt_binary qualified_name opt_column_list opt_oids
copy_from opt_program copy_file_name copy_delimiter opt_with copy_options
{
PGCopyStmt *n = makeNode(PGCopyStmt);
n->relation = $3;
n->query = NULL;
n->attlist = $4;
n->is_from = $6;
n->is_program = $7;
n->filename = $8;
if (n->is_program && n->filename == NULL)
ereport(ERROR,
(errcode(PG_ERRCODE_SYNTAX_ERROR),
errmsg("STDIN/STDOUT not allowed with PROGRAM"),
parser_errposition(@8)));
n->options = NIL;
/* Concatenate user-supplied flags */
if ($2)
n->options = lappend(n->options, $2);
if ($5)
n->options = lappend(n->options, $5);
if ($9)
n->options = lappend(n->options, $9);
if ($11)
n->options = list_concat(n->options, $11);
$$ = (PGNode *)n;
}
| COPY '(' SelectStmt ')' TO opt_program copy_file_name opt_with copy_options
{
PGCopyStmt *n = makeNode(PGCopyStmt);
n->relation = NULL;
n->query = $3;
n->attlist = NIL;
n->is_from = false;
n->is_program = $6;
n->filename = $7;
n->options = $9;
if (n->is_program && n->filename == NULL)
ereport(ERROR,
(errcode(PG_ERRCODE_SYNTAX_ERROR),
errmsg("STDIN/STDOUT not allowed with PROGRAM"),
parser_errposition(@5)));
$$ = (PGNode *)n;
}
| COPY FROM DATABASE ColId TO ColId copy_database_flag
{
PGCopyDatabaseStmt *n = makeNode(PGCopyDatabaseStmt);
n->from_database = $4;
n->to_database = $6;
n->copy_database_flag = $7;
$$ = (PGNode *)n;
}
;
copy_database_flag:
/* empty */ { $$ = NULL; }
| '(' SCHEMA ')' { $$ = "schema"; }
| '(' DATA_P ')' { $$ = "data"; }
;
copy_from:
FROM { $$ = true; }
| TO { $$ = false; }
;
copy_delimiter:
opt_using DELIMITERS Sconst
{
$$ = makeDefElem("delimiter", (PGNode *)makeString($3), @2);
}
| /*EMPTY*/ { $$ = NULL; }
;
copy_generic_opt_arg_list:
copy_generic_opt_arg_list_item
{
$$ = list_make1($1);
}
| copy_generic_opt_arg_list ',' copy_generic_opt_arg_list_item
{
$$ = lappend($1, $3);
}
;
opt_using:
USING {}
| /*EMPTY*/ {}
;
opt_as: AS {}
| /* EMPTY */ {}
;
opt_program:
PROGRAM { $$ = true; }
| /* EMPTY */ { $$ = false; }
;
copy_options: copy_opt_list { $$ = $1; }
| '(' generic_opt_list ')' { $$ = $2; }
;
opt_oids:
WITH OIDS
{
$$ = makeDefElem("oids", NULL, @1);
}
| /*EMPTY*/ { $$ = NULL; }
;
copy_opt_list:
copy_opt_list copy_opt_item { $$ = lappend($1, $2); }
| /* EMPTY */ { $$ = NIL; }
;
opt_binary:
BINARY
{
$$ = makeDefElem("format", (PGNode *)makeStringConst("binary", @1), @1);
}
| /*EMPTY*/ { $$ = NULL; }
;
copy_opt_item:
BINARY
{
$$ = makeDefElem("format", (PGNode *)makeStringConst("binary", @1), @1);
}
| OIDS
{
$$ = makeDefElem("oids", NULL, @1);
}
| FREEZE
{
$$ = makeDefElem("freeze", NULL, @1);
}
| DELIMITER opt_as Sconst
{
$$ = makeDefElem("delimiter", (PGNode *)makeStringConst($3, @3), @1);
}
| NULL_P opt_as Sconst
{
$$ = makeDefElem("null", (PGNode *)makeStringConst($3, @3), @1);
}
| CSV
{
$$ = makeDefElem("format", (PGNode *)makeStringConst("csv", @1), @1);
}
| HEADER_P
{
$$ = makeDefElem("header", NULL, @1);
}
| QUOTE opt_as Sconst
{
$$ = makeDefElem("quote", (PGNode *)makeStringConst($3, @3), @1);
}
| ESCAPE opt_as Sconst
{
$$ = makeDefElem("escape", (PGNode *)makeStringConst($3, @3), @1);
}
| FORCE QUOTE columnList
{
$$ = makeDefElem("force_quote", (PGNode *)$3, @1);
}
| FORCE QUOTE '*'
{
$$ = makeDefElem("force_quote", (PGNode *)makeNode(PGAStar), @1);
}
| PARTITION BY columnList
{
$$ = makeDefElem("partition_by", (PGNode *)$3, @1);
}
| PARTITION BY '*'
{
$$ = makeDefElem("partition_by", (PGNode *)makeNode(PGAStar), @1);
}
| FORCE NOT NULL_P columnList
{
$$ = makeDefElem("force_not_null", (PGNode *)$4, @1);
}
| FORCE NULL_P columnList
{
$$ = makeDefElem("force_null", (PGNode *)$3, @1);
}
| ENCODING Sconst
{
$$ = makeDefElem("encoding", (PGNode *)makeStringConst($2, @2), @1);
}
;
copy_generic_opt_arg_list_item:
opt_boolean_or_string { $$ = (PGNode *) makeString($1); }
;
copy_file_name:
Sconst { $$ = makeStringConst($1, @1); }
| STDIN { $$ = makeStringConst("/dev/stdin", @1); }
| STDOUT { $$ = makeStringConst("/dev/stdout", @1); }
| IDENT '.' ColId { $$ = makeStringConst(psprintf("%s.%s", $1, $3), @1); }
| IDENT { $$ = makeStringConst($1, @1); }
| '(' a_expr ')' { $$ = $2; }
| param_expr { $$ = $1; }
;

View File

@@ -0,0 +1,759 @@
/*****************************************************************************
*
* QUERY :
* CREATE TABLE relname
*
*****************************************************************************/
CreateStmt: CREATE_P OptTemp TABLE qualified_name '(' OptTableElementList ')'
OptWith OnCommitOption
{
PGCreateStmt *n = makeNode(PGCreateStmt);
$4->relpersistence = $2;
n->relation = $4;
n->tableElts = $6;
n->ofTypename = NULL;
n->constraints = NIL;
n->options = $8;
n->oncommit = $9;
n->onconflict = PG_ERROR_ON_CONFLICT;
$$ = (PGNode *)n;
}
| CREATE_P OptTemp TABLE IF_P NOT EXISTS qualified_name '('
OptTableElementList ')' OptWith
OnCommitOption
{
PGCreateStmt *n = makeNode(PGCreateStmt);
$7->relpersistence = $2;
n->relation = $7;
n->tableElts = $9;
n->ofTypename = NULL;
n->constraints = NIL;
n->options = $11;
n->oncommit = $12;
n->onconflict = PG_IGNORE_ON_CONFLICT;
$$ = (PGNode *)n;
}
| CREATE_P OR REPLACE OptTemp TABLE qualified_name '('
OptTableElementList ')' OptWith
OnCommitOption
{
PGCreateStmt *n = makeNode(PGCreateStmt);
$6->relpersistence = $4;
n->relation = $6;
n->tableElts = $8;
n->ofTypename = NULL;
n->constraints = NIL;
n->options = $10;
n->oncommit = $11;
n->onconflict = PG_REPLACE_ON_CONFLICT;
$$ = (PGNode *)n;
}
;
ConstraintAttributeSpec:
/*EMPTY*/
{ $$ = 0; }
| ConstraintAttributeSpec ConstraintAttributeElem
{
/*
* We must complain about conflicting options.
* We could, but choose not to, complain about redundant
* options (ie, where $2's bit is already set in $1).
*/
int newspec = $1 | $2;
/* special message for this case */
if ((newspec & (CAS_NOT_DEFERRABLE | CAS_INITIALLY_DEFERRED)) == (CAS_NOT_DEFERRABLE | CAS_INITIALLY_DEFERRED))
ereport(ERROR,
(errcode(PG_ERRCODE_SYNTAX_ERROR),
errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE"),
parser_errposition(@2)));
/* generic message for other conflicts */
if ((newspec & (CAS_NOT_DEFERRABLE | CAS_DEFERRABLE)) == (CAS_NOT_DEFERRABLE | CAS_DEFERRABLE) ||
(newspec & (CAS_INITIALLY_IMMEDIATE | CAS_INITIALLY_DEFERRED)) == (CAS_INITIALLY_IMMEDIATE | CAS_INITIALLY_DEFERRED))
ereport(ERROR,
(errcode(PG_ERRCODE_SYNTAX_ERROR),
errmsg("conflicting constraint properties"),
parser_errposition(@2)));
$$ = newspec;
}
;
def_arg: func_type { $$ = (PGNode *)$1; }
| reserved_keyword { $$ = (PGNode *)makeString(pstrdup($1)); }
| qual_all_Op { $$ = (PGNode *)$1; }
| NumericOnly { $$ = (PGNode *)$1; }
| Sconst { $$ = (PGNode *)makeString($1); }
| NONE { $$ = (PGNode *)makeString(pstrdup($1)); }
;
OptParenthesizedSeqOptList: '(' SeqOptList ')' { $$ = $2; }
| /*EMPTY*/ { $$ = NIL; }
;
generic_option_arg:
Sconst { $$ = (PGNode *) makeString($1); }
;
key_action:
NO ACTION { $$ = PG_FKCONSTR_ACTION_NOACTION; }
| RESTRICT { $$ = PG_FKCONSTR_ACTION_RESTRICT; }
| CASCADE { $$ = PG_FKCONSTR_ACTION_CASCADE; }
| SET NULL_P { $$ = PG_FKCONSTR_ACTION_SETNULL; }
| SET DEFAULT { $$ = PG_FKCONSTR_ACTION_SETDEFAULT; }
;
ColConstraint:
CONSTRAINT name ColConstraintElem
{
PGConstraint *n = castNode(PGConstraint, $3);
n->conname = $2;
n->location = @1;
$$ = (PGNode *) n;
}
| ColConstraintElem { $$ = $1; }
| ConstraintAttr { $$ = $1; }
| COLLATE any_name
{
/*
* Note: the PGCollateClause is momentarily included in
* the list built by ColQualList, but we split it out
* again in SplitColQualList.
*/
PGCollateClause *n = makeNode(PGCollateClause);
n->arg = NULL;
n->collname = $2;
n->location = @1;
$$ = (PGNode *) n;
}
;
ColConstraintElem:
NOT NULL_P
{
PGConstraint *n = makeNode(PGConstraint);
n->contype = PG_CONSTR_NOTNULL;
n->location = @1;
$$ = (PGNode *)n;
}
| NULL_P
{
PGConstraint *n = makeNode(PGConstraint);
n->contype = PG_CONSTR_NULL;
n->location = @1;
$$ = (PGNode *)n;
}
| UNIQUE opt_definition
{
PGConstraint *n = makeNode(PGConstraint);
n->contype = PG_CONSTR_UNIQUE;
n->location = @1;
n->keys = NULL;
n->options = $2;
n->indexname = NULL;
$$ = (PGNode *)n;
}
| PRIMARY KEY opt_definition
{
PGConstraint *n = makeNode(PGConstraint);
n->contype = PG_CONSTR_PRIMARY;
n->location = @1;
n->keys = NULL;
n->options = $3;
n->indexname = NULL;
$$ = (PGNode *)n;
}
| CHECK_P '(' a_expr ')' opt_no_inherit
{
PGConstraint *n = makeNode(PGConstraint);
n->contype = PG_CONSTR_CHECK;
n->location = @1;
n->is_no_inherit = $5;
n->raw_expr = $3;
n->cooked_expr = NULL;
n->skip_validation = false;
n->initially_valid = true;
$$ = (PGNode *)n;
}
| USING COMPRESSION name
{
PGConstraint *n = makeNode(PGConstraint);
n->contype = PG_CONSTR_COMPRESSION;
n->location = @1;
n->compression_name = $3;
$$ = (PGNode *)n;
}
| DEFAULT b_expr
{
PGConstraint *n = makeNode(PGConstraint);
n->contype = PG_CONSTR_DEFAULT;
n->location = @1;
n->raw_expr = $2;
n->cooked_expr = NULL;
$$ = (PGNode *)n;
}
| REFERENCES qualified_name opt_column_list key_match key_actions
{
PGConstraint *n = makeNode(PGConstraint);
n->contype = PG_CONSTR_FOREIGN;
n->location = @1;
n->pktable = $2;
n->fk_attrs = NIL;
n->pk_attrs = $3;
n->fk_matchtype = $4;
n->fk_upd_action = (char) ($5 >> 8);
n->fk_del_action = (char) ($5 & 0xFF);
n->skip_validation = false;
n->initially_valid = true;
$$ = (PGNode *)n;
}
;
GeneratedColumnType:
VIRTUAL { $$ = PG_CONSTR_GENERATED_VIRTUAL; }
| STORED { $$ = PG_CONSTR_GENERATED_STORED; }
;
opt_GeneratedColumnType:
GeneratedColumnType { $$ = $1; }
| /* EMPTY */ { $$ = PG_CONSTR_GENERATED_VIRTUAL; }
;
GeneratedConstraintElem:
GENERATED generated_when AS IDENTITY_P OptParenthesizedSeqOptList
{
PGConstraint *n = makeNode(PGConstraint);
n->contype = PG_CONSTR_IDENTITY;
n->generated_when = $2;
n->options = $5;
n->location = @1;
$$ = (PGNode *)n;
}
| GENERATED generated_when AS '(' a_expr ')' opt_GeneratedColumnType
{
PGConstraint *n = makeNode(PGConstraint);
n->contype = $7;
n->generated_when = $2;
n->raw_expr = $5;
n->cooked_expr = NULL;
n->location = @1;
/*
* Can't do this in the grammar because of shift/reduce
* conflicts. (IDENTITY allows both ALWAYS and BY
* DEFAULT, but generated columns only allow ALWAYS.) We
* can also give a more useful error message and location.
*/
if ($2 != PG_ATTRIBUTE_IDENTITY_ALWAYS)
ereport(ERROR,
(errcode(PG_ERRCODE_SYNTAX_ERROR),
errmsg("for a generated column, GENERATED ALWAYS must be specified"),
parser_errposition(@2)));
$$ = (PGNode *)n;
}
| AS '(' a_expr ')' opt_GeneratedColumnType
{
PGConstraint *n = makeNode(PGConstraint);
n->contype = $5;
n->generated_when = PG_ATTRIBUTE_IDENTITY_ALWAYS;
n->raw_expr = $3;
n->cooked_expr = NULL;
n->location = @1;
$$ = (PGNode *)n;
}
;
generic_option_elem:
generic_option_name generic_option_arg
{
$$ = makeDefElem($1, $2, @1);
}
;
key_update: ON UPDATE key_action { $$ = $3; }
;
key_actions:
key_update
{ $$ = ($1 << 8) | (PG_FKCONSTR_ACTION_NOACTION & 0xFF); }
| key_delete
{ $$ = (PG_FKCONSTR_ACTION_NOACTION << 8) | ($1 & 0xFF); }
| key_update key_delete
{ $$ = ($1 << 8) | ($2 & 0xFF); }
| key_delete key_update
{ $$ = ($2 << 8) | ($1 & 0xFF); }
| /*EMPTY*/
{ $$ = (PG_FKCONSTR_ACTION_NOACTION << 8) | (PG_FKCONSTR_ACTION_NOACTION & 0xFF); }
;
OnCommitOption: ON COMMIT DROP { $$ = ONCOMMIT_DROP; }
| ON COMMIT DELETE_P ROWS { $$ = PG_ONCOMMIT_DELETE_ROWS; }
| ON COMMIT PRESERVE ROWS { $$ = PG_ONCOMMIT_PRESERVE_ROWS; }
| /*EMPTY*/ { $$ = PG_ONCOMMIT_NOOP; }
;
reloptions:
'(' reloption_list ')' { $$ = $2; }
;
opt_no_inherit: NO INHERIT { $$ = true; }
| /* EMPTY */ { $$ = false; }
;
TableConstraint:
CONSTRAINT name ConstraintElem
{
PGConstraint *n = castNode(PGConstraint, $3);
n->conname = $2;
n->location = @1;
$$ = (PGNode *) n;
}
| ConstraintElem { $$ = $1; }
;
TableLikeOption:
COMMENTS { $$ = PG_CREATE_TABLE_LIKE_COMMENTS; }
| CONSTRAINTS { $$ = PG_CREATE_TABLE_LIKE_CONSTRAINTS; }
| DEFAULTS { $$ = PG_CREATE_TABLE_LIKE_DEFAULTS; }
| IDENTITY_P { $$ = PG_CREATE_TABLE_LIKE_IDENTITY; }
| INDEXES { $$ = PG_CREATE_TABLE_LIKE_INDEXES; }
| STATISTICS { $$ = PG_CREATE_TABLE_LIKE_STATISTICS; }
| STORAGE { $$ = PG_CREATE_TABLE_LIKE_STORAGE; }
| ALL { $$ = PG_CREATE_TABLE_LIKE_ALL; }
;
reloption_list:
reloption_elem { $$ = list_make1($1); }
| reloption_list ',' reloption_elem { $$ = lappend($1, $3); }
;
ExistingIndex: USING INDEX index_name { $$ = $3; }
;
ConstraintAttr:
DEFERRABLE
{
PGConstraint *n = makeNode(PGConstraint);
n->contype = PG_CONSTR_ATTR_DEFERRABLE;
n->location = @1;
$$ = (PGNode *)n;
}
| NOT DEFERRABLE
{
PGConstraint *n = makeNode(PGConstraint);
n->contype = PG_CONSTR_ATTR_NOT_DEFERRABLE;
n->location = @1;
$$ = (PGNode *)n;
}
| INITIALLY DEFERRED
{
PGConstraint *n = makeNode(PGConstraint);
n->contype = PG_CONSTR_ATTR_DEFERRED;
n->location = @1;
$$ = (PGNode *)n;
}
| INITIALLY IMMEDIATE
{
PGConstraint *n = makeNode(PGConstraint);
n->contype = PG_CONSTR_ATTR_IMMEDIATE;
n->location = @1;
$$ = (PGNode *)n;
}
;
OptWith:
WITH reloptions { $$ = $2; }
| WITH OIDS { $$ = list_make1(makeDefElem("oids", (PGNode *) makeInteger(true), @1)); }
| WITHOUT OIDS { $$ = list_make1(makeDefElem("oids", (PGNode *) makeInteger(false), @1)); }
| /*EMPTY*/ { $$ = NIL; }
;
definition: '(' def_list ')' { $$ = $2; }
;
TableLikeOptionList:
TableLikeOptionList INCLUDING TableLikeOption { $$ = $1 | $3; }
| TableLikeOptionList EXCLUDING TableLikeOption { $$ = $1 & ~$3; }
| /* EMPTY */ { $$ = 0; }
;
generic_option_name:
ColLabel { $$ = $1; }
;
ConstraintAttributeElem:
NOT DEFERRABLE { $$ = CAS_NOT_DEFERRABLE; }
| DEFERRABLE { $$ = CAS_DEFERRABLE; }
| INITIALLY IMMEDIATE { $$ = CAS_INITIALLY_IMMEDIATE; }
| INITIALLY DEFERRED { $$ = CAS_INITIALLY_DEFERRED; }
| NOT VALID { $$ = CAS_NOT_VALID; }
| NO INHERIT { $$ = CAS_NO_INHERIT; }
;
regularColumnDef:
Typename ColQualList
{
PGColumnDef *n = makeNode(PGColumnDef);
n->category = COL_STANDARD;
n->typeName = $1;
n->inhcount = 0;
n->is_local = true;
n->is_not_null = false;
n->is_from_type = false;
n->storage = 0;
n->raw_default = NULL;
n->cooked_default = NULL;
n->collOid = InvalidOid;
SplitColQualList($2, &n->constraints, &n->collClause,
yyscanner);
$$ = (PGNode *) n;
}
;
generatedColumnDef:
opt_Typename GeneratedConstraintElem ColQualList
{
PGColumnDef *n = makeNode(PGColumnDef);
n->category = COL_GENERATED;
n->typeName = $1;
n->inhcount = 0;
n->is_local = true;
n->is_not_null = false;
n->is_from_type = false;
n->storage = 0;
n->raw_default = NULL;
n->cooked_default = NULL;
n->collOid = InvalidOid;
// merge the constraints with the generated column constraint
auto constraints = $3;
if (constraints) {
constraints = lappend(constraints, $2);
} else {
constraints = list_make1($2);
}
SplitColQualList(constraints, &n->constraints, &n->collClause,
yyscanner);
$$ = (PGNode *)n;
}
;
columnDef: ColId regularColumnDef
{
PGColumnDef *n = (PGColumnDef *) $2;
n->colname = $1;
n->location = @1;
$$ = (PGNode *)n;
}
|
ColId generatedColumnDef
{
PGColumnDef *n = (PGColumnDef *) $2;
n->colname = $1;
n->location = @1;
$$ = (PGNode *)n;
}
;
def_list: def_elem { $$ = list_make1($1); }
| def_list ',' def_elem { $$ = lappend($1, $3); }
;
index_name: ColId { $$ = $1; };
TableElement:
columnDef { $$ = $1; }
| TableLikeClause { $$ = $1; }
| TableConstraint { $$ = $1; }
;
def_elem: ColLabel '=' def_arg
{
$$ = makeDefElem($1, (PGNode *) $3, @1);
}
| ColLabel
{
$$ = makeDefElem($1, NULL, @1);
}
;
opt_definition:
WITH definition { $$ = $2; }
| /*EMPTY*/ { $$ = NIL; }
;
OptTableElementList:
TableElementList { $$ = $1; }
| TableElementList ',' { $$ = $1; }
| /*EMPTY*/ { $$ = NIL; }
;
columnElem: ColId
{
$$ = (PGNode *) makeString($1);
}
;
opt_column_list:
'(' columnList ')' { $$ = $2; }
| /*EMPTY*/ { $$ = NIL; }
;
ColQualList:
ColQualList ColConstraint { $$ = lappend($1, $2); }
| /*EMPTY*/ { $$ = NIL; }
;
key_delete: ON DELETE_P key_action { $$ = $3; }
;
reloption_elem:
ColLabel '=' def_arg
{
$$ = makeDefElem($1, (PGNode *) $3, @1);
}
| ColLabel
{
$$ = makeDefElem($1, NULL, @1);
}
| ColLabel '.' ColLabel '=' def_arg
{
$$ = makeDefElemExtended($1, $3, (PGNode *) $5,
PG_DEFELEM_UNSPEC, @1);
}
| ColLabel '.' ColLabel
{
$$ = makeDefElemExtended($1, $3, NULL, PG_DEFELEM_UNSPEC, @1);
}
;
columnList:
columnElem { $$ = list_make1($1); }
| columnList ',' columnElem { $$ = lappend($1, $3); }
;
columnList_opt_comma:
columnList { $$ = $1; }
| columnList ',' { $$ = $1; }
;
func_type: Typename { $$ = $1; }
| type_function_name attrs '%' TYPE_P
{
$$ = makeTypeNameFromNameList(lcons(makeString($1), $2));
$$->pct_type = true;
$$->location = @1;
}
| SETOF type_function_name attrs '%' TYPE_P
{
$$ = makeTypeNameFromNameList(lcons(makeString($2), $3));
$$->pct_type = true;
$$->setof = true;
$$->location = @2;
}
;
ConstraintElem:
CHECK_P '(' a_expr ')' ConstraintAttributeSpec
{
PGConstraint *n = makeNode(PGConstraint);
n->contype = PG_CONSTR_CHECK;
n->location = @1;
n->raw_expr = $3;
n->cooked_expr = NULL;
processCASbits($5, @5, "CHECK",
NULL, NULL, &n->skip_validation,
&n->is_no_inherit, yyscanner);
n->initially_valid = !n->skip_validation;
$$ = (PGNode *)n;
}
| UNIQUE '(' columnList_opt_comma ')' opt_definition
ConstraintAttributeSpec
{
PGConstraint *n = makeNode(PGConstraint);
n->contype = PG_CONSTR_UNIQUE;
n->location = @1;
n->keys = $3;
n->options = $5;
n->indexname = NULL;
processCASbits($6, @6, "UNIQUE",
&n->deferrable, &n->initdeferred, NULL,
NULL, yyscanner);
$$ = (PGNode *)n;
}
| UNIQUE ExistingIndex ConstraintAttributeSpec
{
PGConstraint *n = makeNode(PGConstraint);
n->contype = PG_CONSTR_UNIQUE;
n->location = @1;
n->keys = NIL;
n->options = NIL;
n->indexname = $2;
n->indexspace = NULL;
processCASbits($3, @3, "UNIQUE",
&n->deferrable, &n->initdeferred, NULL,
NULL, yyscanner);
$$ = (PGNode *)n;
}
| PRIMARY KEY '(' columnList_opt_comma ')' opt_definition
ConstraintAttributeSpec
{
PGConstraint *n = makeNode(PGConstraint);
n->contype = PG_CONSTR_PRIMARY;
n->location = @1;
n->keys = $4;
n->options = $6;
n->indexname = NULL;
processCASbits($7, @7, "PRIMARY KEY",
&n->deferrable, &n->initdeferred, NULL,
NULL, yyscanner);
$$ = (PGNode *)n;
}
| PRIMARY KEY ExistingIndex ConstraintAttributeSpec
{
PGConstraint *n = makeNode(PGConstraint);
n->contype = PG_CONSTR_PRIMARY;
n->location = @1;
n->keys = NIL;
n->options = NIL;
n->indexname = $3;
n->indexspace = NULL;
processCASbits($4, @4, "PRIMARY KEY",
&n->deferrable, &n->initdeferred, NULL,
NULL, yyscanner);
$$ = (PGNode *)n;
}
| FOREIGN KEY '(' columnList_opt_comma ')' REFERENCES qualified_name
opt_column_list key_match key_actions ConstraintAttributeSpec
{
PGConstraint *n = makeNode(PGConstraint);
n->contype = PG_CONSTR_FOREIGN;
n->location = @1;
n->pktable = $7;
n->fk_attrs = $4;
n->pk_attrs = $8;
n->fk_matchtype = $9;
n->fk_upd_action = (char) ($10 >> 8);
n->fk_del_action = (char) ($10 & 0xFF);
processCASbits($11, @11, "FOREIGN KEY",
&n->deferrable, &n->initdeferred,
&n->skip_validation, NULL,
yyscanner);
n->initially_valid = !n->skip_validation;
$$ = (PGNode *)n;
}
;
TableElementList:
TableElement
{
$$ = list_make1($1);
}
| TableElementList ',' TableElement
{
$$ = lappend($1, $3);
}
;
key_match: MATCH FULL
{
$$ = PG_FKCONSTR_MATCH_FULL;
}
| MATCH PARTIAL
{
ereport(ERROR,
(errcode(PG_ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("MATCH PARTIAL not yet implemented"),
parser_errposition(@1)));
$$ = PG_FKCONSTR_MATCH_PARTIAL;
}
| MATCH SIMPLE
{
$$ = PG_FKCONSTR_MATCH_SIMPLE;
}
| /*EMPTY*/
{
$$ = PG_FKCONSTR_MATCH_SIMPLE;
}
;
TableLikeClause:
LIKE qualified_name TableLikeOptionList
{
PGTableLikeClause *n = makeNode(PGTableLikeClause);
n->relation = $2;
n->options = $3;
$$ = (PGNode *)n;
}
;
OptTemp: TEMPORARY { $$ = PG_RELPERSISTENCE_TEMP; }
| TEMP { $$ = PG_RELPERSISTENCE_TEMP; }
| LOCAL TEMPORARY { $$ = PG_RELPERSISTENCE_TEMP; }
| LOCAL TEMP { $$ = PG_RELPERSISTENCE_TEMP; }
| GLOBAL TEMPORARY
{
ereport(PGWARNING,
(errmsg("GLOBAL is deprecated in temporary table creation"),
parser_errposition(@1)));
$$ = PG_RELPERSISTENCE_TEMP;
}
| GLOBAL TEMP
{
ereport(PGWARNING,
(errmsg("GLOBAL is deprecated in temporary table creation"),
parser_errposition(@1)));
$$ = PG_RELPERSISTENCE_TEMP;
}
| UNLOGGED { $$ = PG_RELPERSISTENCE_UNLOGGED; }
| /*EMPTY*/ { $$ = RELPERSISTENCE_PERMANENT; }
;
generated_when:
ALWAYS { $$ = PG_ATTRIBUTE_IDENTITY_ALWAYS; }
| BY DEFAULT { $$ = ATTRIBUTE_IDENTITY_BY_DEFAULT; }
;

View File

@@ -0,0 +1,71 @@
/*****************************************************************************
*
* QUERY :
* CREATE TABLE relname AS PGSelectStmt [ WITH [NO] DATA ]
*
*
* Note: SELECT ... INTO is a now-deprecated alternative for this.
*
*****************************************************************************/
CreateAsStmt:
CREATE_P OptTemp TABLE create_as_target AS SelectStmt opt_with_data
{
PGCreateTableAsStmt *ctas = makeNode(PGCreateTableAsStmt);
ctas->query = $6;
ctas->into = $4;
ctas->relkind = PG_OBJECT_TABLE;
ctas->is_select_into = false;
ctas->onconflict = PG_ERROR_ON_CONFLICT;
/* cram additional flags into the PGIntoClause */
$4->rel->relpersistence = $2;
$4->skipData = !($7);
$$ = (PGNode *) ctas;
}
| CREATE_P OptTemp TABLE IF_P NOT EXISTS create_as_target AS SelectStmt opt_with_data
{
PGCreateTableAsStmt *ctas = makeNode(PGCreateTableAsStmt);
ctas->query = $9;
ctas->into = $7;
ctas->relkind = PG_OBJECT_TABLE;
ctas->is_select_into = false;
ctas->onconflict = PG_IGNORE_ON_CONFLICT;
/* cram additional flags into the PGIntoClause */
$7->rel->relpersistence = $2;
$7->skipData = !($10);
$$ = (PGNode *) ctas;
}
| CREATE_P OR REPLACE OptTemp TABLE create_as_target AS SelectStmt opt_with_data
{
PGCreateTableAsStmt *ctas = makeNode(PGCreateTableAsStmt);
ctas->query = $8;
ctas->into = $6;
ctas->relkind = PG_OBJECT_TABLE;
ctas->is_select_into = false;
ctas->onconflict = PG_REPLACE_ON_CONFLICT;
/* cram additional flags into the PGIntoClause */
$6->rel->relpersistence = $4;
$6->skipData = !($9);
$$ = (PGNode *) ctas;
}
;
opt_with_data:
WITH DATA_P { $$ = true; }
| WITH NO DATA_P { $$ = false; }
| /*EMPTY*/ { $$ = true; }
;
create_as_target:
qualified_name opt_column_list OptWith OnCommitOption
{
$$ = makeNode(PGIntoClause);
$$->rel = $1;
$$->colNames = $2;
$$->options = $3;
$$->onCommit = $4;
$$->viewQuery = NULL;
$$->skipData = false; /* might get changed later */
}
;

View File

@@ -0,0 +1,180 @@
/*****************************************************************************
*
* CREATE FUNCTION stmt
*
*****************************************************************************/
CreateFunctionStmt:
CREATE_P OptTemp macro_alias qualified_name table_macro_list
{
PGCreateFunctionStmt *n = makeNode(PGCreateFunctionStmt);
$4->relpersistence = $2;
n->name = $4;
n->functions = $5;
n->onconflict = PG_ERROR_ON_CONFLICT;
$$ = (PGNode *)n;
}
| CREATE_P OptTemp macro_alias IF_P NOT EXISTS qualified_name table_macro_list
{
PGCreateFunctionStmt *n = makeNode(PGCreateFunctionStmt);
$7->relpersistence = $2;
n->name = $7;
n->functions = $8;
n->onconflict = PG_IGNORE_ON_CONFLICT;
$$ = (PGNode *)n;
}
| CREATE_P OR REPLACE OptTemp macro_alias qualified_name table_macro_list
{
PGCreateFunctionStmt *n = makeNode(PGCreateFunctionStmt);
$6->relpersistence = $4;
n->name = $6;
n->functions = $7;
n->onconflict = PG_REPLACE_ON_CONFLICT;
$$ = (PGNode *)n;
}
| CREATE_P OptTemp macro_alias qualified_name macro_definition_list
{
PGCreateFunctionStmt *n = makeNode(PGCreateFunctionStmt);
$4->relpersistence = $2;
n->name = $4;
n->functions = $5;
n->onconflict = PG_ERROR_ON_CONFLICT;
$$ = (PGNode *)n;
}
| CREATE_P OptTemp macro_alias IF_P NOT EXISTS qualified_name macro_definition_list
{
PGCreateFunctionStmt *n = makeNode(PGCreateFunctionStmt);
$7->relpersistence = $2;
n->name = $7;
n->functions = $8;
n->onconflict = PG_IGNORE_ON_CONFLICT;
$$ = (PGNode *)n;
}
| CREATE_P OR REPLACE OptTemp macro_alias qualified_name macro_definition_list
{
PGCreateFunctionStmt *n = makeNode(PGCreateFunctionStmt);
$6->relpersistence = $4;
n->name = $6;
n->functions = $7;
n->onconflict = PG_REPLACE_ON_CONFLICT;
$$ = (PGNode *)n;
}
;
table_macro_definition:
param_list AS TABLE select_no_parens
{
PGFunctionDefinition *n = makeNode(PGFunctionDefinition);
n->params = $1;
n->query = $4;
$$ = (PGNode *)n;
}
;
table_macro_definition_parens:
param_list AS TABLE select_with_parens
{
PGFunctionDefinition *n = makeNode(PGFunctionDefinition);
n->params = $1;
n->query = $4;
$$ = (PGNode *)n;
}
;
table_macro_list_internal:
table_macro_definition_parens
{
$$ = list_make1($1);
}
| table_macro_list_internal ',' table_macro_definition_parens
{
$$ = lappend($1, $3);
}
;
table_macro_list:
table_macro_definition
{
$$ = list_make1($1);
}
| table_macro_list_internal
;
macro_definition:
param_list AS a_expr
{
PGFunctionDefinition *n = makeNode(PGFunctionDefinition);
n->params = $1;
n->function = $3;
$$ = (PGNode *)n;
}
;
macro_definition_list:
macro_definition
{
$$ = list_make1($1);
}
| macro_definition_list ',' macro_definition
{
$$ = lappend($1, $3);
}
;
macro_alias:
FUNCTION
| MACRO
;
param_list:
'(' ')'
{
$$ = NIL;
}
| '(' MacroParameterList ',' ')'
{
$$ = $2;
}
| '(' MacroParameterList ')'
{
$$ = $2;
}
;
MacroParameterList:
MacroParameter
{
$$ = list_make1($1);
}
| MacroParameterList ',' MacroParameter
{
$$ = lappend($1, $3);
}
;
MacroParameter:
param_name opt_Typename
{
PGFunctionParameter *n = makeNode(PGFunctionParameter);
n->name = $1;
n->typeName = $2;
n->defaultValue = NULL;
$$ = (PGNode *) n;
}
| param_name opt_Typename COLON_EQUALS a_expr
{
PGFunctionParameter *n = makeNode(PGFunctionParameter);
n->name = $1;
n->typeName = $2;
n->defaultValue = (PGExpr *) $4;
$$ = (PGNode *) n;
}
| param_name opt_Typename EQUALS_GREATER a_expr
{
PGFunctionParameter *n = makeNode(PGFunctionParameter);
n->name = $1;
n->typeName = $2;
n->defaultValue = (PGExpr *) $4;
$$ = (PGNode *) n;
}
;

View File

@@ -0,0 +1,89 @@
/*****************************************************************************
*
* Manipulate a schema
*
*****************************************************************************/
CreateSchemaStmt:
CREATE_P SCHEMA qualified_name OptSchemaEltList
{
PGCreateSchemaStmt *n = makeNode(PGCreateSchemaStmt);
if ($3->catalogname) {
ereport(ERROR,
(errcode(PG_ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("CREATE SCHEMA too many dots: expected \"catalog.schema\" or \"schema\""),
parser_errposition(@3)));
}
if ($3->schemaname) {
n->catalogname = $3->schemaname;
n->schemaname = $3->relname;
} else {
n->schemaname = $3->relname;
}
n->schemaElts = $4;
n->onconflict = PG_ERROR_ON_CONFLICT;
$$ = (PGNode *)n;
}
| CREATE_P SCHEMA IF_P NOT EXISTS qualified_name OptSchemaEltList
{
PGCreateSchemaStmt *n = makeNode(PGCreateSchemaStmt);
if ($6->catalogname) {
ereport(ERROR,
(errcode(PG_ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("CREATE SCHEMA too many dots: expected \"catalog.schema\" or \"schema\""),
parser_errposition(@6)));
}
if ($6->schemaname) {
n->catalogname = $6->schemaname;
n->schemaname = $6->relname;
} else {
n->schemaname = $6->relname;
}
if ($7 != NIL)
ereport(ERROR,
(errcode(PG_ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("CREATE SCHEMA IF NOT EXISTS cannot include schema elements"),
parser_errposition(@7)));
n->schemaElts = $7;
n->onconflict = PG_IGNORE_ON_CONFLICT;
$$ = (PGNode *)n;
}
| CREATE_P OR REPLACE SCHEMA qualified_name OptSchemaEltList
{
PGCreateSchemaStmt *n = makeNode(PGCreateSchemaStmt);
if ($5->catalogname) {
ereport(ERROR,
(errcode(PG_ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("CREATE SCHEMA too many dots: expected \"catalog.schema\" or \"schema\""),
parser_errposition(@5)));
}
if ($5->schemaname) {
n->catalogname = $5->schemaname;
n->schemaname = $5->relname;
} else {
n->schemaname = $5->relname;
}
n->schemaElts = $6;
n->onconflict = PG_REPLACE_ON_CONFLICT;
$$ = (PGNode *)n;
}
;
OptSchemaEltList:
OptSchemaEltList schema_stmt
{
if (@$ < 0) /* see comments for YYLLOC_DEFAULT */
@$ = @2;
$$ = lappend($1, $2);
}
| /* EMPTY */
{ $$ = NIL; }
;
schema_stmt:
CreateStmt
| IndexStmt
| CreateSeqStmt
| ViewStmt
;

View File

@@ -0,0 +1,76 @@
/*****************************************************************************
*
* Create a secret
*
*****************************************************************************/
CreateSecretStmt:
CREATE_P opt_persist SECRET opt_secret_name opt_storage_specifier '(' create_secret_generic_opt_list ')'
{
PGCreateSecretStmt *n = makeNode(PGCreateSecretStmt);
n->persist_type = $2;
n->secret_name = $4;
n->secret_storage = $5;
n->options = $7;
n->onconflict = PG_ERROR_ON_CONFLICT;
$$ = (PGNode *)n;
}
| CREATE_P opt_persist SECRET IF_P NOT EXISTS opt_secret_name opt_storage_specifier '(' create_secret_generic_opt_list ')'
{
PGCreateSecretStmt *n = makeNode(PGCreateSecretStmt);
n->persist_type = $2;
n->secret_name = $7;
n->secret_storage = $8;
n->options = $10;
n->onconflict = PG_IGNORE_ON_CONFLICT;
$$ = (PGNode *)n;
}
| CREATE_P OR REPLACE opt_persist SECRET opt_secret_name opt_storage_specifier '(' create_secret_generic_opt_list ')'
{
PGCreateSecretStmt *n = makeNode(PGCreateSecretStmt);
n->persist_type = $4;
n->secret_name = $6;
n->secret_storage = $7;
n->options = $9;
n->onconflict = PG_REPLACE_ON_CONFLICT;
$$ = (PGNode *)n;
}
;
opt_secret_name:
/* empty */ { $$ = NULL; }
| ColId { $$ = $1; }
;
opt_persist:
/* empty */ { $$ = pstrdup("default"); }
| TEMPORARY { $$ = pstrdup("temporary"); }
| PERSISTENT { $$ = pstrdup("persistent"); }
;
opt_storage_specifier:
/* empty */ { $$ = pstrdup(""); }
| IN_P IDENT { $$ = $2; }
;
create_secret_generic_opt_arg:
a_expr { $$ = (PGNode *) $1; }
;
create_secret_generic_opt_elem:
ColLabel create_secret_generic_opt_arg
{
$$ = makeDefElem($1, $2, @1);
}
;
create_secret_generic_opt_list:
create_secret_generic_opt_elem
{
$$ = list_make1($1);
}
| create_secret_generic_opt_list ',' create_secret_generic_opt_elem
{
$$ = lappend($1, $3);
}
;

View File

@@ -0,0 +1,44 @@
/*****************************************************************************
*
* QUERY :
* CREATE SEQUENCE seqname
* ALTER SEQUENCE seqname
*
*****************************************************************************/
CreateSeqStmt:
CREATE_P OptTemp SEQUENCE qualified_name OptSeqOptList
{
PGCreateSeqStmt *n = makeNode(PGCreateSeqStmt);
$4->relpersistence = $2;
n->sequence = $4;
n->options = $5;
n->ownerId = InvalidOid;
n->onconflict = PG_ERROR_ON_CONFLICT;
$$ = (PGNode *)n;
}
| CREATE_P OptTemp SEQUENCE IF_P NOT EXISTS qualified_name OptSeqOptList
{
PGCreateSeqStmt *n = makeNode(PGCreateSeqStmt);
$7->relpersistence = $2;
n->sequence = $7;
n->options = $8;
n->ownerId = InvalidOid;
n->onconflict = PG_IGNORE_ON_CONFLICT;
$$ = (PGNode *)n;
}
| CREATE_P OR REPLACE OptTemp SEQUENCE qualified_name OptSeqOptList
{
PGCreateSeqStmt *n = makeNode(PGCreateSeqStmt);
$6->relpersistence = $4;
n->sequence = $6;
n->options = $7;
n->ownerId = InvalidOid;
n->onconflict = PG_REPLACE_ON_CONFLICT;
$$ = (PGNode *)n;
}
;
OptSeqOptList: SeqOptList { $$ = $1; }
| /*EMPTY*/ { $$ = NIL; }
;

View File

@@ -0,0 +1,83 @@
/*****************************************************************************
*
* Create Type Statement
*
*****************************************************************************/
CreateTypeStmt:
CREATE_P OptTemp TYPE_P qualified_name AS create_type_value
{
PGCreateTypeStmt *n = (PGCreateTypeStmt *) $6;
$4->relpersistence = $2;
n->typeName = $4;
n->onconflict = PG_ERROR_ON_CONFLICT;
$$ = (PGNode *)n;
}
| CREATE_P OptTemp TYPE_P IF_P NOT EXISTS qualified_name AS create_type_value
{
PGCreateTypeStmt *n = (PGCreateTypeStmt *) $9;
$7->relpersistence = $2;
n->typeName = $7;
n->onconflict = PG_IGNORE_ON_CONFLICT;
$$ = (PGNode *)n;
}
| CREATE_P OR REPLACE OptTemp TYPE_P qualified_name AS create_type_value
{
PGCreateTypeStmt *n = (PGCreateTypeStmt *) $8;
$6->relpersistence = $4;
n->typeName = $6;
n->onconflict = PG_REPLACE_ON_CONFLICT;
$$ = (PGNode *)n;
}
;
create_type_value:
ENUM_P select_with_parens
{
PGCreateTypeStmt *n = makeNode(PGCreateTypeStmt);
n->kind = PG_NEWTYPE_ENUM;
n->query = $2;
n->vals = NULL;
$$ = (PGNode *)n;
}
| ENUM_P '(' opt_enum_val_list ')'
{
PGCreateTypeStmt *n = makeNode(PGCreateTypeStmt);
n->kind = PG_NEWTYPE_ENUM;
n->vals = $3;
n->query = NULL;
$$ = (PGNode *)n;
}
| Typename
{
PGCreateTypeStmt *n = makeNode(PGCreateTypeStmt);
n->query = NULL;
auto name = std::string(reinterpret_cast<PGValue *>($1->names->tail->data.ptr_value)->val.str);
if (name == "enum") {
n->kind = PG_NEWTYPE_ENUM;
n->vals = $1->typmods;
} else {
n->kind = PG_NEWTYPE_ALIAS;
n->ofType = $1;
}
$$ = (PGNode *)n;
}
;
opt_enum_val_list:
enum_val_list { $$ = $1;}
| {$$ = NIL;}
;
enum_val_list: Sconst
{
$$ = list_make1(makeStringConst($1, @1));
}
| enum_val_list ',' Sconst
{
$$ = lappend($1, makeStringConst($3, @3));
}
;

View File

@@ -0,0 +1,31 @@
/*****************************************************************************
*
* QUERY:
* DEALLOCATE [PREPARE] <plan_name>
*
*****************************************************************************/
DeallocateStmt: DEALLOCATE name
{
PGDeallocateStmt *n = makeNode(PGDeallocateStmt);
n->name = $2;
$$ = (PGNode *) n;
}
| DEALLOCATE PREPARE name
{
PGDeallocateStmt *n = makeNode(PGDeallocateStmt);
n->name = $3;
$$ = (PGNode *) n;
}
| DEALLOCATE ALL
{
PGDeallocateStmt *n = makeNode(PGDeallocateStmt);
n->name = NULL;
$$ = (PGNode *) n;
}
| DEALLOCATE PREPARE ALL
{
PGDeallocateStmt *n = makeNode(PGDeallocateStmt);
n->name = NULL;
$$ = (PGNode *) n;
}
;

View File

@@ -0,0 +1,62 @@
/*****************************************************************************
*
* QUERY:
* DELETE STATEMENTS
*
*****************************************************************************/
DeleteStmt: opt_with_clause DELETE_P FROM relation_expr_opt_alias
using_clause where_or_current_clause returning_clause
{
PGDeleteStmt *n = makeNode(PGDeleteStmt);
n->relation = $4;
n->usingClause = $5;
n->whereClause = $6;
n->returningList = $7;
n->withClause = $1;
$$ = (PGNode *)n;
}
| TRUNCATE opt_table relation_expr_opt_alias
{
PGDeleteStmt *n = makeNode(PGDeleteStmt);
n->relation = $3;
n->usingClause = NULL;
n->whereClause = NULL;
n->returningList = NULL;
n->withClause = NULL;
$$ = (PGNode *)n;
}
;
relation_expr_opt_alias: relation_expr %prec UMINUS
{
$$ = $1;
}
| relation_expr ColId
{
PGAlias *alias = makeNode(PGAlias);
alias->aliasname = $2;
$1->alias = alias;
$$ = $1;
}
| relation_expr AS ColId
{
PGAlias *alias = makeNode(PGAlias);
alias->aliasname = $3;
$1->alias = alias;
$$ = $1;
}
;
where_or_current_clause:
WHERE a_expr { $$ = $2; }
| /*EMPTY*/ { $$ = NULL; }
;
using_clause:
USING from_list_opt_comma { $$ = $2; }
| /*EMPTY*/ { $$ = NIL; }
;

View File

@@ -0,0 +1,125 @@
/*****************************************************************************
*
* QUERY:
*
* DROP itemtype [ IF EXISTS ] itemname [, itemname ...]
* [ RESTRICT | CASCADE ]
*
*****************************************************************************/
DropStmt: DROP drop_type_any_name IF_P EXISTS any_name_list opt_drop_behavior
{
PGDropStmt *n = makeNode(PGDropStmt);
n->removeType = $2;
n->missing_ok = true;
n->objects = $5;
n->behavior = $6;
n->concurrent = false;
$$ = (PGNode *)n;
}
| DROP drop_type_any_name any_name_list opt_drop_behavior
{
PGDropStmt *n = makeNode(PGDropStmt);
n->removeType = $2;
n->missing_ok = false;
n->objects = $3;
n->behavior = $4;
n->concurrent = false;
$$ = (PGNode *)n;
}
| DROP drop_type_name IF_P EXISTS name_list opt_drop_behavior
{
PGDropStmt *n = makeNode(PGDropStmt);
n->removeType = $2;
n->missing_ok = true;
n->objects = $5;
n->behavior = $6;
n->concurrent = false;
$$ = (PGNode *)n;
}
| DROP drop_type_name name_list opt_drop_behavior
{
PGDropStmt *n = makeNode(PGDropStmt);
n->removeType = $2;
n->missing_ok = false;
n->objects = $3;
n->behavior = $4;
n->concurrent = false;
$$ = (PGNode *)n;
}
| DROP drop_type_name_on_any_name name ON any_name opt_drop_behavior
{
PGDropStmt *n = makeNode(PGDropStmt);
n->removeType = $2;
n->objects = list_make1(lappend($5, makeString($3)));
n->behavior = $6;
n->missing_ok = false;
n->concurrent = false;
$$ = (PGNode *) n;
}
| DROP drop_type_name_on_any_name IF_P EXISTS name ON any_name opt_drop_behavior
{
PGDropStmt *n = makeNode(PGDropStmt);
n->removeType = $2;
n->objects = list_make1(lappend($7, makeString($5)));
n->behavior = $8;
n->missing_ok = true;
n->concurrent = false;
$$ = (PGNode *) n;
}
;
drop_type_any_name:
TABLE { $$ = PG_OBJECT_TABLE; }
| SEQUENCE { $$ = PG_OBJECT_SEQUENCE; }
| FUNCTION { $$ = PG_OBJECT_FUNCTION; }
| MACRO { $$ = PG_OBJECT_FUNCTION; }
| MACRO TABLE { $$ = PG_OBJECT_TABLE_MACRO; }
| VIEW { $$ = PG_OBJECT_VIEW; }
| MATERIALIZED VIEW { $$ = PG_OBJECT_MATVIEW; }
| INDEX { $$ = PG_OBJECT_INDEX; }
| FOREIGN TABLE { $$ = PG_OBJECT_FOREIGN_TABLE; }
| COLLATION { $$ = PG_OBJECT_COLLATION; }
| CONVERSION_P { $$ = PG_OBJECT_CONVERSION; }
| SCHEMA { $$ = PG_OBJECT_SCHEMA; }
| STATISTICS { $$ = PG_OBJECT_STATISTIC_EXT; }
| TEXT_P SEARCH PARSER { $$ = PG_OBJECT_TSPARSER; }
| TEXT_P SEARCH DICTIONARY { $$ = PG_OBJECT_TSDICTIONARY; }
| TEXT_P SEARCH TEMPLATE { $$ = PG_OBJECT_TSTEMPLATE; }
| TEXT_P SEARCH CONFIGURATION { $$ = PG_OBJECT_TSCONFIGURATION; }
| TYPE_P { $$ = PG_OBJECT_TYPE; }
;
drop_type_name:
ACCESS METHOD { $$ = PG_OBJECT_ACCESS_METHOD; }
| EVENT TRIGGER { $$ = PG_OBJECT_EVENT_TRIGGER; }
| EXTENSION { $$ = PG_OBJECT_EXTENSION; }
| FOREIGN DATA_P WRAPPER { $$ = PG_OBJECT_FDW; }
| PUBLICATION { $$ = PG_OBJECT_PUBLICATION; }
| SERVER { $$ = PG_OBJECT_FOREIGN_SERVER; }
;
any_name_list:
any_name { $$ = list_make1($1); }
| any_name_list ',' any_name { $$ = lappend($1, $3); }
;
opt_drop_behavior:
CASCADE { $$ = PG_DROP_CASCADE; }
| RESTRICT { $$ = PG_DROP_RESTRICT; }
| /* EMPTY */ { $$ = PG_DROP_RESTRICT; /* default */ }
;
drop_type_name_on_any_name:
POLICY { $$ = PG_OBJECT_POLICY; }
| RULE { $$ = PG_OBJECT_RULE; }
| TRIGGER { $$ = PG_OBJECT_TRIGGER; }
;
type_name_list:
Typename { $$ = list_make1($1); }
| type_name_list ',' Typename { $$ = lappend($1, $3); }
;

View File

@@ -0,0 +1,30 @@
/*****************************************************************************
*
* Drop a secret
*
*****************************************************************************/
DropSecretStmt:
DROP opt_persist SECRET ColId opt_storage_drop_specifier
{
PGDropSecretStmt *n = makeNode(PGDropSecretStmt);
n->persist_type = $2;
n->secret_name = $4;
n->secret_storage = $5;
n->missing_ok = false;
$$ = (PGNode *)n;
}
| DROP opt_persist SECRET IF_P EXISTS ColId opt_storage_drop_specifier
{
PGDropSecretStmt *n = makeNode(PGDropSecretStmt);
n->persist_type = $2;
n->secret_name = $6;
n->secret_storage = $7;
n->missing_ok = true;
$$ = (PGNode *)n;
}
;
opt_storage_drop_specifier:
/* empty */ { $$ = pstrdup(""); }
| FROM IDENT { $$ = $2; }
;

View File

@@ -0,0 +1,77 @@
/*****************************************************************************
*
* EXECUTE <plan_name> [(params, ...)]
* CREATE TABLE <name> AS EXECUTE <plan_name> [(params, ...)]
*
*****************************************************************************/
ExecuteStmt: EXECUTE name execute_param_clause
{
PGExecuteStmt *n = makeNode(PGExecuteStmt);
n->name = $2;
n->params = $3;
$$ = (PGNode *) n;
}
| CREATE_P OptTemp TABLE create_as_target AS
EXECUTE name execute_param_clause opt_with_data
{
PGCreateTableAsStmt *ctas = makeNode(PGCreateTableAsStmt);
PGExecuteStmt *n = makeNode(PGExecuteStmt);
n->name = $7;
n->params = $8;
ctas->query = (PGNode *) n;
ctas->into = $4;
ctas->relkind = PG_OBJECT_TABLE;
ctas->is_select_into = false;
ctas->onconflict = PG_ERROR_ON_CONFLICT;
/* cram additional flags into the PGIntoClause */
$4->rel->relpersistence = $2;
$4->skipData = !($9);
$$ = (PGNode *) ctas;
}
| CREATE_P OptTemp TABLE IF_P NOT EXISTS create_as_target AS
EXECUTE name execute_param_clause opt_with_data
{
PGCreateTableAsStmt *ctas = makeNode(PGCreateTableAsStmt);
PGExecuteStmt *n = makeNode(PGExecuteStmt);
n->name = $10;
n->params = $11;
ctas->query = (PGNode *) n;
ctas->into = $7;
ctas->relkind = PG_OBJECT_TABLE;
ctas->is_select_into = false;
ctas->onconflict = PG_IGNORE_ON_CONFLICT;
/* cram additional flags into the PGIntoClause */
$7->rel->relpersistence = $2;
$7->skipData = !($12);
$$ = (PGNode *) ctas;
}
;
execute_param_expr: a_expr
{
$$ = $1;
}
| param_name COLON_EQUALS a_expr
{
PGNamedArgExpr *na = makeNode(PGNamedArgExpr);
na->name = $1;
na->arg = (PGExpr *) $3;
na->argnumber = -1; /* until determined */
na->location = @1;
$$ = (PGNode *) na;
}
execute_param_list: execute_param_expr
{
$$ = list_make1($1);
}
| execute_param_list ',' execute_param_expr
{
$$ = lappend($1, $3);
}
;
execute_param_clause: '(' execute_param_list ')' { $$ = $2; }
| /* EMPTY */ { $$ = NIL; }
;

View File

@@ -0,0 +1,146 @@
/*****************************************************************************
*
* QUERY:
* EXPLAIN [ANALYZE] [VERBOSE] query
* EXPLAIN ( options ) query
*
*****************************************************************************/
ExplainStmt:
EXPLAIN ExplainableStmt
{
PGExplainStmt *n = makeNode(PGExplainStmt);
n->query = $2;
n->options = NIL;
$$ = (PGNode *) n;
}
| EXPLAIN analyze_keyword opt_verbose ExplainableStmt
{
PGExplainStmt *n = makeNode(PGExplainStmt);
n->query = $4;
n->options = list_make1(makeDefElem("analyze", NULL, @2));
if ($3)
n->options = lappend(n->options,
makeDefElem("verbose", NULL, @3));
$$ = (PGNode *) n;
}
| EXPLAIN VERBOSE ExplainableStmt
{
PGExplainStmt *n = makeNode(PGExplainStmt);
n->query = $3;
n->options = list_make1(makeDefElem("verbose", NULL, @2));
$$ = (PGNode *) n;
}
| EXPLAIN '(' explain_option_list ')' ExplainableStmt
{
PGExplainStmt *n = makeNode(PGExplainStmt);
n->query = $5;
n->options = $3;
$$ = (PGNode *) n;
}
;
opt_verbose:
VERBOSE { $$ = true; }
| /*EMPTY*/ { $$ = false; }
;
explain_option_arg:
opt_boolean_or_string { $$ = (PGNode *) makeString($1); }
| NumericOnly { $$ = (PGNode *) $1; }
| /* EMPTY */ { $$ = NULL; }
;
ExplainableStmt:
AlterObjectSchemaStmt
| AlterSeqStmt
| AlterTableStmt
| CallStmt
| CheckPointStmt
| CopyStmt
| CreateAsStmt
| CreateFunctionStmt
| CreateSchemaStmt
| CreateSeqStmt
| CreateStmt
| CreateTypeStmt
| DeallocateStmt
| DeleteStmt
| DropStmt
| ExecuteStmt
| IndexStmt
| InsertStmt
| LoadStmt
| MergeIntoStmt
| PragmaStmt
| PrepareStmt
| RenameStmt
| SelectStmt
| TransactionStmt
| UpdateStmt
| UpdateExtensionsStmt
| VacuumStmt
| VariableResetStmt
| VariableSetStmt
| VariableShowStmt
| ViewStmt
;
NonReservedWord: IDENT { $$ = $1; }
| unreserved_keyword { $$ = pstrdup($1); }
| other_keyword { $$ = pstrdup($1); }
;
NonReservedWord_or_Sconst:
NonReservedWord { $$ = $1; }
| Sconst { $$ = $1; }
;
explain_option_list:
explain_option_elem
{
$$ = list_make1($1);
}
| explain_option_list ',' explain_option_elem
{
$$ = lappend($1, $3);
}
;
analyze_keyword:
ANALYZE {}
| ANALYSE /* British */ {}
;
opt_boolean_or_string:
TRUE_P { $$ = (char*) "true"; }
| FALSE_P { $$ = (char*) "false"; }
| ON { $$ = (char*) "on"; }
/*
* 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.
*/
| NonReservedWord_or_Sconst { $$ = $1; }
;
explain_option_elem:
explain_option_name explain_option_arg
{
$$ = makeDefElem($1, $2, @1);
}
;
explain_option_name:
NonReservedWord { $$ = $1; }
| analyze_keyword { $$ = (char*) "analyze"; }
;

View File

@@ -0,0 +1,39 @@
/*****************************************************************************
*
* EXPORT/IMPORT stmt
*
*****************************************************************************/
ExportStmt:
EXPORT_P DATABASE Sconst copy_options
{
PGExportStmt *n = makeNode(PGExportStmt);
n->database = NULL;
n->filename = $3;
n->options = NIL;
if ($4) {
n->options = list_concat(n->options, $4);
}
$$ = (PGNode *)n;
}
|
EXPORT_P DATABASE ColId TO Sconst copy_options
{
PGExportStmt *n = makeNode(PGExportStmt);
n->database = $3;
n->filename = $5;
n->options = NIL;
if ($6) {
n->options = list_concat(n->options, $6);
}
$$ = (PGNode *)n;
}
;
ImportStmt:
IMPORT_P DATABASE Sconst
{
PGImportStmt *n = makeNode(PGImportStmt);
n->filename = $3;
$$ = (PGNode *)n;
}
;

View File

@@ -0,0 +1,91 @@
/*****************************************************************************
*
* QUERY: CREATE INDEX
*
* Note: we cannot put TABLESPACE clause after WHERE clause unless we are
* willing to make TABLESPACE a fully reserved word.
*****************************************************************************/
IndexStmt: CREATE_P opt_unique INDEX opt_concurrently opt_index_name
ON qualified_name access_method_clause '(' index_params ')'
opt_reloptions where_clause
{
PGIndexStmt *n = makeNode(PGIndexStmt);
n->unique = $2;
n->concurrent = $4;
n->idxname = $5;
n->relation = $7;
n->accessMethod = $8;
n->indexParams = $10;
n->options = $12;
n->whereClause = $13;
n->excludeOpNames = NIL;
n->idxcomment = NULL;
n->indexOid = InvalidOid;
n->oldNode = InvalidOid;
n->primary = false;
n->isconstraint = false;
n->deferrable = false;
n->initdeferred = false;
n->transformed = false;
n->onconflict = PG_ERROR_ON_CONFLICT;
$$ = (PGNode *)n;
}
| CREATE_P opt_unique INDEX opt_concurrently IF_P NOT EXISTS index_name
ON qualified_name access_method_clause '(' index_params ')'
opt_reloptions where_clause
{
PGIndexStmt *n = makeNode(PGIndexStmt);
n->unique = $2;
n->concurrent = $4;
n->idxname = $8;
n->relation = $10;
n->accessMethod = $11;
n->indexParams = $13;
n->options = $15;
n->whereClause = $16;
n->excludeOpNames = NIL;
n->idxcomment = NULL;
n->indexOid = InvalidOid;
n->oldNode = InvalidOid;
n->primary = false;
n->isconstraint = false;
n->deferrable = false;
n->initdeferred = false;
n->transformed = false;
n->onconflict = PG_IGNORE_ON_CONFLICT;
$$ = (PGNode *)n;
}
;
access_method:
ColId { $$ = $1; };
access_method_clause:
USING access_method { $$ = $2; }
| /*EMPTY*/ { $$ = (char*) DEFAULT_INDEX_TYPE; }
;
opt_concurrently:
CONCURRENTLY { $$ = true; }
| /*EMPTY*/ { $$ = false; }
;
opt_index_name:
index_name { $$ = $1; }
| /*EMPTY*/ { $$ = NULL; }
;
opt_reloptions: WITH reloptions { $$ = $2; }
| /* EMPTY */ { $$ = NIL; }
;
opt_unique:
UNIQUE { $$ = true; }
| /*EMPTY*/ { $$ = false; }
;

View File

@@ -0,0 +1,291 @@
/*****************************************************************************
*
* QUERY:
* INSERT STATEMENTS
*
*****************************************************************************/
InsertStmt:
opt_with_clause INSERT opt_or_action INTO insert_target opt_by_name_or_position insert_rest
opt_on_conflict returning_clause
{
$7->relation = $5;
$7->onConflictAlias = $3;
$7->onConflictClause = $8;
$7->returningList = $9;
$7->withClause = $1;
$7->insert_column_order = $6;
$$ = (PGNode *) $7;
}
;
insert_rest:
SelectStmt
{
$$ = makeNode(PGInsertStmt);
$$->cols = NIL;
$$->selectStmt = $1;
}
| OVERRIDING override_kind VALUE_P SelectStmt
{
$$ = makeNode(PGInsertStmt);
$$->cols = NIL;
$$->override = $2;
$$->selectStmt = $4;
}
| '(' insert_column_list ')' SelectStmt
{
$$ = makeNode(PGInsertStmt);
$$->cols = $2;
$$->selectStmt = $4;
}
| '(' insert_column_list ')' OVERRIDING override_kind VALUE_P SelectStmt
{
$$ = makeNode(PGInsertStmt);
$$->cols = $2;
$$->override = $5;
$$->selectStmt = $7;
}
| DEFAULT VALUES
{
$$ = makeNode(PGInsertStmt);
$$->cols = NIL;
$$->selectStmt = NULL;
}
;
insert_target:
qualified_name
{
$$ = $1;
}
| qualified_name AS ColId
{
$1->alias = makeAlias($3, NIL);
$$ = $1;
}
;
opt_by_name_or_position:
BY NAME_P { $$ = PG_INSERT_BY_NAME; }
| BY POSITION { $$ = PG_INSERT_BY_POSITION; }
| /* empty */ { $$ = PG_INSERT_BY_POSITION; }
;
opt_conf_expr:
'(' index_params ')' where_clause
{
$$ = makeNode(PGInferClause);
$$->indexElems = $2;
$$->whereClause = $4;
$$->conname = NULL;
$$->location = @1;
}
|
ON CONSTRAINT name
{
$$ = makeNode(PGInferClause);
$$->indexElems = NIL;
$$->whereClause = NULL;
$$->conname = $3;
$$->location = @1;
}
| /*EMPTY*/
{
$$ = NULL;
}
;
opt_with_clause:
with_clause { $$ = $1; }
| /*EMPTY*/ { $$ = NULL; }
;
insert_column_item:
ColId opt_indirection
{
$$ = makeNode(PGResTarget);
$$->name = $1;
$$->indirection = check_indirection($2, yyscanner);
$$->val = NULL;
$$->location = @1;
}
;
set_clause:
set_target '=' a_expr
{
$1->val = (PGNode *) $3;
$$ = list_make1($1);
}
| '(' set_target_list ')' '=' a_expr
{
int ncolumns = list_length($2);
int i = 1;
PGListCell *col_cell;
/* Create a PGMultiAssignRef source for each target */
foreach(col_cell, $2)
{
PGResTarget *res_col = (PGResTarget *) lfirst(col_cell);
PGMultiAssignRef *r = makeNode(PGMultiAssignRef);
r->source = (PGNode *) $5;
r->colno = i;
r->ncolumns = ncolumns;
res_col->val = (PGNode *) r;
i++;
}
$$ = $2;
}
;
opt_or_action:
OR REPLACE
{
$$ = PG_ONCONFLICT_ALIAS_REPLACE;
}
|
OR IGNORE_P
{
$$ = PG_ONCONFLICT_ALIAS_IGNORE;
}
| /*EMPTY*/
{
$$ = PG_ONCONFLICT_ALIAS_NONE;
}
;
opt_on_conflict:
ON CONFLICT opt_conf_expr DO UPDATE SET set_clause_list_opt_comma where_clause
{
$$ = makeNode(PGOnConflictClause);
$$->action = PG_ONCONFLICT_UPDATE;
$$->infer = $3;
$$->targetList = $7;
$$->whereClause = $8;
$$->location = @1;
}
|
ON CONFLICT opt_conf_expr DO NOTHING
{
$$ = makeNode(PGOnConflictClause);
$$->action = PG_ONCONFLICT_NOTHING;
$$->infer = $3;
$$->targetList = NIL;
$$->whereClause = NULL;
$$->location = @1;
}
| /*EMPTY*/
{
$$ = NULL;
}
;
index_elem: ColId opt_collate opt_class opt_asc_desc opt_nulls_order
{
$$ = makeNode(PGIndexElem);
$$->name = $1;
$$->expr = NULL;
$$->indexcolname = NULL;
$$->collation = $2;
$$->opclass = $3;
$$->ordering = $4;
$$->nulls_ordering = $5;
}
| func_expr_windowless opt_collate opt_class opt_asc_desc opt_nulls_order
{
$$ = makeNode(PGIndexElem);
$$->name = NULL;
$$->expr = $1;
$$->indexcolname = NULL;
$$->collation = $2;
$$->opclass = $3;
$$->ordering = $4;
$$->nulls_ordering = $5;
}
| '(' a_expr ')' opt_collate opt_class opt_asc_desc opt_nulls_order
{
$$ = makeNode(PGIndexElem);
$$->name = NULL;
$$->expr = $2;
$$->indexcolname = NULL;
$$->collation = $4;
$$->opclass = $5;
$$->ordering = $6;
$$->nulls_ordering = $7;
}
;
returning_clause:
RETURNING target_list { $$ = $2; }
| /* EMPTY */ { $$ = NIL; }
;
override_kind:
USER { $$ = PG_OVERRIDING_USER_VALUE; }
| SYSTEM_P { $$ = OVERRIDING_SYSTEM_VALUE; }
;
set_target_list:
set_target { $$ = list_make1($1); }
| set_target_list ',' set_target { $$ = lappend($1,$3); }
;
opt_collate: COLLATE any_name { $$ = $2; }
| /*EMPTY*/ { $$ = NIL; }
;
opt_class: any_name { $$ = $1; }
| /*EMPTY*/ { $$ = NIL; }
;
insert_column_list:
insert_column_item
{ $$ = list_make1($1); }
| insert_column_list ',' insert_column_item
{ $$ = lappend($1, $3); }
;
set_clause_list:
set_clause { $$ = $1; }
| set_clause_list ',' set_clause { $$ = list_concat($1,$3); }
;
set_clause_list_opt_comma:
set_clause_list { $$ = $1; }
| set_clause_list ',' { $$ = $1; }
;
index_params: index_elem { $$ = list_make1($1); }
| index_params ',' index_elem { $$ = lappend($1, $3); }
;
set_target:
ColId opt_indirection
{
$$ = makeNode(PGResTarget);
$$->name = $1;
$$->indirection = check_indirection($2, yyscanner);
$$->val = NULL; /* upper production sets this */
$$->location = @1;
}
;

View File

@@ -0,0 +1,55 @@
/*****************************************************************************
*
* QUERY:
* LOAD "filename"
*
*****************************************************************************/
LoadStmt: LOAD file_name
{
PGLoadStmt *n = makeNode(PGLoadStmt);
n->filename = $2;
n->repository = NULL;
n->repo_is_alias = false;
n->version = NULL;
n->load_type = PG_LOAD_TYPE_LOAD;
$$ = (PGNode *)n;
} |
opt_force INSTALL file_name opt_ext_version {
PGLoadStmt *n = makeNode(PGLoadStmt);
n->filename = $3;
n->repository = NULL;
n->repo_is_alias = false;
n->version = $4;
n->load_type = $1;
$$ = (PGNode *)n;
} |
opt_force INSTALL file_name FROM ColId opt_ext_version {
PGLoadStmt *n = makeNode(PGLoadStmt);
n->repository = $5;
n->repo_is_alias = true;
n->filename = $3;
n->version = $6;
n->load_type = $1;
$$ = (PGNode *)n;
} |
opt_force INSTALL file_name FROM Sconst opt_ext_version {
PGLoadStmt *n = makeNode(PGLoadStmt);
n->filename = $3;
n->repository = $5;
n->repo_is_alias = false;
n->version = $6;
n->load_type = $1;
$$ = (PGNode *)n;
}
;
opt_force: /* empty*/ { $$ = PG_LOAD_TYPE_INSTALL; } |
FORCE { $$ = PG_LOAD_TYPE_FORCE_INSTALL; };
file_name: Sconst { $$ = $1; } |
ColId { $$ = $1; };
opt_ext_version:
/* empty */ { $$ = NULL; } |
VERSION_P Sconst { $$ = $2; } |
VERSION_P ColId { $$ = $2; };

View File

@@ -0,0 +1,148 @@
/*****************************************************************************
*
* QUERY:
* MERGE INTO
*
*****************************************************************************/
MergeIntoStmt: opt_with_clause
MERGE INTO relation_expr_opt_alias
USING table_ref
join_qual
merge_match_list
returning_clause
{
PGMergeIntoStmt *n = makeNode(PGMergeIntoStmt);
n->targetTable = $4;
n->source = $6;
if ($5 != NULL && IsA($7, PGList))
n->usingClause = (PGList *) $7; /* USING clause */
else
n->joinCondition = $7; /* ON clause */
n->matchActions = $8;
n->withClause = $1;
n->returningList = $9;
$$ = (PGNode *)n;
}
;
opt_and_clause:
AND a_expr { $$ = $2; }
| /* EMPTY */ { $$ = NULL; }
;
opt_insert_column_list:
'(' insert_column_list ')' { $$ = $2; }
| /* EMPTY */ { $$ = NULL; }
;
opt_star_expr:
'*' | /* EMPTY */
;
matched_clause_action:
UPDATE SET set_clause_list_opt_comma
{
PGMatchAction *n = makeNode(PGMatchAction);
n->actionType = MERGE_ACTION_TYPE_UPDATE;
n->insert_column_order = PG_INSERT_BY_POSITION;
n->updateTargets = $3;
$$ = (PGNode *)n;
}
| UPDATE SET '*'
{
PGMatchAction *n = makeNode(PGMatchAction);
n->actionType = MERGE_ACTION_TYPE_UPDATE;
n->insert_column_order = PG_INSERT_BY_POSITION;
$$ = (PGNode *)n;
}
| UPDATE opt_by_name_or_position
{
PGMatchAction *n = makeNode(PGMatchAction);
n->actionType = MERGE_ACTION_TYPE_UPDATE;
n->insert_column_order = $2;
$$ = (PGNode *)n;
}
| DELETE_P
{
PGMatchAction *n = makeNode(PGMatchAction);
n->actionType = MERGE_ACTION_TYPE_DELETE;
$$ = (PGNode *)n;
}
| INSERT opt_insert_column_list VALUES '(' expr_list_opt_comma ')'
{
PGMatchAction *n = makeNode(PGMatchAction);
n->actionType = MERGE_ACTION_TYPE_INSERT;
n->insert_column_order = PG_INSERT_BY_POSITION;
n->insertCols = $2;
n->insertValues = $5;
$$ = (PGNode *)n;
}
| INSERT opt_by_name_or_position opt_star_expr
{
PGMatchAction *n = makeNode(PGMatchAction);
n->actionType = MERGE_ACTION_TYPE_INSERT;
n->insert_column_order = $2;
$$ = (PGNode *)n;
}
| INSERT DEFAULT VALUES
{
PGMatchAction *n = makeNode(PGMatchAction);
n->actionType = MERGE_ACTION_TYPE_INSERT;
n->insert_column_order = PG_INSERT_BY_POSITION;
n->defaultValues = true;
$$ = (PGNode *)n;
}
| DO NOTHING
{
PGMatchAction *n = makeNode(PGMatchAction);
n->actionType = MERGE_ACTION_TYPE_DO_NOTHING;
$$ = (PGNode *)n;
}
| ERROR_P opt_error_message
{
PGMatchAction *n = makeNode(PGMatchAction);
n->actionType = MERGE_ACTION_TYPE_ERROR;
n->errorMessage = $2;
$$ = (PGNode *)n;
}
;
opt_error_message:
a_expr { $$ = $1; }
| /* EMPTY */ { $$ = NULL; }
;
matched_clause:
WHEN MATCHED opt_and_clause THEN matched_clause_action
{
PGMatchAction *n = (PGMatchAction *) $5;
n->when = MERGE_ACTION_WHEN_MATCHED;
n->andClause = $3;
$$ = (PGNode *)n;
}
;
opt_source_or_target:
BY SOURCE_P { $$ = MERGE_ACTION_WHEN_NOT_MATCHED_BY_SOURCE; }
| BY TARGET_P { $$ = MERGE_ACTION_WHEN_NOT_MATCHED_BY_TARGET; }
| /* empty */ { $$ = MERGE_ACTION_WHEN_NOT_MATCHED_BY_TARGET; }
;
not_matched_clause:
WHEN NOT MATCHED opt_source_or_target opt_and_clause THEN matched_clause_action
{
PGMatchAction *n = (PGMatchAction *) $7;
n->when = $4;
n->andClause = $5;
$$ = (PGNode *)n;
}
;
matched_or_not_matched_clause:
matched_clause | not_matched_clause
;
merge_match_list:
matched_or_not_matched_clause { $$ = list_make1($1); }
| matched_or_not_matched_clause merge_match_list { $$ = list_concat(list_make1($1), $2); }
;

View File

@@ -0,0 +1,31 @@
/*****************************************************************************
*
* PRAGMA stmt
*
*****************************************************************************/
PragmaStmt:
PRAGMA_P ColId
{
PGPragmaStmt *n = makeNode(PGPragmaStmt);
n->kind = PG_PRAGMA_TYPE_NOTHING;
n->name = $2;
$$ = (PGNode *)n;
}
| PRAGMA_P ColId '=' var_list
{
PGPragmaStmt *n = makeNode(PGPragmaStmt);
n->kind = PG_PRAGMA_TYPE_ASSIGNMENT;
n->name = $2;
n->args = $4;
$$ = (PGNode *)n;
}
| PRAGMA_P ColId '(' func_arg_list ')'
{
PGPragmaStmt *n = makeNode(PGPragmaStmt);
n->kind = PG_PRAGMA_TYPE_CALL;
n->name = $2;
n->args = $4;
$$ = (PGNode *)n;
}
;

View File

@@ -0,0 +1,29 @@
/*****************************************************************************
*
* QUERY:
* PREPARE <plan_name> [(args, ...)] AS <query>
*
*****************************************************************************/
PrepareStmt: PREPARE name prep_type_clause AS PreparableStmt
{
PGPrepareStmt *n = makeNode(PGPrepareStmt);
n->name = $2;
n->argtypes = $3;
n->query = $5;
$$ = (PGNode *) n;
}
;
prep_type_clause: '(' type_list ')' { $$ = $2; }
| /* EMPTY */ { $$ = NIL; }
;
PreparableStmt:
SelectStmt
| InsertStmt
| UpdateStmt
| CopyStmt
| DeleteStmt
| VariableShowStmt /* by default all are $$=$1 */
;

View File

@@ -0,0 +1,142 @@
/*****************************************************************************
*
* ALTER THING name RENAME TO newname
*
*****************************************************************************/
RenameStmt: ALTER SCHEMA name RENAME TO name
{
PGRenameStmt *n = makeNode(PGRenameStmt);
n->renameType = PG_OBJECT_SCHEMA;
n->subname = $3;
n->newname = $6;
n->missing_ok = false;
$$ = (PGNode *)n;
}
| ALTER TABLE relation_expr RENAME TO name
{
PGRenameStmt *n = makeNode(PGRenameStmt);
n->renameType = PG_OBJECT_TABLE;
n->relation = $3;
n->subname = NULL;
n->newname = $6;
n->missing_ok = false;
$$ = (PGNode *)n;
}
| ALTER TABLE IF_P EXISTS relation_expr RENAME TO name
{
PGRenameStmt *n = makeNode(PGRenameStmt);
n->renameType = PG_OBJECT_TABLE;
n->relation = $5;
n->subname = NULL;
n->newname = $8;
n->missing_ok = true;
$$ = (PGNode *)n;
}
| ALTER SEQUENCE qualified_name RENAME TO name
{
PGRenameStmt *n = makeNode(PGRenameStmt);
n->renameType = PG_OBJECT_SEQUENCE;
n->relation = $3;
n->subname = NULL;
n->newname = $6;
n->missing_ok = false;
$$ = (PGNode *)n;
}
| ALTER SEQUENCE IF_P EXISTS qualified_name RENAME TO name
{
PGRenameStmt *n = makeNode(PGRenameStmt);
n->renameType = PG_OBJECT_SEQUENCE;
n->relation = $5;
n->subname = NULL;
n->newname = $8;
n->missing_ok = true;
$$ = (PGNode *)n;
}
| ALTER VIEW qualified_name RENAME TO name
{
PGRenameStmt *n = makeNode(PGRenameStmt);
n->renameType = PG_OBJECT_VIEW;
n->relation = $3;
n->subname = NULL;
n->newname = $6;
n->missing_ok = false;
$$ = (PGNode *)n;
}
| ALTER VIEW IF_P EXISTS qualified_name RENAME TO name
{
PGRenameStmt *n = makeNode(PGRenameStmt);
n->renameType = PG_OBJECT_VIEW;
n->relation = $5;
n->subname = NULL;
n->newname = $8;
n->missing_ok = true;
$$ = (PGNode *)n;
}
| ALTER INDEX qualified_name RENAME TO name
{
PGRenameStmt *n = makeNode(PGRenameStmt);
n->renameType = PG_OBJECT_INDEX;
n->relation = $3;
n->subname = NULL;
n->newname = $6;
n->missing_ok = false;
$$ = (PGNode *)n;
}
| ALTER INDEX IF_P EXISTS qualified_name RENAME TO name
{
PGRenameStmt *n = makeNode(PGRenameStmt);
n->renameType = PG_OBJECT_INDEX;
n->relation = $5;
n->subname = NULL;
n->newname = $8;
n->missing_ok = true;
$$ = (PGNode *)n;
}
| ALTER TABLE relation_expr RENAME opt_column qualified_column TO name
{
PGRenameStmt *n = makeNode(PGRenameStmt);
n->renameType = PG_OBJECT_COLUMN;
n->relationType = PG_OBJECT_TABLE;
n->relation = $3;
n->name_list = $6;
n->newname = $8;
n->missing_ok = false;
$$ = (PGNode *)n;
}
| ALTER TABLE IF_P EXISTS relation_expr RENAME opt_column qualified_column TO name
{
PGRenameStmt *n = makeNode(PGRenameStmt);
n->renameType = PG_OBJECT_COLUMN;
n->relationType = PG_OBJECT_TABLE;
n->relation = $5;
n->name_list = $8;
n->newname = $10;
n->missing_ok = true;
$$ = (PGNode *)n;
}
| ALTER TABLE relation_expr RENAME CONSTRAINT name TO name
{
PGRenameStmt *n = makeNode(PGRenameStmt);
n->renameType = PG_OBJECT_TABCONSTRAINT;
n->relation = $3;
n->subname = $6;
n->newname = $8;
n->missing_ok = false;
$$ = (PGNode *)n;
}
| ALTER TABLE IF_P EXISTS relation_expr RENAME CONSTRAINT name TO name
{
PGRenameStmt *n = makeNode(PGRenameStmt);
n->renameType = PG_OBJECT_TABCONSTRAINT;
n->relation = $5;
n->subname = $8;
n->newname = $10;
n->missing_ok = true;
$$ = (PGNode *)n;
}
;
opt_column: COLUMN { $$ = COLUMN; }
| /*EMPTY*/ { $$ = 0; }
;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,60 @@
TransactionStmt:
ABORT_P opt_transaction
{
PGTransactionStmt *n = makeNode(PGTransactionStmt);
n->kind = PG_TRANS_STMT_ROLLBACK;
n->options = NIL;
n->transaction_type = PG_TRANS_TYPE_DEFAULT;
$$ = (PGNode *)n;
}
| BEGIN_P opt_transaction opt_transaction_type
{
PGTransactionStmt *n = makeNode(PGTransactionStmt);
n->kind = PG_TRANS_STMT_BEGIN;
n->transaction_type = $3;
$$ = (PGNode *)n;
}
| START opt_transaction opt_transaction_type
{
PGTransactionStmt *n = makeNode(PGTransactionStmt);
n->kind = PG_TRANS_STMT_START;
n->transaction_type = $3;
$$ = (PGNode *)n;
}
| COMMIT opt_transaction
{
PGTransactionStmt *n = makeNode(PGTransactionStmt);
n->kind = PG_TRANS_STMT_COMMIT;
n->options = NIL;
n->transaction_type = PG_TRANS_TYPE_DEFAULT;
$$ = (PGNode *)n;
}
| END_P opt_transaction
{
PGTransactionStmt *n = makeNode(PGTransactionStmt);
n->kind = PG_TRANS_STMT_COMMIT;
n->options = NIL;
n->transaction_type = PG_TRANS_TYPE_DEFAULT;
$$ = (PGNode *)n;
}
| ROLLBACK opt_transaction
{
PGTransactionStmt *n = makeNode(PGTransactionStmt);
n->kind = PG_TRANS_STMT_ROLLBACK;
n->options = NIL;
n->transaction_type = PG_TRANS_TYPE_DEFAULT;
$$ = (PGNode *)n;
}
;
opt_transaction: WORK {}
| TRANSACTION {}
| /*EMPTY*/ {}
;
opt_transaction_type:
READ_P ONLY { $$ = PG_TRANS_TYPE_READ_ONLY; }
| READ_P WRITE_P { $$ = PG_TRANS_TYPE_READ_WRITE; }
| /*EMPTY*/ { $$ = PG_TRANS_TYPE_DEFAULT; }
;

View File

@@ -0,0 +1,22 @@
/*****************************************************************************
*
* QUERY:
* PGUpdateStmt (UPDATE)
*
*****************************************************************************/
UpdateStmt: opt_with_clause UPDATE relation_expr_opt_alias
SET set_clause_list_opt_comma
from_clause
where_or_current_clause
returning_clause
{
PGUpdateStmt *n = makeNode(PGUpdateStmt);
n->relation = $3;
n->targetList = $5;
n->fromClause = $6;
n->whereClause = $7;
n->returningList = $8;
n->withClause = $1;
$$ = (PGNode *)n;
}
;

View File

@@ -0,0 +1,22 @@
/*****************************************************************************
*
* QUERY:
* PGUpdateExtensionsStmt (UPDATE EXTENSIONS)
*
*****************************************************************************/
UpdateExtensionsStmt: opt_with_clause UPDATE EXTENSIONS opt_column_list
{
PGUpdateExtensionsStmt *n = makeNode(PGUpdateExtensionsStmt);
n->extensions = $4;
if ($1) {
ereport(ERROR,
(errcode(PG_ERRCODE_SYNTAX_ERROR),
errmsg("Providing a with clause with an UPDATE EXTENSIONS statement is not allowed"),
parser_errposition(@1)));
break;
}
$$ = (PGNode *)n;
}
;

View File

@@ -0,0 +1,8 @@
UseStmt:
USE_P qualified_name
{
PGUseStmt *n = makeNode(PGUseStmt);
n->name = $2;
$$ = (PGNode *) n;
}
;

View File

@@ -0,0 +1,100 @@
/*****************************************************************************
*
* QUERY:
* VACUUM
* ANALYZE
*
*****************************************************************************/
VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
{
PGVacuumStmt *n = makeNode(PGVacuumStmt);
n->options = PG_VACOPT_VACUUM;
if ($2)
n->options |= PG_VACOPT_FULL;
if ($3)
n->options |= PG_VACOPT_FREEZE;
if ($4)
n->options |= PG_VACOPT_VERBOSE;
n->relation = NULL;
n->va_cols = NIL;
$$ = (PGNode *)n;
}
| VACUUM opt_full opt_freeze opt_verbose qualified_name opt_name_list
{
PGVacuumStmt *n = makeNode(PGVacuumStmt);
n->options = PG_VACOPT_VACUUM;
if ($2)
n->options |= PG_VACOPT_FULL;
if ($3)
n->options |= PG_VACOPT_FREEZE;
if ($4)
n->options |= PG_VACOPT_VERBOSE;
n->relation = $5;
n->va_cols = $6;
$$ = (PGNode *)n;
}
| VACUUM opt_full opt_freeze opt_verbose AnalyzeStmt
{
PGVacuumStmt *n = (PGVacuumStmt *) $5;
n->options |= PG_VACOPT_VACUUM;
if ($2)
n->options |= PG_VACOPT_FULL;
if ($3)
n->options |= PG_VACOPT_FREEZE;
if ($4)
n->options |= PG_VACOPT_VERBOSE;
$$ = (PGNode *)n;
}
| VACUUM '(' vacuum_option_list ')'
{
PGVacuumStmt *n = makeNode(PGVacuumStmt);
n->options = PG_VACOPT_VACUUM | $3;
n->relation = NULL;
n->va_cols = NIL;
$$ = (PGNode *) n;
}
| VACUUM '(' vacuum_option_list ')' qualified_name opt_name_list
{
PGVacuumStmt *n = makeNode(PGVacuumStmt);
n->options = PG_VACOPT_VACUUM | $3;
n->relation = $5;
n->va_cols = $6;
if (n->va_cols != NIL) /* implies analyze */
n->options |= PG_VACOPT_ANALYZE;
$$ = (PGNode *) n;
}
;
vacuum_option_elem:
analyze_keyword { $$ = PG_VACOPT_ANALYZE; }
| VERBOSE { $$ = PG_VACOPT_VERBOSE; }
| FREEZE { $$ = PG_VACOPT_FREEZE; }
| FULL { $$ = PG_VACOPT_FULL; }
| IDENT
{
if (strcmp($1, "disable_page_skipping") == 0)
$$ = PG_VACOPT_DISABLE_PAGE_SKIPPING;
else
ereport(ERROR,
(errcode(PG_ERRCODE_SYNTAX_ERROR),
errmsg("unrecognized VACUUM option \"%s\"", $1),
parser_errposition(@1)));
}
;
opt_full: FULL { $$ = true; }
| /*EMPTY*/ { $$ = false; }
;
vacuum_option_list:
vacuum_option_elem { $$ = $1; }
| vacuum_option_list ',' vacuum_option_elem { $$ = $1 | $3; }
;
opt_freeze: FREEZE { $$ = true; }
| /*EMPTY*/ { $$ = false; }
;

View File

@@ -0,0 +1,63 @@
VariableResetStmt:
RESET reset_rest
{
$2->scope = VAR_SET_SCOPE_DEFAULT;
$$ = (PGNode *) $2;
}
| RESET LOCAL reset_rest
{
$3->scope = VAR_SET_SCOPE_LOCAL;
$$ = (PGNode *) $3;
}
| RESET SESSION reset_rest
{
$3->scope = VAR_SET_SCOPE_SESSION;
$$ = (PGNode *) $3;
}
| RESET GLOBAL reset_rest
{
$3->scope = VAR_SET_SCOPE_GLOBAL;
$$ = (PGNode *) $3;
}
| RESET VARIABLE_P reset_rest
{
$3->scope = VAR_SET_SCOPE_VARIABLE;
$$ = (PGNode *) $3;
}
;
generic_reset:
var_name
{
PGVariableSetStmt *n = makeNode(PGVariableSetStmt);
n->kind = VAR_RESET;
n->name = $1;
$$ = n;
}
| ALL
{
PGVariableSetStmt *n = makeNode(PGVariableSetStmt);
n->kind = VAR_RESET_ALL;
$$ = n;
}
;
reset_rest:
generic_reset { $$ = $1; }
| TIME ZONE
{
PGVariableSetStmt *n = makeNode(PGVariableSetStmt);
n->kind = VAR_RESET;
n->name = (char*) "timezone";
$$ = n;
}
| TRANSACTION ISOLATION LEVEL
{
PGVariableSetStmt *n = makeNode(PGVariableSetStmt);
n->kind = VAR_RESET;
n->name = (char*) "transaction_isolation";
$$ = n;
}
;

View File

@@ -0,0 +1,139 @@
/*****************************************************************************
*
* Set PG internal variable
* SET name TO 'var_value'
* Include SQL syntax (thomas 1997-10-22):
* SET TIME ZONE 'var_value'
*
*****************************************************************************/
VariableSetStmt:
SET set_rest
{
PGVariableSetStmt *n = $2;
n->scope = VAR_SET_SCOPE_DEFAULT;
$$ = (PGNode *) n;
}
| SET LOCAL set_rest
{
PGVariableSetStmt *n = $3;
n->scope = VAR_SET_SCOPE_LOCAL;
$$ = (PGNode *) n;
}
| SET SESSION set_rest
{
PGVariableSetStmt *n = $3;
n->scope = VAR_SET_SCOPE_SESSION;
$$ = (PGNode *) n;
}
| SET GLOBAL set_rest
{
PGVariableSetStmt *n = $3;
n->scope = VAR_SET_SCOPE_GLOBAL;
$$ = (PGNode *) n;
}
| SET VARIABLE_P set_rest
{
PGVariableSetStmt *n = $3;
n->scope = VAR_SET_SCOPE_VARIABLE;
$$ = (PGNode *) n;
}
;
set_rest: /* Generic SET syntaxes: */
generic_set {$$ = $1;}
| var_name FROM CURRENT_P
{
PGVariableSetStmt *n = makeNode(PGVariableSetStmt);
n->kind = VAR_SET_CURRENT;
n->name = $1;
$$ = n;
}
/* Special syntaxes mandated by SQL standard: */
| TIME ZONE zone_value
{
PGVariableSetStmt *n = makeNode(PGVariableSetStmt);
n->kind = VAR_SET_VALUE;
n->name = (char*) "timezone";
if ($3 != NULL)
n->args = list_make1($3);
else
n->kind = VAR_SET_DEFAULT;
$$ = n;
}
| SCHEMA Sconst
{
PGVariableSetStmt *n = makeNode(PGVariableSetStmt);
n->kind = VAR_SET_VALUE;
n->name = (char*) "search_path";
n->args = list_make1(makeStringConst($2, @2));
$$ = n;
}
;
generic_set:
var_name TO var_list
{
PGVariableSetStmt *n = makeNode(PGVariableSetStmt);
n->kind = VAR_SET_VALUE;
n->name = $1;
n->args = $3;
$$ = n;
}
| var_name '=' var_list
{
PGVariableSetStmt *n = makeNode(PGVariableSetStmt);
n->kind = VAR_SET_VALUE;
n->name = $1;
n->args = $3;
$$ = n;
}
;
var_value: a_expr
{ $$ = $1; }
;
zone_value:
Sconst
{
$$ = makeStringConst($1, @1);
}
| IDENT
{
$$ = makeStringConst($1, @1);
}
| ConstInterval Sconst opt_interval
{
PGTypeName *t = $1;
if ($3 != NIL)
{
PGAConst *n = (PGAConst *) linitial($3);
if ((n->val.val.ival & ~(INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE))) != 0)
ereport(ERROR,
(errcode(PG_ERRCODE_SYNTAX_ERROR),
errmsg("time zone interval must be HOUR or HOUR TO MINUTE"),
parser_errposition(@3)));
}
t->typmods = $3;
$$ = makeStringConstCast($2, @2, t);
}
| ConstInterval '(' Iconst ')' Sconst
{
PGTypeName *t = $1;
t->typmods = list_make2(makeIntConst(INTERVAL_FULL_RANGE, -1),
makeIntConst($3, @3));
$$ = makeStringConstCast($5, @5, t);
}
| NumericOnly { $$ = makeAConst($1, @1); }
| DEFAULT { $$ = NULL; }
| LOCAL { $$ = NULL; }
;
var_list: var_value { $$ = list_make1($1); }
| var_list ',' var_value { $$ = lappend($1, $3); }
;

View File

@@ -0,0 +1,78 @@
/* allows SET or RESET without LOCAL */
VariableShowStmt:
show_or_describe SelectStmt {
PGVariableShowSelectStmt *n = makeNode(PGVariableShowSelectStmt);
n->stmt = $2;
n->name = (char*) "select";
n->is_summary = 0;
$$ = (PGNode *) n;
}
| SUMMARIZE SelectStmt {
PGVariableShowSelectStmt *n = makeNode(PGVariableShowSelectStmt);
n->stmt = $2;
n->name = (char*) "select";
n->is_summary = 1;
$$ = (PGNode *) n;
}
| SUMMARIZE qualified_name
{
PGVariableShowStmt *n = makeNode(PGVariableShowStmt);
n->relation = $2;
n->is_summary = 1;
$$ = (PGNode *) n;
}
| show_or_describe TABLES FROM qualified_name
{
PGVariableShowStmt *n = makeNode(PGVariableShowStmt);
n->relation = $4;
n->set = (char*) "__show_tables_from_database";
n->is_summary = 0;
$$ = (PGNode *) n;
}
| show_or_describe qualified_name
{
PGVariableShowStmt *n = makeNode(PGVariableShowStmt);
n->relation = $2;
n->is_summary = 0;
$$ = (PGNode *) n;
}
| show_or_describe TIME ZONE
{
PGVariableShowStmt *n = makeNode(PGVariableShowStmt);
n->set = (char*) "timezone";
n->is_summary = 0;
$$ = (PGNode *) n;
}
| show_or_describe TRANSACTION ISOLATION LEVEL
{
PGVariableShowStmt *n = makeNode(PGVariableShowStmt);
n->set = (char*) "transaction_isolation";
n->is_summary = 0;
$$ = (PGNode *) n;
}
| show_or_describe ALL opt_tables
{
PGVariableShowStmt *n = makeNode(PGVariableShowStmt);
n->set = (char*) "__show_tables_expanded";
n->is_summary = 0;
$$ = (PGNode *) n;
}
| show_or_describe
{
PGVariableShowStmt *n = makeNode(PGVariableShowStmt);
n->set = (char*) "__show_tables_expanded";
n->is_summary = 0;
$$ = (PGNode *) n;
}
;
describe_or_desc: DESCRIBE | DESC_P
show_or_describe: SHOW | describe_or_desc
opt_tables: TABLES | /* empty */
var_name: ColId { $$ = $1; }
| var_name '.' ColId
{ $$ = psprintf("%s.%s", $1, $3); }
;

View File

@@ -0,0 +1,91 @@
/*****************************************************************************
*
* QUERY:
* CREATE [ OR REPLACE ] [ TEMP ] VIEW <viewname> '('target-list ')'
* AS <query> [ WITH [ CASCADED | LOCAL ] CHECK OPTION ]
*
*****************************************************************************/
ViewStmt: CREATE_P OptTemp VIEW qualified_name opt_column_list opt_reloptions
AS SelectStmt opt_check_option
{
PGViewStmt *n = makeNode(PGViewStmt);
n->view = $4;
n->view->relpersistence = $2;
n->aliases = $5;
n->query = $8;
n->onconflict = PG_ERROR_ON_CONFLICT;
n->options = $6;
n->withCheckOption = $9;
$$ = (PGNode *) n;
}
| CREATE_P OptTemp VIEW IF_P NOT EXISTS qualified_name opt_column_list opt_reloptions
AS SelectStmt opt_check_option
{
PGViewStmt *n = makeNode(PGViewStmt);
n->view = $7;
n->view->relpersistence = $2;
n->aliases = $8;
n->query = $11;
n->onconflict = PG_IGNORE_ON_CONFLICT;
n->options = $9;
n->withCheckOption = $12;
$$ = (PGNode *) n;
}
| CREATE_P OR REPLACE OptTemp VIEW qualified_name opt_column_list opt_reloptions
AS SelectStmt opt_check_option
{
PGViewStmt *n = makeNode(PGViewStmt);
n->view = $6;
n->view->relpersistence = $4;
n->aliases = $7;
n->query = $10;
n->onconflict = PG_REPLACE_ON_CONFLICT;
n->options = $8;
n->withCheckOption = $11;
$$ = (PGNode *) n;
}
| CREATE_P OptTemp RECURSIVE VIEW qualified_name '(' columnList ')' opt_reloptions
AS SelectStmt opt_check_option
{
PGViewStmt *n = makeNode(PGViewStmt);
n->view = $5;
n->view->relpersistence = $2;
n->aliases = $7;
n->query = makeRecursiveViewSelect(n->view->relname, n->aliases, $11);
n->onconflict = PG_ERROR_ON_CONFLICT;
n->options = $9;
n->withCheckOption = $12;
if (n->withCheckOption != PG_NO_CHECK_OPTION)
ereport(ERROR,
(errcode(PG_ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("WITH CHECK OPTION not supported on recursive views"),
parser_errposition(@12)));
$$ = (PGNode *) n;
}
| CREATE_P OR REPLACE OptTemp RECURSIVE VIEW qualified_name '(' columnList ')' opt_reloptions
AS SelectStmt opt_check_option
{
PGViewStmt *n = makeNode(PGViewStmt);
n->view = $7;
n->view->relpersistence = $4;
n->aliases = $9;
n->query = makeRecursiveViewSelect(n->view->relname, n->aliases, $13);
n->onconflict = PG_REPLACE_ON_CONFLICT;
n->options = $11;
n->withCheckOption = $14;
if (n->withCheckOption != PG_NO_CHECK_OPTION)
ereport(ERROR,
(errcode(PG_ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("WITH CHECK OPTION not supported on recursive views"),
parser_errposition(@14)));
$$ = (PGNode *) n;
}
;
opt_check_option:
WITH CHECK_P OPTION { $$ = CASCADED_CHECK_OPTION; }
| WITH CASCADED CHECK_P OPTION { $$ = CASCADED_CHECK_OPTION; }
| WITH LOCAL CHECK_P OPTION { $$ = PG_LOCAL_CHECK_OPTION; }
| /* EMPTY */ { $$ = PG_NO_CHECK_OPTION; }
;

View File

@@ -0,0 +1,4 @@
%type <list> SeqOptList
%type <value> NumericOnly
%type <defelt> SeqOptElem
%type <ival> SignedIconst

View File

@@ -0,0 +1,13 @@
%type <list> alter_identity_column_option_list
%type <node> alter_column_default
%type <defelt> alter_identity_column_option
%type <list> alter_generic_option_list
%type <node> alter_table_cmd
%type <node> alter_using
%type <defelt> alter_generic_option_elem
%type <list> alter_table_cmds
%type <list> alter_generic_options
%type <ival> opt_set_data
%type <list> qualifiedColumnDef qualify_list qualified_column
%type <str> qualify_el

View File

@@ -0,0 +1,6 @@
%type <str> opt_database_alias
%type <list> ident_list ident_name
%type <node> generic_opt_arg
%type <list> generic_opt_list opt_attach_options
%type <defelt> generic_opt_elem

View File

@@ -0,0 +1 @@
%type <str> opt_col_id

View File

@@ -0,0 +1,2 @@
%type <node> comment_value
%type <objtype> comment_on_type_any_name

View File

@@ -0,0 +1,7 @@
%type <range> qualified_name
%type <str> Sconst ColId ColLabel ColIdOrString
%type <keyword> unreserved_keyword reserved_keyword other_keyword
%type <list> indirection
%type <keyword> col_name_keyword
%type <node> indirection_el
%type <str> attr_name

View File

@@ -0,0 +1,13 @@
%type <boolean> copy_from
%type <defelt> copy_delimiter
%type <list> copy_generic_opt_arg_list
%type <ival> opt_as
%type <boolean> opt_program
%type <list> copy_options
%type <defelt> opt_oids
%type <list> copy_opt_list
%type <defelt> opt_binary
%type <defelt> copy_opt_item
%type <node> copy_generic_opt_arg_list_item
%type <node> copy_file_name
%type <conststr> copy_database_flag

View File

@@ -0,0 +1,44 @@
%type <ival> ConstraintAttributeSpec
%type <node> def_arg
%type <list> OptParenthesizedSeqOptList
%type <node> generic_option_arg
%type <ival> key_action
%type <node> ColConstraint
%type <node> ColConstraintElem
%type <defelt> generic_option_elem
%type <ival> key_update
%type <ival> key_actions
%type <oncommit> OnCommitOption
%type <list> reloptions
%type <boolean> opt_no_inherit
%type <node> TableConstraint
%type <ival> TableLikeOption
%type <list> reloption_list
%type <str> ExistingIndex
%type <node> ConstraintAttr
%type <list> OptWith
%type <list> definition
%type <ival> TableLikeOptionList
%type <str> generic_option_name
%type <ival> ConstraintAttributeElem
%type <node> columnDef regularColumnDef generatedColumnDef
%type <list> def_list
%type <str> index_name
%type <node> TableElement
%type <defelt> def_elem
%type <list> opt_definition
%type <list> OptTableElementList
%type <node> columnElem
%type <list> opt_column_list
%type <list> ColQualList
%type <ival> key_delete
%type <defelt> reloption_elem
%type <list> columnList columnList_opt_comma
%type <typnam> func_type
%type <constr> GeneratedColumnType opt_GeneratedColumnType
%type <node> ConstraintElem GeneratedConstraintElem
%type <list> TableElementList
%type <ival> key_match
%type <node> TableLikeClause
%type <ival> OptTemp
%type <ival> generated_when

View File

@@ -0,0 +1,2 @@
%type <boolean> opt_with_data
%type <into> create_as_target

View File

@@ -0,0 +1,5 @@
%type <list> param_list
%type <node> macro_definition table_macro_definition table_macro_definition_parens
%type <list> macro_definition_list table_macro_list table_macro_list_internal
%type <list> MacroParameterList
%type <node> MacroParameter

View File

@@ -0,0 +1,2 @@
%type <list> OptSchemaEltList
%type <node> schema_stmt

View File

@@ -0,0 +1,4 @@
%type <str> opt_secret_name opt_persist opt_storage_specifier
%type <node> create_secret_generic_opt_arg
%type <list> create_secret_generic_opt_list
%type <defelt> create_secret_generic_opt_elem

View File

@@ -0,0 +1 @@
%type <list> OptSeqOptList

View File

@@ -0,0 +1,3 @@
%type <list> opt_enum_val_list
%type <list> enum_val_list
%type <node> create_type_value

View File

@@ -0,0 +1,3 @@
%type <range> relation_expr_opt_alias
%type <node> where_or_current_clause
%type <list> using_clause

View File

@@ -0,0 +1,6 @@
%type <objtype> drop_type_any_name
%type <objtype> drop_type_name
%type <list> any_name_list
%type <dbehavior> opt_drop_behavior
%type <objtype> drop_type_name_on_any_name
%type <list> type_name_list

View File

@@ -0,0 +1 @@
%type <str> opt_storage_drop_specifier

View File

@@ -0,0 +1,3 @@
%type <list> execute_param_clause
%type <list> execute_param_list
%type <node> execute_param_expr

View File

@@ -0,0 +1,9 @@
%type <boolean> opt_verbose
%type <node> explain_option_arg
%type <node> ExplainableStmt
%type <str> NonReservedWord
%type <str> NonReservedWord_or_Sconst
%type <list> explain_option_list
%type <str> opt_boolean_or_string
%type <defelt> explain_option_elem
%type <str> explain_option_name

View File

@@ -0,0 +1,6 @@
%type <str> access_method
%type <str> access_method_clause
%type <boolean> opt_concurrently
%type <str> opt_index_name
%type <list> opt_reloptions
%type <boolean> opt_unique

View File

@@ -0,0 +1,19 @@
%type <istmt> insert_rest
%type <range> insert_target
%type <infer> opt_conf_expr
%type <with> opt_with_clause
%type <target> insert_column_item
%type <list> set_clause
%type <onconflict> opt_on_conflict
%type <onconflictshorthand> opt_or_action
%type <bynameorposition> opt_by_name_or_position
%type <ielem> index_elem
%type <list> returning_clause
%type <override> override_kind
%type <list> set_target_list
%type <list> opt_collate
%type <list> opt_class
%type <list> insert_column_list
%type <list> set_clause_list set_clause_list_opt_comma
%type <list> index_params
%type <target> set_target

View File

@@ -0,0 +1,3 @@
%type <str> file_name
%type <str> opt_ext_version
%type <loadinstalltype> opt_force

View File

@@ -0,0 +1,4 @@
%type <list> merge_match_list opt_insert_column_list
%type <node> matched_or_not_matched_clause matched_clause not_matched_clause opt_and_clause matched_clause_action opt_star_expr opt_error_message
%type <mergeaction> opt_source_or_target

View File

@@ -0,0 +1,2 @@
%type <list> prep_type_clause
%type <node> PreparableStmt

View File

@@ -0,0 +1 @@
%type <ival> opt_column

View File

@@ -0,0 +1,134 @@
%type <node> select_no_parens select_with_parens select_clause
simple_select values_clause values_clause_opt_comma
%type <sortorder> opt_asc_desc
%type <nullorder> opt_nulls_order
%type <ignorenulls> opt_ignore_nulls
%type <node> opt_collate_clause
%type <node> indirection_expr indirection_expr_or_a_expr
%type <node> struct_expr list_expr map_expr param_expr sample_value
%type <lockwaitpolicy> opt_nowait_or_skip
%type <str> name
%type <list> func_name qual_Op qual_all_Op subquery_Op
%type <str> all_Op
%type <conststr> MathOp
%type <list> distinct_clause opt_all_clause name_list_opt_comma opt_name_list name_list_opt_comma_opt_bracket opt_on_key column_ref_list_opt_comma column_ref_list
sort_clause opt_sort_clause sortby_list name_list from_clause from_list from_list_opt_comma opt_array_bounds
qualified_name_list any_name any_operator expr_list attrs expr_list_opt_comma opt_expr_list_opt_comma c_expr_list c_expr_list_opt_comma
target_list opt_indirection target_list_opt_comma opt_target_list_opt_comma
group_clause select_limit
opt_select_limit TableFuncElementList opt_type_modifiers opt_select extended_indirection opt_extended_indirection
qualified_typename
%type <list> group_by_list group_by_list_opt_comma opt_func_arguments unpivot_header
%type <node> group_by_item empty_grouping_set rollup_clause cube_clause grouping_sets_clause grouping_or_grouping_id
%type <range> OptTempTableName
%type <into> into_clause
%type <lockstrength> 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
%type <boolean> all_or_distinct
%type <node> join_outer join_qual
%type <jtype> join_type
%type <list> extract_list overlay_list position_list
%type <list> substr_list trim_list
%type <list> opt_interval
%type <node> overlay_placing substr_from substr_for
%type <list> except_list opt_except_list replace_list_el replace_list opt_replace_list replace_list_opt_comma
%type <list> rename_list_el rename_list rename_list_opt_comma opt_rename_list
%type <list> except_name except_name_list except_name_list_opt_comma
%type <node> limit_clause select_limit_value
offset_clause select_offset_value
select_fetch_first_value I_or_F_const
%type <ival> row_or_rows first_or_next
%type <node> TableFuncElement
%type <list> columnrefList
%type <node> where_clause a_expr b_expr c_expr d_expr AexprConst opt_slice_bound extended_indirection_el
columnref columnref_opt_indirection in_expr having_clause qualify_clause func_table opt_at_clause at_specifier
%type <list> rowsfrom_item rowsfrom_list opt_col_def_list
%type <boolean> opt_ordinality
%type <list> func_arg_list
%type <node> func_arg_expr
%type <node> list_comprehension
%type <list> row qualified_row type_list colid_type_list
%type <node> case_expr case_arg when_clause case_default
%type <list> when_clause_list
%type <subquerytype> sub_type
%type <node> dict_arg
%type <list> dict_arguments dict_arguments_opt_comma
%type <list> map_arg map_arguments map_arguments_opt_comma opt_map_arguments_opt_comma
%type <alias> alias_clause opt_alias_clause alias_prefix_colon_clause
%type <list> func_alias_clause
%type <sortby> sortby
%type <node> table_ref
%type <jexpr> joined_table
%type <range> relation_expr
%type <node> tablesample_clause opt_tablesample_clause tablesample_entry
%type <node> sample_clause sample_count
%type <str> opt_sample_func at_unit
%type <ival> opt_repeatable_clause
%type <target> target_el
%type <typnam> Typename SimpleTypename ConstTypename opt_Typename
GenericType Numeric opt_float
Character ConstCharacter
CharacterWithLength CharacterWithoutLength
ConstDatetime ConstInterval
Bit ConstBit BitWithLength BitWithoutLength
%type <conststr> character
%type <str> extract_arg
%type <boolean> opt_varying opt_timezone
%type <ival> Iconst
%type <str> type_function_name param_name type_name_token function_name_token
%type <str> ColLabelOrString
%type <keyword> type_func_name_keyword type_name_keyword func_name_keyword
%type <node> func_application func_expr_common_subexpr
%type <node> func_expr func_expr_windowless
%type <node> common_table_expr
%type <with> with_clause
%type <list> cte_list
%type <ctematerialize> opt_materialized
%type <list> within_group_clause
%type <node> filter_clause
%type <boolean> export_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 <ival> opt_window_exclusion_clause
%type <str> opt_existing_window_name
%type <node> pivot_value pivot_column_entry single_pivot_value unpivot_value
%type <list> pivot_value_list pivot_column_list_internal pivot_column_list pivot_header opt_pivot_group_by unpivot_value_list
%type <boolean> opt_include_nulls

View File

@@ -0,0 +1 @@
%type <transactiontype> opt_transaction_type

View File

@@ -0,0 +1,4 @@
%type <ival> vacuum_option_elem
%type <boolean> opt_full
%type <ival> vacuum_option_list
%type <boolean> opt_freeze

View File

@@ -0,0 +1,2 @@
%type <vsetstmt> generic_reset
%type <vsetstmt> reset_rest

View File

@@ -0,0 +1,5 @@
%type <vsetstmt> set_rest
%type <vsetstmt> generic_set
%type <node> var_value
%type <node> zone_value
%type <list> var_list

View File

@@ -0,0 +1 @@
%type <str> var_name

View File

@@ -0,0 +1 @@
%type <viewcheckoption> opt_check_option

View File

@@ -0,0 +1,62 @@
/*-------------------------------------------------------------------------
*
* attnum.h
* POSTGRES attribute number definitions.
*
*
* Portions Copyright (c) 1996-2017, PostgreSQL Global Development PGGroup
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/include/access/attnum.h
*
*-------------------------------------------------------------------------
*/
#pragma once
#include <cstdint>
/*
* user defined attribute numbers start at 1. -ay 2/95
*/
typedef int16_t PGAttrNumber;
#define InvalidAttrNumber 0
#define MaxAttrNumber 32767
/* ----------------
* support macros
* ----------------
*/
/*
* AttributeNumberIsValid
* True iff the attribute number is valid.
*/
#define AttributeNumberIsValid(attributeNumber) \
((bool) ((attributeNumber) != InvalidAttrNumber))
/*
* AttrNumberIsForUserDefinedAttr
* True iff the attribute number corresponds to an user defined attribute.
*/
#define AttrNumberIsForUserDefinedAttr(attributeNumber) \
((bool) ((attributeNumber) > 0))
/*
* AttrNumberGetAttrOffset
* Returns the attribute offset for an attribute number.
*
* Note:
* Assumes the attribute number is for a user defined attribute.
*/
#define AttrNumberGetAttrOffset(attNum) \
( \
AssertMacro(AttrNumberIsForUserDefinedAttr(attNum)), \
((attNum) - 1) \
)
/*
* AttributeOffsetGetAttributeNumber
* Returns the attribute number for an attribute offset.
*/
#define AttrOffsetGetAttrNumber(attributeOffset) \
((PGAttrNumber) (1 + (attributeOffset)))

View File

@@ -0,0 +1,47 @@
/*-------------------------------------------------------------------------
*
* genbki.h
* Required include file for all POSTGRES catalog header files
*
* genbki.h defines CATALOG(), DATA(), BKI_BOOTSTRAP and related macros
* so that the catalog header files can be read by the C compiler.
* (These same words are recognized by genbki.pl to build the BKI
* bootstrap file from these header files.)
*
*
* Portions Copyright (c) 1996-2017, PostgreSQL Global Development PGGroup
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/include/catalog/genbki.h
*
*-------------------------------------------------------------------------
*/
#pragma once
/* Introduces a catalog's structure definition */
#define CATALOG(name,oid) typedef struct CppConcat(FormData_,name)
/* Options that may appear after CATALOG (on the same line) */
#define BKI_BOOTSTRAP
#define BKI_SHARED_RELATION
#define BKI_WITHOUT_OIDS
#define BKI_ROWTYPE_OID(oid)
#define BKI_SCHEMA_MACRO
#define BKI_FORCE_NULL
#define BKI_FORCE_NOT_NULL
/*
* This is never defined; it's here only for documentation.
*
* Variable-length catalog fields (except possibly the first not nullable one)
* should not be visible in C structures, so they are made invisible by #ifdefs
* of an undefined symbol. See also MARKNOTNULL in bootstrap.c for how this is
* handled.
*/
#undef CATALOG_VARLEN
/* Declarations that provide the initial content of a catalog */
/* In C, these need to expand into some harmless, repeatable declaration */
#define DATA(x) int no_such_variable
#define DESCR(x) int no_such_variable
#define SHDESCR(x) int no_such_variable

View File

@@ -0,0 +1,34 @@
/*-------------------------------------------------------------------------
*
* keywords.h
* lexical token lookup for key words in PostgreSQL
*
*
* Portions Copyright (c) 1996-2017, PostgreSQL Global Development PGGroup
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/include/common/keywords.h
*
*-------------------------------------------------------------------------
*/
#pragma once
#include <cstdint>
#include "pg_simplified_token.hpp"
/* Keyword categories --- should match lists in gram.y */
#define UNRESERVED_KEYWORD 0
#define COL_NAME_KEYWORD 1
#define TYPE_FUNC_NAME_KEYWORD 2
#define RESERVED_KEYWORD 3
namespace duckdb_libpgquery {
typedef struct PGScanKeyword {
const char *name; /* in lower case */
int16_t value; /* grammar's token code */
int16_t category; /* see codes above */
} PGScanKeyword;
const PGScanKeyword *ScanKeywordLookup(const char *text, const PGScanKeyword *keywords, int num_keywords);
}

View File

@@ -0,0 +1,51 @@
/*-------------------------------------------------------------------------
*
* timestamp.h
* PGTimestamp and PGInterval typedefs and related macros.
*
* Note: this file must be includable in both frontend and backend contexts.
*
* Portions Copyright (c) 1996-2017, PostgreSQL Global Development PGGroup
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/include/datatype/timestamp.h
*
*-------------------------------------------------------------------------
*/
#pragma once
#include <cstdint>
/*
* PGTimestamp represents absolute time.
*
* PGInterval represents delta time. Keep track of months (and years), days,
* and hours/minutes/seconds separately since the elapsed time spanned is
* unknown until instantiated relative to an absolute time.
*
* Note that Postgres uses "time interval" to mean a bounded interval,
* consisting of a beginning and ending time, not a time span - thomas 97/03/20
*
* Timestamps, as well as the h/m/s fields of intervals, are stored as
* int64_t values with units of microseconds. (Once upon a time they were
* double values with units of seconds.)
*
* PGTimeOffset and pg_fsec_t are convenience typedefs for temporary variables.
* Do not use pg_fsec_t in values stored on-disk.
* Also, pg_fsec_t is only meant for *fractional* seconds; beware of overflow
* if the value you need to store could be many seconds.
*/
namespace duckdb_libpgquery {
typedef int64_t PGTimestamp;
typedef int64_t PGTimestampTz;
typedef int64_t PGTimeOffset;
typedef int32_t pg_fsec_t; /* fractional seconds (in microseconds) */
typedef struct {
PGTimeOffset time; /* all time units other than days, months and
* years */
int32_t day; /* days, after time for alignment */
int32_t month; /* months and years, after time for alignment */
} PGInterval;
}

View File

@@ -0,0 +1,25 @@
/*-------------------------------------------------------------------------
*
* fmgr.h
* Definitions for the Postgres function manager and function-call
* interface.
*
* This file must be included by all Postgres modules that either define
* or call fmgr-callable functions.
*
*
* Portions Copyright (c) 1996-2017, PostgreSQL Global Development PGGroup
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/include/fmgr.h
*
*-------------------------------------------------------------------------
*/
#pragma once
#include "pg_definitions.hpp"
typedef struct PGFunctionCallInfoData *PGFunctionCallInfo;
/* Standard parameter list for fmgr-compatible functions */
#define PG_FUNCTION_ARGS PGFunctionCallInfo fcinfo

View File

@@ -0,0 +1,28 @@
/*-------------------------------------------------------------------------
*
* pg_wchar.h
* multibyte-character support
*
* Portions Copyright (c) 1996-2017, PostgreSQL Global Development PGGroup
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/include/mb/pg_wchar.h
*
* NOTES
* This is used both by the backend and by libpq, but should not be
* included by libpq client programs. In particular, a libpq client
* should not assume that the encoding IDs used by the version of libpq
* it's linked to match up with the IDs declared here.
*
*-------------------------------------------------------------------------
*/
#pragma once
#include <cstdint>
/*
* The pg_wchar type
*/
namespace duckdb_libpgquery {
typedef unsigned int pg_wchar;
}

View File

@@ -0,0 +1,102 @@
/*-------------------------------------------------------------------------
*
* bitmapset.h
* PostgreSQL generic bitmap set package
*
* A bitmap set can represent any set of nonnegative integers, although
* it is mainly intended for sets where the maximum value is not large,
* say at most a few hundred. By convention, a NULL pointer is always
* accepted by all operations to represent the empty set. (But beware
* that this is not the only representation of the empty set. Use
* bms_is_empty() in preference to testing for NULL.)
*
*
* Copyright (c) 2003-2017, PostgreSQL Global Development PGGroup
*
* src/include/nodes/bitmapset.h
*
*-------------------------------------------------------------------------
*/
#pragma once
#include <cstdint>
namespace duckdb_libpgquery {
/*
* Forward decl to save including pg_list.h
*/
struct PGList;
/*
* Data representation
*/
/* The unit size can be adjusted by changing these three declarations: */
#define BITS_PER_BITMAPWORD 32
typedef uint32_t bitmapword; /* must be an unsigned type */
typedef int32_t signedbitmapword; /* must be the matching signed type */
typedef struct PGBitmapset {
int nwords; /* number of words in array */
bitmapword words[1]; /* really [nwords] */
} PGBitmapset;
/* result of bms_subset_compare */
typedef enum PG_BMS_Comparison {
PG_BMS_EQUAL, /* sets are equal */
PG_BMS_SUBSET1, /* first set is a subset of the second */
PG_BMS_SUBSET2, /* second set is a subset of the first */
BMS_DIFFERENT /* neither set is a subset of the other */
} PG_BMS_Comparison;
/* result of bms_membership */
typedef enum PG_BMS_Membership {
PG_BMS_EMPTY_SET, /* 0 members */
PG_BMS_SINGLETON, /* 1 member */
BMS_MULTIPLE /* >1 member */
} PG_BMS_Membership;
/*
* function prototypes in nodes/bitmapset.c
*/
PGBitmapset *bms_copy(const PGBitmapset *a);
bool bms_equal(const PGBitmapset *a, const PGBitmapset *b);
PGBitmapset *bms_make_singleton(int x);
void bms_free(PGBitmapset *a);
PGBitmapset *bms_union(const PGBitmapset *a, const PGBitmapset *b);
PGBitmapset *bms_intersect(const PGBitmapset *a, const PGBitmapset *b);
PGBitmapset *bms_difference(const PGBitmapset *a, const PGBitmapset *b);
bool bms_is_subset(const PGBitmapset *a, const PGBitmapset *b);
PG_BMS_Comparison bms_subset_compare(const PGBitmapset *a, const PGBitmapset *b);
bool bms_is_member(int x, const PGBitmapset *a);
bool bms_overlap(const PGBitmapset *a, const PGBitmapset *b);
bool bms_overlap_list(const PGBitmapset *a, const struct PGList *b);
bool bms_nonempty_difference(const PGBitmapset *a, const PGBitmapset *b);
int bms_singleton_member(const PGBitmapset *a);
bool bms_get_singleton_member(const PGBitmapset *a, int *member);
int bms_num_members(const PGBitmapset *a);
/* optimized tests when we don't need to know exact membership count: */
PG_BMS_Membership bms_membership(const PGBitmapset *a);
bool bms_is_empty(const PGBitmapset *a);
/* these routines recycle (modify or free) their non-const inputs: */
PGBitmapset *bms_add_member(PGBitmapset *a, int x);
PGBitmapset *bms_del_member(PGBitmapset *a, int x);
PGBitmapset *bms_add_members(PGBitmapset *a, const PGBitmapset *b);
PGBitmapset *bms_int_members(PGBitmapset *a, const PGBitmapset *b);
PGBitmapset *bms_del_members(PGBitmapset *a, const PGBitmapset *b);
PGBitmapset *bms_join(PGBitmapset *a, PGBitmapset *b);
/* support for iterating through the integer elements of a set: */
int bms_first_member(PGBitmapset *a);
int bms_next_member(const PGBitmapset *a, int prevbit);
/* support for hashtables using Bitmapsets as keys: */
uint32_t bms_hash_value(const PGBitmapset *a);
}

View File

@@ -0,0 +1,44 @@
/*-------------------------------------------------------------------------
*
* lockoptions.h
* Common header for some locking-related declarations.
*
*
* Copyright (c) 2014-2017, PostgreSQL Global Development PGGroup
*
* src/include/nodes/lockoptions.h
*
*-------------------------------------------------------------------------
*/
#pragma once
namespace duckdb_libpgquery {
/*
* This enum represents the different strengths of FOR UPDATE/SHARE clauses.
* The ordering here is important, because the highest numerical value takes
* precedence when a RTE is specified multiple ways. See applyLockingClause.
*/
typedef enum PGLockClauseStrength {
PG_LCS_NONE, /* no such clause - only used in PGPlanRowMark */
PG_LCS_FORKEYSHARE, /* FOR KEY SHARE */
PG_LCS_FORSHARE, /* FOR SHARE */
PG_LCS_FORNOKEYUPDATE, /* FOR NO KEY UPDATE */
LCS_FORUPDATE /* FOR UPDATE */
} PGLockClauseStrength;
/*
* This enum controls how to deal with rows being locked by FOR UPDATE/SHARE
* clauses (i.e., it represents the NOWAIT and SKIP LOCKED options).
* The ordering here is important, because the highest numerical value takes
* precedence when a RTE is specified multiple ways. See applyLockingClause.
*/
typedef enum PGLockWaitPolicy {
/* Wait for the lock to become available (default behavior) */
PGLockWaitBlock,
/* Skip rows that can't be locked (SKIP LOCKED) */
PGLockWaitSkip,
/* Raise an error if a row cannot be locked (NOWAIT) */
LockWaitError
} PGLockWaitPolicy;
}

View File

@@ -0,0 +1,69 @@
/*-------------------------------------------------------------------------
*
* makefuncs.h
* prototypes for the creator functions (for primitive nodes)
*
*
* Portions Copyright (c) 1996-2017, PostgreSQL Global Development PGGroup
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/include/nodes/makefuncs.h
*
*-------------------------------------------------------------------------
*/
#pragma once
#include "nodes/parsenodes.hpp"
namespace duckdb_libpgquery {
PGAExpr *makeAExpr(PGAExpr_Kind kind, PGList *name, PGNode *lexpr, PGNode *rexpr, int location);
PGAExpr *makeSimpleAExpr(PGAExpr_Kind kind, const char *name, PGNode *lexpr, PGNode *rexpr, int location);
PGVar *makeVar(PGIndex varno, PGAttrNumber varattno, PGOid vartype, int32_t vartypmod, PGOid varcollid,
PGIndex varlevelsup);
PGVar *makeVarFromTargetEntry(PGIndex varno, PGTargetEntry *tle);
PGVar *makeWholeRowVar(PGRangeTblEntry *rte, PGIndex varno, PGIndex varlevelsup, bool allowScalar);
PGTargetEntry *makeTargetEntry(PGExpr *expr, PGAttrNumber resno, char *resname, bool resjunk);
PGTargetEntry *flatCopyTargetEntry(PGTargetEntry *src_tle);
PGFromExpr *makeFromExpr(PGList *fromlist, PGNode *quals);
PGConst *makeConst(PGOid consttype, int32_t consttypmod, PGOid constcollid, int constlen, PGDatum constvalue,
bool constisnull, bool constbyval);
PGConst *makeNullConst(PGOid consttype, int32_t consttypmod, PGOid constcollid);
PGNode *makeBoolConst(bool value, bool isnull);
PGExpr *makeBoolExpr(PGBoolExprType boolop, PGList *args, int location);
PGAlias *makeAlias(const char *aliasname, PGList *colnames);
PGRelabelType *makeRelabelType(PGExpr *arg, PGOid rtype, int32_t rtypmod, PGOid rcollid, PGCoercionForm rformat);
PGRangeVar *makeRangeVar(char *schemaname, char *relname, int location);
PGTypeName *makeTypeName(char *typnam);
PGTypeName *makeTypeNameFromNameList(PGList *names);
PGTypeName *makeTypeNameFromOid(PGOid typeOid, int32_t typmod);
PGColumnDef *makeColumnDef(const char *colname, PGOid typeOid, int32_t typmod, PGOid collOid);
PGFuncExpr *makeFuncExpr(PGOid funcid, PGOid rettype, PGList *args, PGOid funccollid, PGOid inputcollid,
PGCoercionForm fformat);
PGFuncCall *makeFuncCall(PGList *name, PGList *args, int location);
PGDefElem *makeDefElem(const char *name, PGNode *arg, int location);
PGDefElem *makeDefElemExtended(const char *nameSpace, const char *name, PGNode *arg, PGDefElemAction defaction,
int location);
PGGroupingSet *makeGroupingSet(GroupingSetKind kind, PGList *content, int location);
}

View File

@@ -0,0 +1,68 @@
/*-------------------------------------------------------------------------
*
* nodeFuncs.h
* Various general-purpose manipulations of PGNode trees
*
* Portions Copyright (c) 1996-2017, PostgreSQL Global Development PGGroup
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/include/nodes/nodeFuncs.h
*
*-------------------------------------------------------------------------
*/
#pragma once
#include "nodes/parsenodes.hpp"
namespace duckdb_libpgquery {
/* flags bits for query_tree_walker and query_tree_mutator */
#define QTW_IGNORE_RT_SUBQUERIES 0x01 /* subqueries in rtable */
#define QTW_IGNORE_CTE_SUBQUERIES 0x02 /* subqueries in cteList */
#define QTW_IGNORE_RC_SUBQUERIES 0x03 /* both of above */
#define QTW_IGNORE_JOINALIASES 0x04 /* JOIN alias var lists */
#define QTW_IGNORE_RANGE_TABLE 0x08 /* skip rangetable entirely */
#define QTW_EXAMINE_RTES 0x10 /* examine RTEs */
#define QTW_DONT_COPY_QUERY 0x20 /* do not copy top PGQuery */
/* callback function for check_functions_in_node */
typedef bool (*check_function_callback)(PGOid func_id, void *context);
PGOid exprType(const PGNode *expr);
int32_t exprTypmod(const PGNode *expr);
bool exprIsLengthCoercion(const PGNode *expr, int32_t *coercedTypmod);
PGNode *relabel_to_typmod(PGNode *expr, int32_t typmod);
PGNode *strip_implicit_coercions(PGNode *node);
bool expression_returns_set(PGNode *clause);
PGOid exprCollation(const PGNode *expr);
PGOid exprInputCollation(const PGNode *expr);
void exprSetCollation(PGNode *expr, PGOid collation);
void exprSetInputCollation(PGNode *expr, PGOid inputcollation);
int exprLocation(const PGNode *expr);
void fix_opfuncids(PGNode *node);
void set_opfuncid(PGOpExpr *opexpr);
void set_sa_opfuncid(PGScalarArrayOpExpr *opexpr);
bool check_functions_in_node(PGNode *node, check_function_callback checker, void *context);
bool expression_tree_walker(PGNode *node, bool (*walker)(), void *context);
PGNode *expression_tree_mutator(PGNode *node, PGNode *(*mutator)(), void *context);
bool query_tree_walker(PGQuery *query, bool (*walker)(), void *context, int flags);
PGQuery *query_tree_mutator(PGQuery *query, PGNode *(*mutator)(), void *context, int flags);
bool range_table_walker(PGList *rtable, bool (*walker)(), void *context, int flags);
PGList *range_table_mutator(PGList *rtable, PGNode *(*mutator)(), void *context, int flags);
bool query_or_expression_tree_walker(PGNode *node, bool (*walker)(), void *context, int flags);
PGNode *query_or_expression_tree_mutator(PGNode *node, PGNode *(*mutator)(), void *context, int flags);
bool raw_expression_tree_walker(PGNode *node, bool (*walker)(), void *context);
struct PlanState;
bool planstate_tree_walker(struct PlanState *planstate, bool (*walker)(), void *context);
}

View File

@@ -0,0 +1,836 @@
/*-------------------------------------------------------------------------
*
* nodes.h
* Definitions for tagged nodes.
*
*
* Portions Copyright (c) 1996-2017, PostgreSQL Global Development PGGroup
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/include/nodes/nodes.h
*
*-------------------------------------------------------------------------
*/
#pragma once
#include "pg_definitions.hpp"
namespace duckdb_libpgquery {
/*
* The first field of every node is NodeTag. Each node created (with makeNode)
* will have one of the following tags as the value of its first field.
*
* Note that inserting or deleting node types changes the numbers of other
* node types later in the list. This is no problem during development, since
* the node numbers are never stored on disk. But don't do it in a released
* branch, because that would represent an ABI break for extensions.
*/
typedef enum PGNodeTag {
T_PGInvalid = 0,
/*
* TAGS FOR EXECUTOR NODES (execnodes.h)
*/
T_PGIndexInfo,
T_PGExprContext,
T_PGProjectionInfo,
T_PGJunkFilter,
T_PGResultRelInfo,
T_PGEState,
T_PGTupleTableSlot,
/*
* TAGS FOR PLAN NODES (plannodes.h)
*/
T_PGPlan,
T_PGResult,
T_PGProjectSet,
T_PGModifyTable,
T_PGAppend,
T_PGMergeAppend,
T_PGRecursiveUnion,
T_PGBitmapAnd,
T_PGBitmapOr,
T_PGScan,
T_PGSeqScan,
T_PGSampleScan,
T_PGIndexScan,
T_PGIndexOnlyScan,
T_PGBitmapIndexScan,
T_PGBitmapHeapScan,
T_PGTidScan,
T_PGSubqueryScan,
T_PGFunctionScan,
T_PGValuesScan,
T_PGTableFuncScan,
T_PGCteScan,
T_PGNamedTuplestoreScan,
T_PGWorkTableScan,
T_PGForeignScan,
T_PGCustomScan,
T_PGJoin,
T_PGNestLoop,
T_PGMergeJoin,
T_PGHashJoin,
T_PGMaterial,
T_PGSort,
T_PGGroup,
T_PGAgg,
T_PGWindowAgg,
T_PGUnique,
T_PGGather,
T_PGGatherMerge,
T_PGHash,
T_PGSetOp,
T_PGLockRows,
T_PGLimit,
/* these aren't subclasses of PGPlan: */
T_PGNestLoopParam,
T_PGPlanRowMark,
T_PGPlanInvalItem,
/*
* TAGS FOR PLAN STATE NODES (execnodes.h)
*
* These should correspond one-to-one with PGPlan node types.
*/
T_PGPlanState,
T_PGResultState,
T_PGProjectSetState,
T_PGModifyTableState,
T_PGAppendState,
T_PGMergeAppendState,
T_PGRecursiveUnionState,
T_PGBitmapAndState,
T_PGBitmapOrState,
T_PGScanState,
T_PGSeqScanState,
T_PGSampleScanState,
T_PGIndexScanState,
T_PGIndexOnlyScanState,
T_PGBitmapIndexScanState,
T_PGBitmapHeapScanState,
T_PGTidScanState,
T_PGSubqueryScanState,
T_PGFunctionScanState,
T_PGTableFuncScanState,
T_PGValuesScanState,
T_PGCteScanState,
T_PGNamedTuplestoreScanState,
T_PGWorkTableScanState,
T_PGForeignScanState,
T_PGCustomScanState,
T_PGJoinState,
T_PGNestLoopState,
T_PGMergeJoinState,
T_PGHashJoinState,
T_PGMaterialState,
T_PGSortState,
T_PGGroupState,
T_PGAggState,
T_PGWindowAggState,
T_PGUniqueState,
T_PGGatherState,
T_PGGatherMergeState,
T_PGHashState,
T_PGSetOpState,
T_PGLockRowsState,
T_PGLimitState,
/*
* TAGS FOR PRIMITIVE NODES (primnodes.h)
*/
T_PGAlias,
T_PGRangeVar,
T_PGTableFunc,
T_PGExpr,
T_PGVar,
T_PGConst,
T_PGParam,
T_PGAggref,
T_PGGroupingFunc,
T_PGWindowFunc,
T_PGArrayRef,
T_PGFuncExpr,
T_PGNamedArgExpr,
T_PGOpExpr,
T_PGDistinctExpr,
T_PGNullIfExpr,
T_PGScalarArrayOpExpr,
T_PGBoolExpr,
T_PGSubLink,
T_PGSubPlan,
T_PGAlternativeSubPlan,
T_PGFieldSelect,
T_PGFieldStore,
T_PGRelabelType,
T_PGCoerceViaIO,
T_PGArrayCoerceExpr,
T_PGConvertRowtypeExpr,
T_PGCollateExpr,
T_PGCaseExpr,
T_PGCaseWhen,
T_PGCaseTestExpr,
T_PGArrayExpr,
T_PGRowExpr,
T_PGRowCompareExpr,
T_PGCoalesceExpr,
T_PGMinMaxExpr,
T_PGSQLValueFunction,
T_PGXmlExpr,
T_PGNullTest,
T_PGBooleanTest,
T_PGCoerceToDomain,
T_PGCoerceToDomainValue,
T_PGSetToDefault,
T_PGCurrentOfExpr,
T_PGNextValueExpr,
T_PGInferenceElem,
T_PGTargetEntry,
T_PGRangeTblRef,
T_PGJoinExpr,
T_PGFromExpr,
T_PGOnConflictExpr,
T_PGIntoClause,
T_PGLambdaFunction,
T_PGPivotExpr,
T_PGPivot,
T_PGPivotStmt,
T_PGAtClause,
T_PGSingleArrowFunction,
/*
* TAGS FOR EXPRESSION STATE NODES (execnodes.h)
*
* ExprState represents the evaluation state for a whole expression tree.
* Most Expr-based plan nodes do not have a corresponding expression state
* node, they're fully handled within execExpr* - but sometimes the state
* needs to be shared with other parts of the executor, as for example
* with AggrefExprState, which nodeAgg.c has to modify.
*/
T_PGExprState,
T_PGAggrefExprState,
T_PGWindowFuncExprState,
T_PGSetExprState,
T_PGSubPlanState,
T_PGAlternativeSubPlanState,
T_PGDomainConstraintState,
/*
* TAGS FOR PLANNER NODES (relation.h)
*/
T_PGPlannerInfo,
T_PGPlannerGlobal,
T_PGRelOptInfo,
T_PGIndexOptInfo,
T_PGForeignKeyOptInfo,
T_PGParamPathInfo,
T_PGPath,
T_PGIndexPath,
T_PGBitmapHeapPath,
T_PGBitmapAndPath,
T_PGBitmapOrPath,
T_PGTidPath,
T_PGSubqueryScanPath,
T_PGForeignPath,
T_PGCustomPath,
T_PGNestPath,
T_PGMergePath,
T_PGHashPath,
T_PGAppendPath,
T_PGMergeAppendPath,
T_PGResultPath,
T_PGMaterialPath,
T_PGUniquePath,
T_PGGatherPath,
T_PGGatherMergePath,
T_PGProjectionPath,
T_PGProjectSetPath,
T_PGSortPath,
T_PGGroupPath,
T_PGUpperUniquePath,
T_PGAggPath,
T_PGGroupingSetsPath,
T_PGMinMaxAggPath,
T_PGWindowAggPath,
T_PGSetOpPath,
T_PGRecursiveUnionPath,
T_PGLockRowsPath,
T_PGModifyTablePath,
T_PGLimitPath,
/* these aren't subclasses of Path: */
T_PGEquivalenceClass,
T_PGEquivalenceMember,
T_PGPathKey,
T_PGPathTarget,
T_PGRestrictInfo,
T_PGPlaceHolderVar,
T_PGSpecialJoinInfo,
T_PGAppendRelInfo,
T_PGPartitionedChildRelInfo,
T_PGPlaceHolderInfo,
T_PGMinMaxAggInfo,
T_PGPlannerParamItem,
T_PGRollupData,
T_PGGroupingSetData,
T_PGStatisticExtInfo,
/*
* TAGS FOR MEMORY NODES (memnodes.h)
*/
T_PGMemoryContext,
T_PGAllocSetContext,
T_PGSlabContext,
/*
* TAGS FOR VALUE NODES (value.h)
*/
T_PGValue,
T_PGInteger,
T_PGFloat,
T_PGString,
T_PGBitString,
T_PGNull,
/*
* TAGS FOR LIST NODES (pg_list.h)
*/
T_PGList,
T_PGIntList,
T_PGOidList,
/*
* TAGS FOR EXTENSIBLE NODES (extensible.h)
*/
T_PGExtensibleNode,
/*
* TAGS FOR STATEMENT NODES (mostly in parsenodes.h)
*/
T_PGRawStmt,
T_PGQuery,
T_PGPlannedStmt,
T_PGInsertStmt,
T_PGDeleteStmt,
T_PGUpdateStmt,
T_PGUpdateExtensionsStmt,
T_PGSelectStmt,
T_PGAlterTableStmt,
T_PGAlterTableCmd,
T_PGAlterDomainStmt,
T_PGSetOperationStmt,
T_PGGrantStmt,
T_PGGrantRoleStmt,
T_PGAlterDefaultPrivilegesStmt,
T_PGClosePortalStmt,
T_PGClusterStmt,
T_PGCopyStmt,
T_PGCopyDatabaseStmt,
T_PGCreateStmt,
T_PGDefineStmt,
T_PGDropStmt,
T_PGTruncateStmt,
T_PGCommentStmt,
T_PGCommentOnStmt,
T_PGMergeIntoStmt,
T_PGFetchStmt,
T_PGIndexStmt,
T_PGFunctionDefinition,
T_PGCreateFunctionStmt,
T_PGAlterFunctionStmt,
T_PGDoStmt,
T_PGRenameStmt,
T_PGRuleStmt,
T_PGNotifyStmt,
T_PGListenStmt,
T_PGUnlistenStmt,
T_PGTransactionStmt,
T_PGViewStmt,
T_PGLoadStmt,
T_PGCreateDomainStmt,
T_PGCreatedbStmt,
T_PGDropdbStmt,
T_PGVacuumStmt,
T_PGExplainStmt,
T_PGCreateTableAsStmt,
T_PGCreateSeqStmt,
T_PGAlterSeqStmt,
T_PGVariableSetStmt,
T_PGVariableShowStmt,
T_PGVariableShowSelectStmt,
T_PGDiscardStmt,
T_PGCreateTrigStmt,
T_PGCreatePLangStmt,
T_PGCreateRoleStmt,
T_PGAlterRoleStmt,
T_PGDropRoleStmt,
T_PGLockStmt,
T_PGConstraintsSetStmt,
T_PGReindexStmt,
T_PGCheckPointStmt,
T_PGCreateSchemaStmt,
T_PGCreateSecretStmt,
T_PGAlterDatabaseStmt,
T_PGAlterDatabaseSetStmt,
T_PGAlterRoleSetStmt,
T_PGCreateConversionStmt,
T_PGCreateCastStmt,
T_PGCreateOpClassStmt,
T_PGCreateOpFamilyStmt,
T_PGAlterOpFamilyStmt,
T_PGPrepareStmt,
T_PGExecuteStmt,
T_PGCallStmt,
T_PGDeallocateStmt,
T_PGDeclareCursorStmt,
T_PGCreateTableSpaceStmt,
T_PGDropSecretStmt,
T_PGDropTableSpaceStmt,
T_PGAlterObjectDependsStmt,
T_PGAlterObjectSchemaStmt,
T_PGAlterOwnerStmt,
T_PGAlterOperatorStmt,
T_PGDropOwnedStmt,
T_PGReassignOwnedStmt,
T_PGCompositeTypeStmt,
T_PGCreateTypeStmt,
T_PGCreateRangeStmt,
T_PGAlterEnumStmt,
T_PGAlterTSDictionaryStmt,
T_PGAlterTSConfigurationStmt,
T_PGCreateFdwStmt,
T_PGAlterFdwStmt,
T_PGCreateForeignServerStmt,
T_PGAlterForeignServerStmt,
T_PGCreateUserMappingStmt,
T_PGAlterUserMappingStmt,
T_PGDropUserMappingStmt,
T_PGAlterTableSpaceOptionsStmt,
T_PGAlterTableMoveAllStmt,
T_PGSecLabelStmt,
T_PGCreateForeignTableStmt,
T_PGImportForeignSchemaStmt,
T_PGCreateExtensionStmt,
T_PGAlterExtensionStmt,
T_PGAlterExtensionContentsStmt,
T_PGCreateEventTrigStmt,
T_PGAlterEventTrigStmt,
T_PGRefreshMatViewStmt,
T_PGReplicaIdentityStmt,
T_PGAlterSystemStmt,
T_PGCreatePolicyStmt,
T_PGAlterPolicyStmt,
T_PGCreateTransformStmt,
T_PGCreateAmStmt,
T_PGCreatePublicationStmt,
T_PGAlterPublicationStmt,
T_PGCreateSubscriptionStmt,
T_PGAlterSubscriptionStmt,
T_PGDropSubscriptionStmt,
T_PGCreateStatsStmt,
T_PGAlterCollationStmt,
T_PGPragmaStmt,
T_PGExportStmt,
T_PGImportStmt,
T_PGAttachStmt,
T_PGDetachStmt,
T_PGUseStmt,
/*
* TAGS FOR PARSE TREE NODES (parsenodes.h)
*/
T_PGAExpr,
T_PGColumnRef,
T_PGParamRef,
T_PGAConst,
T_PGFuncCall,
T_PGAStar,
T_PGAIndices,
T_PGAIndirection,
T_PGAArrayExpr,
T_PGResTarget,
T_PGMultiAssignRef,
T_PGTypeCast,
T_PGCollateClause,
T_PGSortBy,
T_PGWindowDef,
T_PGRangeSubselect,
T_PGRangeFunction,
T_PGRangeTableSample,
T_PGRangeTableFunc,
T_PGRangeTableFuncCol,
T_PGTypeName,
T_PGColumnDef,
T_PGIndexElem,
T_PGConstraint,
T_PGDefElem,
T_PGRangeTblEntry,
T_PGRangeTblFunction,
T_PGTableSampleClause,
T_PGWithCheckOption,
T_PGSortGroupClause,
T_PGGroupingSet,
T_PGWindowClause,
T_PGObjectWithArgs,
T_PGAccessPriv,
T_PGCreateOpClassItem,
T_PGTableLikeClause,
T_PGFunctionParameter,
T_PGLockingClause,
T_PGRowMarkClause,
T_PGXmlSerialize,
T_PGWithClause,
T_PGInferClause,
T_PGOnConflictClause,
T_PGCommonTableExpr,
T_PGRoleSpec,
T_PGTriggerTransition,
T_PGPartitionElem,
T_PGPartitionSpec,
T_PGPartitionBoundSpec,
T_PGPartitionRangeDatum,
T_PGPartitionCmd,
T_PGIntervalConstant,
T_PGSampleSize,
T_PGSampleOptions,
T_PGLimitPercent,
T_PGPositionalReference,
T_PGMatchEntry,
T_PGMatchAction,
/*
* TAGS FOR REPLICATION GRAMMAR PARSE NODES (replnodes.h)
*/
T_PGIdentifySystemCmd,
T_PGBaseBackupCmd,
T_PGCreateReplicationSlotCmd,
T_PGDropReplicationSlotCmd,
T_PGStartReplicationCmd,
T_PGTimeLineHistoryCmd,
T_PGSQLCmd,
/*
* TAGS FOR RANDOM OTHER STUFF
*
* These are objects that aren't part of parse/plan/execute node tree
* structures, but we give them NodeTags anyway for identification
* purposes (usually because they are involved in APIs where we want to
* pass multiple object types through the same pointer).
*/
T_PGTriggerData, /* in commands/trigger.h */
T_PGEventTriggerData, /* in commands/event_trigger.h */
T_PGReturnSetInfo, /* in nodes/execnodes.h */
T_PGWindowObjectData, /* private in nodeWindowAgg.c */
T_PGTIDBitmap, /* in nodes/tidbitmap.h */
T_PGInlineCodeBlock, /* in nodes/parsenodes.h */
T_PGFdwRoutine, /* in foreign/fdwapi.h */
T_PGIndexAmRoutine, /* in access/amapi.h */
T_PGTsmRoutine, /* in access/tsmapi.h */
T_PGForeignKeyCacheInfo /* in utils/rel.h */
} PGNodeTag;
/*
* The first field of a node of any type is guaranteed to be the NodeTag.
* Hence the type of any node can be gotten by casting it to Node. Declaring
* a variable to be of PGNode * (instead of void *) can also facilitate
* debugging.
*/
typedef struct PGNode {
PGNodeTag type;
} PGNode;
#define nodeTag(nodeptr) (((const PGNode *)(nodeptr))->type)
#define makeNode(_type_) ((_type_ *)newNode(sizeof(_type_), T_##_type_))
#define NodeSetTag(nodeptr, t) (((PGNode *)(nodeptr))->type = (t))
#define IsA(nodeptr, _type_) (nodeTag(nodeptr) == T_##_type_)
/*
* castNode(type, ptr) casts ptr to "type *", and if assertions are enabled,
* verifies that the node has the appropriate type (using its nodeTag()).
*
* Use an inline function when assertions are enabled, to avoid multiple
* evaluations of the ptr argument (which could e.g. be a function call).
*/
#ifdef USE_ASSERT_CHECKING
static inline PGNode *castNodeImpl(PGNodeTag type, void *ptr) {
Assert(ptr == NULL || nodeTag(ptr) == type);
return (PGNode *)ptr;
}
#define castNode(_type_, nodeptr) ((_type_ *)castNodeImpl(T_##_type_, nodeptr))
#else
#define castNode(_type_, nodeptr) ((_type_ *)(nodeptr))
#endif /* USE_ASSERT_CHECKING */
/* ----------------------------------------------------------------
* extern declarations follow
* ----------------------------------------------------------------
*/
/*
* nodes/{outfuncs.c,print.c}
*/
struct PGBitmapset; /* not to include bitmapset.h here */
struct PGStringInfoData; /* not to include stringinfo.h here */
PGNode* newNode(size_t size, PGNodeTag type);
void outNode(struct PGStringInfoData *str, const void *obj);
void outToken(struct PGStringInfoData *str, const char *s);
void outBitmapset(struct PGStringInfoData *str, const struct PGBitmapset *bms);
void outDatum(struct PGStringInfoData *str, uintptr_t value, int typlen, bool typbyval);
char *nodeToString(const void *obj);
char *bmsToString(const struct PGBitmapset *bms);
/*
* nodes/{readfuncs.c,read.c}
*/
void *stringToNode(char *str);
struct PGBitmapset *readBitmapset(void);
uintptr_t readDatum(bool typbyval);
bool *readBoolCols(int numCols);
int *readIntCols(int numCols);
PGOid *readOidCols(int numCols);
int16_t *readAttrNumberCols(int numCols);
/*
* nodes/copyfuncs.c
*/
void *copyObjectImpl(const void *obj);
/* cast result back to argument type, if supported by compiler */
//#ifdef HAVE_TYPEOF
//#define copyObject(obj) ((typeof(obj)) copyObjectImpl(obj))
//#else
//#define copyObject(obj) copyObjectImpl(obj)
//#endif
/*
* nodes/equalfuncs.c
*/
// extern bool equal(const void *a, const void *b);
/*
* Typedefs for identifying qualifier selectivities and plan costs as such.
* These are just plain "double"s, but declaring a variable as Selectivity
* or Cost makes the intent more obvious.
*
* These could have gone into plannodes.h or some such, but many files
* depend on them...
*/
typedef double Selectivity; /* fraction of tuples a qualifier will pass */
typedef double Cost; /* execution cost (in page-access units) */
/*
* PGCmdType -
* enums for type of operation represented by a PGQuery or PGPlannedStmt
*
* This is needed in both parsenodes.h and plannodes.h, so put it here...
*/
typedef enum PGCmdType {
PG_CMD_UNKNOWN,
PG_CMD_SELECT, /* select stmt */
PG_CMD_UPDATE, /* update stmt */
PG_CMD_INSERT, /* insert stmt */
PG_CMD_DELETE,
PG_CMD_UTILITY, /* cmds like create, destroy, copy, vacuum,
* etc. */
PG_CMD_NOTHING /* dummy command for instead nothing rules
* with qual */
} PGCmdType;
/*
* PGJoinType -
* enums for types of relation joins
*
* PGJoinType determines the exact semantics of joining two relations using
* a matching qualification. For example, it tells what to do with a tuple
* that has no match in the other relation.
*
* This is needed in both parsenodes.h and plannodes.h, so put it here...
*/
typedef enum PGJoinType {
/*
* The canonical kinds of joins according to the SQL JOIN syntax. Only
* these codes can appear in parser output (e.g., PGJoinExpr nodes).
*/
PG_JOIN_INNER, /* matching tuple pairs only */
PG_JOIN_LEFT, /* pairs + unmatched LHS tuples */
PG_JOIN_FULL, /* pairs + unmatched LHS + unmatched RHS */
PG_JOIN_RIGHT, /* pairs + unmatched RHS tuples */
/*
* Semijoins and anti-semijoins (as defined in relational theory) do not
* appear in the SQL JOIN syntax, but there are standard idioms for
* representing them (e.g., using EXISTS). The planner recognizes these
* cases and converts them to joins. So the planner and executor must
* support these codes. NOTE: in PG_JOIN_SEMI output, it is unspecified
* which matching RHS row is joined to. In PG_JOIN_ANTI output, the row is
* guaranteed to be null-extended.
*/
PG_JOIN_SEMI, /* 1 copy of each LHS row that has match(es) */
PG_JOIN_ANTI, /* 1 copy of each LHS row that has no match */
/*
* These codes are used internally in the planner, but are not supported
* by the executor (nor, indeed, by most of the planner).
*/
PG_JOIN_UNIQUE_OUTER, /* LHS path must be made unique */
PG_JOIN_UNIQUE_INNER, /* RHS path must be made unique */
/*
* Positional joins are essentially parallel table scans.
*/
PG_JOIN_POSITION /* Two tables of the same length */
/*
* We might need additional join types someday.
*/
} PGJoinType;
/*
* PGJoinRefType -
* enums for the types of implied conditions
*
* PGJoinRefType specifies the semantics of interpreting the join conditions.
* These can be explicit (e.g., REGULAR) implied (e.g., NATURAL)
* or interpreted in a particular manner (e.g., ASOF)
*
* This is a generalisation of the old Postgres isNatural flag.
*/
typedef enum PGJoinRefType {
PG_JOIN_REGULAR, /* Join conditions are interpreted as is */
PG_JOIN_NATURAL, /* Join conditions are inferred from the column names */
/*
* ASOF joins are joins with a single inequality predicate
* and optional equality predicates.
* The semantics are equivalent to the following window join:
* times t
* <jointype> JOIN (
* SELECT *,
* LEAD(begin, 1, 'infinity') OVER ([PARTITION BY key] ORDER BY begin) AS end)
* FROM events) e
* ON t.ts >= e.begin AND t.ts < e.end [AND t.key = e.key]
*/
PG_JOIN_ASOF
/*
* Positional join is a candidate to move here
*/
} PGJoinRefType;
/*
* OUTER joins are those for which pushed-down quals must behave differently
* from the join's own quals. This is in fact everything except INNER and
* SEMI joins. However, this macro must also exclude the JOIN_UNIQUE symbols
* since those are temporary proxies for what will eventually be an INNER
* join.
*
* Note: semijoins are a hybrid case, but we choose to treat them as not
* being outer joins. This is okay principally because the SQL syntax makes
* it impossible to have a pushed-down qual that refers to the inner relation
* of a semijoin; so there is no strong need to distinguish join quals from
* pushed-down quals. This is convenient because for almost all purposes,
* quals attached to a semijoin can be treated the same as innerjoin quals.
*/
#define IS_OUTER_JOIN(jointype) \
(((1 << (jointype)) & ((1 << PG_JOIN_LEFT) | (1 << PG_JOIN_FULL) | (1 << PG_JOIN_RIGHT) | (1 << PG_JOIN_ANTI))) != 0)
/*
* PGAggStrategy -
* overall execution strategies for PGAgg plan nodes
*
* This is needed in both plannodes.h and relation.h, so put it here...
*/
typedef enum PGAggStrategy {
PG_AGG_PLAIN, /* simple agg across all input rows */
PG_AGG_SORTED, /* grouped agg, input must be sorted */
PG_AGG_HASHED, /* grouped agg, use internal hashtable */
AGG_MIXED /* grouped agg, hash and sort both used */
} PGAggStrategy;
/*
* PGAggSplit -
* splitting (partial aggregation) modes for PGAgg plan nodes
*
* This is needed in both plannodes.h and relation.h, so put it here...
*/
/* Primitive options supported by nodeAgg.c: */
#define AGGSPLITOP_COMBINE 0x01 /* substitute combinefn for transfn */
#define AGGSPLITOP_SKIPFINAL 0x02 /* skip finalfn, return state as-is */
#define AGGSPLITOP_SERIALIZE 0x04 /* apply serializefn to output */
#define AGGSPLITOP_DESERIALIZE 0x08 /* apply deserializefn to input */
/* Supported operating modes (i.e., useful combinations of these options): */
typedef enum PGAggSplit {
/* Basic, non-split aggregation: */
PG_AGGSPLIT_SIMPLE = 0,
/* Initial phase of partial aggregation, with serialization: */
PG_AGGSPLIT_INITIAL_SERIAL = AGGSPLITOP_SKIPFINAL | AGGSPLITOP_SERIALIZE,
/* Final phase of partial aggregation, with deserialization: */
PG_AGGSPLIT_FINAL_DESERIAL = AGGSPLITOP_COMBINE | AGGSPLITOP_DESERIALIZE
} PGAggSplit;
/* Test whether an PGAggSplit value selects each primitive option: */
#define DO_AGGSPLIT_COMBINE(as) (((as)&AGGSPLITOP_COMBINE) != 0)
#define DO_AGGSPLIT_SKIPFINAL(as) (((as)&AGGSPLITOP_SKIPFINAL) != 0)
#define DO_AGGSPLIT_SERIALIZE(as) (((as)&AGGSPLITOP_SERIALIZE) != 0)
#define DO_AGGSPLIT_DESERIALIZE(as) (((as)&AGGSPLITOP_DESERIALIZE) != 0)
/*
* PGSetOpCmd and PGSetOpStrategy -
* overall semantics and execution strategies for PGSetOp plan nodes
*
* This is needed in both plannodes.h and relation.h, so put it here...
*/
typedef enum PGSetOpCmd {
PG_SETOPCMD_INTERSECT,
PG_SETOPCMD_INTERSECT_ALL,
PG_SETOPCMD_EXCEPT,
PG_SETOPCMD_EXCEPT_ALL
} PGSetOpCmd;
typedef enum PGSetOpStrategy {
PG_SETOP_SORTED, /* input must be sorted */
PG_SETOP_HASHED /* use internal hashtable */
} PGSetOpStrategy;
/*
* PGOnConflictAction -
* "ON CONFLICT" clause type of query
*
* This is needed in both parsenodes.h and plannodes.h, so put it here...
*/
typedef enum PGOnConflictAction {
PG_ONCONFLICT_NONE, /* No "ON CONFLICT" clause */
PG_ONCONFLICT_NOTHING, /* ON CONFLICT ... DO NOTHING */
PG_ONCONFLICT_UPDATE /* ON CONFLICT ... DO UPDATE */
} PGOnConflictAction;
/*
* PGOnConflictActionAlias -
* "INSERT OR [REPLACE|IGNORE]" aliases for OnConflictAction
*
* This is needed in both parsenodes.h and plannodes.h, so put it here...
*/
typedef enum PGOnConflictActionAlias {
PG_ONCONFLICT_ALIAS_NONE, /* No "OR [IGNORE|REPLACE]" clause */
PG_ONCONFLICT_ALIAS_REPLACE, /* INSERT OR REPLACE */
PG_ONCONFLICT_ALIAS_IGNORE /* INSERT OR IGNORE */
} PGOnConflictActionAlias;
/*
* PGInsertByNameOrPosition
* "INSERT BY [POSITION|NAME]
*/
typedef enum PGInsertColumnOrder {
PG_INSERT_BY_POSITION, /* INSERT BY POSITION (default behavior) */
PG_INSERT_BY_NAME, /* INSERT BY NAME */
} PGInsertColumnOrder;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,339 @@
/*-------------------------------------------------------------------------
*
* pg_list.h
* interface for PostgreSQL generic linked list package
*
* This package implements singly-linked homogeneous lists.
*
* It is important to have constant-time length, append, and prepend
* operations. To achieve this, we deal with two distinct data
* structures:
*
* 1. A set of "list cells": each cell contains a data field and
* a link to the next cell in the list or NULL.
* 2. A single structure containing metadata about the list: the
* type of the list, pointers to the head and tail cells, and
* the length of the list.
*
* We support three types of lists:
*
* duckdb_libpgquery::T_PGList: lists of pointers
* (in practice usually pointers to Nodes, but not always;
* declared as "void *" to minimize casting annoyances)
* duckdb_libpgquery::T_PGIntList: lists of integers
* duckdb_libpgquery::T_PGOidList: lists of Oids
*
* (At the moment, ints and Oids are the same size, but they may not
* always be so; try to be careful to maintain the distinction.)
*
*
* Portions Copyright (c) 1996-2017, PostgreSQL Global Development PGGroup
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/include/nodes/pg_list.h
*
*-------------------------------------------------------------------------
*/
#pragma once
#include "nodes/nodes.hpp"
namespace duckdb_libpgquery {
typedef struct PGListCell ListCell;
typedef struct PGList {
PGNodeTag type; /* duckdb_libpgquery::T_PGList, duckdb_libpgquery::T_PGIntList, or duckdb_libpgquery::T_PGOidList */
int length;
PGListCell *head;
PGListCell *tail;
} PGList;
struct PGListCell {
union
{
void *ptr_value;
int int_value;
PGOid oid_value;
} data;
PGListCell *next;
};
/*
* The *only* valid representation of an empty list is NIL; in other
* words, a non-NIL list is guaranteed to have length >= 1 and
* head/tail != NULL
*/
#define NIL ((PGList *) NULL)
/*
* These routines are used frequently. However, we can't implement
* them as macros, since we want to avoid double-evaluation of macro
* arguments.
*/
static inline PGListCell *
list_head(const PGList *l)
{
return l ? l->head : NULL;
}
static inline PGListCell *
list_tail(PGList *l)
{
return l ? l->tail : NULL;
}
static inline int
list_length(const PGList *l)
{
return l ? l->length : 0;
}
/*
* NB: There is an unfortunate legacy from a previous incarnation of
* the PGList API: the macro lfirst() was used to mean "the data in this
* cons cell". To avoid changing every usage of lfirst(), that meaning
* has been kept. As a result, lfirst() takes a PGListCell and returns
* the data it contains; to get the data in the first cell of a
* PGList, use linitial(). Worse, lsecond() is more closely related to
* linitial() than lfirst(): given a PGList, lsecond() returns the data
* in the second cons cell.
*/
#define lnext(lc) ((lc)->next)
#define lfirst(lc) ((lc)->data.ptr_value)
#define lfirst_int(lc) ((lc)->data.int_value)
#define lfirst_oid(lc) ((lc)->data.oid_value)
#define lfirst_node(type,lc) castNode(type, lfirst(lc))
#define linitial(l) lfirst(list_head(l))
#define linitial_int(l) lfirst_int(list_head(l))
#define linitial_oid(l) lfirst_oid(list_head(l))
#define linitial_node(type,l) castNode(type, linitial(l))
#define lsecond(l) lfirst(lnext(list_head(l)))
#define lsecond_int(l) lfirst_int(lnext(list_head(l)))
#define lsecond_oid(l) lfirst_oid(lnext(list_head(l)))
#define lsecond_node(type,l) castNode(type, lsecond(l))
#define lthird(l) lfirst(lnext(lnext(list_head(l))))
#define lthird_int(l) lfirst_int(lnext(lnext(list_head(l))))
#define lthird_oid(l) lfirst_oid(lnext(lnext(list_head(l))))
#define lthird_node(type,l) castNode(type, lthird(l))
#define lfourth(l) lfirst(lnext(lnext(lnext(list_head(l)))))
#define lfourth_int(l) lfirst_int(lnext(lnext(lnext(list_head(l)))))
#define lfourth_oid(l) lfirst_oid(lnext(lnext(lnext(list_head(l)))))
#define lfourth_node(type,l) castNode(type, lfourth(l))
#define llast(l) lfirst(list_tail(l))
#define llast_int(l) lfirst_int(list_tail(l))
#define llast_oid(l) lfirst_oid(list_tail(l))
#define llast_node(type,l) castNode(type, llast(l))
/*
* Convenience macros for building fixed-length lists
*/
#define list_make1(x1) lcons(x1, NIL)
#define list_make2(x1,x2) lcons(x1, list_make1(x2))
#define list_make3(x1,x2,x3) lcons(x1, list_make2(x2, x3))
#define list_make4(x1,x2,x3,x4) lcons(x1, list_make3(x2, x3, x4))
#define list_make5(x1,x2,x3,x4,x5) lcons(x1, list_make4(x2, x3, x4, x5))
#define list_make1_int(x1) lcons_int(x1, NIL)
#define list_make2_int(x1,x2) lcons_int(x1, list_make1_int(x2))
#define list_make3_int(x1,x2,x3) lcons_int(x1, list_make2_int(x2, x3))
#define list_make4_int(x1,x2,x3,x4) lcons_int(x1, list_make3_int(x2, x3, x4))
#define list_make5_int(x1,x2,x3,x4,x5) lcons_int(x1, list_make4_int(x2, x3, x4, x5))
#define list_make1_oid(x1) lcons_oid(x1, NIL)
#define list_make2_oid(x1,x2) lcons_oid(x1, list_make1_oid(x2))
#define list_make3_oid(x1,x2,x3) lcons_oid(x1, list_make2_oid(x2, x3))
#define list_make4_oid(x1,x2,x3,x4) lcons_oid(x1, list_make3_oid(x2, x3, x4))
#define list_make5_oid(x1,x2,x3,x4,x5) lcons_oid(x1, list_make4_oid(x2, x3, x4, x5))
/*
* foreach -
* a convenience macro which loops through the list
*/
#define foreach(cell, l) \
for ((cell) = list_head(l); (cell) != NULL; (cell) = lnext(cell))
/*
* for_each_cell -
* a convenience macro which loops through a list starting from a
* specified cell
*/
#define for_each_cell(cell, initcell) \
for ((cell) = (initcell); (cell) != NULL; (cell) = lnext(cell))
/*
* forboth -
* a convenience macro for advancing through two linked lists
* simultaneously. This macro loops through both lists at the same
* time, stopping when either list runs out of elements. Depending
* on the requirements of the call site, it may also be wise to
* assert that the lengths of the two lists are equal.
*/
#define forboth(cell1, list1, cell2, list2) \
for ((cell1) = list_head(list1), (cell2) = list_head(list2); \
(cell1) != NULL && (cell2) != NULL; \
(cell1) = lnext(cell1), (cell2) = lnext(cell2))
/*
* for_both_cell -
* a convenience macro which loops through two lists starting from the
* specified cells of each. This macro loops through both lists at the same
* time, stopping when either list runs out of elements. Depending on the
* requirements of the call site, it may also be wise to assert that the
* lengths of the two lists are equal, and initcell1 and initcell2 are at
* the same position in the respective lists.
*/
#define for_both_cell(cell1, initcell1, cell2, initcell2) \
for ((cell1) = (initcell1), (cell2) = (initcell2); \
(cell1) != NULL && (cell2) != NULL; \
(cell1) = lnext(cell1), (cell2) = lnext(cell2))
/*
* forthree -
* the same for three lists
*/
#define forthree(cell1, list1, cell2, list2, cell3, list3) \
for ((cell1) = list_head(list1), (cell2) = list_head(list2), (cell3) = list_head(list3); \
(cell1) != NULL && (cell2) != NULL && (cell3) != NULL; \
(cell1) = lnext(cell1), (cell2) = lnext(cell2), (cell3) = lnext(cell3))
PGList *lappend(PGList *list, void *datum);
PGList *lappend_int(PGList *list, int datum);
PGList *lappend_oid(PGList *list, PGOid datum);
PGListCell *lappend_cell(PGList *list, PGListCell *prev, void *datum);
PGListCell *lappend_cell_int(PGList *list, PGListCell *prev, int datum);
PGListCell *lappend_cell_oid(PGList *list, PGListCell *prev, PGOid datum);
PGList *lcons(void *datum, PGList *list);
PGList *lcons_int(int datum, PGList *list);
PGList *lcons_oid(PGOid datum, PGList *list);
PGList *list_concat(PGList *list1, PGList *list2);
PGList *list_truncate(PGList *list, int new_size);
PGListCell *list_nth_cell(const PGList *list, int n);
void *list_nth(const PGList *list, int n);
int list_nth_int(const PGList *list, int n);
PGOid list_nth_oid(const PGList *list, int n);
#define list_nth_node(type,list,n) castNode(type, list_nth(list, n))
bool list_member(const PGList *list, const void *datum);
bool list_member_ptr(const PGList *list, const void *datum);
bool list_member_int(const PGList *list, int datum);
bool list_member_oid(const PGList *list, PGOid datum);
PGList *list_delete(PGList *list, void *datum);
PGList *list_delete_ptr(PGList *list, void *datum);
PGList *list_delete_int(PGList *list, int datum);
PGList *list_delete_oid(PGList *list, PGOid datum);
PGList *list_delete_first(PGList *list);
PGList *list_delete_cell(PGList *list, PGListCell *cell, PGListCell *prev);
PGList *list_union(const PGList *list1, const PGList *list2);
PGList *list_union_ptr(const PGList *list1, const PGList *list2);
PGList *list_union_int(const PGList *list1, const PGList *list2);
PGList *list_union_oid(const PGList *list1, const PGList *list2);
PGList *list_intersection(const PGList *list1, const PGList *list2);
PGList *list_intersection_int(const PGList *list1, const PGList *list2);
/* currently, there's no need for list_intersection_ptr etc */
PGList *list_difference(const PGList *list1, const PGList *list2);
PGList *list_difference_ptr(const PGList *list1, const PGList *list2);
PGList *list_difference_int(const PGList *list1, const PGList *list2);
PGList *list_difference_oid(const PGList *list1, const PGList *list2);
PGList *list_append_unique(PGList *list, void *datum);
PGList *list_append_unique_ptr(PGList *list, void *datum);
PGList *list_append_unique_int(PGList *list, int datum);
PGList *list_append_unique_oid(PGList *list, PGOid datum);
PGList *list_concat_unique(PGList *list1, PGList *list2);
PGList *list_concat_unique_ptr(PGList *list1, PGList *list2);
PGList *list_concat_unique_int(PGList *list1, PGList *list2);
PGList *list_concat_unique_oid(PGList *list1, PGList *list2);
void list_free(PGList *list);
void list_free_deep(PGList *list);
PGList *list_copy(const PGList *list);
PGList *list_copy_tail(const PGList *list, int nskip);
/*
* To ease migration to the new list API, a set of compatibility
* macros are provided that reduce the impact of the list API changes
* as far as possible. Until client code has been rewritten to use the
* new list API, the ENABLE_LIST_COMPAT symbol can be defined before
* including pg_list.h
*/
#ifdef ENABLE_LIST_COMPAT
#define lfirsti(lc) lfirst_int(lc)
#define lfirsto(lc) lfirst_oid(lc)
#define makeList1(x1) list_make1(x1)
#define makeList2(x1, x2) list_make2(x1, x2)
#define makeList3(x1, x2, x3) list_make3(x1, x2, x3)
#define makeList4(x1, x2, x3, x4) list_make4(x1, x2, x3, x4)
#define makeListi1(x1) list_make1_int(x1)
#define makeListi2(x1, x2) list_make2_int(x1, x2)
#define makeListo1(x1) list_make1_oid(x1)
#define makeListo2(x1, x2) list_make2_oid(x1, x2)
#define lconsi(datum, list) lcons_int(datum, list)
#define lconso(datum, list) lcons_oid(datum, list)
#define lappendi(list, datum) lappend_int(list, datum)
#define lappendo(list, datum) lappend_oid(list, datum)
#define nconc(l1, l2) list_concat(l1, l2)
#define nth(n, list) list_nth(list, n)
#define member(datum, list) list_member(list, datum)
#define ptrMember(datum, list) list_member_ptr(list, datum)
#define intMember(datum, list) list_member_int(list, datum)
#define oidMember(datum, list) list_member_oid(list, datum)
/*
* Note that the old lremove() determined equality via pointer
* comparison, whereas the new list_delete() uses equal(); in order to
* keep the same behavior, we therefore need to map lremove() calls to
* list_delete_ptr() rather than list_delete()
*/
#define lremove(elem, list) list_delete_ptr(list, elem)
#define LispRemove(elem, list) list_delete(list, elem)
#define lremovei(elem, list) list_delete_int(list, elem)
#define lremoveo(elem, list) list_delete_oid(list, elem)
#define ltruncate(n, list) list_truncate(list, n)
#define set_union(l1, l2) list_union(l1, l2)
#define set_uniono(l1, l2) list_union_oid(l1, l2)
#define set_ptrUnion(l1, l2) list_union_ptr(l1, l2)
#define set_difference(l1, l2) list_difference(l1, l2)
#define set_differenceo(l1, l2) list_difference_oid(l1, l2)
#define set_ptrDifference(l1, l2) list_difference_ptr(l1, l2)
#define equali(l1, l2) equal(l1, l2)
#define equalo(l1, l2) equal(l1, l2)
#define freeList(list) list_free(list)
#define listCopy(list) list_copy(list)
int length(PGList *list);
#endif /* ENABLE_LIST_COMPAT */
}

Some files were not shown because too many files have changed in this diff Show More