Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: master
14437 lines (13428 sloc) 387.584 kb
%{
/*#define YYDEBUG 1*/
/*-------------------------------------------------------------------------
*
* gram.y
* POSTGRESQL BISON rules/actions
*
* Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group
* 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 SQL_inheritance 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. The handling of SQL_inheritance is
* a good example.
*
* 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 "postgres.h"
#include <ctype.h>
#include <limits.h>
#include "catalog/index.h"
#include "catalog/namespace.h"
#include "catalog/pg_trigger.h"
#include "commands/defrem.h"
#include "commands/trigger.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "parser/gramparse.h"
#include "parser/parser.h"
#include "storage/lmgr.h"
#include "utils/date.h"
#include "utils/datetime.h"
#include "utils/numeric.h"
#include "utils/xml.h"
/*
* 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. This is problematic
* for nonterminals defined like
* OptFooList: / * EMPTY * / { ... } | OptFooList Foo { ... } ;
* because we'll set -1 as the location during the first reduction and then
* copy it during each subsequent reduction, leaving us with -1 for the
* location even when the list is not empty. To fix that, do this in the
* action for the nonempty rule(s):
* if (@$ < 0) @$ = @2;
* (Although we have many nonterminals that follow this pattern, we only
* bother with fixing @$ like this when the nonterminal's parse location
* is actually referenced in some rule.)
*/
/*
* Bison doesn't allocate anything that needs to live across parser calls,
* so we can easily have it use palloc instead of malloc. This prevents
* memory leaks if we error out during parsing. Note this only works with
* 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
/* Private struct for the result of privilege_target production */
typedef struct PrivTarget
{
GrantTargetType targtype;
GrantObjectType objtype;
List *objs;
} PrivTarget;
/* Private struct for the result of import_qualification production */
typedef struct ImportQual
{
ImportForeignSchemaType type;
List *table_names;
} ImportQual;
/* ConstraintAttributeSpec 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)
static void base_yyerror(YYLTYPE *yylloc, core_yyscan_t yyscanner,
const char *msg);
static Node *makeColumnRef(char *colname, List *indirection,
int location, core_yyscan_t yyscanner);
static Node *makeTypeCast(Node *arg, TypeName *typename, int location);
static Node *makeStringConst(char *str, int location);
static Node *makeStringConstCast(char *str, int location, TypeName *typename);
static Node *makeIntConst(int val, int location);
static Node *makeFloatConst(char *str, int location);
static Node *makeBitStringConst(char *str, int location);
static Node *makeNullAConst(int location);
static Node *makeAConst(Value *v, int location);
static Node *makeBoolAConst(bool state, int location);
static void check_qualified_name(List *names, core_yyscan_t yyscanner);
static List *check_func_name(List *names, core_yyscan_t yyscanner);
static List *check_indirection(List *indirection, core_yyscan_t yyscanner);
static List *extractArgTypes(List *parameters);
static List *extractAggrArgTypes(List *aggrargs);
static List *makeOrderedSetArgs(List *directargs, List *orderedargs,
core_yyscan_t yyscanner);
static void insertSelectOptions(SelectStmt *stmt,
List *sortClause, List *lockingClause,
Node *limitOffset, Node *limitCount,
WithClause *withClause,
core_yyscan_t yyscanner);
static Node *makeSetOp(SetOperation op, bool all, Node *larg, Node *rarg);
static Node *doNegate(Node *n, int location);
static void doNegateFloat(Value *v);
static Node *makeAndExpr(Node *lexpr, Node *rexpr, int location);
static Node *makeOrExpr(Node *lexpr, Node *rexpr, int location);
static Node *makeNotExpr(Node *expr, int location);
static Node *makeAArrayExpr(List *elements, int location);
static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args,
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);
static void SplitColQualList(List *qualList,
List **constraintList, CollateClause **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 Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%}
%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;
char chr;
bool boolean;
JoinType jtype;
DropBehavior dbehavior;
OnCommitAction oncommit;
List *list;
Node *node;
Value *value;
ObjectType objtype;
TypeName *typnam;
FunctionParameter *fun_param;
FunctionParameterMode fun_param_mode;
FuncWithArgs *funwithargs;
DefElem *defelt;
SortBy *sortby;
WindowDef *windef;
JoinExpr *jexpr;
IndexElem *ielem;
Alias *alias;
RangeVar *range;
IntoClause *into;
WithClause *with;
A_Indices *aind;
ResTarget *target;
struct PrivTarget *privtarget;
AccessPriv *accesspriv;
struct ImportQual *importqual;
InsertStmt *istmt;
VariableSetStmt *vsetstmt;
}
%type <node> stmt schema_stmt
AlterEventTrigStmt
AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterEnumStmt
AlterFdwStmt AlterForeignServerStmt AlterGroupStmt
AlterObjectSchemaStmt AlterOwnerStmt AlterSeqStmt AlterSystemStmt AlterTableStmt
AlterTblSpcStmt AlterExtensionStmt AlterExtensionContentsStmt AlterForeignTableStmt
AlterCompositeTypeStmt AlterUserStmt AlterUserMappingStmt AlterUserSetStmt
AlterRoleStmt AlterRoleSetStmt AlterPolicyStmt
AlterDefaultPrivilegesStmt DefACLAction
AnalyzeStmt ClosePortalStmt ClusterStmt CommentStmt
ConstraintsSetStmt CopyStmt CreateAsStmt CreateCastStmt
CreateDomainStmt CreateExtensionStmt CreateGroupStmt CreateOpClassStmt
CreateOpFamilyStmt AlterOpFamilyStmt CreatePLangStmt
CreateSchemaStmt CreateSeqStmt CreateStmt CreateTableSpaceStmt
CreateFdwStmt CreateForeignServerStmt CreateForeignTableStmt
CreateAssertStmt CreateTrigStmt CreateEventTrigStmt
CreateUserStmt CreateUserMappingStmt CreateRoleStmt CreatePolicyStmt
CreatedbStmt DeclareCursorStmt DefineStmt DeleteStmt DiscardStmt DoStmt
DropGroupStmt DropOpClassStmt DropOpFamilyStmt DropPLangStmt DropStmt
DropAssertStmt DropTrigStmt DropRuleStmt DropCastStmt DropRoleStmt
DropPolicyStmt DropUserStmt DropdbStmt DropTableSpaceStmt DropFdwStmt
DropForeignServerStmt DropUserMappingStmt ExplainStmt FetchStmt
GrantStmt GrantRoleStmt ImportForeignSchemaStmt IndexStmt InsertStmt
ListenStmt LoadStmt LockStmt NotifyStmt ExplainableStmt PreparableStmt
CreateFunctionStmt AlterFunctionStmt ReindexStmt RemoveAggrStmt
RemoveFuncStmt RemoveOperStmt RenameStmt RevokeStmt RevokeRoleStmt
RuleActionStmt RuleActionStmtOrEmpty RuleStmt
SecLabelStmt SelectStmt TransactionStmt TruncateStmt
UnlistenStmt UpdateStmt VacuumStmt
VariableResetStmt VariableSetStmt VariableShowStmt
ViewStmt CheckPointStmt CreateConversionStmt
DeallocateStmt PrepareStmt ExecuteStmt
DropOwnedStmt ReassignOwnedStmt
AlterTSConfigurationStmt AlterTSDictionaryStmt
CreateMatViewStmt RefreshMatViewStmt
%type <node> select_no_parens select_with_parens select_clause
simple_select values_clause
%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 alter_type_cmd opt_collate_clause
replica_identity
%type <list> alter_table_cmds alter_type_cmds
%type <dbehavior> opt_drop_behavior
%type <list> createdb_opt_list createdb_opt_items copy_opt_list
transaction_mode_list
create_extension_opt_list alter_extension_opt_list
%type <defelt> createdb_opt_item copy_opt_item
transaction_mode_item
create_extension_opt_item alter_extension_opt_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 <ival> opt_nowait_or_skip
%type <list> OptRoleList AlterOptRoleList
%type <defelt> CreateOptRoleElem AlterOptRoleElem
%type <str> opt_type
%type <str> foreign_server_version opt_foreign_server_version
%type <str> auth_ident
%type <str> opt_in_database
%type <str> OptSchemaName
%type <list> OptSchemaEltList
%type <boolean> TriggerForSpec TriggerForType
%type <ival> TriggerActionTime
%type <list> TriggerEvents TriggerOneEvent
%type <value> TriggerFuncArg
%type <node> TriggerWhen
%type <list> event_trigger_when_list event_trigger_value_list
%type <defelt> event_trigger_when_item
%type <chr> enable_trigger
%type <str> copy_file_name
database_name access_method_clause access_method attr_name
name cursor_name file_name
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
opt_collate
%type <range> qualified_name OptConstrFromTable
%type <str> all_Op MathOp
%type <str> row_security_cmd RowSecurityDefaultForCmd
%type <node> RowSecurityOptionalWithCheck RowSecurityOptionalExpr
%type <list> RowSecurityDefaultToRole RowSecurityOptionalToRole
%type <str> iso_level opt_encoding
%type <node> grantee
%type <list> grantee_list
%type <accesspriv> privilege
%type <list> privileges privilege_list
%type <privtarget> privilege_target
%type <funwithargs> function_with_argtypes
%type <list> function_with_argtypes_list
%type <ival> defacl_privilege_target
%type <defelt> DefACLOption
%type <list> DefACLOptionList
%type <ival> import_qualification_type
%type <importqual> import_qualification
%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
aggr_args aggr_args_list
func_as createfunc_opt_list alterfunc_opt_list
old_aggr_definition old_aggr_list
oper_argtypes RuleActionList RuleActionMulti
opt_column_list columnList opt_name_list
sort_clause opt_sort_clause sortby_list index_params
name_list role_list from_clause from_list opt_array_bounds
qualified_name_list any_name any_name_list type_name_list
any_operator expr_list attrs
target_list opt_target_list insert_column_list set_target_list
set_clause_list set_clause multiple_set_clause
ctext_expr_list ctext_row def_list indirection opt_indirection
reloption_list group_clause TriggerFuncArgs select_limit
opt_select_limit opclass_item_list opclass_drop_list
opclass_purpose opt_opfamily transaction_mode_list_or_empty
OptTableFuncElementList TableFuncElementList opt_type_modifiers
prep_type_clause
execute_param_clause using_clause returning_clause
opt_enum_val_list enum_val_list table_func_column_list
create_generic_options alter_generic_options
relation_expr_list dostmt_opt_list
%type <list> opt_fdw_options fdw_options
%type <defelt> fdw_option
%type <range> OptTempTableName
%type <into> into_clause create_as_target create_mv_target
%type <defelt> createfunc_opt_item common_func_opt_item dostmt_opt_item
%type <fun_param> func_arg func_arg_with_default table_func_column aggr_arg
%type <fun_param_mode> arg_class
%type <typnam> func_return func_type
%type <boolean> opt_trusted opt_restart_seqs
%type <ival> OptTemp
%type <ival> OptNoLog
%type <oncommit> OnCommitOption
%type <ival> for_locking_strength
%type <node> for_locking_item
%type <list> for_locking_clause opt_for_locking_clause for_locking_items
%type <list> locked_rels_list
%type <boolean> opt_all
%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 interval_second
%type <node> overlay_placing substr_from substr_for
%type <boolean> opt_instead
%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 opt_program
%type <ival> opt_column event cursor_options opt_hold opt_set_data
%type <objtype> drop_type comment_type security_label_type
%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 <list> OptSeqOptList SeqOptList
%type <defelt> SeqOptElem
%type <istmt> insert_rest
%type <vsetstmt> generic_set set_rest set_rest_more generic_reset reset_rest
SetResetClause FunctionSetResetClause
%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 AexprConst indirection_el
columnref in_expr having_clause func_table array_expr
ExclusionWhereClause
%type <list> rowsfrom_item rowsfrom_list opt_col_def_list
%type <boolean> opt_ordinality
%type <list> ExclusionConstraintList ExclusionConstraintElem
%type <list> func_arg_list
%type <node> func_arg_expr
%type <list> row type_list array_expr_list
%type <node> case_expr case_arg when_clause case_default
%type <list> when_clause_list
%type <ival> sub_type
%type <node> ctext_expr
%type <value> NumericOnly
%type <list> NumericOnly_list
%type <alias> alias_clause opt_alias_clause
%type <list> func_alias_clause
%type <sortby> sortby
%type <ielem> index_elem
%type <node> table_ref
%type <jexpr> joined_table
%type <range> relation_expr
%type <range> relation_expr_opt_alias
%type <target> target_el single_set_clause set_target insert_column_item
%type <str> generic_option_name
%type <node> generic_option_arg
%type <defelt> generic_option_elem alter_generic_option_elem
%type <list> generic_option_list alter_generic_option_list
%type <str> explain_option_name
%type <node> explain_option_arg
%type <defelt> explain_option_elem
%type <list> explain_option_list
%type <node> copy_generic_opt_arg copy_generic_opt_arg_list_item
%type <defelt> copy_generic_opt_elem
%type <list> copy_generic_opt_list copy_generic_opt_arg_list
%type <list> copy_options
%type <typnam> Typename SimpleTypename ConstTypename
GenericType Numeric opt_float
Character ConstCharacter
CharacterWithLength CharacterWithoutLength
ConstDatetime ConstInterval
Bit ConstBit BitWithLength BitWithoutLength
%type <str> character
%type <str> extract_arg
%type <str> opt_charset
%type <boolean> opt_varying opt_timezone opt_no_inherit
%type <ival> Iconst SignedIconst
%type <str> Sconst comment_text notify_payload
%type <str> RoleId opt_granted_by opt_boolean_or_string
%type <list> var_list
%type <str> ColId ColLabel var_name type_function_name param_name
%type <str> NonReservedWord NonReservedWord_or_Sconst
%type <str> createdb_opt_name
%type <node> var_value zone_value
%type <keyword> unreserved_keyword type_func_name_keyword
%type <keyword> col_name_keyword reserved_keyword
%type <node> TableConstraint TableLikeClause
%type <ival> TableLikeOptionList TableLikeOption
%type <list> ColQualList
%type <node> ColConstraint ColConstraintElem ConstraintAttr
%type <ival> key_actions key_delete key_match key_update key_action
%type <ival> ConstraintAttributeSpec ConstraintAttributeElem
%type <str> ExistingIndex
%type <list> constraints_set_list
%type <boolean> constraints_set_mode
%type <str> OptTableSpace OptConsTableSpace OptTableSpaceOwner
%type <ival> 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> func_application func_expr_common_subexpr
%type <node> func_expr func_expr_windowless
%type <node> common_table_expr
%type <with> with_clause opt_with_clause
%type <list> cte_list
%type <list> within_group_clause
%type <node> filter_clause
%type <list> window_clause window_definition_list opt_partition_clause
%type <windef> window_definition over_clause window_specification
opt_frame_clause frame_extent frame_bound
%type <str> opt_existing_window_name
%type <boolean> opt_if_not_exists
/*
* Non-keyword token types. These are hard-wired into the "flex" lexer.
* 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
/*
* 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 */
%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 ATTRIBUTE AUTHORIZATION
BACKWARD BEFORE BEGIN_P BETWEEN BIGINT BINARY BIT
BOOLEAN_P BOTH BY
CACHE CALLED CASCADE CASCADED CASE CAST CATALOG_P CHAIN CHAR_P
CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLOSE
CLUSTER COALESCE COLLATE COLLATION COLUMN COMMENT COMMENTS COMMIT
COMMITTED CONCURRENTLY CONFIGURATION CONNECTION CONSTRAINT CONSTRAINTS
CONTENT_P CONTINUE_P CONVERSION_P COPY COST CREATE
CROSS CSV CURRENT_P
CURRENT_CATALOG CURRENT_DATE CURRENT_ROLE CURRENT_SCHEMA
CURRENT_TIME CURRENT_TIMESTAMP CURRENT_USER CURSOR CYCLE
DATA_P DATABASE DAY_P DEALLOCATE DEC DECIMAL_P DECLARE DEFAULT DEFAULTS
DEFERRABLE DEFERRED DEFINER DELETE_P DELIMITER DELIMITERS DESC
DICTIONARY DISABLE_P DISCARD DISTINCT DO DOCUMENT_P DOMAIN_P DOUBLE_P DROP
EACH ELSE ENABLE_P ENCODING ENCRYPTED END_P ENUM_P ESCAPE EVENT EXCEPT
EXCLUDE EXCLUDING EXCLUSIVE EXECUTE EXISTS EXPLAIN
EXTENSION EXTERNAL EXTRACT
FALSE_P FAMILY FETCH FILTER FIRST_P FLOAT_P FOLLOWING FOR
FORCE FOREIGN FORWARD FREEZE FROM FULL FUNCTION FUNCTIONS
GLOBAL GRANT GRANTED GREATEST GROUP_P
HANDLER HAVING HEADER_P HOLD HOUR_P
IDENTITY_P IF_P ILIKE IMMEDIATE IMMUTABLE IMPLICIT_P IMPORT_P IN_P
INCLUDING INCREMENT INDEX INDEXES INHERIT INHERITS INITIALLY INLINE_P
INNER_P INOUT INPUT_P INSENSITIVE INSERT INSTEAD INT_P INTEGER
INTERSECT INTERVAL INTO INVOKER IS ISNULL ISOLATION
JOIN
KEY
LABEL LANGUAGE LARGE_P LAST_P LATERAL_P
LEADING LEAKPROOF LEAST LEFT LEVEL LIKE LIMIT LISTEN LOAD LOCAL
LOCALTIME LOCALTIMESTAMP LOCATION LOCK_P LOCKED LOGGED
MAPPING MATCH MATERIALIZED MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE
NAME_P NAMES NATIONAL NATURAL NCHAR NEXT NO NONE
NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF
NULLS_P NUMERIC
OBJECT_P OF OFF OFFSET OIDS ON ONLY OPERATOR OPTION OPTIONS OR
ORDER ORDINALITY OUT_P OUTER_P OVER OVERLAPS OVERLAY OWNED OWNER
PARSER PARTIAL PARTITION PASSING PASSWORD PLACING PLANS POLICY POSITION
PRECEDING PRECISION PRESERVE PREPARE PREPARED PRIMARY
PRIOR PRIVILEGES PROCEDURAL PROCEDURE PROGRAM
QUOTE
RANGE READ REAL REASSIGN RECHECK RECURSIVE REF REFERENCES REFRESH REINDEX
RELATIVE_P RELEASE RENAME REPEATABLE REPLACE REPLICA
RESET RESTART RESTRICT RETURNING RETURNS REVOKE RIGHT ROLE ROLLBACK
ROW ROWS RULE
SAVEPOINT SCHEMA SCROLL SEARCH SECOND_P SECURITY SELECT SEQUENCE SEQUENCES
SERIALIZABLE SERVER SESSION SESSION_USER SET SETOF SHARE
SHOW SIMILAR SIMPLE SKIP SMALLINT SNAPSHOT SOME STABLE STANDALONE_P START
STATEMENT STATISTICS STDIN STDOUT STORAGE STRICT_P STRIP_P SUBSTRING
SYMMETRIC SYSID SYSTEM_P
TABLE TABLES TABLESPACE TEMP TEMPLATE TEMPORARY TEXT_P THEN TIME TIMESTAMP
TO TRAILING TRANSACTION TREAT TRIGGER TRIM TRUE_P
TRUNCATE TRUSTED TYPE_P TYPES_P
UNBOUNDED UNCOMMITTED UNENCRYPTED UNION UNIQUE UNKNOWN UNLISTEN UNLOGGED
UNTIL UPDATE USER USING
VACUUM VALID VALIDATE VALIDATOR VALUE_P VALUES VARCHAR VARIADIC VARYING
VERBOSE VERSION_P VIEW VIEWS VOLATILE
WHEN WHERE WHITESPACE_P WINDOW WITH WITHIN WITHOUT WORK WRAPPER WRITE
XML_P XMLATTRIBUTES XMLCONCAT XMLELEMENT XMLEXISTS XMLFOREST XMLPARSE
XMLPI XMLROOT XMLSERIALIZE
YEAR_P YES_P
ZONE
/*
* 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).
*/
%token NULLS_LA WITH_LA
/* Precedence: lowest to highest */
%nonassoc SET /* see relation_expr_opt_alias */
%left UNION EXCEPT
%left INTERSECT
%left OR
%left AND
%right NOT
%right '='
%nonassoc '<' '>'
%nonassoc LIKE ILIKE SIMILAR
%nonassoc ESCAPE
%nonassoc OVERLAPS
%nonassoc BETWEEN
%nonassoc IN_P
%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;
* and for NULL so that it can follow b_expr in ColQualList 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 UNBOUNDED /* ideally should have same precedence as IDENT */
%nonassoc IDENT NULL_P PARTITION RANGE ROWS PRECEDING FOLLOWING
%left Op OPERATOR /* multi-character ops and user-defined operators */
%nonassoc NOTNULL
%nonassoc ISNULL
%nonassoc IS /* sets precedence for IS NULL, etc */
%left '+' '-'
%left '*' '/' '%'
%left '^'
/* 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
/* kluge to keep xml_whitespace_option from causing shift/reduce conflicts */
%right PRESERVE STRIP_P
%%
/*
* The target production for the whole parse.
*/
stmtblock: stmtmulti
{
pg_yyget_extra(yyscanner)->parsetree = $1;
}
;
/* the thrashing around here is to discard "empty" statements... */
stmtmulti: stmtmulti ';' stmt
{
if ($3 != NULL)
$$ = lappend($1, $3);
else
$$ = $1;
}
| stmt
{
if ($1 != NULL)
$$ = list_make1($1);
else
$$ = NIL;
}
;
stmt :
AlterEventTrigStmt
| AlterDatabaseStmt
| AlterDatabaseSetStmt
| AlterDefaultPrivilegesStmt
| AlterDomainStmt
| AlterEnumStmt
| AlterExtensionStmt
| AlterExtensionContentsStmt
| AlterFdwStmt
| AlterForeignServerStmt
| AlterForeignTableStmt
| AlterFunctionStmt
| AlterGroupStmt
| AlterObjectSchemaStmt
| AlterOwnerStmt
| AlterPolicyStmt
| AlterSeqStmt
| AlterSystemStmt
| AlterTableStmt
| AlterTblSpcStmt
| AlterCompositeTypeStmt
| AlterRoleSetStmt
| AlterRoleStmt
| AlterTSConfigurationStmt
| AlterTSDictionaryStmt
| AlterUserMappingStmt
| AlterUserSetStmt
| AlterUserStmt
| AnalyzeStmt
| CheckPointStmt
| ClosePortalStmt
| ClusterStmt
| CommentStmt
| ConstraintsSetStmt
| CopyStmt
| CreateAsStmt
| CreateAssertStmt
| CreateCastStmt
| CreateConversionStmt
| CreateDomainStmt
| CreateExtensionStmt
| CreateFdwStmt
| CreateForeignServerStmt
| CreateForeignTableStmt
| CreateFunctionStmt
| CreateGroupStmt
| CreateMatViewStmt
| CreateOpClassStmt
| CreateOpFamilyStmt
| AlterOpFamilyStmt
| CreatePolicyStmt
| CreatePLangStmt
| CreateSchemaStmt
| CreateSeqStmt
| CreateStmt
| CreateTableSpaceStmt
| CreateTrigStmt
| CreateEventTrigStmt
| CreateRoleStmt
| CreateUserStmt
| CreateUserMappingStmt
| CreatedbStmt
| DeallocateStmt
| DeclareCursorStmt
| DefineStmt
| DeleteStmt
| DiscardStmt
| DoStmt
| DropAssertStmt
| DropCastStmt
| DropFdwStmt
| DropForeignServerStmt
| DropGroupStmt
| DropOpClassStmt
| DropOpFamilyStmt
| DropOwnedStmt
| DropPolicyStmt
| DropPLangStmt
| DropRuleStmt
| DropStmt
| DropTableSpaceStmt
| DropTrigStmt
| DropRoleStmt
| DropUserStmt
| DropUserMappingStmt
| DropdbStmt
| ExecuteStmt
| ExplainStmt
| FetchStmt
| GrantStmt
| GrantRoleStmt
| ImportForeignSchemaStmt
| IndexStmt
| InsertStmt
| ListenStmt
| RefreshMatViewStmt
| LoadStmt
| LockStmt
| NotifyStmt
| PrepareStmt
| ReassignOwnedStmt
| ReindexStmt
| RemoveAggrStmt
| RemoveFuncStmt
| RemoveOperStmt
| RenameStmt
| RevokeStmt
| RevokeRoleStmt
| RuleStmt
| SecLabelStmt
| SelectStmt
| TransactionStmt
| TruncateStmt
| UnlistenStmt
| UpdateStmt
| VacuumStmt
| VariableResetStmt
| VariableSetStmt
| VariableShowStmt
| ViewStmt
| /*EMPTY*/
{ $$ = NULL; }
;
/*****************************************************************************
*
* Create a new Postgres DBMS role
*
*****************************************************************************/
CreateRoleStmt:
CREATE ROLE RoleId opt_with OptRoleList
{
CreateRoleStmt *n = makeNode(CreateRoleStmt);
n->stmt_type = ROLESTMT_ROLE;
n->role = $3;
n->options = $5;
$$ = (Node *)n;
}
;
opt_with: WITH {}
| WITH_LA {}
| /*EMPTY*/ {}
;
/*
* Options for CREATE ROLE and ALTER ROLE (also used by CREATE/ALTER USER
* for backwards compatibility). Note: the only option required by SQL99
* is "WITH ADMIN name".
*/
OptRoleList:
OptRoleList CreateOptRoleElem { $$ = lappend($1, $2); }
| /* EMPTY */ { $$ = NIL; }
;
AlterOptRoleList:
AlterOptRoleList AlterOptRoleElem { $$ = lappend($1, $2); }
| /* EMPTY */ { $$ = NIL; }
;
AlterOptRoleElem:
PASSWORD Sconst
{
$$ = makeDefElem("password",
(Node *)makeString($2));
}
| PASSWORD NULL_P
{
$$ = makeDefElem("password", NULL);
}
| ENCRYPTED PASSWORD Sconst
{
$$ = makeDefElem("encryptedPassword",
(Node *)makeString($3));
}
| UNENCRYPTED PASSWORD Sconst
{
$$ = makeDefElem("unencryptedPassword",
(Node *)makeString($3));
}
| INHERIT
{
$$ = makeDefElem("inherit", (Node *)makeInteger(TRUE));
}
| CONNECTION LIMIT SignedIconst
{
$$ = makeDefElem("connectionlimit", (Node *)makeInteger($3));
}
| VALID UNTIL Sconst
{
$$ = makeDefElem("validUntil", (Node *)makeString($3));
}
/* Supported but not documented for roles, for use by ALTER GROUP. */
| USER role_list
{
$$ = makeDefElem("rolemembers", (Node *)$2);
}
| IDENT
{
/*
* We handle identifiers that aren't parser keywords with
* the following special-case codes, to avoid bloating the
* size of the main parser.
*/
if (strcmp($1, "superuser") == 0)
$$ = makeDefElem("superuser", (Node *)makeInteger(TRUE));
else if (strcmp($1, "nosuperuser") == 0)
$$ = makeDefElem("superuser", (Node *)makeInteger(FALSE));
else if (strcmp($1, "createuser") == 0)
{
/* For backwards compatibility, synonym for SUPERUSER */
$$ = makeDefElem("superuser", (Node *)makeInteger(TRUE));
}
else if (strcmp($1, "nocreateuser") == 0)
{
/* For backwards compatibility, synonym for SUPERUSER */
$$ = makeDefElem("superuser", (Node *)makeInteger(FALSE));
}
else if (strcmp($1, "createrole") == 0)
$$ = makeDefElem("createrole", (Node *)makeInteger(TRUE));
else if (strcmp($1, "nocreaterole") == 0)
$$ = makeDefElem("createrole", (Node *)makeInteger(FALSE));
else if (strcmp($1, "replication") == 0)
$$ = makeDefElem("isreplication", (Node *)makeInteger(TRUE));
else if (strcmp($1, "noreplication") == 0)
$$ = makeDefElem("isreplication", (Node *)makeInteger(FALSE));
else if (strcmp($1, "createdb") == 0)
$$ = makeDefElem("createdb", (Node *)makeInteger(TRUE));
else if (strcmp($1, "nocreatedb") == 0)
$$ = makeDefElem("createdb", (Node *)makeInteger(FALSE));
else if (strcmp($1, "login") == 0)
$$ = makeDefElem("canlogin", (Node *)makeInteger(TRUE));
else if (strcmp($1, "nologin") == 0)
$$ = makeDefElem("canlogin", (Node *)makeInteger(FALSE));
else if (strcmp($1, "bypassrls") == 0)
$$ = makeDefElem("bypassrls", (Node *)makeInteger(TRUE));
else if (strcmp($1, "nobypassrls") == 0)
$$ = makeDefElem("bypassrls", (Node *)makeInteger(FALSE));
else if (strcmp($1, "noinherit") == 0)
{
/*
* Note that INHERIT is a keyword, so it's handled by main parser, but
* NOINHERIT is handled here.
*/
$$ = makeDefElem("inherit", (Node *)makeInteger(FALSE));
}
else
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("unrecognized role option \"%s\"", $1),
parser_errposition(@1)));
}
;
CreateOptRoleElem:
AlterOptRoleElem { $$ = $1; }
/* The following are not supported by ALTER ROLE/USER/GROUP */
| SYSID Iconst
{
$$ = makeDefElem("sysid", (Node *)makeInteger($2));
}
| ADMIN role_list
{
$$ = makeDefElem("adminmembers", (Node *)$2);
}
| ROLE role_list
{
$$ = makeDefElem("rolemembers", (Node *)$2);
}
| IN_P ROLE role_list
{
$$ = makeDefElem("addroleto", (Node *)$3);
}
| IN_P GROUP_P role_list
{
$$ = makeDefElem("addroleto", (Node *)$3);
}
;
/*****************************************************************************
*
* Create a new Postgres DBMS user (role with implied login ability)
*
*****************************************************************************/
CreateUserStmt:
CREATE USER RoleId opt_with OptRoleList
{
CreateRoleStmt *n = makeNode(CreateRoleStmt);
n->stmt_type = ROLESTMT_USER;
n->role = $3;
n->options = $5;
$$ = (Node *)n;
}
;
/*****************************************************************************
*
* Alter a postgresql DBMS role
*
*****************************************************************************/
AlterRoleStmt:
ALTER ROLE RoleId opt_with AlterOptRoleList
{
AlterRoleStmt *n = makeNode(AlterRoleStmt);
n->role = $3;
n->action = +1; /* add, if there are members */
n->options = $5;
$$ = (Node *)n;
}
;
opt_in_database:
/* EMPTY */ { $$ = NULL; }
| IN_P DATABASE database_name { $$ = $3; }
;
AlterRoleSetStmt:
ALTER ROLE RoleId opt_in_database SetResetClause
{
AlterRoleSetStmt *n = makeNode(AlterRoleSetStmt);
n->role = $3;
n->database = $4;
n->setstmt = $5;
$$ = (Node *)n;
}
| ALTER ROLE ALL opt_in_database SetResetClause
{
AlterRoleSetStmt *n = makeNode(AlterRoleSetStmt);
n->role = NULL;
n->database = $4;
n->setstmt = $5;
$$ = (Node *)n;
}
;
/*****************************************************************************
*
* Alter a postgresql DBMS user
*
*****************************************************************************/
AlterUserStmt:
ALTER USER RoleId opt_with AlterOptRoleList
{
AlterRoleStmt *n = makeNode(AlterRoleStmt);
n->role = $3;
n->action = +1; /* add, if there are members */
n->options = $5;
$$ = (Node *)n;
}
;
AlterUserSetStmt:
ALTER USER RoleId SetResetClause
{
AlterRoleSetStmt *n = makeNode(AlterRoleSetStmt);
n->role = $3;
n->database = NULL;
n->setstmt = $4;
$$ = (Node *)n;
}
;
/*****************************************************************************
*
* Drop a postgresql DBMS role
*
* XXX Ideally this would have CASCADE/RESTRICT options, but since a role
* might own objects in multiple databases, there is presently no way to
* implement either cascading or restricting. Caveat DBA.
*****************************************************************************/
DropRoleStmt:
DROP ROLE role_list
{
DropRoleStmt *n = makeNode(DropRoleStmt);
n->missing_ok = FALSE;
n->roles = $3;
$$ = (Node *)n;
}
| DROP ROLE IF_P EXISTS role_list
{
DropRoleStmt *n = makeNode(DropRoleStmt);
n->missing_ok = TRUE;
n->roles = $5;
$$ = (Node *)n;
}
;
/*****************************************************************************
*
* Drop a postgresql DBMS user
*
* XXX Ideally this would have CASCADE/RESTRICT options, but since a user
* might own objects in multiple databases, there is presently no way to
* implement either cascading or restricting. Caveat DBA.
*****************************************************************************/
DropUserStmt:
DROP USER role_list
{
DropRoleStmt *n = makeNode(DropRoleStmt);
n->missing_ok = FALSE;
n->roles = $3;
$$ = (Node *)n;
}
| DROP USER IF_P EXISTS role_list
{
DropRoleStmt *n = makeNode(DropRoleStmt);
n->roles = $5;
n->missing_ok = TRUE;
$$ = (Node *)n;
}
;
/*****************************************************************************
*
* Create a postgresql group (role without login ability)
*
*****************************************************************************/
CreateGroupStmt:
CREATE GROUP_P RoleId opt_with OptRoleList
{
CreateRoleStmt *n = makeNode(CreateRoleStmt);
n->stmt_type = ROLESTMT_GROUP;
n->role = $3;
n->options = $5;
$$ = (Node *)n;
}
;
/*****************************************************************************
*
* Alter a postgresql group
*
*****************************************************************************/
AlterGroupStmt:
ALTER GROUP_P RoleId add_drop USER role_list
{
AlterRoleStmt *n = makeNode(AlterRoleStmt);
n->role = $3;
n->action = $4;
n->options = list_make1(makeDefElem("rolemembers",
(Node *)$6));
$$ = (Node *)n;
}
;
add_drop: ADD_P { $$ = +1; }
| DROP { $$ = -1; }
;
/*****************************************************************************
*
* Drop a postgresql group
*
* XXX see above notes about cascading DROP USER; groups have same problem.
*****************************************************************************/
DropGroupStmt:
DROP GROUP_P role_list
{
DropRoleStmt *n = makeNode(DropRoleStmt);
n->missing_ok = FALSE;
n->roles = $3;
$$ = (Node *)n;
}
| DROP GROUP_P IF_P EXISTS role_list
{
DropRoleStmt *n = makeNode(DropRoleStmt);
n->missing_ok = TRUE;
n->roles = $5;
$$ = (Node *)n;
}
;
/*****************************************************************************
*
* Manipulate a schema
*
*****************************************************************************/
CreateSchemaStmt:
CREATE SCHEMA OptSchemaName AUTHORIZATION RoleId OptSchemaEltList
{
CreateSchemaStmt *n = makeNode(CreateSchemaStmt);
/* One can omit the schema name or the authorization id. */
if ($3 != NULL)
n->schemaname = $3;
else
n->schemaname = $5;
n->authid = $5;
n->schemaElts = $6;
n->if_not_exists = false;
$$ = (Node *)n;
}
| CREATE SCHEMA ColId OptSchemaEltList
{
CreateSchemaStmt *n = makeNode(CreateSchemaStmt);
/* ...but not both */
n->schemaname = $3;
n->authid = NULL;
n->schemaElts = $4;
n->if_not_exists = false;
$$ = (Node *)n;
}
| CREATE SCHEMA IF_P NOT EXISTS OptSchemaName AUTHORIZATION RoleId OptSchemaEltList
{
CreateSchemaStmt *n = makeNode(CreateSchemaStmt);
/* One can omit the schema name or the authorization id. */
if ($6 != NULL)
n->schemaname = $6;
else
n->schemaname = $8;
n->authid = $8;
if ($9 != NIL)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("CREATE SCHEMA IF NOT EXISTS cannot include schema elements"),
parser_errposition(@9)));
n->schemaElts = $9;
n->if_not_exists = true;
$$ = (Node *)n;
}
| CREATE SCHEMA IF_P NOT EXISTS ColId OptSchemaEltList
{
CreateSchemaStmt *n = makeNode(CreateSchemaStmt);
/* ...but not both */
n->schemaname = $6;
n->authid = NULL;
if ($7 != NIL)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("CREATE SCHEMA IF NOT EXISTS cannot include schema elements"),
parser_errposition(@7)));
n->schemaElts = $7;
n->if_not_exists = true;
$$ = (Node *)n;
}
;
OptSchemaName:
ColId { $$ = $1; }
| /* EMPTY */ { $$ = NULL; }
;
OptSchemaEltList:
OptSchemaEltList schema_stmt
{
if (@$ < 0) /* see comments for YYLLOC_DEFAULT */
@$ = @2;
$$ = lappend($1, $2);
}
| /* EMPTY */
{ $$ = NIL; }
;
/*
* schema_stmt are the ones that can show up inside a CREATE SCHEMA
* statement (in addition to by themselves).
*/
schema_stmt:
CreateStmt
| IndexStmt
| CreateSeqStmt
| CreateTrigStmt
| GrantStmt
| ViewStmt
;
/*****************************************************************************
*
* 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
{
VariableSetStmt *n = $2;
n->is_local = false;
$$ = (Node *) n;
}
| SET LOCAL set_rest
{
VariableSetStmt *n = $3;
n->is_local = true;
$$ = (Node *) n;
}
| SET SESSION set_rest
{
VariableSetStmt *n = $3;
n->is_local = false;
$$ = (Node *) n;
}
;
set_rest:
TRANSACTION transaction_mode_list
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_SET_MULTI;
n->name = "TRANSACTION";
n->args = $2;
$$ = n;
}
| SESSION CHARACTERISTICS AS TRANSACTION transaction_mode_list
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_SET_MULTI;
n->name = "SESSION CHARACTERISTICS";
n->args = $5;
$$ = n;
}
| set_rest_more
;
generic_set:
var_name TO var_list
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_SET_VALUE;
n->name = $1;
n->args = $3;
$$ = n;
}
| var_name '=' var_list
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_SET_VALUE;
n->name = $1;
n->args = $3;
$$ = n;
}
| var_name TO DEFAULT
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_SET_DEFAULT;
n->name = $1;
$$ = n;
}
| var_name '=' DEFAULT
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_SET_DEFAULT;
n->name = $1;
$$ = n;
}
set_rest_more: /* Generic SET syntaxes: */
generic_set {$$ = $1;}
| var_name FROM CURRENT_P
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_SET_CURRENT;
n->name = $1;
$$ = n;
}
/* Special syntaxes mandated by SQL standard: */
| TIME ZONE zone_value
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_SET_VALUE;
n->name = "timezone";
if ($3 != NULL)
n->args = list_make1($3);
else
n->kind = VAR_SET_DEFAULT;
$$ = n;
}
| CATALOG_P Sconst
{
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("current database cannot be changed"),
parser_errposition(@2)));
$$ = NULL; /*not reached*/
}
| SCHEMA Sconst
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_SET_VALUE;
n->name = "search_path";
n->args = list_make1(makeStringConst($2, @2));
$$ = n;
}
| NAMES opt_encoding
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_SET_VALUE;
n->name = "client_encoding";
if ($2 != NULL)
n->args = list_make1(makeStringConst($2, @2));
else
n->kind = VAR_SET_DEFAULT;
$$ = n;
}
| ROLE NonReservedWord_or_Sconst
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_SET_VALUE;
n->name = "role";
n->args = list_make1(makeStringConst($2, @2));
$$ = n;
}
| SESSION AUTHORIZATION NonReservedWord_or_Sconst
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_SET_VALUE;
n->name = "session_authorization";
n->args = list_make1(makeStringConst($3, @3));
$$ = n;
}
| SESSION AUTHORIZATION DEFAULT
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_SET_DEFAULT;
n->name = "session_authorization";
$$ = n;
}
| XML_P OPTION document_or_content
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_SET_VALUE;
n->name = "xmloption";
n->args = list_make1(makeStringConst($3 == XMLOPTION_DOCUMENT ? "DOCUMENT" : "CONTENT", @3));
$$ = n;
}
/* Special syntaxes invented by PostgreSQL: */
| TRANSACTION SNAPSHOT Sconst
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_SET_MULTI;
n->name = "TRANSACTION SNAPSHOT";
n->args = list_make1(makeStringConst($3, @3));
$$ = n;
}
;
var_name: ColId { $$ = $1; }
| var_name '.' ColId
{ $$ = psprintf("%s.%s", $1, $3); }
;
var_list: var_value { $$ = list_make1($1); }
| var_list ',' var_value { $$ = lappend($1, $3); }
;
var_value: opt_boolean_or_string
{ $$ = makeStringConst($1, @1); }
| NumericOnly
{ $$ = makeAConst($1, @1); }
;
iso_level: READ UNCOMMITTED { $$ = "read uncommitted"; }
| READ COMMITTED { $$ = "read committed"; }
| REPEATABLE READ { $$ = "repeatable read"; }
| SERIALIZABLE { $$ = "serializable"; }
;
opt_boolean_or_string:
TRUE_P { $$ = "true"; }
| FALSE_P { $$ = "false"; }
| ON { $$ = "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; }
;
/* Timezone values can be:
* - a string such as 'pst8pdt'
* - an identifier such as "pst8pdt"
* - an integer or floating point number
* - a time interval per SQL99
* ColId gives reduce/reduce errors against ConstInterval and LOCAL,
* so use IDENT (meaning we reject anything that is a key word).
*/
zone_value:
Sconst
{
$$ = makeStringConst($1, @1);
}
| IDENT
{
$$ = makeStringConst($1, @1);
}
| ConstInterval Sconst opt_interval
{
TypeName *t = $1;
if ($3 != NIL)
{
A_Const *n = (A_Const *) linitial($3);
if ((n->val.val.ival & ~(INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE))) != 0)
ereport(ERROR,
(errcode(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
{
TypeName *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; }
;
opt_encoding:
Sconst { $$ = $1; }
| DEFAULT { $$ = NULL; }
| /*EMPTY*/ { $$ = NULL; }
;
NonReservedWord_or_Sconst:
NonReservedWord { $$ = $1; }
| Sconst { $$ = $1; }
;
VariableResetStmt:
RESET reset_rest { $$ = (Node *) $2; }
;
reset_rest:
generic_reset { $$ = $1; }
| TIME ZONE
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_RESET;
n->name = "timezone";
$$ = n;
}
| TRANSACTION ISOLATION LEVEL
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_RESET;
n->name = "transaction_isolation";
$$ = n;
}
| SESSION AUTHORIZATION
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_RESET;
n->name = "session_authorization";
$$ = n;
}
;
generic_reset:
var_name
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_RESET;
n->name = $1;
$$ = n;
}
| ALL
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_RESET_ALL;
$$ = n;
}
;
/* SetResetClause allows SET or RESET without LOCAL */
SetResetClause:
SET set_rest { $$ = $2; }
| VariableResetStmt { $$ = (VariableSetStmt *) $1; }
;
/* SetResetClause allows SET or RESET without LOCAL */
FunctionSetResetClause:
SET set_rest_more { $$ = $2; }
| VariableResetStmt { $$ = (VariableSetStmt *) $1; }
;
VariableShowStmt:
SHOW var_name
{
VariableShowStmt *n = makeNode(VariableShowStmt);
n->name = $2;
$$ = (Node *) n;
}
| SHOW TIME ZONE
{
VariableShowStmt *n = makeNode(VariableShowStmt);
n->name = "timezone";
$$ = (Node *) n;
}
| SHOW TRANSACTION ISOLATION LEVEL
{
VariableShowStmt *n = makeNode(VariableShowStmt);
n->name = "transaction_isolation";
$$ = (Node *) n;
}
| SHOW SESSION AUTHORIZATION
{
VariableShowStmt *n = makeNode(VariableShowStmt);
n->name = "session_authorization";
$$ = (Node *) n;
}
| SHOW ALL
{
VariableShowStmt *n = makeNode(VariableShowStmt);
n->name = "all";
$$ = (Node *) n;
}
;
ConstraintsSetStmt:
SET CONSTRAINTS constraints_set_list constraints_set_mode
{
ConstraintsSetStmt *n = makeNode(ConstraintsSetStmt);
n->constraints = $3;
n->deferred = $4;
$$ = (Node *) n;
}
;
constraints_set_list:
ALL { $$ = NIL; }
| qualified_name_list { $$ = $1; }
;
constraints_set_mode:
DEFERRED { $$ = TRUE; }
| IMMEDIATE { $$ = FALSE; }
;
/*
* Checkpoint statement
*/
CheckPointStmt:
CHECKPOINT
{
CheckPointStmt *n = makeNode(CheckPointStmt);
$$ = (Node *)n;
}
;
/*****************************************************************************
*
* DISCARD { ALL | TEMP | PLANS | SEQUENCES }
*
*****************************************************************************/
DiscardStmt:
DISCARD ALL
{
DiscardStmt *n = makeNode(DiscardStmt);
n->target = DISCARD_ALL;
$$ = (Node *) n;
}
| DISCARD TEMP
{
DiscardStmt *n = makeNode(DiscardStmt);
n->target = DISCARD_TEMP;
$$ = (Node *) n;
}
| DISCARD TEMPORARY
{
DiscardStmt *n = makeNode(DiscardStmt);
n->target = DISCARD_TEMP;
$$ = (Node *) n;
}
| DISCARD PLANS
{
DiscardStmt *n = makeNode(DiscardStmt);
n->target = DISCARD_PLANS;
$$ = (Node *) n;
}
| DISCARD SEQUENCES
{
DiscardStmt *n = makeNode(DiscardStmt);
n->target = DISCARD_SEQUENCES;
$$ = (Node *) n;
}
;
/*****************************************************************************
*
* 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
{
AlterTableStmt *n = makeNode(AlterTableStmt);
n->relation = $3;
n->cmds = $4;
n->relkind = OBJECT_TABLE;
n->missing_ok = false;
$$ = (Node *)n;
}
| ALTER TABLE IF_P EXISTS relation_expr alter_table_cmds
{
AlterTableStmt *n = makeNode(AlterTableStmt);
n->relation = $5;
n->cmds = $6;
n->relkind = OBJECT_TABLE;
n->missing_ok = true;
$$ = (Node *)n;
}
| ALTER TABLE ALL IN_P TABLESPACE name SET TABLESPACE name opt_nowait
{
AlterTableMoveAllStmt *n =
makeNode(AlterTableMoveAllStmt);
n->orig_tablespacename = $6;
n->objtype = OBJECT_TABLE;
n->roles = NIL;
n->new_tablespacename = $9;
n->nowait = $10;
$$ = (Node *)n;
}
| ALTER TABLE ALL IN_P TABLESPACE name OWNED BY role_list SET TABLESPACE name opt_nowait
{
AlterTableMoveAllStmt *n =
makeNode(AlterTableMoveAllStmt);
n->orig_tablespacename = $6;
n->objtype = OBJECT_TABLE;
n->roles = $9;
n->new_tablespacename = $12;
n->nowait = $13;
$$ = (Node *)n;
}
| ALTER INDEX qualified_name alter_table_cmds
{
AlterTableStmt *n = makeNode(AlterTableStmt);
n->relation = $3;
n->cmds = $4;
n->relkind = OBJECT_INDEX;
n->missing_ok = false;
$$ = (Node *)n;
}
| ALTER INDEX IF_P EXISTS qualified_name alter_table_cmds
{
AlterTableStmt *n = makeNode(AlterTableStmt);
n->relation = $5;
n->cmds = $6;
n->relkind = OBJECT_INDEX;
n->missing_ok = true;
$$ = (Node *)n;
}
| ALTER INDEX ALL IN_P TABLESPACE name SET TABLESPACE name opt_nowait
{
AlterTableMoveAllStmt *n =
makeNode(AlterTableMoveAllStmt);
n->orig_tablespacename = $6;
n->objtype = OBJECT_INDEX;
n->roles = NIL;
n->new_tablespacename = $9;
n->nowait = $10;
$$ = (Node *)n;
}
| ALTER INDEX ALL IN_P TABLESPACE name OWNED BY role_list SET TABLESPACE name opt_nowait
{
AlterTableMoveAllStmt *n =
makeNode(AlterTableMoveAllStmt);
n->orig_tablespacename = $6;
n->objtype = OBJECT_INDEX;
n->roles = $9;
n->new_tablespacename = $12;
n->nowait = $13;
$$ = (Node *)n;
}
| ALTER SEQUENCE qualified_name alter_table_cmds
{
AlterTableStmt *n = makeNode(AlterTableStmt);
n->relation = $3;
n->cmds = $4;
n->relkind = OBJECT_SEQUENCE;
n->missing_ok = false;
$$ = (Node *)n;
}
| ALTER SEQUENCE IF_P EXISTS qualified_name alter_table_cmds
{
AlterTableStmt *n = makeNode(AlterTableStmt);
n->relation = $5;
n->cmds = $6;
n->relkind = OBJECT_SEQUENCE;
n->missing_ok = true;
$$ = (Node *)n;
}
| ALTER VIEW qualified_name alter_table_cmds
{
AlterTableStmt *n = makeNode(AlterTableStmt);
n->relation = $3;
n->cmds = $4;
n->relkind = OBJECT_VIEW;
n->missing_ok = false;
$$ = (Node *)n;
}
| ALTER VIEW IF_P EXISTS qualified_name alter_table_cmds
{
AlterTableStmt *n = makeNode(AlterTableStmt);
n->relation = $5;
n->cmds = $6;
n->relkind = OBJECT_VIEW;
n->missing_ok = true;
$$ = (Node *)n;
}
| ALTER MATERIALIZED VIEW qualified_name alter_table_cmds
{
AlterTableStmt *n = makeNode(AlterTableStmt);
n->relation = $4;
n->cmds = $5;
n->relkind = OBJECT_MATVIEW;
n->missing_ok = false;
$$ = (Node *)n;
}
| ALTER MATERIALIZED VIEW IF_P EXISTS qualified_name alter_table_cmds
{
AlterTableStmt *n = makeNode(AlterTableStmt);
n->relation = $6;
n->cmds = $7;
n->relkind = OBJECT_MATVIEW;
n->missing_ok = true;
$$ = (Node *)n;
}
| ALTER MATERIALIZED VIEW ALL IN_P TABLESPACE name SET TABLESPACE name opt_nowait
{
AlterTableMoveAllStmt *n =
makeNode(AlterTableMoveAllStmt);
n->orig_tablespacename = $7;
n->objtype = OBJECT_MATVIEW;
n->roles = NIL;
n->new_tablespacename = $10;
n->nowait = $11;
$$ = (Node *)n;
}
| ALTER MATERIALIZED VIEW ALL IN_P TABLESPACE name OWNED BY role_list SET TABLESPACE name opt_nowait
{
AlterTableMoveAllStmt *n =
makeNode(AlterTableMoveAllStmt);
n->orig_tablespacename = $7;
n->objtype = OBJECT_MATVIEW;
n->roles = $10;
n->new_tablespacename = $13;
n->nowait = $14;
$$ = (Node *)n;
}
;
alter_table_cmds:
alter_table_cmd { $$ = list_make1($1); }
| alter_table_cmds ',' alter_table_cmd { $$ = lappend($1, $3); }
;
alter_table_cmd:
/* 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 = $3;
$$ = (Node *)n;
}
/* ALTER TABLE <name> ALTER [COLUMN] <colname> {SET DEFAULT <expr>|DROP DEFAULT} */
| ALTER opt_column ColId alter_column_default
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_ColumnDefault;
n->name = $3;
n->def = $4;
$$ = (Node *)n;
}
/* ALTER TABLE <name> ALTER [COLUMN] <colname> DROP NOT NULL */
| ALTER opt_column ColId DROP NOT NULL_P
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_DropNotNull;
n->name = $3;
$$ = (Node *)n;
}
/* ALTER TABLE <name> ALTER [COLUMN] <colname> SET NOT NULL */
| ALTER opt_column ColId SET NOT NULL_P
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_SetNotNull;
n->name = $3;
$$ = (Node *)n;
}
/* ALTER TABLE <name> ALTER [COLUMN] <colname> SET STATISTICS <SignedIconst> */
| ALTER opt_column ColId SET STATISTICS SignedIconst
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_SetStatistics;
n->name = $3;
n->def = (Node *) makeInteger($6);
$$ = (Node *)n;
}
/* 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_ResetOptions;
n->name = $3;
n->def = (Node *) $5;
$$ = (Node *)n;
}
/* ALTER TABLE <name> ALTER [COLUMN] <colname> SET STORAGE <storagemode> */
| ALTER opt_column ColId SET STORAGE ColId
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_SetStorage;
n->name = $3;
n->def = (Node *) makeString($6);
$$ = (Node *)n;
}
/* ALTER TABLE <name> DROP [COLUMN] IF EXISTS <colname> [RESTRICT|CASCADE] */
| DROP opt_column IF_P EXISTS ColId opt_drop_behavior
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_DropColumn;
n->name = $5;
n->behavior = $6;
n->missing_ok = TRUE;
$$ = (Node *)n;
}
/* ALTER TABLE <name> DROP [COLUMN] <colname> [RESTRICT|CASCADE] */
| DROP opt_column ColId opt_drop_behavior
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_DropColumn;
n->name = $3;
n->behavior = $4;
n->missing_ok = FALSE;
$$ = (Node *)n;
}
/*
* ALTER TABLE <name> ALTER [COLUMN] <colname> [SET DATA] TYPE <typename>
* [ USING <expression> ]
*/
| ALTER opt_column ColId opt_set_data TYPE_P Typename opt_collate_clause alter_using
{
AlterTableCmd *n = makeNode(AlterTableCmd);
ColumnDef *def = makeNode(ColumnDef);
n->subtype = AT_AlterColumnType;
n->name = $3;
n->def = (Node *) def;
/* We only use these fields of the ColumnDef node */
def->typeName = $6;
def->collClause = (CollateClause *) $7;
def->raw_default = $8;
def->location = @3;
$$ = (Node *)n;
}
/* ALTER FOREIGN TABLE <name> ALTER [COLUMN] <colname> OPTIONS */
| ALTER opt_column ColId alter_generic_options
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_AlterColumnGenericOptions;
n->name = $3;
n->def = (Node *) $4;
$$ = (Node *)n;
}
/* ALTER TABLE <name> ADD CONSTRAINT ... */
| ADD_P TableConstraint
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_AddConstraint;
n->def = $2;
$$ = (Node *)n;
}
/* ALTER TABLE <name> ALTER CONSTRAINT ... */
| ALTER CONSTRAINT name ConstraintAttributeSpec
{
AlterTableCmd *n = makeNode(AlterTableCmd);
Constraint *c = makeNode(Constraint);
n->subtype = AT_AlterConstraint;
n->def = (Node *) c;
c->contype = CONSTR_FOREIGN; /* others not supported, yet */
c->conname = $3;
processCASbits($4, @4, "ALTER CONSTRAINT statement",
&c->deferrable,
&c->initdeferred,
NULL, NULL, yyscanner);
$$ = (Node *)n;
}
/* ALTER TABLE <name> VALIDATE CONSTRAINT ... */
| VALIDATE CONSTRAINT name
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_ValidateConstraint;
n->name = $3;
$$ = (Node *)n;
}
/* ALTER TABLE <name> DROP CONSTRAINT IF EXISTS <name> [RESTRICT|CASCADE] */
| DROP CONSTRAINT IF_P EXISTS name opt_drop_behavior
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_DropConstraint;
n->name = $5;
n->behavior = $6;
n->missing_ok = TRUE;
$$ = (Node *)n;
}
/* ALTER TABLE <name> DROP CONSTRAINT <name> [RESTRICT|CASCADE] */
| DROP CONSTRAINT name opt_drop_behavior
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_DropConstraint;
n->name = $3;
n->behavior = $4;
n->missing_ok = FALSE;
$$ = (Node *)n;
}
/* ALTER TABLE <name> SET WITH OIDS */
| SET WITH OIDS
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_AddOids;
$$ = (Node *)n;
}
/* ALTER TABLE <name> SET WITHOUT OIDS */
| SET WITHOUT OIDS
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_DropOids;
$$ = (Node *)n;
}
/* ALTER TABLE <name> CLUSTER ON <indexname> */
| CLUSTER ON name
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_ClusterOn;
n->name = $3;
$$ = (Node *)n;
}
/* ALTER TABLE <name> SET WITHOUT CLUSTER */
| SET WITHOUT CLUSTER
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_DropCluster;
n->name = NULL;
$$ = (Node *)n;
}
/* ALTER TABLE <name> SET LOGGED */
| SET LOGGED
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_SetLogged;
$$ = (Node *)n;
}
/* ALTER TABLE <name> SET UNLOGGED */
| SET UNLOGGED
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_SetUnLogged;
$$ = (Node *)n;
}
/* ALTER TABLE <name> ENABLE TRIGGER <trig> */
| ENABLE_P TRIGGER name
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_EnableTrig;
n->name = $3;
$$ = (Node *)n;
}
/* ALTER TABLE <name> ENABLE ALWAYS TRIGGER <trig> */
| ENABLE_P ALWAYS TRIGGER name
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_EnableAlwaysTrig;
n->name = $4;
$$ = (Node *)n;
}
/* ALTER TABLE <name> ENABLE REPLICA TRIGGER <trig> */
| ENABLE_P REPLICA TRIGGER name
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_EnableReplicaTrig;
n->name = $4;
$$ = (Node *)n;
}
/* ALTER TABLE <name> ENABLE TRIGGER ALL */
| ENABLE_P TRIGGER ALL
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_EnableTrigAll;
$$ = (Node *)n;
}
/* ALTER TABLE <name> ENABLE TRIGGER USER */
| ENABLE_P TRIGGER USER
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_EnableTrigUser;
$$ = (Node *)n;
}
/* ALTER TABLE <name> DISABLE TRIGGER <trig> */
| DISABLE_P TRIGGER name
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_DisableTrig;
n->name = $3;
$$ = (Node *)n;
}
/* ALTER TABLE <name> DISABLE TRIGGER ALL */
| DISABLE_P TRIGGER ALL
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_DisableTrigAll;
$$ = (Node *)n;
}
/* ALTER TABLE <name> DISABLE TRIGGER USER */
| DISABLE_P TRIGGER USER
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_DisableTrigUser;
$$ = (Node *)n;
}
/* ALTER TABLE <name> ENABLE RULE <rule> */
| ENABLE_P RULE name
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_EnableRule;
n->name = $3;
$$ = (Node *)n;
}
/* ALTER TABLE <name> ENABLE ALWAYS RULE <rule> */
| ENABLE_P ALWAYS RULE name
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_EnableAlwaysRule;
n->name = $4;
$$ = (Node *)n;
}
/* ALTER TABLE <name> ENABLE REPLICA RULE <rule> */
| ENABLE_P REPLICA RULE name
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_EnableReplicaRule;
n->name = $4;
$$ = (Node *)n;
}
/* ALTER TABLE <name> DISABLE RULE <rule> */
| DISABLE_P RULE name
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_DisableRule;
n->name = $3;
$$ = (Node *)n;
}
/* ALTER TABLE <name> INHERIT <parent> */
| INHERIT qualified_name
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_AddInherit;
n->def = (Node *) $2;
$$ = (Node *)n;
}
/* ALTER TABLE <name> NO INHERIT <parent> */
| NO INHERIT qualified_name
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_DropInherit;
n->def = (Node *) $3;
$$ = (Node *)n;
}
/* ALTER TABLE <name> OF <type_name> */
| OF any_name
{
AlterTableCmd *n = makeNode(AlterTableCmd);
TypeName *def = makeTypeNameFromNameList($2);
def->location = @2;
n->subtype = AT_AddOf;
n->def = (Node *) def;
$$ = (Node *)n;
}
/* ALTER TABLE <name> NOT OF */
| NOT OF
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_DropOf;
$$ = (Node *)n;
}
/* ALTER TABLE <name> OWNER TO RoleId */
| OWNER TO RoleId
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_ChangeOwner;
n->name = $3;
$$ = (Node *)n;
}
/* ALTER TABLE <name> SET TABLESPACE <tablespacename> */
| SET TABLESPACE name
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_SetTableSpace;
n->name = $3;
$$ = (Node *)n;
}
/* ALTER TABLE <name> SET (...) */
| SET reloptions
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_SetRelOptions;
n->def = (Node *)$2;
$$ = (Node *)n;
}
/* ALTER TABLE <name> RESET (...) */
| RESET reloptions
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_ResetRelOptions;
n->def = (Node *)$2;
$$ = (Node *)n;
}
/* ALTER TABLE <name> REPLICA IDENTITY */
| REPLICA IDENTITY_P replica_identity
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_ReplicaIdentity;
n->def = $3;
$$ = (Node *)n;
}
/* ALTER TABLE <name> ENABLE ROW LEVEL SECURITY */
| ENABLE_P ROW LEVEL SECURITY
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_EnableRowSecurity;
$$ = (Node *)n;
}
/* ALTER TABLE <name> DISABLE ROW LEVEL SECURITY */
| DISABLE_P ROW LEVEL SECURITY
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_DisableRowSecurity;
$$ = (Node *)n;
}
| alter_generic_options
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_GenericOptions;
n->def = (Node *)$1;
$$ = (Node *) n;
}
;
alter_column_default:
SET DEFAULT a_expr { $$ = $3; }
| DROP DEFAULT { $$ = NULL; }
;
opt_drop_behavior:
CASCADE { $$ = DROP_CASCADE; }
| RESTRICT { $$ = DROP_RESTRICT; }
| /* EMPTY */ { $$ = DROP_RESTRICT; /* default */ }
;
opt_collate_clause:
COLLATE any_name
{
CollateClause *n = makeNode(CollateClause);
n->arg = NULL;
n->collname = $2;
n->location = @1;
$$ = (Node *) n;
}
| /* EMPTY */ { $$ = NULL; }
;
alter_using:
USING a_expr { $$ = $2; }
| /* EMPTY */ { $$ = NULL; }
;
replica_identity:
NOTHING
{
ReplicaIdentityStmt *n = makeNode(ReplicaIdentityStmt);
n->identity_type = REPLICA_IDENTITY_NOTHING;
n->name = NULL;
$$ = (Node *) n;
}
| FULL
{
ReplicaIdentityStmt *n = makeNode(ReplicaIdentityStmt);
n->identity_type = REPLICA_IDENTITY_FULL;
n->name = NULL;
$$ = (Node *) n;
}
| DEFAULT
{
ReplicaIdentityStmt *n = makeNode(ReplicaIdentityStmt);
n->identity_type = REPLICA_IDENTITY_DEFAULT;
n->name = NULL;
$$ = (Node *) n;
}
| USING INDEX name
{
ReplicaIdentityStmt *n = makeNode(ReplicaIdentityStmt);
n->identity_type = REPLICA_IDENTITY_INDEX;
n->name = $3;
$$ = (Node *) n;
}
;
reloptions:
'(' reloption_list ')' { $$ = $2; }
;
opt_reloptions: WITH reloptions { $$ = $2; }
| /* EMPTY */ { $$ = NIL; }
;
reloption_list:
reloption_elem { $$ = list_make1($1); }
| reloption_list ',' reloption_elem { $$ = lappend($1, $3); }
;
/* This should match def_elem and also allow qualified names */
reloption_elem:
ColLabel '=' def_arg
{
$$ = makeDefElem($1, (Node *) $3);
}
| ColLabel
{
$$ = makeDefElem($1, NULL);
}
| ColLabel '.' ColLabel '=' def_arg
{
$$ = makeDefElemExtended($1, $3, (Node *) $5,
DEFELEM_UNSPEC);
}
| ColLabel '.' ColLabel
{
$$ = makeDefElemExtended($1, $3, NULL, DEFELEM_UNSPEC);
}
;
/*****************************************************************************
*
* 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> [RESTRICT|CASCADE] */
ADD_P ATTRIBUTE TableFuncElement opt_drop_behavior
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_AddColumn;
n->def = $3;
n->behavior = $4;
$$ = (Node *)n;
}
/* ALTER TYPE <name> DROP ATTRIBUTE IF EXISTS <attname> [RESTRICT|CASCADE] */
| DROP ATTRIBUTE IF_P EXISTS ColId opt_drop_behavior
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_DropColumn;
n->name = $5;
n->behavior = $6;
n->missing_ok = TRUE;
$$ = (Node *)n;
}
/* ALTER TYPE <name> DROP ATTRIBUTE <attname> [RESTRICT|CASCADE] */
| DROP ATTRIBUTE ColId opt_drop_behavior
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_DropColumn;
n->name = $3;
n->behavior = $4;
n->missing_ok = FALSE;
$$ = (Node *)n;
}
/* ALTER TYPE <name> ALTER ATTRIBUTE <attname> [SET DATA] TYPE <typename> [RESTRICT|CASCADE] */
| ALTER ATTRIBUTE ColId opt_set_data TYPE_P Typename opt_collate_clause opt_drop_behavior
{
AlterTableCmd *n = makeNode(AlterTableCmd);
ColumnDef *def = makeNode(ColumnDef);
n->subtype = AT_AlterColumnType;
n->name = $3;
n->def = (Node *) def;
n->behavior = $8;
/* We only use these fields of the ColumnDef node */
def->typeName = $6;
def->collClause = (CollateClause *) $7;
def->raw_default = NULL;
def->location = @3;
$$ = (Node *)n;
}
;
/*****************************************************************************
*
* QUERY :
* close <portalname>
*
*****************************************************************************/
ClosePortalStmt:
CLOSE cursor_name
{
ClosePortalStmt *n = makeNode(ClosePortalStmt);
n->portalname = $2;
$$ = (Node *)n;
}
| CLOSE ALL
{
ClosePortalStmt *n = makeNode(ClosePortalStmt);
n->portalname = NULL;
$$ = (Node *)n;
}
;
/*****************************************************************************
*
* QUERY :
* COPY relname [(columnList)] FROM/TO file [WITH] [(options)]
* COPY ( SELECT ... ) TO file [WITH] [(options)]
*
* where 'file' can be one of:
* { PROGRAM 'command' | STDIN | STDOUT | 'filename' }
*
* In the preferred syntax the options are comma-separated
* and use generic identifiers instead of keywords. The pre-9.0
* syntax had a hard-wired, space-separated set of options.
*
* Really old syntax, from versions 7.2 and prior:
* COPY [ BINARY ] table [ WITH OIDS ] FROM/TO file
* [ [ USING ] DELIMITERS 'delimiter' ] ]
* [ WITH NULL AS 'null string' ]
* This option placement is not supported with COPY (SELECT...).
*
*****************************************************************************/
CopyStmt: COPY opt_binary qualified_name opt_column_list opt_oids
copy_from opt_program copy_file_name copy_delimiter opt_with copy_options
{
CopyStmt *n = makeNode(CopyStmt);
n->relation = $3;
n->query = NULL;
n->attlist = $4;
n->is_from = $6;
n->is_program = $7;
n->filename = $8;
if (n->is_program && n->filename == NULL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("STDIN/STDOUT not allowed with PROGRAM"),
parser_errposition(@8)));
n->options = NIL;
/* Concatenate user-supplied flags */
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);
$$ = (Node *)n;
}
| COPY select_with_parens TO opt_program copy_file_name opt_with copy_options
{
CopyStmt *n = makeNode(CopyStmt);
n->relation = NULL;
n->query = $2;
n->attlist = NIL;
n->is_from = false;
n->is_program = $4;
n->filename = $5;
n->options = $7;
if (n->is_program && n->filename == NULL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("STDIN/STDOUT not allowed with PROGRAM"),
parser_errposition(@5)));
$$ = (Node *)n;
}
;
copy_from:
FROM { $$ = TRUE; }
| TO { $$ = FALSE; }
;
opt_program:
PROGRAM { $$ = TRUE; }
| /* EMPTY */ { $$ = FALSE; }
;
/*
* copy_file_name NULL indicates stdio is used. Whether stdin or stdout is
* used depends on the direction. (It really doesn't make sense to copy from
* stdout. We silently correct the "typo".) - AY 9/94
*/
copy_file_name:
Sconst { $$ = $1; }
| STDIN { $$ = NULL; }
| STDOUT { $$ = NULL; }
;
copy_options: copy_opt_list { $$ = $1; }
| '(' copy_generic_opt_list ')' { $$ = $2; }
;
/* old COPY option syntax */
copy_opt_list:
copy_opt_list copy_opt_item { $$ = lappend($1, $2); }
| /* EMPTY */ { $$ = NIL; }
;
copy_opt_item:
BINARY
{
$$ = makeDefElem("format", (Node *)makeString("binary"));
}
| OIDS
{
$$ = makeDefElem("oids", (Node *)makeInteger(TRUE));
}
| FREEZE
{
$$ = makeDefElem("freeze", (Node *)makeInteger(TRUE));
}
| DELIMITER opt_as Sconst
{
$$ = makeDefElem("delimiter", (Node *)makeString($3));
}
| NULL_P opt_as Sconst
{
$$ = makeDefElem("null", (Node *)makeString($3));
}
| CSV
{
$$ = makeDefElem("format", (Node *)makeString("csv"));
}
| HEADER_P
{
$$ = makeDefElem("header", (Node *)makeInteger(TRUE));
}
| QUOTE opt_as Sconst
{
$$ = makeDefElem("quote", (Node *)makeString($3));
}
| ESCAPE opt_as Sconst
{
$$ = makeDefElem("escape", (Node *)makeString($3));
}
| FORCE QUOTE columnList
{
$$ = makeDefElem("force_quote", (Node *)$3);
}
| FORCE QUOTE '*'
{
$$ = makeDefElem("force_quote", (Node *)makeNode(A_Star));
}
| FORCE NOT NULL_P columnList
{
$$ = makeDefElem("force_not_null", (Node *)$4);
}
| FORCE NULL_P columnList
{
$$ = makeDefElem("force_null", (Node *)$3);
}
| ENCODING Sconst
{
$$ = makeDefElem("encoding", (Node *)makeString($2));
}
;
/* The following exist for backward compatibility with very old versions */
opt_binary:
BINARY
{
$$ = makeDefElem("format", (Node *)makeString("binary"));
}
| /*EMPTY*/ { $$ = NULL; }
;
opt_oids:
WITH OIDS
{
$$ = makeDefElem("oids", (Node *)makeInteger(TRUE));
}
| /*EMPTY*/ { $$ = NULL; }
;
copy_delimiter:
opt_using DELIMITERS Sconst
{
$$ = makeDefElem("delimiter", (Node *)makeString($3));
}
| /*EMPTY*/ { $$ = NULL; }
;
opt_using:
USING {}
| /*EMPTY*/ {}
;
/* new COPY option syntax */
copy_generic_opt_list:
copy_generic_opt_elem
{
$$ = list_make1($1);
}
| copy_generic_opt_list ',' copy_generic_opt_elem
{
$$ = lappend($1, $3);
}
;
copy_generic_opt_elem:
ColLabel copy_generic_opt_arg
{
$$ = makeDefElem($1, $2);
}
;
copy_generic_opt_arg:
opt_boolean_or_string { $$ = (Node *) makeString($1); }
| NumericOnly { $$ = (Node *) $1; }
| '*' { $$ = (Node *) makeNode(A_Star); }
| '(' copy_generic_opt_arg_list ')' { $$ = (Node *) $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);
}
;
/* beware of emitting non-string list elements here; see commands/define.c */
copy_generic_opt_arg_list_item:
opt_boolean_or_string { $$ = (Node *) makeString($1); }
;
/*****************************************************************************
*
* QUERY :
* CREATE TABLE relname
*
*****************************************************************************/
CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
OptInherit OptWith OnCommitOption OptTableSpace
{
CreateStmt *n = makeNode(CreateStmt);
$4->relpersistence = $2;
n->relation = $4;
n->tableElts = $6;
n->inhRelations = $8;
n->constraints = NIL;
n->options = $9;
n->oncommit = $10;
n->tablespacename = $11;
n->if_not_exists = false;
$$ = (Node *)n;
}
| CREATE OptTemp TABLE IF_P NOT EXISTS qualified_name '('
OptTableElementList ')' OptInherit OptWith OnCommitOption
OptTableSpace
{
CreateStmt *n = makeNode(CreateStmt);
$7->relpersistence = $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
{
CreateStmt *n = makeNode(CreateStmt);
$4->relpersistence = $2;
n->relation = $4;
n->tableElts = $7;
n->ofTypename = makeTypeNameFromNameList($6);
n->ofTypename->location = @6;
n->constraints = NIL;
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->relpersistence = $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;
}
;
/*
* Redundancy here is needed to avoid shift/reduce conflicts,
* since TEMP is not a reserved word. See also OptTempTableName.
*
* NOTE: we accept both GLOBAL and LOCAL options. They currently do nothing,
* but future versions might consider GLOBAL to request SQL-spec-compliant
* temp table behavior, so warn about that. Since we have no modules the
* LOCAL keyword is really meaningless; furthermore, some other products
* implement LOCAL as meaning the same as our default temp table behavior,
* so we'll probably continue to treat LOCAL as a noise word.
*/
OptTemp: TEMPORARY { $$ = RELPERSISTENCE_TEMP; }
| TEMP { $$ = RELPERSISTENCE_TEMP; }
| LOCAL TEMPORARY { $$ = RELPERSISTENCE_TEMP; }
| LOCAL TEMP { $$ = RELPERSISTENCE_TEMP; }
| GLOBAL TEMPORARY
{
ereport(WARNING,
(errmsg("GLOBAL is deprecated in temporary table creation"),
parser_errposition(@1)));
$$ = RELPERSISTENCE_TEMP;
}
| GLOBAL TEMP
{
ereport(WARNING,
(errmsg("GLOBAL is deprecated in temporary table creation"),
parser_errposition(@1)));
$$ = RELPERSISTENCE_TEMP;
}
| UNLOGGED { $$ = RELPERSISTENCE_UNLOGGED; }
| /*EMPTY*/ { $$ = RELPERSISTENCE_PERMANENT; }
;
OptTableElementList:
TableElementList { $$ = $1; }
| /*EMPTY*/ { $$ = NIL; }
;
OptTypedTableElementList:
'(' TypedTableElementList ')' { $$ = $2; }
| /*EMPTY*/ { $$ = NIL; }
;
TableElementList:
TableElement
{
$$ = list_make1($1);
}
| TableElementList ',' TableElement
{
$$ = lappend($1, $3);
}
;
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 create_generic_options ColQualList
{
ColumnDef *n = makeNode(ColumnDef);
n->colname = $1;
n->typeName = $2;
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;
n->fdwoptions = $3;
SplitColQualList($4, &n->constraints, &n->collClause,
yyscanner);
n->location = @1;
$$ = (Node *)n;
}
;
columnOptions: ColId WITH OPTIONS ColQualList
{
ColumnDef *n = makeNode(ColumnDef);
n->colname = $1;
n->typeName = NULL;
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($4, &n->constraints, &n->collClause,
yyscanner);
n->location = @1;
$$ = (Node *)n;
}
;
ColQualList:
ColQualList ColConstraint { $$ = lappend($1, $2); }
| /*EMPTY*/ { $$ = NIL; }
;
ColConstraint:
CONSTRAINT name ColConstraintElem
{
Constraint *n = (Constraint *) $3;
Assert(IsA(n, Constraint));
n->conname = $2;
n->location = @1;
$$ = (Node *) n;
}
| ColConstraintElem { $$ = $1; }
| ConstraintAttr { $$ = $1; }
| COLLATE any_name
{
/*
* Note: the CollateClause is momentarily included in
* the list built by ColQualList, but we split it out
* again in SplitColQualList.
*/
CollateClause *n = makeNode(CollateClause);
n->arg = NULL;
n->collname = $2;
n->location = @1;
$$ = (Node *) n;
}
;
/* DEFAULT NULL is already the default for Postgres.
* But define it here and carry it forward into the system
* to make it explicit.
* - thomas 1998-09-13
*
* WITH NULL and NULL are not SQL-standard syntax elements,
* so leave them out. Use DEFAULT NULL to explicitly indicate
* that a column may have that value. WITH NULL leads to
* shift/reduce conflicts with WITH TIME ZONE anyway.
* - thomas 1999-01-08
*
* DEFAULT expression must be b_expr not a_expr to prevent shift/reduce
* conflict on NOT (since NOT might start a subsequent NOT NULL constraint,
* or be part of a_expr NOT LIKE or similar constructs).
*/
ColConstraintElem:
NOT NULL_P
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_NOTNULL;
n->location = @1;
$$ = (Node *)n;
}
| NULL_P
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_NULL;
n->location = @1;
$$ = (Node *)n;
}
| UNIQUE opt_definition OptConsTableSpace
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_UNIQUE;
n->location = @1;
n->keys = NULL;
n->options = $2;
n->indexname = NULL;
n->indexspace = $3;
$$ = (Node *)n;
}
| PRIMARY KEY opt_definition OptConsTableSpace
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_PRIMARY;
n->location = @1;
n->keys = NULL;
n->options = $3;
n->indexname = NULL;
n->indexspace = $4;
$$ = (Node *)n;
}
| CHECK '(' a_expr ')' opt_no_inherit
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_CHECK;
n->location = @1;
n->is_no_inherit = $5;
n->raw_expr = $3;
n->cooked_expr = NULL;
$$ = (Node *)n;
}
| DEFAULT b_expr
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_DEFAULT;
n->location = @1;
n->raw_expr = $2;
n->cooked_expr = NULL;
$$ = (Node *)n;
}
| REFERENCES qualified_name opt_column_list key_match key_actions
{
Constraint *n = makeNode(Constraint);
n->contype = 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;
$$ = (Node *)n;
}
;
/*
* ConstraintAttr represents constraint attributes, which we parse as if
* they were independent constraint clauses, in order to avoid shift/reduce
* conflicts (since NOT might start either an independent NOT NULL clause
* or an attribute). parse_utilcmd.c is responsible for attaching the
* attribute information to the preceding "real" constraint node, and for
* complaining if attribute clauses appear in the wrong place or wrong
* combinations.
*
* See also ConstraintAttributeSpec, which can be used in places where
* there is no parsing conflict. (Note: currently, NOT VALID and NO INHERIT
* are allowed clauses in ConstraintAttributeSpec, but not here. Someday we
* might need to allow them here too, but for the moment it doesn't seem
* useful in the statements that use ConstraintAttr.)
*/
ConstraintAttr:
DEFERRABLE
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_ATTR_DEFERRABLE;
n->location = @1;
$$ = (Node *)n;
}
| NOT DEFERRABLE
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_ATTR_NOT_DEFERRABLE;
n->location = @1;
$$ = (Node *)n;
}
| INITIALLY DEFERRED
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_ATTR_DEFERRED;
n->location = @1;
$$ = (Node *)n;
}
| INITIALLY IMMEDIATE
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_ATTR_IMMEDIATE;
n->location = @1;
$$ = (Node *)n;
}
;
TableLikeClause:
LIKE qualified_name TableLikeOptionList
{
TableLikeClause *n = makeNode(TableLikeClause);
n->relation = $2;
n->options = $3;
$$ = (Node *)n;
}
;
TableLikeOptionList:
TableLikeOptionList INCLUDING TableLikeOption { $$ = $1 | $3; }
| TableLikeOptionList EXCLUDING TableLikeOption { $$ = $1 & ~$3; }
| /* EMPTY */ { $$ = 0; }
;
TableLikeOption:
DEFAULTS { $$ = CREATE_TABLE_LIKE_DEFAULTS; }
| CONSTRAINTS { $$ = CREATE_TABLE_LIKE_CONSTRAINTS; }
| INDEXES { $$ = CREATE_TABLE_LIKE_INDEXES; }
| STORAGE { $$ = CREATE_TABLE_LIKE_STORAGE; }
| COMMENTS { $$ = CREATE_TABLE_LIKE_COMMENTS; }
| ALL { $$ = CREATE_TABLE_LIKE_ALL; }
;
/* ConstraintElem specifies constraint syntax which is not embedded into
* a column definition. ColConstraintElem specifies the embedded form.
* - thomas 1997-12-03
*/
TableConstraint:
CONSTRAINT name ConstraintElem
{
Constraint *n = (Constraint *) $3;
Assert(IsA(n, Constraint));
n->conname = $2;
n->location = @1;
$$ = (Node *) n;
}
| ConstraintElem { $$ = $1; }
;
ConstraintElem:
CHECK '(' a_expr ')' ConstraintAttributeSpec
{
Constraint *n = makeNode(Constraint);
n->contype = 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;
$$ = (Node *)n;
}
| UNIQUE '(' columnList ')' opt_definition OptConsTableSpace
ConstraintAttributeSpec
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_UNIQUE;
n->location = @1;
n->keys = $3;
n->options = $5;
n->indexname = NULL;
n->indexspace = $6;
processCASbits($7, @7, "UNIQUE",
&n->deferrable, &n->initdeferred, NULL,
NULL, yyscanner);
$$ = (Node *)n;
}
| UNIQUE ExistingIndex ConstraintAttributeSpec
{
Constraint *n = makeNode(Constraint);
n->contype = 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);
$$ = (Node *)n;
}
| PRIMARY KEY '(' columnList ')' opt_definition OptConsTableSpace
ConstraintAttributeSpec
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_PRIMARY;
n->location = @1;
n->keys = $4;
n->options = $6;
n->indexname = NULL;
n->indexspace = $7;
processCASbits($8, @8, "PRIMARY KEY",
&n->deferrable, &n->initdeferred, NULL,
NULL, yyscanner);
$$ = (Node *)n;
}
| PRIMARY KEY ExistingIndex ConstraintAttributeSpec
{
Constraint *n = makeNode(Constraint);
n->contype = 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);
$$ = (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->indexname = NULL;
n->indexspace = $7;
n->where_clause = $8;
processCASbits($9, @9, "EXCLUDE",
&n->deferrable, &n->initdeferred, NULL,
NULL, yyscanner);
$$ = (Node *)n;
}
| FOREIGN KEY '(' columnList ')' REFERENCES qualified_name
opt_column_list key_match key_actions ConstraintAttributeSpec
{
Constraint *n = makeNode(Constraint);
n->contype = 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;
$$ = (Node *)n;
}
;
opt_no_inherit: NO INHERIT { $$ = TRUE; }
| /* EMPTY */ { $$ = FALSE; }
;
opt_column_list:
'(' columnList ')' { $$ = $2; }
| /*EMPTY*/ { $$ = NIL; }
;
columnList:
columnElem { $$ = list_make1($1); }
| columnList ',' columnElem { $$ = lappend($1, $3); }
;
columnElem: ColId
{
$$ = (Node *) makeString($1);
}
;
key_match: MATCH FULL
{
$$ = FKCONSTR_MATCH_FULL;
}
| MATCH PARTIAL
{
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("MATCH PARTIAL not yet implemented"),
parser_errposition(@1)));
$$ = FKCONSTR_MATCH_PARTIAL;
}
| MATCH SIMPLE
{
$$ = FKCONSTR_MATCH_SIMPLE;
}
| /*EMPTY*/
{
$$ = FKCONSTR_MATCH_SIMPLE;
}
;
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
* calling production. update is in the left 8 bits, delete in the right.
* Note that NOACTION is the default.
*/
key_actions:
key_update
{ $$ = ($1 << 8) | (FKCONSTR_ACTION_NOACTION & 0xFF); }
| key_delete
{ $$ = (FKCONSTR_ACTION_NOACTION << 8) | ($1 & 0xFF); }
| key_update key_delete
{ $$ = ($1 << 8) | ($2 & 0xFF); }
| key_delete key_update
{ $$ = ($2 << 8) | ($1 & 0xFF); }
| /*EMPTY*/
{ $$ = (FKCONSTR_ACTION_NOACTION << 8) | (FKCONSTR_ACTION_NOACTION & 0xFF); }
;
key_update: ON UPDATE key_action { $$ = $3; }
;
key_delete: ON DELETE_P key_action { $$ = $3; }
;
key_action:
NO ACTION { $$ = FKCONSTR_ACTION_NOACTION; }
| RESTRICT { $$ = FKCONSTR_ACTION_RESTRICT; }
| CASCADE { $$ = FKCONSTR_ACTION_CASCADE; }
| SET NULL_P { $$ = FKCONSTR_ACTION_SETNULL; }
| SET DEFAULT { $$ = FKCONSTR_ACTION_SETDEFAULT; }
;
OptInherit: INHERITS '(' qualified_name_list ')' { $$ = $3; }
| /*EMPTY*/ { $$ = NIL; }
;
/* WITH (options) is preferred, WITH OIDS and WITHOUT OIDS are legacy forms */
OptWith:
WITH reloptions { $$ = $2; }
| WITH OIDS { $$ = list_make1(defWithOids(true)); }
| WITHOUT OIDS { $$ = list_make1(defWithOids(false)); }
| /*EMPTY*/ { $$ = NIL; }
;
OnCommitOption: ON COMMIT DROP { $$ = ONCOMMIT_DROP; }
| ON COMMIT DELETE_P ROWS { $$ = ONCOMMIT_DELETE_ROWS; }
| ON COMMIT PRESERVE ROWS { $$ = ONCOMMIT_PRESERVE_ROWS; }
| /*EMPTY*/ { $$ = ONCOMMIT_NOOP; }
;
OptTableSpace: TABLESPACE name { $$ = $2; }
| /*EMPTY*/ { $$ = NULL; }
;
OptConsTableSpace: USING INDEX TABLESPACE name { $$ = $4; }
| /*EMPTY*/ { $$ = NULL; }
;
ExistingIndex: USING INDEX index_name { $$ = $3; }
;
/*****************************************************************************
*
* QUERY :
* CREATE TABLE relname AS SelectStmt [ WITH [NO] DATA ]
*
*
* Note: SELECT ... INTO is a now-deprecated alternative for this.
*
*****************************************************************************/
CreateAsStmt:
CREATE OptTemp TABLE create_as_target AS SelectStmt opt_with_data
{
CreateTableAsStmt *ctas = makeNode(CreateTableAsStmt);
ctas->query = $6;
ctas->into = $4;
ctas->relkind = OBJECT_TABLE;
ctas->is_select_into = false;
ctas->if_not_exists = false;
/* cram additional flags into the IntoClause */
$4->rel->relpersistence = $2;
$4->skipData = !($7);
$$ = (Node *) ctas;
}
| CREATE OptTemp TABLE IF_P NOT EXISTS create_as_target AS SelectStmt opt_with_data
{
CreateTableAsStmt *ctas = makeNode(CreateTableAsStmt);
ctas->query = $9;
ctas->into = $7;
ctas->relkind = OBJECT_TABLE;
ctas->is_select_into = false;
ctas->if_not_exists = true;
/* cram additional flags into the IntoClause */
$7->rel->relpersistence = $2;
$7->skipData = !($10);
$$ = (Node *) ctas;
}
;
create_as_target:
qualified_name opt_column_list OptWith OnCommitOption OptTableSpace
{
$$ = makeNode(IntoClause);
$$->rel = $1;
$$->colNames = $2;
$$->options = $3;
$$->onCommit = $4;
$$->tableSpaceName = $5;
$$->viewQuery = NULL;
$$->skipData = false; /* might get changed later */
}
;
opt_with_data:
WITH DATA_P { $$ = TRUE; }
| WITH NO DATA_P { $$ = FALSE; }
| /*EMPTY*/ { $$ = TRUE; }
;
/*****************************************************************************
*
* QUERY :
* CREATE MATERIALIZED VIEW relname AS SelectStmt
*
*****************************************************************************/
CreateMatViewStmt:
CREATE OptNoLog MATERIALIZED VIEW create_mv_target AS SelectStmt opt_with_data
{
CreateTableAsStmt *ctas = makeNode(CreateTableAsStmt);
ctas->query = $7;
ctas->into = $5;
ctas->relkind = OBJECT_MATVIEW;
ctas->is_select_into = false;
ctas->if_not_exists = false;
/* cram additional flags into the IntoClause */
$5->rel->relpersistence = $2;
$5->skipData = !($8);
$$ = (Node *) ctas;
}
| CREATE OptNoLog MATERIALIZED VIEW IF_P NOT EXISTS create_mv_target AS SelectStmt opt_with_data
{
CreateTableAsStmt *ctas = makeNode(CreateTableAsStmt);
ctas->query = $10;
ctas->into = $8;
ctas->relkind = OBJECT_MATVIEW;
ctas->is_select_into = false;
ctas->if_not_exists = true;
/* cram additional flags into the IntoClause */
$8->rel->relpersistence = $2;
$8->skipData = !($11);
$$ = (Node *) ctas;
}
;
create_mv_target:
qualified_name opt_column_list opt_reloptions OptTableSpace
{
$$ = makeNode(IntoClause);
$$->rel = $1;
$$->colNames = $2;
$$->options = $3;
$$->onCommit = ONCOMMIT_NOOP;
$$->tableSpaceName = $4;
$$->viewQuery = NULL; /* filled at analysis time */
$$->skipData = false; /* might get changed later */
}
;
OptNoLog: UNLOGGED { $$ = RELPERSISTENCE_UNLOGGED; }
| /*EMPTY*/ { $$ = RELPERSISTENCE_PERMANENT; }
;
/*****************************************************************************
*
* QUERY :
* REFRESH MATERIALIZED VIEW qualified_name
*
*****************************************************************************/
RefreshMatViewStmt:
REFRESH MATERIALIZED VIEW opt_concurrently qualified_name opt_with_data
{
RefreshMatViewStmt *n = makeNode(RefreshMatViewStmt);
n->concurrent = $4;
n->relation = $5;
n->skipData = !($6);
$$ = (Node *) n;
}
;
/*****************************************************************************
*
* QUERY :
* CREATE SEQUENCE seqname
* ALTER SEQUENCE seqname
*
*****************************************************************************/
CreateSeqStmt:
CREATE OptTemp SEQUENCE qualified_name OptSeqOptList
{
CreateSeqStmt *n = makeNode(CreateSeqStmt);
$4->relpersistence = $2;
n->sequence = $4;
n->options = $5;
n->ownerId = InvalidOid;
n->if_not_exists = false;
$$ = (Node *)n;
}
| CREATE OptTemp SEQUENCE IF_P NOT EXISTS qualified_name OptSeqOptList
{
CreateSeqStmt *n = makeNode(CreateSeqStmt);
$7->relpersistence = $2;
n->sequence = $7;
n->options = $8;
n->ownerId = InvalidOid;
n->if_not_exists = true;
$$ = (Node *)n;
}
;
AlterSeqStmt:
ALTER SEQUENCE qualified_name SeqOptList
{
AlterSeqStmt *n = makeNode(AlterSeqStmt);
n->sequence = $3;
n->options = $4;
n->missing_ok = false;
$$ = (Node *)n;
}
| ALTER SEQUENCE IF_P EXISTS qualified_name SeqOptList
{
AlterSeqStmt *n = makeNode(AlterSeqStmt);
n->sequence = $5;
n->options = $6;
n->missing_ok = true;
$$ = (Node *)n;
}
;
OptSeqOptList: SeqOptList { $$ = $1; }
| /*EMPTY*/ { $$ = NIL; }
;
SeqOptList: SeqOptElem { $$ = list_make1($1); }
| SeqOptList SeqOptElem { $$ = lappend($1, $2); }
;
SeqOptElem: CACHE NumericOnly
{
$$ = makeDefElem("cache", (Node *)$2);
}
| CYCLE
{
$$ = makeDefElem("cycle", (Node *)makeInteger(TRUE));
}
| NO CYCLE
{
$$ = makeDefElem("cycle", (Node *)makeInteger(FALSE));
}
| INCREMENT opt_by NumericOnly
{
$$ = makeDefElem("increment", (Node *)$3);
}
| MAXVALUE NumericOnly
{
$$ = makeDefElem("maxvalue", (Node *)$2);
}
| MINVALUE NumericOnly
{
$$ = makeDefElem("minvalue", (Node *)$2);
}
| NO MAXVALUE
{
$$ = makeDefElem("maxvalue", NULL);
}
| NO MINVALUE
{
$$ = makeDefElem("minvalue", NULL);
}
| OWNED BY any_name
{
$$ = makeDefElem("owned_by", (Node *)$3);
}
| START opt_with NumericOnly
{
$$ = makeDefElem("start", (Node *)$3);
}
| RESTART
{
$$ = makeDefElem("restart", NULL);
}
| RESTART opt_with NumericOnly
{
$$ = makeDefElem("restart", (Node *)$3);
}
;
opt_by: BY {}
| /* empty */ {}
;
NumericOnly:
FCONST { $$ = makeFloat($1); }
| '-' FCONST
{
$$ = makeFloat($2);
doNegateFloat($$);
}
| SignedIconst { $$ = makeInteger($1); }
;
NumericOnly_list: NumericOnly { $$ = list_make1($1); }
| NumericOnly_list ',' NumericOnly { $$ = lappend($1, $3); }
;
/*****************************************************************************
*
* QUERIES :
* CREATE [OR REPLACE] [TRUSTED] [PROCEDURAL] LANGUAGE ...
* DROP [PROCEDURAL] LANGUAGE ...
*
*****************************************************************************/
CreatePLangStmt:
CREATE opt_or_replace opt_trusted opt_procedural LANGUAGE NonReservedWord_or_Sconst
{
CreatePLangStmt *n = makeNode(CreatePLangStmt);
n->replace = $2;
n->plname = $6;
/* parameters are all to be supplied by system */
n->plhandler = NIL;
n->plinline = NIL;
n->plvalidator = NIL;
n->pltrusted = false;
$$ = (Node *)n;
}
| CREATE opt_or_replace opt_trusted opt_procedural LANGUAGE NonReservedWord_or_Sconst
HANDLER handler_name opt_inline_handler opt_validator
{
CreatePLangStmt *n = makeNode(CreatePLangStmt);
n->replace = $2;
n->plname = $6;
n->plhandler = $8;
n->plinline = $9;
n->plvalidator = $10;
n->pltrusted = $3;
$$ = (Node *)n;
}
;
opt_trusted:
TRUSTED { $$ = TRUE; }
| /*EMPTY*/ { $$ = FALSE; }
;
/* This ought to be just func_name, but that causes reduce/reduce conflicts
* (CREATE LANGUAGE is the only place where func_name isn't followed by '(').
* Work around by using simple names, instead.
*/
handler_name:
name { $$ = list_make1(makeString($1)); }
| name attrs { $$ = lcons(makeString($1), $2); }
;
opt_inline_handler:
INLINE_P handler_name { $$ = $2; }
| /*EMPTY*/ { $$ = NIL; }
;
validator_clause:
VALIDATOR handler_name { $$ = $2; }
| NO VALIDATOR { $$ = NIL; }
;
opt_validator:
validator_clause { $$ = $1; }
<