* gram.y
* POSTGRESQL BISON rules/actions
*
- * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.690 2009/11/09 18:38:48 tgl Exp $
+ * src/backend/parser/gram.y
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
List *args, int location);
static List *mergeTableFuncParameters(List *func_args, List *columns);
static TypeName *TableFuncTypeName(List *columns);
+static RangeVar *makeRangeVarFromAnyName(List *names, int position, core_yyscan_t yyscanner);
%}
AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterFdwStmt
AlterForeignServerStmt AlterGroupStmt
AlterObjectSchemaStmt AlterOwnerStmt AlterSeqStmt AlterTableStmt
- AlterUserStmt AlterUserMappingStmt AlterUserSetStmt
+ AlterCompositeTypeStmt AlterUserStmt AlterUserMappingStmt AlterUserSetStmt
AlterRoleStmt AlterRoleSetStmt
AlterDefaultPrivilegesStmt DefACLAction
AnalyzeStmt ClosePortalStmt ClusterStmt CommentStmt
CreateFunctionStmt AlterFunctionStmt ReindexStmt RemoveAggrStmt
RemoveFuncStmt RemoveOperStmt RenameStmt RevokeStmt RevokeRoleStmt
RuleActionStmt RuleActionStmtOrEmpty RuleStmt
- SelectStmt TransactionStmt TruncateStmt
+ SecLabelStmt SelectStmt TransactionStmt TruncateStmt
UnlistenStmt UpdateStmt VacuumStmt
VariableResetStmt VariableSetStmt VariableShowStmt
ViewStmt CheckPointStmt CreateConversionStmt
%type <node> alter_column_default opclass_item opclass_drop alter_using
%type <ival> add_drop opt_asc_desc opt_nulls_order
-%type <node> alter_table_cmd
-%type <list> alter_table_cmds
+%type <node> alter_table_cmd alter_type_cmd
+%type <list> alter_table_cmds alter_type_cmds
%type <dbehavior> opt_drop_behavior
transaction_mode_item
%type <ival> opt_lock lock_type cast_context
+%type <ival> vacuum_option_list vacuum_option_elem
%type <boolean> opt_force opt_or_replace
opt_grant_grant_option opt_grant_admin_option
opt_nowait opt_if_exists opt_with_data
%type <str> OptSchemaName
%type <list> OptSchemaEltList
-%type <boolean> TriggerActionTime TriggerForSpec opt_trusted opt_restart_seqs
-
+%type <boolean> TriggerForSpec TriggerForType
+%type <ival> TriggerActionTime
%type <list> TriggerEvents TriggerOneEvent
%type <value> TriggerFuncArg
+%type <node> TriggerWhen
%type <str> copy_file_name
database_name access_method_clause access_method attr_name
- index_name name file_name cluster_index_specification
+ name cursor_name file_name
+ index_name opt_index_name cluster_index_specification
%type <list> func_name handler_name qual_Op qual_all_Op subquery_Op
opt_class opt_inline_handler opt_validator validator_clause
%type <list> stmtblock stmtmulti
OptTableElementList TableElementList OptInherit definition
+ OptTypedTableElementList TypedTableElementList
reloptions opt_reloptions
OptWith opt_distinct opt_definition func_args func_args_list
func_args_with_defaults func_args_with_defaults_list
reloption_list group_clause TriggerFuncArgs select_limit
opt_select_limit opclass_item_list opclass_drop_list
opt_opfamily transaction_mode_list_or_empty
- TableFuncElementList opt_type_modifiers
+ OptTableFuncElementList TableFuncElementList opt_type_modifiers
prep_type_clause
execute_param_clause using_clause returning_clause
- enum_val_list table_func_column_list
+ opt_enum_val_list enum_val_list table_func_column_list
create_generic_options alter_generic_options
relation_expr_list dostmt_opt_list
%type <fun_param_mode> arg_class
%type <typnam> func_return func_type
-%type <boolean> TriggerForType OptTemp
+%type <boolean> OptTemp opt_trusted opt_restart_seqs
%type <oncommit> OnCommitOption
%type <node> for_locking_item
%type <node> overlay_placing substr_from substr_for
%type <boolean> opt_instead
-%type <boolean> index_opt_unique opt_verbose opt_full
+%type <boolean> opt_unique opt_concurrently opt_verbose opt_full
%type <boolean> opt_freeze opt_default opt_recheck
%type <defelt> opt_binary opt_oids copy_delimiter
%type <boolean> copy_from
%type <ival> opt_column event cursor_options opt_hold opt_set_data
-%type <objtype> reindex_type drop_type comment_type
+%type <objtype> reindex_type drop_type comment_type security_label_type
-%type <node> fetch_direction limit_clause select_limit_value
+%type <node> fetch_args limit_clause select_limit_value
offset_clause select_offset_value
select_offset_value2 opt_select_fetch_first_value
%type <ival> row_or_rows first_or_next
%type <vsetstmt> set_rest SetResetClause
-%type <node> TableElement ConstraintElem TableFuncElement
-%type <node> columnDef
+%type <node> TableElement TypedTableElement ConstraintElem TableFuncElement
+%type <node> columnDef columnOptions
%type <defelt> def_elem reloption_elem old_aggr_elem
%type <node> def_arg columnElem where_clause where_or_current_clause
a_expr b_expr c_expr func_expr AexprConst indirection_el
columnref in_expr having_clause func_table array_expr
+ ExclusionWhereClause
+%type <list> ExclusionConstraintList ExclusionConstraintElem
%type <list> func_arg_list
%type <node> func_arg_expr
%type <list> row type_list array_expr_list
%type <list> OptCreateAs CreateAsList
%type <node> CreateAsElement ctext_expr
%type <value> NumericOnly
+%type <list> NumericOnly_list
%type <alias> alias_clause
%type <sortby> sortby
%type <ielem> index_elem
%type <boolean> opt_varying opt_timezone
%type <ival> Iconst SignedIconst
-%type <str> Sconst comment_text
+%type <str> Sconst comment_text notify_payload
%type <str> RoleId opt_granted_by opt_boolean ColId_or_Sconst
%type <list> var_list
%type <str> ColId ColLabel var_name type_function_name param_name
%type <str> OptTableSpace OptConsTableSpace OptTableSpaceOwner
%type <list> opt_check_option
+%type <str> opt_provider security_label
+
%type <target> xml_attribute_el
%type <list> xml_attribute_list xml_attributes
%type <node> xml_root_version opt_xml_root_standalone
+%type <node> xmlexists_argument
%type <ival> document_or_content
%type <boolean> xml_whitespace_option
%type <node> common_table_expr
-%type <with> with_clause
+%type <with> with_clause opt_with_clause
%type <list> cte_list
%type <list> window_clause window_definition_list opt_partition_clause
%type <windef> window_definition over_clause window_specification
+ opt_frame_clause frame_extent frame_bound
%type <str> opt_existing_window_name
-%type <ival> opt_frame_clause frame_extent frame_bound
/*
* 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 and COLON_EQUALS are unused in the core SQL grammar, and so will
- * always provoke parse errors. They are needed by PL/pgsql.
+ * 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
/* ordinary key words in alphabetical order */
%token <keyword> ABORT_P ABSOLUTE_P ACCESS ACTION ADD_P ADMIN AFTER
AGGREGATE ALL ALSO ALTER ALWAYS ANALYSE ANALYZE AND ANY ARRAY AS ASC
- ASSERTION ASSIGNMENT ASYMMETRIC AT AUTHORIZATION
+ ASSERTION ASSIGNMENT ASYMMETRIC AT ATTRIBUTE AUTHORIZATION
BACKWARD BEFORE BEGIN_P BETWEEN BIGINT BINARY BIT
BOOLEAN_P BOTH BY
DICTIONARY DISABLE_P DISCARD DISTINCT DO DOCUMENT_P DOMAIN_P DOUBLE_P DROP
EACH ELSE ENABLE_P ENCODING ENCRYPTED END_P ENUM_P ESCAPE EXCEPT
- EXCLUDING EXCLUSIVE EXECUTE EXISTS EXPLAIN EXTERNAL EXTRACT
+ EXCLUDE EXCLUDING EXCLUSIVE EXECUTE EXISTS EXPLAIN EXTERNAL EXTRACT
FALSE_P FAMILY FETCH FIRST_P FLOAT_P FOLLOWING FOR FORCE FOREIGN FORWARD
FREEZE FROM FULL FUNCTION FUNCTIONS
KEY
- LANGUAGE LARGE_P LAST_P LC_COLLATE_P LC_CTYPE_P LEADING
+ LABEL LANGUAGE LARGE_P LAST_P LC_COLLATE_P LC_CTYPE_P LEADING
LEAST LEFT LEVEL LIKE LIMIT LISTEN LOAD LOCAL LOCALTIME LOCALTIMESTAMP
LOCATION LOCK_P LOGIN_P
OBJECT_P OF OFF OFFSET OIDS ON ONLY OPERATOR OPTION OPTIONS OR
ORDER OUT_P OUTER_P OVER OVERLAPS OVERLAY OWNED OWNER
- PARSER PARTIAL PARTITION PASSWORD PLACING PLANS POSITION
+ PARSER PARTIAL PARTITION PASSING PASSWORD PLACING PLANS POSITION
PRECEDING PRECISION PRESERVE PREPARE PREPARED PRIMARY
PRIOR PRIVILEGES PROCEDURAL PROCEDURE
QUOTE
- RANGE READ REAL REASSIGN RECHECK RECURSIVE REFERENCES REINDEX
+ RANGE READ REAL REASSIGN RECHECK RECURSIVE REF REFERENCES REINDEX
RELATIVE_P RELEASE RENAME REPEATABLE REPLACE REPLICA RESET RESTART
RESTRICT RETURNING RETURNS REVOKE RIGHT ROLE ROLLBACK ROW ROWS RULE
WHEN WHERE WHITESPACE_P WINDOW WITH WITHOUT WORK WRAPPER WRITE
- XML_P XMLATTRIBUTES XMLCONCAT XMLELEMENT XMLFOREST XMLPARSE
+ XML_P XMLATTRIBUTES XMLCONCAT XMLELEMENT XMLEXISTS XMLFOREST XMLPARSE
XMLPI XMLROOT XMLSERIALIZE
YEAR_P YES_P
* RANGE, ROWS to support opt_existing_window_name; and for RANGE, ROWS
* so that they can follow a_expr without creating
* postfix-operator problems.
+ *
+ * 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 IDENT PARTITION RANGE ROWS
+%nonassoc UNBOUNDED /* ideally should have same precedence as IDENT */
+%nonassoc IDENT PARTITION RANGE ROWS PRECEDING FOLLOWING
%left Op OPERATOR /* multi-character ops and user-defined operators */
%nonassoc NOTNULL
%nonassoc ISNULL
| AlterOwnerStmt
| AlterSeqStmt
| AlterTableStmt
+ | AlterCompositeTypeStmt
| AlterRoleSetStmt
| AlterRoleStmt
| AlterTSConfigurationStmt
| RevokeStmt
| RevokeRoleStmt
| RuleStmt
+ | SecLabelStmt
| SelectStmt
| TransactionStmt
| TruncateStmt
;
alter_table_cmd:
- /* ALTER TABLE <name> ADD [COLUMN] <coldef> */
- ADD_P opt_column columnDef
+ /* ALTER TABLE <name> ADD <coldef> */
+ ADD_P columnDef
+ {
+ AlterTableCmd *n = makeNode(AlterTableCmd);
+ n->subtype = AT_AddColumn;
+ n->def = $2;
+ $$ = (Node *)n;
+ }
+ /* ALTER TABLE <name> ADD COLUMN <coldef> */
+ | ADD_P COLUMN columnDef
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_AddColumn;
n->def = (Node *) makeInteger($6);
$$ = (Node *)n;
}
- /* ALTER TABLE <name> ALTER [COLUMN] <colname> SET STATISTICS DISTINCT <NumericOnly> */
- | ALTER opt_column ColId SET STATISTICS DISTINCT NumericOnly
+ /* ALTER TABLE <name> ALTER [COLUMN] <colname> SET ( column_parameter = value [, ... ] ) */
+ | ALTER opt_column ColId SET reloptions
+ {
+ AlterTableCmd *n = makeNode(AlterTableCmd);
+ n->subtype = AT_SetOptions;
+ n->name = $3;
+ n->def = (Node *) $5;
+ $$ = (Node *)n;
+ }
+ /* ALTER TABLE <name> ALTER [COLUMN] <colname> SET ( column_parameter = value [, ... ] ) */
+ | ALTER opt_column ColId RESET reloptions
{
AlterTableCmd *n = makeNode(AlterTableCmd);
- n->subtype = AT_SetDistinct;
+ n->subtype = AT_ResetOptions;
n->name = $3;
- n->def = (Node *) $7;
+ n->def = (Node *) $5;
$$ = (Node *)n;
}
/* ALTER TABLE <name> ALTER [COLUMN] <colname> SET STORAGE <storagemode> */
;
+/*****************************************************************************
+ *
+ * ALTER TYPE
+ *
+ * really variants of the ALTER TABLE subcommands with different spellings
+ *****************************************************************************/
+
+AlterCompositeTypeStmt:
+ ALTER TYPE_P any_name alter_type_cmds
+ {
+ AlterTableStmt *n = makeNode(AlterTableStmt);
+
+ /* can't use qualified_name, sigh */
+ n->relation = makeRangeVarFromAnyName($3, @3, yyscanner);
+ n->cmds = $4;
+ n->relkind = OBJECT_TYPE;
+ $$ = (Node *)n;
+ }
+ ;
+
+alter_type_cmds:
+ alter_type_cmd { $$ = list_make1($1); }
+ | alter_type_cmds ',' alter_type_cmd { $$ = lappend($1, $3); }
+ ;
+
+alter_type_cmd:
+ /* ALTER TYPE <name> ADD ATTRIBUTE <coldef> */
+ ADD_P ATTRIBUTE TableFuncElement
+ {
+ AlterTableCmd *n = makeNode(AlterTableCmd);
+ n->subtype = AT_AddColumn;
+ n->def = $3;
+ $$ = (Node *)n;
+ }
+ /* ALTER TYPE <name> DROP ATTRIBUTE IF EXISTS <attname> */
+ | DROP ATTRIBUTE IF_P EXISTS ColId
+ {
+ AlterTableCmd *n = makeNode(AlterTableCmd);
+ n->subtype = AT_DropColumn;
+ n->name = $5;
+ n->behavior = DROP_RESTRICT; /* currently no effect */
+ n->missing_ok = TRUE;
+ $$ = (Node *)n;
+ }
+ /* ALTER TYPE <name> DROP ATTRIBUTE <attname> */
+ | DROP ATTRIBUTE ColId opt_drop_behavior
+ {
+ AlterTableCmd *n = makeNode(AlterTableCmd);
+ n->subtype = AT_DropColumn;
+ n->name = $3;
+ n->behavior = DROP_RESTRICT; /* currently no effect */
+ n->missing_ok = FALSE;
+ $$ = (Node *)n;
+ }
+ /* ALTER TYPE <name> ALTER ATTRIBUTE <attname> [SET DATA] TYPE <typename> */
+ | ALTER ATTRIBUTE ColId opt_set_data TYPE_P Typename
+ {
+ AlterTableCmd *n = makeNode(AlterTableCmd);
+ n->subtype = AT_AlterColumnType;
+ n->name = $3;
+ n->def = (Node *) $6;
+ $$ = (Node *)n;
+ }
+ ;
+
+
/*****************************************************************************
*
* QUERY :
*****************************************************************************/
ClosePortalStmt:
- CLOSE name
+ CLOSE cursor_name
{
ClosePortalStmt *n = makeNode(ClosePortalStmt);
n->portalname = $2;
* COPY ( SELECT ... ) TO file [WITH] [(options)]
*
* In the preferred syntax the options are comma-separated
- * and use generic identifiers instead of keywords. The pre-8.5
+ * and use generic identifiers instead of keywords. The pre-9.0
* syntax had a hard-wired, space-separated set of options.
*
* Really old syntax, from versions 7.2 and prior:
n->options = $9;
n->oncommit = $10;
n->tablespacename = $11;
+ n->if_not_exists = false;
$$ = (Node *)n;
}
- | CREATE OptTemp TABLE qualified_name OF qualified_name
- '(' OptTableElementList ')' OptWith OnCommitOption OptTableSpace
+ | CREATE OptTemp TABLE IF_P NOT EXISTS qualified_name '('
+ OptTableElementList ')' OptInherit OptWith OnCommitOption
+ OptTableSpace
+ {
+ CreateStmt *n = makeNode(CreateStmt);
+ $7->istemp = $2;
+ n->relation = $7;
+ n->tableElts = $9;
+ n->inhRelations = $11;
+ n->constraints = NIL;
+ n->options = $12;
+ n->oncommit = $13;
+ n->tablespacename = $14;
+ n->if_not_exists = true;
+ $$ = (Node *)n;
+ }
+ | CREATE OptTemp TABLE qualified_name OF any_name
+ OptTypedTableElementList OptWith OnCommitOption OptTableSpace
{
- /* SQL99 CREATE TABLE OF <UDT> (cols) seems to be satisfied
- * by our inheritance capabilities. Let's try it...
- */
CreateStmt *n = makeNode(CreateStmt);
$4->istemp = $2;
n->relation = $4;
- n->tableElts = $8;
- n->inhRelations = list_make1($6);
+ n->tableElts = $7;
+ n->ofTypename = makeTypeNameFromNameList($6);
+ n->ofTypename->location = @6;
n->constraints = NIL;
- n->options = $10;
- n->oncommit = $11;
- n->tablespacename = $12;
+ n->options = $8;
+ n->oncommit = $9;
+ n->tablespacename = $10;
+ n->if_not_exists = false;
+ $$ = (Node *)n;
+ }
+ | CREATE OptTemp TABLE IF_P NOT EXISTS qualified_name OF any_name
+ OptTypedTableElementList OptWith OnCommitOption OptTableSpace
+ {
+ CreateStmt *n = makeNode(CreateStmt);
+ $7->istemp = $2;
+ n->relation = $7;
+ n->tableElts = $10;
+ n->ofTypename = makeTypeNameFromNameList($9);
+ n->ofTypename->location = @9;
+ n->constraints = NIL;
+ n->options = $11;
+ n->oncommit = $12;
+ n->tablespacename = $13;
+ n->if_not_exists = true;
$$ = (Node *)n;
}
;
| /*EMPTY*/ { $$ = NIL; }
;
+OptTypedTableElementList:
+ '(' TypedTableElementList ')' { $$ = $2; }
+ | /*EMPTY*/ { $$ = NIL; }
+ ;
+
TableElementList:
TableElement
{
}
;
+TypedTableElementList:
+ TypedTableElement
+ {
+ $$ = list_make1($1);
+ }
+ | TypedTableElementList ',' TypedTableElement
+ {
+ $$ = lappend($1, $3);
+ }
+ ;
+
TableElement:
columnDef { $$ = $1; }
| TableLikeClause { $$ = $1; }
| TableConstraint { $$ = $1; }
;
+TypedTableElement:
+ columnOptions { $$ = $1; }
+ | TableConstraint { $$ = $1; }
+ ;
+
columnDef: ColId Typename ColQualList
{
ColumnDef *n = makeNode(ColumnDef);
}
;
+columnOptions: ColId WITH OPTIONS ColQualList
+ {
+ ColumnDef *n = makeNode(ColumnDef);
+ n->colname = $1;
+ n->constraints = $4;
+ n->is_local = true;
+ $$ = (Node *)n;
+ }
+ ;
+
ColQualList:
ColQualList ColConstraint { $$ = lappend($1, $2); }
| /*EMPTY*/ { $$ = NIL; }
n->initdeferred = ($8 & 2) != 0;
$$ = (Node *)n;
}
+ | EXCLUDE access_method_clause '(' ExclusionConstraintList ')'
+ opt_definition OptConsTableSpace ExclusionWhereClause
+ ConstraintAttributeSpec
+ {
+ Constraint *n = makeNode(Constraint);
+ n->contype = CONSTR_EXCLUSION;
+ n->location = @1;
+ n->access_method = $2;
+ n->exclusions = $4;
+ n->options = $6;
+ n->indexspace = $7;
+ n->where_clause = $8;
+ n->deferrable = ($9 & 1) != 0;
+ n->initdeferred = ($9 & 2) != 0;
+ $$ = (Node *)n;
+ }
| FOREIGN KEY '(' columnList ')' REFERENCES qualified_name
opt_column_list key_match key_actions ConstraintAttributeSpec
{
}
;
+ExclusionConstraintList:
+ ExclusionConstraintElem { $$ = list_make1($1); }
+ | ExclusionConstraintList ',' ExclusionConstraintElem
+ { $$ = lappend($1, $3); }
+ ;
+
+ExclusionConstraintElem: index_elem WITH any_operator
+ {
+ $$ = list_make2($1, $3);
+ }
+ /* allow OPERATOR() decoration for the benefit of ruleutils.c */
+ | index_elem WITH OPERATOR '(' any_operator ')'
+ {
+ $$ = list_make2($1, $5);
+ }
+ ;
+
+ExclusionWhereClause:
+ WHERE '(' a_expr ')' { $$ = $3; }
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
+
/*
* We combine the update and delete actions into one value temporarily
* for simplicity of parsing, and then break them down again in the
$4->istemp = $2;
n->sequence = $4;
n->options = $5;
+ n->ownerId = InvalidOid;
$$ = (Node *)n;
}
;
| SignedIconst { $$ = makeInteger($1); }
;
+NumericOnly_list: NumericOnly { $$ = list_make1($1); }
+ | NumericOnly_list ',' NumericOnly { $$ = lappend($1, $3); }
+ ;
+
/*****************************************************************************
*
* QUERIES :
- * CREATE PROCEDURAL LANGUAGE ...
- * DROP PROCEDURAL LANGUAGE ...
+ * CREATE [OR REPLACE] [TRUSTED] [PROCEDURAL] LANGUAGE ...
+ * DROP [PROCEDURAL] LANGUAGE ...
*
*****************************************************************************/
CreatePLangStmt:
- CREATE opt_trusted opt_procedural LANGUAGE ColId_or_Sconst
+ CREATE opt_or_replace opt_trusted opt_procedural LANGUAGE ColId_or_Sconst
{
CreatePLangStmt *n = makeNode(CreatePLangStmt);
- n->plname = $5;
+ n->replace = $2;
+ n->plname = $6;
/* parameters are all to be supplied by system */
n->plhandler = NIL;
n->plinline = NIL;
n->pltrusted = false;
$$ = (Node *)n;
}
- | CREATE opt_trusted opt_procedural LANGUAGE ColId_or_Sconst
+ | CREATE opt_or_replace opt_trusted opt_procedural LANGUAGE ColId_or_Sconst
HANDLER handler_name opt_inline_handler opt_validator
{
CreatePLangStmt *n = makeNode(CreatePLangStmt);
- n->plname = $5;
- n->plhandler = $7;
- n->plinline = $8;
- n->plvalidator = $9;
- n->pltrusted = $2;
+ n->replace = $2;
+ n->plname = $6;
+ n->plhandler = $8;
+ n->plinline = $9;
+ n->plvalidator = $10;
+ n->pltrusted = $3;
$$ = (Node *)n;
}
;
CreateTrigStmt:
CREATE TRIGGER name TriggerActionTime TriggerEvents ON
- qualified_name TriggerForSpec EXECUTE PROCEDURE
- func_name '(' TriggerFuncArgs ')'
+ qualified_name TriggerForSpec TriggerWhen
+ EXECUTE PROCEDURE func_name '(' TriggerFuncArgs ')'
{
CreateTrigStmt *n = makeNode(CreateTrigStmt);
n->trigname = $3;
n->relation = $7;
- n->funcname = $11;
- n->args = $13;
- n->before = $4;
+ n->funcname = $12;
+ n->args = $14;
n->row = $8;
+ n->timing = $4;
n->events = intVal(linitial($5));
n->columns = (List *) lsecond($5);
+ n->whenClause = $9;
n->isconstraint = FALSE;
n->deferrable = FALSE;
n->initdeferred = FALSE;
$$ = (Node *)n;
}
| CREATE CONSTRAINT TRIGGER name AFTER TriggerEvents ON
- qualified_name OptConstrFromTable
- ConstraintAttributeSpec
- FOR EACH ROW EXECUTE PROCEDURE
- func_name '(' TriggerFuncArgs ')'
+ qualified_name OptConstrFromTable ConstraintAttributeSpec
+ FOR EACH ROW TriggerWhen
+ EXECUTE PROCEDURE func_name '(' TriggerFuncArgs ')'
{
CreateTrigStmt *n = makeNode(CreateTrigStmt);
n->trigname = $4;
n->relation = $8;
- n->funcname = $16;
- n->args = $18;
- n->before = FALSE;
+ n->funcname = $17;
+ n->args = $19;
n->row = TRUE;
+ n->timing = TRIGGER_TYPE_AFTER;
n->events = intVal(linitial($6));
n->columns = (List *) lsecond($6);
+ n->whenClause = $14;
n->isconstraint = TRUE;
n->deferrable = ($10 & 1) != 0;
n->initdeferred = ($10 & 2) != 0;
;
TriggerActionTime:
- BEFORE { $$ = TRUE; }
- | AFTER { $$ = FALSE; }
+ BEFORE { $$ = TRIGGER_TYPE_BEFORE; }
+ | AFTER { $$ = TRIGGER_TYPE_AFTER; }
+ | INSTEAD OF { $$ = TRIGGER_TYPE_INSTEAD; }
;
TriggerEvents:
;
TriggerForSpec:
- FOR TriggerForOpt TriggerForType
+ FOR TriggerForOptEach TriggerForType
{
$$ = $3;
}
}
;
-TriggerForOpt:
+TriggerForOptEach:
EACH {}
| /*EMPTY*/ {}
;
| STATEMENT { $$ = FALSE; }
;
+TriggerWhen:
+ WHEN '(' a_expr ')' { $$ = $3; }
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
+
TriggerFuncArgs:
TriggerFuncArg { $$ = list_make1($1); }
| TriggerFuncArgs ',' TriggerFuncArg { $$ = lappend($1, $3); }
n->definition = NIL;
$$ = (Node *)n;
}
- | CREATE TYPE_P any_name AS '(' TableFuncElementList ')'
+ | CREATE TYPE_P any_name AS '(' OptTableFuncElementList ')'
{
CompositeTypeStmt *n = makeNode(CompositeTypeStmt);
- RangeVar *r = makeNode(RangeVar);
/* can't use qualified_name, sigh */
- switch (list_length($3))
- {
- case 1:
- r->catalogname = NULL;
- r->schemaname = NULL;
- r->relname = strVal(linitial($3));
- break;
- case 2:
- r->catalogname = NULL;
- r->schemaname = strVal(linitial($3));
- r->relname = strVal(lsecond($3));
- break;
- case 3:
- r->catalogname = strVal(linitial($3));
- r->schemaname = strVal(lsecond($3));
- r->relname = strVal(lthird($3));
- break;
- default:
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("improper qualified name (too many dotted names): %s",
- NameListToString($3)),
- parser_errposition(@3)));
- break;
- }
- r->location = @3;
- n->typevar = r;
+ n->typevar = makeRangeVarFromAnyName($3, @3, yyscanner);
n->coldeflist = $6;
$$ = (Node *)n;
}
- | CREATE TYPE_P any_name AS ENUM_P '(' enum_val_list ')'
+ | CREATE TYPE_P any_name AS ENUM_P '(' opt_enum_val_list ')'
{
CreateEnumStmt *n = makeNode(CreateEnumStmt);
n->typeName = $3;
}
;
+opt_enum_val_list:
+ enum_val_list { $$ = $1; }
+ | /*EMPTY*/ { $$ = NIL; }
+ ;
+
enum_val_list: Sconst
{ $$ = list_make1(makeString($1)); }
| enum_val_list ',' Sconst
| NULL_P { $$ = NULL; }
;
+
+/*****************************************************************************
+ *
+ * SECURITY LABEL [FOR <provider>] ON <object> IS <label>
+ *
+ * As with COMMENT ON, <object> can refer to various types of database
+ * objects (e.g. TABLE, COLUMN, etc.).
+ *
+ *****************************************************************************/
+
+SecLabelStmt:
+ SECURITY LABEL opt_provider ON security_label_type any_name
+ IS security_label
+ {
+ SecLabelStmt *n = makeNode(SecLabelStmt);
+ n->provider = $3;
+ n->objtype = $5;
+ n->objname = $6;
+ n->objargs = NIL;
+ n->label = $8;
+ $$ = (Node *) n;
+ }
+ | SECURITY LABEL opt_provider ON AGGREGATE func_name aggr_args
+ IS security_label
+ {
+ SecLabelStmt *n = makeNode(SecLabelStmt);
+ n->provider = $3;
+ n->objtype = OBJECT_AGGREGATE;
+ n->objname = $6;
+ n->objargs = $7;
+ n->label = $9;
+ $$ = (Node *) n;
+ }
+ | SECURITY LABEL opt_provider ON FUNCTION func_name func_args
+ IS security_label
+ {
+ SecLabelStmt *n = makeNode(SecLabelStmt);
+ n->provider = $3;
+ n->objtype = OBJECT_FUNCTION;
+ n->objname = $6;
+ n->objargs = extractArgTypes($7);
+ n->label = $9;
+ $$ = (Node *) n;
+ }
+ | SECURITY LABEL opt_provider ON LARGE_P OBJECT_P NumericOnly
+ IS security_label
+ {
+ SecLabelStmt *n = makeNode(SecLabelStmt);
+ n->provider = $3;
+ n->objtype = OBJECT_LARGEOBJECT;
+ n->objname = list_make1($7);
+ n->objargs = NIL;
+ n->label = $9;
+ $$ = (Node *) n;
+ }
+ | SECURITY LABEL opt_provider ON opt_procedural LANGUAGE any_name
+ IS security_label
+ {
+ SecLabelStmt *n = makeNode(SecLabelStmt);
+ n->provider = $3;
+ n->objtype = OBJECT_LANGUAGE;
+ n->objname = $7;
+ n->objargs = NIL;
+ n->label = $9;
+ $$ = (Node *) n;
+ }
+ ;
+
+opt_provider: FOR ColId_or_Sconst { $$ = $2; }
+ | /* empty */ { $$ = NULL; }
+ ;
+
+security_label_type:
+ COLUMN { $$ = OBJECT_COLUMN; }
+ | SCHEMA { $$ = OBJECT_SCHEMA; }
+ | SEQUENCE { $$ = OBJECT_SEQUENCE; }
+ | TABLE { $$ = OBJECT_TABLE; }
+ | DOMAIN_P { $$ = OBJECT_TYPE; }
+ | TYPE_P { $$ = OBJECT_TYPE; }
+ | VIEW { $$ = OBJECT_VIEW; }
+ ;
+
+security_label: Sconst { $$ = $1; }
+ | NULL_P { $$ = NULL; }
+ ;
+
/*****************************************************************************
*
* QUERY:
*
*****************************************************************************/
-FetchStmt: FETCH fetch_direction from_in name
+FetchStmt: FETCH fetch_args
{
FetchStmt *n = (FetchStmt *) $2;
- n->portalname = $4;
n->ismove = FALSE;
$$ = (Node *)n;
}
- | FETCH name
- {
- FetchStmt *n = makeNode(FetchStmt);
- n->direction = FETCH_FORWARD;
- n->howMany = 1;
- n->portalname = $2;
- n->ismove = FALSE;
- $$ = (Node *)n;
- }
- | MOVE fetch_direction from_in name
+ | MOVE fetch_args
{
FetchStmt *n = (FetchStmt *) $2;
- n->portalname = $4;
n->ismove = TRUE;
$$ = (Node *)n;
}
- | MOVE name
+ ;
+
+fetch_args: cursor_name
{
FetchStmt *n = makeNode(FetchStmt);
+ n->portalname = $1;
n->direction = FETCH_FORWARD;
n->howMany = 1;
- n->portalname = $2;
- n->ismove = TRUE;
$$ = (Node *)n;
}
- ;
-
-fetch_direction:
- /*EMPTY*/
+ | from_in cursor_name
{
FetchStmt *n = makeNode(FetchStmt);
+ n->portalname = $2;
n->direction = FETCH_FORWARD;
n->howMany = 1;
$$ = (Node *)n;
}
- | NEXT
+ | NEXT opt_from_in cursor_name
{
FetchStmt *n = makeNode(FetchStmt);
+ n->portalname = $3;
n->direction = FETCH_FORWARD;
n->howMany = 1;
$$ = (Node *)n;
}
- | PRIOR
+ | PRIOR opt_from_in cursor_name
{
FetchStmt *n = makeNode(FetchStmt);
+ n->portalname = $3;
n->direction = FETCH_BACKWARD;
n->howMany = 1;
$$ = (Node *)n;
}
- | FIRST_P
+ | FIRST_P opt_from_in cursor_name
{
FetchStmt *n = makeNode(FetchStmt);
+ n->portalname = $3;
n->direction = FETCH_ABSOLUTE;
n->howMany = 1;
$$ = (Node *)n;
}
- | LAST_P
+ | LAST_P opt_from_in cursor_name
{
FetchStmt *n = makeNode(FetchStmt);
+ n->portalname = $3;
n->direction = FETCH_ABSOLUTE;
n->howMany = -1;
$$ = (Node *)n;
}
- | ABSOLUTE_P SignedIconst
+ | ABSOLUTE_P SignedIconst opt_from_in cursor_name
{
FetchStmt *n = makeNode(FetchStmt);
+ n->portalname = $4;
n->direction = FETCH_ABSOLUTE;
n->howMany = $2;
$$ = (Node *)n;
}
- | RELATIVE_P SignedIconst
+ | RELATIVE_P SignedIconst opt_from_in cursor_name
{
FetchStmt *n = makeNode(FetchStmt);
+ n->portalname = $4;
n->direction = FETCH_RELATIVE;
n->howMany = $2;
$$ = (Node *)n;
}
- | SignedIconst
+ | SignedIconst opt_from_in cursor_name
{
FetchStmt *n = makeNode(FetchStmt);
+ n->portalname = $3;
n->direction = FETCH_FORWARD;
n->howMany = $1;
$$ = (Node *)n;
}
- | ALL
+ | ALL opt_from_in cursor_name
{
FetchStmt *n = makeNode(FetchStmt);
+ n->portalname = $3;
n->direction = FETCH_FORWARD;
n->howMany = FETCH_ALL;
$$ = (Node *)n;
}
- | FORWARD
+ | FORWARD opt_from_in cursor_name
{
FetchStmt *n = makeNode(FetchStmt);
+ n->portalname = $3;
n->direction = FETCH_FORWARD;
n->howMany = 1;
$$ = (Node *)n;
}
- | FORWARD SignedIconst
+ | FORWARD SignedIconst opt_from_in cursor_name
{
FetchStmt *n = makeNode(FetchStmt);
+ n->portalname = $4;
n->direction = FETCH_FORWARD;
n->howMany = $2;
$$ = (Node *)n;
}
- | FORWARD ALL
+ | FORWARD ALL opt_from_in cursor_name
{
FetchStmt *n = makeNode(FetchStmt);
+ n->portalname = $4;
n->direction = FETCH_FORWARD;
n->howMany = FETCH_ALL;
$$ = (Node *)n;
}
- | BACKWARD
+ | BACKWARD opt_from_in cursor_name
{
FetchStmt *n = makeNode(FetchStmt);
+ n->portalname = $3;
n->direction = FETCH_BACKWARD;
n->howMany = 1;
$$ = (Node *)n;
}
- | BACKWARD SignedIconst
+ | BACKWARD SignedIconst opt_from_in cursor_name
{
FetchStmt *n = makeNode(FetchStmt);
+ n->portalname = $4;
n->direction = FETCH_BACKWARD;
n->howMany = $2;
$$ = (Node *)n;
}
- | BACKWARD ALL
+ | BACKWARD ALL opt_from_in cursor_name
{
FetchStmt *n = makeNode(FetchStmt);
+ n->portalname = $4;
n->direction = FETCH_BACKWARD;
n->howMany = FETCH_ALL;
$$ = (Node *)n;
| IN_P {}
;
+opt_from_in: from_in {}
+ | /* EMPTY */ {}
+ ;
+
/*****************************************************************************
*
n->objs = $2;
$$ = n;
}
+ | LARGE_P OBJECT_P NumericOnly_list
+ {
+ PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+ n->targtype = ACL_TARGET_OBJECT;
+ n->objtype = ACL_OBJECT_LARGEOBJECT;
+ n->objs = $3;
+ $$ = n;
+ }
| SCHEMA name_list
{
PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
*
* QUERY: CREATE INDEX
*
- * Note: we can't factor CONCURRENTLY into a separate production without
- * making it a reserved word.
- *
* Note: we cannot put TABLESPACE clause after WHERE clause unless we are
* willing to make TABLESPACE a fully reserved word.
*****************************************************************************/
-IndexStmt: CREATE index_opt_unique INDEX index_name
- ON qualified_name access_method_clause '(' index_params ')'
- opt_reloptions OptTableSpace where_clause
- {
- IndexStmt *n = makeNode(IndexStmt);
- n->unique = $2;
- n->concurrent = false;
- n->idxname = $4;
- n->relation = $6;
- n->accessMethod = $7;
- n->indexParams = $9;
- n->options = $11;
- n->tableSpace = $12;
- n->whereClause = $13;
- $$ = (Node *)n;
- }
- | CREATE index_opt_unique INDEX CONCURRENTLY index_name
+IndexStmt: CREATE opt_unique INDEX opt_concurrently opt_index_name
ON qualified_name access_method_clause '(' index_params ')'
opt_reloptions OptTableSpace where_clause
{
IndexStmt *n = makeNode(IndexStmt);
n->unique = $2;
- n->concurrent = true;
+ n->concurrent = $4;
n->idxname = $5;
n->relation = $7;
n->accessMethod = $8;
}
;
-index_opt_unique:
+opt_unique:
UNIQUE { $$ = TRUE; }
| /*EMPTY*/ { $$ = FALSE; }
;
+opt_concurrently:
+ CONCURRENTLY { $$ = TRUE; }
+ | /*EMPTY*/ { $$ = FALSE; }
+ ;
+
+opt_index_name:
+ index_name { $$ = $1; }
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
+
access_method_clause:
USING access_method { $$ = $2; }
| /*EMPTY*/ { $$ = DEFAULT_INDEX_TYPE; }
$$ = makeNode(IndexElem);
$$->name = $1;
$$->expr = NULL;
+ $$->indexcolname = NULL;
$$->opclass = $2;
$$->ordering = $3;
$$->nulls_ordering = $4;
$$ = makeNode(IndexElem);
$$->name = NULL;
$$->expr = $1;
+ $$->indexcolname = NULL;
$$->opclass = $2;
$$->ordering = $3;
$$->nulls_ordering = $4;
$$ = makeNode(IndexElem);
$$->name = NULL;
$$->expr = $2;
+ $$->indexcolname = NULL;
$$->opclass = $4;
$$->ordering = $5;
$$->nulls_ordering = $6;
n->newname = $6;
$$ = (Node *)n;
}
+ | ALTER TABLESPACE name SET reloptions
+ {
+ AlterTableSpaceOptionsStmt *n =
+ makeNode(AlterTableSpaceOptionsStmt);
+ n->tablespacename = $3;
+ n->options = $5;
+ n->isReset = FALSE;
+ $$ = (Node *)n;
+ }
+ | ALTER TABLESPACE name RESET reloptions
+ {
+ AlterTableSpaceOptionsStmt *n =
+ makeNode(AlterTableSpaceOptionsStmt);
+ n->tablespacename = $3;
+ n->options = $5;
+ n->isReset = TRUE;
+ $$ = (Node *)n;
+ }
| ALTER TEXT_P SEARCH PARSER any_name RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
n->newname = $6;
$$ = (Node *)n;
}
+ | ALTER TYPE_P any_name RENAME ATTRIBUTE name TO name
+ {
+ RenameStmt *n = makeNode(RenameStmt);
+ n->renameType = OBJECT_ATTRIBUTE;
+ n->relation = makeRangeVarFromAnyName($3, @3, yyscanner);
+ n->subname = $6;
+ n->newname = $8;
+ $$ = (Node *)n;
+ }
;
opt_column: COLUMN { $$ = COLUMN; }
n->newowner = $7;
$$ = (Node *)n;
}
+ | ALTER LARGE_P OBJECT_P NumericOnly OWNER TO RoleId
+ {
+ AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
+ n->objectType = OBJECT_LARGEOBJECT;
+ n->object = list_make1($4);
+ n->newowner = $7;
+ $$ = (Node *)n;
+ }
| ALTER OPERATOR any_operator oper_argtypes OWNER TO RoleId
{
AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
*
*****************************************************************************/
-NotifyStmt: NOTIFY ColId
+NotifyStmt: NOTIFY ColId notify_payload
{
NotifyStmt *n = makeNode(NotifyStmt);
n->conditionname = $2;
+ n->payload = $3;
$$ = (Node *)n;
}
;
+notify_payload:
+ ',' Sconst { $$ = $2; }
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
+
ListenStmt: LISTEN ColId
{
ListenStmt *n = makeNode(ListenStmt);
VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
{
VacuumStmt *n = makeNode(VacuumStmt);
- n->vacuum = true;
- n->analyze = false;
- n->full = $2;
+ n->options = VACOPT_VACUUM;
+ if ($2)
+ n->options |= VACOPT_FULL;
+ if ($4)
+ n->options |= VACOPT_VERBOSE;
n->freeze_min_age = $3 ? 0 : -1;
n->freeze_table_age = $3 ? 0 : -1;
- n->verbose = $4;
n->relation = NULL;
n->va_cols = NIL;
$$ = (Node *)n;
| VACUUM opt_full opt_freeze opt_verbose qualified_name
{
VacuumStmt *n = makeNode(VacuumStmt);
- n->vacuum = true;
- n->analyze = false;
- n->full = $2;
+ n->options = VACOPT_VACUUM;
+ if ($2)
+ n->options |= VACOPT_FULL;
+ if ($4)
+ n->options |= VACOPT_VERBOSE;
n->freeze_min_age = $3 ? 0 : -1;
n->freeze_table_age = $3 ? 0 : -1;
- n->verbose = $4;
n->relation = $5;
n->va_cols = NIL;
$$ = (Node *)n;
| VACUUM opt_full opt_freeze opt_verbose AnalyzeStmt
{
VacuumStmt *n = (VacuumStmt *) $5;
- n->vacuum = true;
- n->full = $2;
+ n->options |= VACOPT_VACUUM;
+ if ($2)
+ n->options |= VACOPT_FULL;
+ if ($4)
+ n->options |= VACOPT_VERBOSE;
n->freeze_min_age = $3 ? 0 : -1;
n->freeze_table_age = $3 ? 0 : -1;
- n->verbose |= $4;
$$ = (Node *)n;
}
+ | VACUUM '(' vacuum_option_list ')'
+ {
+ VacuumStmt *n = makeNode(VacuumStmt);
+ n->options = VACOPT_VACUUM | $3;
+ if (n->options & VACOPT_FREEZE)
+ n->freeze_min_age = n->freeze_table_age = 0;
+ else
+ n->freeze_min_age = n->freeze_table_age = -1;
+ n->relation = NULL;
+ n->va_cols = NIL;
+ $$ = (Node *) n;
+ }
+ | VACUUM '(' vacuum_option_list ')' qualified_name opt_name_list
+ {
+ VacuumStmt *n = makeNode(VacuumStmt);
+ n->options = VACOPT_VACUUM | $3;
+ if (n->options & VACOPT_FREEZE)
+ n->freeze_min_age = n->freeze_table_age = 0;
+ else
+ n->freeze_min_age = n->freeze_table_age = -1;
+ n->relation = $5;
+ n->va_cols = $6;
+ if (n->va_cols != NIL) /* implies analyze */
+ n->options |= VACOPT_ANALYZE;
+ $$ = (Node *) n;
+ }
+ ;
+
+vacuum_option_list:
+ vacuum_option_elem { $$ = $1; }
+ | vacuum_option_list ',' vacuum_option_elem { $$ = $1 | $3; }
+ ;
+
+vacuum_option_elem:
+ analyze_keyword { $$ = VACOPT_ANALYZE; }
+ | VERBOSE { $$ = VACOPT_VERBOSE; }
+ | FREEZE { $$ = VACOPT_FREEZE; }
+ | FULL { $$ = VACOPT_FULL; }
;
AnalyzeStmt:
analyze_keyword opt_verbose
{
VacuumStmt *n = makeNode(VacuumStmt);
- n->vacuum = false;
- n->analyze = true;
- n->full = false;
+ n->options = VACOPT_ANALYZE;
+ if ($2)
+ n->options |= VACOPT_VERBOSE;
n->freeze_min_age = -1;
n->freeze_table_age = -1;
- n->verbose = $2;
n->relation = NULL;
n->va_cols = NIL;
$$ = (Node *)n;
| analyze_keyword opt_verbose qualified_name opt_name_list
{
VacuumStmt *n = makeNode(VacuumStmt);
- n->vacuum = false;
- n->analyze = true;
- n->full = false;
+ n->options = VACOPT_ANALYZE;
+ if ($2)
+ n->options |= VACOPT_VERBOSE;
n->freeze_min_age = -1;
n->freeze_table_age = -1;
- n->verbose = $2;
n->relation = $3;
n->va_cols = $4;
$$ = (Node *)n;
*****************************************************************************/
InsertStmt:
- INSERT INTO qualified_name insert_rest returning_clause
+ opt_with_clause INSERT INTO qualified_name insert_rest returning_clause
{
- $4->relation = $3;
- $4->returningList = $5;
- $$ = (Node *) $4;
+ $5->relation = $4;
+ $5->returningList = $6;
+ $5->withClause = $1;
+ $$ = (Node *) $5;
}
;
*
*****************************************************************************/
-DeleteStmt: DELETE_P FROM relation_expr_opt_alias
+DeleteStmt: opt_with_clause DELETE_P FROM relation_expr_opt_alias
using_clause where_or_current_clause returning_clause
{
DeleteStmt *n = makeNode(DeleteStmt);
- n->relation = $3;
- n->usingClause = $4;
- n->whereClause = $5;
- n->returningList = $6;
+ n->relation = $4;
+ n->usingClause = $5;
+ n->whereClause = $6;
+ n->returningList = $7;
+ n->withClause = $1;
$$ = (Node *)n;
}
;
*
*****************************************************************************/
-UpdateStmt: UPDATE relation_expr_opt_alias
+UpdateStmt: opt_with_clause UPDATE relation_expr_opt_alias
SET set_clause_list
from_clause
where_or_current_clause
returning_clause
{
UpdateStmt *n = makeNode(UpdateStmt);
- n->relation = $2;
- n->targetList = $4;
- n->fromClause = $5;
- n->whereClause = $6;
- n->returningList = $7;
+ n->relation = $3;
+ n->targetList = $5;
+ n->fromClause = $6;
+ n->whereClause = $7;
+ n->returningList = $8;
+ n->withClause = $1;
$$ = (Node *)n;
}
;
* CURSOR STATEMENTS
*
*****************************************************************************/
-DeclareCursorStmt: DECLARE name cursor_options CURSOR opt_hold FOR SelectStmt
+DeclareCursorStmt: DECLARE cursor_name cursor_options CURSOR opt_hold FOR SelectStmt
{
DeclareCursorStmt *n = makeNode(DeclareCursorStmt);
n->portalname = $2;
}
;
+cursor_name: name { $$ = $1; }
+ ;
+
cursor_options: /*EMPTY*/ { $$ = 0; }
| cursor_options NO SCROLL { $$ = $1 | CURSOR_OPT_NO_SCROLL; }
| cursor_options SCROLL { $$ = $1 | CURSOR_OPT_SCROLL; }
}
;
+opt_with_clause:
+ with_clause { $$ = $1; }
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
+
into_clause:
INTO OptTempTableName
{
;
+OptTableFuncElementList:
+ TableFuncElementList { $$ = $1; }
+ | /*EMPTY*/ { $$ = NIL; }
+ ;
+
TableFuncElementList:
TableFuncElement
{
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("timezone");
n->args = list_make2($5, $1);
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("like_escape");
n->args = list_make2($3, $5);
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("like_escape");
n->args = list_make2($4, $6);
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("like_escape");
n->args = list_make2($3, $5);
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("like_escape");
n->args = list_make2($4, $6);
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("similar_escape");
n->args = list_make2($4, makeNullAConst(-1));
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("similar_escape");
n->args = list_make2($4, $6);
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("similar_escape");
n->args = list_make2($5, makeNullAConst(-1));
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("similar_escape");
n->args = list_make2($5, $7);
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = $1;
n->args = NIL;
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = $1;
n->args = $3;
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = $1;
n->args = list_make1($4);
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = TRUE;
FuncCall *n = makeNode(FuncCall);
n->funcname = $1;
n->args = lappend($3, $6);
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = TRUE;
n->location = @1;
$$ = (Node *)n;
}
- | func_name '(' ALL func_arg_list ')' over_clause
+ | func_name '(' func_arg_list sort_clause ')' over_clause
+ {
+ FuncCall *n = makeNode(FuncCall);
+ n->funcname = $1;
+ n->args = $3;
+ n->agg_order = $4;
+ n->agg_star = FALSE;
+ n->agg_distinct = FALSE;
+ n->func_variadic = FALSE;
+ n->over = $6;
+ n->location = @1;
+ $$ = (Node *)n;
+ }
+ | func_name '(' ALL func_arg_list opt_sort_clause ')' over_clause
{
FuncCall *n = makeNode(FuncCall);
n->funcname = $1;
n->args = $4;
+ n->agg_order = $5;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
/* Ideally we'd mark the FuncCall node to indicate
* for that in FuncCall at the moment.
*/
n->func_variadic = FALSE;
- n->over = $6;
+ n->over = $7;
n->location = @1;
$$ = (Node *)n;
}
- | func_name '(' DISTINCT func_arg_list ')' over_clause
+ | func_name '(' DISTINCT func_arg_list opt_sort_clause ')' over_clause
{
FuncCall *n = makeNode(FuncCall);
n->funcname = $1;
n->args = $4;
+ n->agg_order = $5;
n->agg_star = FALSE;
n->agg_distinct = TRUE;
n->func_variadic = FALSE;
- n->over = $6;
+ n->over = $7;
n->location = @1;
$$ = (Node *)n;
}
FuncCall *n = makeNode(FuncCall);
n->funcname = $1;
n->args = NIL;
+ n->agg_order = NIL;
n->agg_star = TRUE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("now");
n->args = NIL;
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("current_user");
n->args = NIL;
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("current_user");
n->args = NIL;
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("session_user");
n->args = NIL;
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("current_user");
n->args = NIL;
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("current_database");
n->args = NIL;
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("current_schema");
n->args = NIL;
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("date_part");
n->args = $3;
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
| OVERLAY '(' overlay_list ')'
{
/* overlay(A PLACING B FROM C FOR D) is converted to
- * substring(A, 1, C-1) || B || substring(A, C+1, C+D)
+ * overlay(A, B, C, D)
* overlay(A PLACING B FROM C) is converted to
- * substring(A, 1, C-1) || B || substring(A, C+1, C+char_length(B))
+ * overlay(A, B, C)
*/
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("overlay");
n->args = $3;
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("position");
n->args = $3;
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("substring");
n->args = $3;
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
*/
n->funcname = SystemFuncName(((Value *)llast($5->names))->val.str);
n->args = list_make1($3);
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("btrim");
n->args = $4;
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("ltrim");
n->args = $4;
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("rtrim");
n->args = $4;
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("btrim");
n->args = $3;
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
{
$$ = makeXmlExpr(IS_XMLELEMENT, $4, $6, $8, @1);
}
+ | XMLEXISTS '(' c_expr xmlexists_argument ')'
+ {
+ /* xmlexists(A PASSING [BY REF] B [BY REF]) is
+ * converted to xmlexists(A, B)*/
+ FuncCall *n = makeNode(FuncCall);
+ n->funcname = SystemFuncName("xmlexists");
+ n->args = list_make2($3, $4);
+ n->agg_order = NIL;
+ n->agg_star = FALSE;
+ n->agg_distinct = FALSE;
+ n->func_variadic = FALSE;
+ n->over = NULL;
+ n->location = @1;
+ $$ = (Node *)n;
+ }
| XMLFOREST '(' xml_attribute_list ')'
{
$$ = makeXmlExpr(IS_XMLFOREST, NULL, $3, NIL, @1);
| /*EMPTY*/ { $$ = FALSE; }
;
+/* We allow several variants for SQL and other compatibility. */
+xmlexists_argument:
+ PASSING c_expr
+ {
+ $$ = $2;
+ }
+ | PASSING c_expr BY REF
+ {
+ $$ = $2;
+ }
+ | PASSING BY REF c_expr
+ {
+ $$ = $4;
+ }
+ | PASSING BY REF c_expr BY REF
+ {
+ $$ = $4;
+ }
+ ;
+
+
/*
* Window Definitions
*/
n->partitionClause = NIL;
n->orderClause = NIL;
n->frameOptions = FRAMEOPTION_DEFAULTS;
+ n->startOffset = NULL;
+ n->endOffset = NULL;
n->location = @2;
$$ = n;
}
n->refname = $2;
n->partitionClause = $3;
n->orderClause = $4;
- n->frameOptions = $5;
+ /* copy relevant fields of opt_frame_clause */
+ n->frameOptions = $5->frameOptions;
+ n->startOffset = $5->startOffset;
+ n->endOffset = $5->endOffset;
n->location = @1;
$$ = n;
}
;
/*
+ * For frame clauses, we return a WindowDef, but only some fields are used:
+ * frameOptions, startOffset, and endOffset.
+ *
* This is only a subset of the full SQL:2008 frame_clause grammar.
- * We don't support <expression> PRECEDING, <expression> FOLLOWING,
- * nor <window frame exclusion> yet.
+ * We don't support <window frame exclusion> yet.
*/
opt_frame_clause:
RANGE frame_extent
{
- $$ = FRAMEOPTION_NONDEFAULT | FRAMEOPTION_RANGE | $2;
+ WindowDef *n = $2;
+ n->frameOptions |= FRAMEOPTION_NONDEFAULT | FRAMEOPTION_RANGE;
+ if (n->frameOptions & (FRAMEOPTION_START_VALUE_PRECEDING |
+ FRAMEOPTION_END_VALUE_PRECEDING))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("RANGE PRECEDING is only supported with UNBOUNDED"),
+ parser_errposition(@1)));
+ if (n->frameOptions & (FRAMEOPTION_START_VALUE_FOLLOWING |
+ FRAMEOPTION_END_VALUE_FOLLOWING))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("RANGE FOLLOWING is only supported with UNBOUNDED"),
+ parser_errposition(@1)));
+ $$ = n;
}
| ROWS frame_extent
{
- $$ = FRAMEOPTION_NONDEFAULT | FRAMEOPTION_ROWS | $2;
+ WindowDef *n = $2;
+ n->frameOptions |= FRAMEOPTION_NONDEFAULT | FRAMEOPTION_ROWS;
+ $$ = n;
}
| /*EMPTY*/
- { $$ = FRAMEOPTION_DEFAULTS; }
+ {
+ WindowDef *n = makeNode(WindowDef);
+ n->frameOptions = FRAMEOPTION_DEFAULTS;
+ n->startOffset = NULL;
+ n->endOffset = NULL;
+ $$ = n;
+ }
;
frame_extent: frame_bound
{
+ WindowDef *n = $1;
/* reject invalid cases */
- if ($1 & FRAMEOPTION_START_UNBOUNDED_FOLLOWING)
+ if (n->frameOptions & FRAMEOPTION_START_UNBOUNDED_FOLLOWING)
ereport(ERROR,
(errcode(ERRCODE_WINDOWING_ERROR),
errmsg("frame start cannot be UNBOUNDED FOLLOWING"),
parser_errposition(@1)));
- if ($1 & FRAMEOPTION_START_CURRENT_ROW)
+ if (n->frameOptions & FRAMEOPTION_START_VALUE_FOLLOWING)
ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("frame start at CURRENT ROW is not implemented"),
+ (errcode(ERRCODE_WINDOWING_ERROR),
+ errmsg("frame starting from following row cannot end with current row"),
parser_errposition(@1)));
- $$ = $1 | FRAMEOPTION_END_CURRENT_ROW;
+ n->frameOptions |= FRAMEOPTION_END_CURRENT_ROW;
+ $$ = n;
}
| BETWEEN frame_bound AND frame_bound
{
+ WindowDef *n1 = $2;
+ WindowDef *n2 = $4;
+ /* form merged options */
+ int frameOptions = n1->frameOptions;
+ /* shift converts START_ options to END_ options */
+ frameOptions |= n2->frameOptions << 1;
+ frameOptions |= FRAMEOPTION_BETWEEN;
/* reject invalid cases */
- if ($2 & FRAMEOPTION_START_UNBOUNDED_FOLLOWING)
+ if (frameOptions & FRAMEOPTION_START_UNBOUNDED_FOLLOWING)
ereport(ERROR,
(errcode(ERRCODE_WINDOWING_ERROR),
errmsg("frame start cannot be UNBOUNDED FOLLOWING"),
parser_errposition(@2)));
- if ($2 & FRAMEOPTION_START_CURRENT_ROW)
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("frame start at CURRENT ROW is not implemented"),
- parser_errposition(@2)));
- if ($4 & FRAMEOPTION_START_UNBOUNDED_PRECEDING)
+ if (frameOptions & FRAMEOPTION_END_UNBOUNDED_PRECEDING)
ereport(ERROR,
(errcode(ERRCODE_WINDOWING_ERROR),
errmsg("frame end cannot be UNBOUNDED PRECEDING"),
parser_errposition(@4)));
- /* shift converts START_ options to END_ options */
- $$ = FRAMEOPTION_BETWEEN | $2 | ($4 << 1);
+ if ((frameOptions & FRAMEOPTION_START_CURRENT_ROW) &&
+ (frameOptions & FRAMEOPTION_END_VALUE_PRECEDING))
+ ereport(ERROR,
+ (errcode(ERRCODE_WINDOWING_ERROR),
+ errmsg("frame starting from current row cannot have preceding rows"),
+ parser_errposition(@4)));
+ if ((frameOptions & FRAMEOPTION_START_VALUE_FOLLOWING) &&
+ (frameOptions & (FRAMEOPTION_END_VALUE_PRECEDING |
+ FRAMEOPTION_END_CURRENT_ROW)))
+ ereport(ERROR,
+ (errcode(ERRCODE_WINDOWING_ERROR),
+ errmsg("frame starting from following row cannot have preceding rows"),
+ parser_errposition(@4)));
+ n1->frameOptions = frameOptions;
+ n1->endOffset = n2->startOffset;
+ $$ = n1;
}
;
frame_bound:
UNBOUNDED PRECEDING
{
- $$ = FRAMEOPTION_START_UNBOUNDED_PRECEDING;
+ WindowDef *n = makeNode(WindowDef);
+ n->frameOptions = FRAMEOPTION_START_UNBOUNDED_PRECEDING;
+ n->startOffset = NULL;
+ n->endOffset = NULL;
+ $$ = n;
}
| UNBOUNDED FOLLOWING
{
- $$ = FRAMEOPTION_START_UNBOUNDED_FOLLOWING;
+ WindowDef *n = makeNode(WindowDef);
+ n->frameOptions = FRAMEOPTION_START_UNBOUNDED_FOLLOWING;
+ n->startOffset = NULL;
+ n->endOffset = NULL;
+ $$ = n;
}
| CURRENT_P ROW
{
- $$ = FRAMEOPTION_START_CURRENT_ROW;
+ WindowDef *n = makeNode(WindowDef);
+ n->frameOptions = FRAMEOPTION_START_CURRENT_ROW;
+ n->startOffset = NULL;
+ n->endOffset = NULL;
+ $$ = n;
+ }
+ | a_expr PRECEDING
+ {
+ WindowDef *n = makeNode(WindowDef);
+ n->frameOptions = FRAMEOPTION_START_VALUE_PRECEDING;
+ n->startOffset = $1;
+ n->endOffset = NULL;
+ $$ = n;
+ }
+ | a_expr FOLLOWING
+ {
+ WindowDef *n = makeNode(WindowDef);
+ n->frameOptions = FRAMEOPTION_START_VALUE_FOLLOWING;
+ n->startOffset = $1;
+ n->endOffset = NULL;
+ $$ = n;
}
;
{
$$ = $1;
}
- | a_expr AS param_name
+ | param_name COLON_EQUALS a_expr
{
NamedArgExpr *na = makeNode(NamedArgExpr);
- na->arg = (Expr *) $1;
- na->name = $3;
+ na->name = $1;
+ na->arg = (Expr *) $3;
na->argnumber = -1; /* until determined */
- na->location = @3;
+ na->location = @1;
$$ = (Node *) na;
}
;
* SQL99 defines the OVERLAY() function:
* o overlay(text placing text from int for int)
* o overlay(text placing text from int)
+ * and similarly for binary strings
*/
overlay_list:
a_expr overlay_placing substr_from substr_for
if (IsA(arg, NamedArgExpr))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("type modifier cannot have AS name"),
+ errmsg("type modifier cannot have parameter name"),
parser_errposition(arg->location)));
}
t->typmods = $3;
| ASSERTION
| ASSIGNMENT
| AT
+ | ATTRIBUTE
| BACKWARD
| BEFORE
| BEGIN_P
| COMMENTS
| COMMIT
| COMMITTED
- | CONCURRENTLY
| CONFIGURATION
| CONNECTION
| CONSTRAINTS
| ENCRYPTED
| ENUM_P
| ESCAPE
+ | EXCLUDE
| EXCLUDING
| EXCLUSIVE
| EXECUTE
| INVOKER
| ISOLATION
| KEY
+ | LABEL
| LANGUAGE
| LARGE_P
| LAST_P
| PARSER
| PARTIAL
| PARTITION
+ | PASSING
| PASSWORD
| PLANS
| PRECEDING
| REASSIGN
| RECHECK
| RECURSIVE
+ | REF
| REINDEX
| RELATIVE_P
| RELEASE
* looks too much like a function call for an LR(1) parser.
*/
col_name_keyword:
- BIGINT
+ BETWEEN
+ | BIGINT
| BIT
| BOOLEAN_P
| CHAR_P
| XMLATTRIBUTES
| XMLCONCAT
| XMLELEMENT
+ | XMLEXISTS
| XMLFOREST
| XMLPARSE
| XMLPI
*/
type_func_name_keyword:
AUTHORIZATION
- | BETWEEN
| BINARY
+ | CONCURRENTLY
| CROSS
| CURRENT_SCHEMA
| FREEZE
errmsg("wrong number of parameters on right side of OVERLAPS expression"),
parser_errposition(location)));
n->args = list_concat(largs, rargs);
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
return result;
}
+/*
+ * Convert a list of (dotted) names to a RangeVar (like
+ * makeRangeVarFromNameList, but with position support). The
+ * "AnyName" refers to the any_name production in the grammar.
+ */
+static RangeVar *
+makeRangeVarFromAnyName(List *names, int position, core_yyscan_t yyscanner)
+{
+ RangeVar *r = makeNode(RangeVar);
+
+ switch (list_length(names))
+ {
+ case 1:
+ r->catalogname = NULL;
+ r->schemaname = NULL;
+ r->relname = strVal(linitial(names));
+ break;
+ case 2:
+ r->catalogname = NULL;
+ r->schemaname = strVal(linitial(names));
+ r->relname = strVal(lsecond(names));
+ break;
+ case 3:
+ r->catalogname = strVal(linitial(names));;
+ r->schemaname = strVal(lsecond(names));
+ r->relname = strVal(lthird(names));
+ break;
+ default:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("improper qualified name (too many dotted names): %s",
+ NameListToString(names)),
+ parser_errposition(position)));
+ break;
+ }
+
+ r->location = position;
+
+ return r;
+}
+
/*
* Must undefine this stuff before including scan.c, since it has different
* definitions for these macros.