%{ /*#define YYDEBUG 1*/ /*------------------------------------------------------------------------- * * gram.y * POSTGRESQL BISON rules/actions * * Portions Copyright (c) 1996-2023, 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 constraint_exclusion TO off; SELECT * FROM foo; * because the entire string is parsed by gram.y before the SET gets * executed. Anything that depends on the database or changeable state * should be handled during parse analysis so that it happens at the * right time not the wrong time. * * WARNINGS * If you use a list, make sure the datum is a node so that the printing * routines work. * * Sometimes we assign constants to makeStrings. Make sure we don't free * those. * *------------------------------------------------------------------------- */ #include "postgres.h" #include #include #include "access/tableam.h" #include "catalog/index.h" #include "catalog/namespace.h" #include "catalog/pg_am.h" #include "catalog/pg_trigger.h" #include "commands/defrem.h" #include "commands/trigger.h" #include "gramparse.h" #include "nodes/makefuncs.h" #include "nodes/nodeFuncs.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, or whose leftmost * component was reduced from an empty rule. This is problematic * for nonterminals defined like * OptFooList: / * EMPTY * / { ... } | OptFooList Foo { ... } ; * because we'll set -1 as the location during the first reduction and then * copy it during each subsequent reduction, leaving us with -1 for the * location even when the list is not empty. To fix that, do this in the * action for the nonempty rule(s): * if (@$ < 0) @$ = @2; * (Although we have many nonterminals that follow this pattern, we only * bother with fixing @$ like this when the nonterminal's parse location * is actually referenced in some rule.) * * A cleaner answer would be to make YYLLOC_DEFAULT scan all the Rhs * locations until it's found one that's not -1. Then we'd get a correct * location for any nonterminal that isn't entirely empty. But this way * would add overhead to every rule reduction, and so far there's not been * a compelling reason to pay that overhead. */ /* * Bison doesn't allocate anything that needs to live across parser calls, * so we can easily have it use palloc instead of malloc. This prevents * memory leaks if we error out during parsing. */ #define YYMALLOC palloc #define YYFREE pfree /* Private struct for the result of privilege_target production */ typedef struct PrivTarget { GrantTargetType targtype; ObjectType objtype; List *objs; } PrivTarget; /* Private struct for the result of import_qualification production */ typedef struct ImportQual { ImportForeignSchemaType type; List *table_names; } ImportQual; /* Private struct for the result of opt_select_limit production */ typedef struct SelectLimit { Node *limitOffset; Node *limitCount; LimitOption limitOption; } SelectLimit; /* Private struct for the result of group_clause production */ typedef struct GroupClause { bool distinct; List *list; } GroupClause; /* Private structs for the result of key_actions and key_action productions */ typedef struct KeyAction { char action; List *cols; } KeyAction; typedef struct KeyActions { KeyAction *updateAction; KeyAction *deleteAction; } KeyActions; /* 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 RawStmt *makeRawStmt(Node *stmt, int stmt_location); static void updateRawStmtEnd(RawStmt *rs, int end_location); 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 *makeBoolAConst(bool state, int location); static Node *makeBitStringConst(char *str, int location); static Node *makeNullAConst(int location); static Node *makeAConst(Node *v, int location); static RoleSpec *makeRoleSpec(RoleSpecType type, 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, SelectLimit *limitClause, 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(Float *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 *makeSQLValueFunction(SQLValueFunctionOp op, int32 typmod, 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 RangeVar *makeRangeVarFromQualifiedName(char *name, List *namelist, int location, 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 PartitionStrategy parsePartitionStrategy(char *strategy); static void preprocess_pubobj_list(List *pubobjspec_list, 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; ObjectType objtype; TypeName *typnam; FunctionParameter *fun_param; FunctionParameterMode fun_param_mode; ObjectWithArgs *objwithargs; DefElem *defelt; SortBy *sortby; WindowDef *windef; JoinExpr *jexpr; IndexElem *ielem; StatsElem *selem; Alias *alias; RangeVar *range; IntoClause *into; WithClause *with; InferClause *infer; OnConflictClause *onconflict; A_Indices *aind; ResTarget *target; struct PrivTarget *privtarget; AccessPriv *accesspriv; struct ImportQual *importqual; InsertStmt *istmt; VariableSetStmt *vsetstmt; PartitionElem *partelem; PartitionSpec *partspec; PartitionBoundSpec *partboundspec; RoleSpec *rolespec; PublicationObjSpec *publicationobjectspec; struct SelectLimit *selectlimit; SetQuantifier setquantifier; struct GroupClause *groupclause; MergeWhenClause *mergewhen; struct KeyActions *keyactions; struct KeyAction *keyaction; } %type stmt toplevel_stmt schema_stmt routine_body_stmt AlterEventTrigStmt AlterCollationStmt AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterEnumStmt AlterFdwStmt AlterForeignServerStmt AlterGroupStmt AlterObjectDependsStmt AlterObjectSchemaStmt AlterOwnerStmt AlterOperatorStmt AlterTypeStmt AlterSeqStmt AlterSystemStmt AlterTableStmt AlterTblSpcStmt AlterExtensionStmt AlterExtensionContentsStmt AlterCompositeTypeStmt AlterUserMappingStmt AlterRoleStmt AlterRoleSetStmt AlterPolicyStmt AlterStatsStmt AlterDefaultPrivilegesStmt DefACLAction AnalyzeStmt CallStmt ClosePortalStmt ClusterStmt CommentStmt ConstraintsSetStmt CopyStmt CreateAsStmt CreateCastStmt CreateDomainStmt CreateExtensionStmt CreateGroupStmt CreateOpClassStmt CreateOpFamilyStmt AlterOpFamilyStmt CreatePLangStmt CreateSchemaStmt CreateSeqStmt CreateStmt CreateStatsStmt CreateTableSpaceStmt CreateFdwStmt CreateForeignServerStmt CreateForeignTableStmt CreateAssertionStmt CreateTransformStmt CreateTrigStmt CreateEventTrigStmt CreateUserStmt CreateUserMappingStmt CreateRoleStmt CreatePolicyStmt CreatedbStmt DeclareCursorStmt DefineStmt DeleteStmt DiscardStmt DoStmt DropOpClassStmt DropOpFamilyStmt DropStmt DropCastStmt DropRoleStmt DropdbStmt DropTableSpaceStmt DropTransformStmt DropUserMappingStmt ExplainStmt FetchStmt GrantStmt GrantRoleStmt ImportForeignSchemaStmt IndexStmt InsertStmt ListenStmt LoadStmt LockStmt MergeStmt NotifyStmt ExplainableStmt PreparableStmt CreateFunctionStmt AlterFunctionStmt ReindexStmt RemoveAggrStmt RemoveFuncStmt RemoveOperStmt RenameStmt ReturnStmt RevokeStmt RevokeRoleStmt RuleActionStmt RuleActionStmtOrEmpty RuleStmt SecLabelStmt SelectStmt TransactionStmt TransactionStmtLegacy TruncateStmt UnlistenStmt UpdateStmt VacuumStmt VariableResetStmt VariableSetStmt VariableShowStmt ViewStmt CheckPointStmt CreateConversionStmt DeallocateStmt PrepareStmt ExecuteStmt DropOwnedStmt ReassignOwnedStmt AlterTSConfigurationStmt AlterTSDictionaryStmt CreateMatViewStmt RefreshMatViewStmt CreateAmStmt CreatePublicationStmt AlterPublicationStmt CreateSubscriptionStmt AlterSubscriptionStmt DropSubscriptionStmt %type select_no_parens select_with_parens select_clause simple_select values_clause PLpgSQL_Expr PLAssignStmt %type opt_single_name %type opt_qualified_name %type opt_concurrently %type opt_drop_behavior %type alter_column_default opclass_item opclass_drop alter_using %type add_drop opt_asc_desc opt_nulls_order %type alter_table_cmd alter_type_cmd opt_collate_clause replica_identity partition_cmd index_partition_cmd %type alter_table_cmds alter_type_cmds %type alter_identity_column_option_list %type alter_identity_column_option %type createdb_opt_list createdb_opt_items copy_opt_list transaction_mode_list create_extension_opt_list alter_extension_opt_list %type createdb_opt_item copy_opt_item transaction_mode_item create_extension_opt_item alter_extension_opt_item %type opt_lock lock_type cast_context %type utility_option_name %type utility_option_elem %type utility_option_list %type utility_option_arg %type drop_option %type opt_or_replace opt_no opt_grant_grant_option opt_nowait opt_if_exists opt_with_data opt_transaction_chain %type grant_role_opt_list %type grant_role_opt %type grant_role_opt_value %type opt_nowait_or_skip %type OptRoleList AlterOptRoleList %type CreateOptRoleElem AlterOptRoleElem %type opt_type %type foreign_server_version opt_foreign_server_version %type opt_in_database %type parameter_name %type OptSchemaEltList parameter_name_list %type am_type %type TriggerForSpec TriggerForType %type TriggerActionTime %type TriggerEvents TriggerOneEvent %type TriggerFuncArg %type TriggerWhen %type TransitionRelName %type TransitionRowOrTable TransitionOldOrNew %type TriggerTransition %type event_trigger_when_list event_trigger_value_list %type event_trigger_when_item %type enable_trigger %type copy_file_name access_method_clause attr_name table_access_method_clause name cursor_name file_name cluster_index_specification %type func_name handler_name qual_Op qual_all_Op subquery_Op opt_inline_handler opt_validator validator_clause opt_collate %type qualified_name insert_target OptConstrFromTable %type all_Op MathOp %type row_security_cmd RowSecurityDefaultForCmd %type RowSecurityDefaultPermissive %type RowSecurityOptionalWithCheck RowSecurityOptionalExpr %type RowSecurityDefaultToRole RowSecurityOptionalToRole %type iso_level opt_encoding %type grantee %type grantee_list %type privilege %type privileges privilege_list %type privilege_target %type function_with_argtypes aggregate_with_argtypes operator_with_argtypes %type function_with_argtypes_list aggregate_with_argtypes_list operator_with_argtypes_list %type defacl_privilege_target %type DefACLOption %type DefACLOptionList %type import_qualification_type %type import_qualification %type vacuum_relation %type opt_select_limit select_limit limit_clause %type parse_toplevel stmtmulti routine_body_stmt_list OptTableElementList TableElementList OptInherit definition OptTypedTableElementList TypedTableElementList reloptions opt_reloptions OptWith 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 opt_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 stats_params opt_include opt_c_include index_including_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 distinct_clause opt_distinct_clause target_list opt_target_list insert_column_list set_target_list merge_values_clause set_clause_list set_clause def_list operator_def_list indirection opt_indirection reloption_list TriggerFuncArgs 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 transform_element_list transform_type_list TriggerTransitions TriggerReferencing vacuum_relation_list opt_vacuum_relation_list drop_option_list pub_obj_list %type opt_routine_body %type group_clause %type group_by_list %type group_by_item empty_grouping_set rollup_clause cube_clause %type grouping_sets_clause %type opt_fdw_options fdw_options %type fdw_option %type OptTempTableName %type into_clause create_as_target create_mv_target %type createfunc_opt_item common_func_opt_item dostmt_opt_item %type func_arg func_arg_with_default table_func_column aggr_arg %type arg_class %type func_return func_type %type opt_trusted opt_restart_seqs %type OptTemp %type OptNoLog %type OnCommitOption %type for_locking_strength %type for_locking_item %type for_locking_clause opt_for_locking_clause for_locking_items %type locked_rels_list %type set_quantifier %type join_qual %type join_type %type extract_list overlay_list position_list %type substr_list trim_list %type opt_interval interval_second %type unicode_normal_form %type opt_instead %type opt_unique opt_verbose opt_full %type opt_freeze opt_analyze opt_default opt_recheck %type opt_binary copy_delimiter %type copy_from opt_program %type event cursor_options opt_hold opt_set_data %type object_type_any_name object_type_name object_type_name_on_any_name drop_type_name %type fetch_args select_limit_value offset_clause select_offset_value select_fetch_first_value I_or_F_const %type row_or_rows first_or_next %type OptSeqOptList SeqOptList OptParenthesizedSeqOptList %type SeqOptElem %type insert_rest %type opt_conf_expr %type opt_on_conflict %type merge_insert merge_update merge_delete %type merge_when_clause opt_merge_when_condition %type merge_when_list %type generic_set set_rest set_rest_more generic_reset reset_rest SetResetClause FunctionSetResetClause %type TableElement TypedTableElement ConstraintElem TableFuncElement %type columnDef columnOptions %type def_elem reloption_elem old_aggr_elem operator_def_elem %type def_arg columnElem where_clause where_or_current_clause a_expr b_expr c_expr AexprConst indirection_el opt_slice_bound columnref in_expr having_clause func_table xmltable array_expr OptWhereClause operator_def_arg %type rowsfrom_item rowsfrom_list opt_col_def_list %type opt_ordinality %type ExclusionConstraintList ExclusionConstraintElem %type func_arg_list func_arg_list_opt %type func_arg_expr %type row explicit_row implicit_row type_list array_expr_list %type case_expr case_arg when_clause case_default %type when_clause_list %type opt_search_clause opt_cycle_clause %type sub_type opt_materialized %type NumericOnly %type NumericOnly_list %type alias_clause opt_alias_clause opt_alias_clause_for_join_using %type func_alias_clause %type sortby %type index_elem index_elem_options %type stats_param %type table_ref %type joined_table %type relation_expr %type extended_relation_expr %type relation_expr_opt_alias %type tablesample_clause opt_repeatable_clause %type target_el set_target insert_column_item %type generic_option_name %type generic_option_arg %type generic_option_elem alter_generic_option_elem %type generic_option_list alter_generic_option_list %type reindex_target_relation reindex_target_all %type opt_reindex_option_list %type copy_generic_opt_arg copy_generic_opt_arg_list_item %type copy_generic_opt_elem %type copy_generic_opt_list copy_generic_opt_arg_list %type copy_options %type Typename SimpleTypename ConstTypename GenericType Numeric opt_float Character ConstCharacter CharacterWithLength CharacterWithoutLength ConstDatetime ConstInterval Bit ConstBit BitWithLength BitWithoutLength %type character %type extract_arg %type opt_varying opt_timezone opt_no_inherit %type Iconst SignedIconst %type Sconst comment_text notify_payload %type RoleId opt_boolean_or_string %type var_list %type ColId ColLabel BareColLabel %type NonReservedWord NonReservedWord_or_Sconst %type var_name type_function_name param_name %type createdb_opt_name plassign_target %type var_value zone_value %type auth_ident RoleSpec opt_granted_by %type PublicationObjSpec %type unreserved_keyword type_func_name_keyword %type col_name_keyword reserved_keyword %type bare_label_keyword %type TableConstraint TableLikeClause %type TableLikeOptionList TableLikeOption %type column_compression opt_column_compression column_storage opt_column_storage %type ColQualList %type ColConstraint ColConstraintElem ConstraintAttr %type key_match %type key_delete key_update key_action %type key_actions %type ConstraintAttributeSpec ConstraintAttributeElem %type ExistingIndex %type constraints_set_list %type constraints_set_mode %type OptTableSpace OptConsTableSpace %type OptTableSpaceOwner %type opt_check_option %type opt_provider security_label %type xml_attribute_el %type xml_attribute_list xml_attributes %type xml_root_version opt_xml_root_standalone %type xmlexists_argument %type document_or_content %type xml_indent_option xml_whitespace_option %type xmltable_column_list xmltable_column_option_list %type xmltable_column_el %type xmltable_column_option_el %type xml_namespace_list %type xml_namespace_el %type func_application func_expr_common_subexpr %type func_expr func_expr_windowless %type common_table_expr %type with_clause opt_with_clause %type cte_list %type within_group_clause %type filter_clause %type window_clause window_definition_list opt_partition_clause %type window_definition over_clause window_specification opt_frame_clause frame_extent frame_bound %type opt_window_exclusion_clause %type opt_existing_window_name %type opt_if_not_exists %type opt_unique_null_treatment %type generated_when override_kind %type PartitionSpec OptPartitionSpec %type part_elem %type part_params %type PartitionBoundSpec %type hash_partbound %type hash_partbound_elem %type json_format_clause_opt json_value_expr json_output_clause_opt json_name_and_value json_aggregate_func %type json_name_and_value_list json_value_expr_list json_array_aggregate_order_by_clause_opt %type json_encoding_clause_opt json_predicate_type_constraint %type json_key_uniqueness_constraint_opt json_object_constructor_null_clause_opt json_array_constructor_null_clause_opt /* * 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! * * UIDENT and USCONST are reduced to IDENT and SCONST in parser.c, so that * they need no productions here; but we must assign token codes to them. * * DOT_DOT is unused in the core SQL grammar, and so will always provoke * parse errors. It is needed by PL/pgSQL. */ %token IDENT UIDENT FCONST SCONST USCONST BCONST XCONST Op %token ICONST PARAM %token TYPECAST DOT_DOT COLON_EQUALS EQUALS_GREATER %token LESS_EQUALS GREATER_EQUALS NOT_EQUALS /* * If you want to make any keyword changes, update the keyword table in * src/include/parser/kwlist.h and add new keywords to the appropriate one * of the reserved-or-not-so-reserved keyword lists, below; search * this file for "Keyword category lists". */ /* ordinary key words in alphabetical order */ %token ABORT_P ABSENT ABSOLUTE_P ACCESS ACTION ADD_P ADMIN AFTER AGGREGATE ALL ALSO ALTER ALWAYS ANALYSE ANALYZE AND ANY ARRAY AS ASC ASENSITIVE ASSERTION ASSIGNMENT ASYMMETRIC ATOMIC AT ATTACH ATTRIBUTE AUTHORIZATION BACKWARD BEFORE BEGIN_P BETWEEN BIGINT BINARY BIT BOOLEAN_P BOTH BREADTH BY CACHE CALL CALLED CASCADE CASCADED CASE CAST CATALOG_P CHAIN CHAR_P CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLOSE CLUSTER COALESCE COLLATE COLLATION COLUMN COLUMNS COMMENT COMMENTS COMMIT COMMITTED COMPRESSION CONCURRENTLY CONFIGURATION CONFLICT CONNECTION CONSTRAINT CONSTRAINTS CONTENT_P CONTINUE_P CONVERSION_P COPY COST CREATE CROSS CSV CUBE 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 DEPENDS DEPTH DESC DETACH 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 EXPRESSION EXTENSION EXTERNAL EXTRACT FALSE_P FAMILY FETCH FILTER FINALIZE FIRST_P FLOAT_P FOLLOWING FOR FORCE FOREIGN FORMAT FORWARD FREEZE FROM FULL FUNCTION FUNCTIONS GENERATED GLOBAL GRANT GRANTED GREATEST GROUP_P GROUPING GROUPS HANDLER HAVING HEADER_P HOLD HOUR_P IDENTITY_P IF_P ILIKE IMMEDIATE IMMUTABLE IMPLICIT_P IMPORT_P IN_P INCLUDE INCLUDING INCREMENT INDENT 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 JSON JSON_ARRAY JSON_ARRAYAGG JSON_OBJECT JSON_OBJECTAGG KEY KEYS 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 MATCHED MATERIALIZED MAXVALUE MERGE METHOD MINUTE_P MINVALUE MODE MONTH_P MOVE NAME_P NAMES NATIONAL NATURAL NCHAR NEW NEXT NFC NFD NFKC NFKD NO NONE NORMALIZE NORMALIZED NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF NULLS_P NUMERIC OBJECT_P OF OFF OFFSET OIDS OLD ON ONLY OPERATOR OPTION OPTIONS OR ORDER ORDINALITY OTHERS OUT_P OUTER_P OVER OVERLAPS OVERLAY OVERRIDING OWNED OWNER PARALLEL PARAMETER PARSER PARTIAL PARTITION PASSING PASSWORD PLACING PLANS POLICY POSITION PRECEDING PRECISION PRESERVE PREPARE PREPARED PRIMARY PRIOR PRIVILEGES PROCEDURAL PROCEDURE PROCEDURES PROGRAM PUBLICATION QUOTE RANGE READ REAL REASSIGN RECHECK RECURSIVE REF_P REFERENCES REFERENCING REFRESH REINDEX RELATIVE_P RELEASE RENAME REPEATABLE REPLACE REPLICA RESET RESTART RESTRICT RETURN RETURNING RETURNS REVOKE RIGHT ROLE ROLLBACK ROLLUP ROUTINE ROUTINES ROW ROWS RULE SAVEPOINT SCALAR SCHEMA SCHEMAS SCROLL SEARCH SECOND_P SECURITY SELECT SEQUENCE SEQUENCES SERIALIZABLE SERVER SESSION SESSION_USER SET SETS SETOF SHARE SHOW SIMILAR SIMPLE SKIP SMALLINT SNAPSHOT SOME SQL_P STABLE STANDALONE_P START STATEMENT STATISTICS STDIN STDOUT STORAGE STORED STRICT_P STRIP_P SUBSCRIPTION SUBSTRING SUPPORT SYMMETRIC SYSID SYSTEM_P SYSTEM_USER TABLE TABLES TABLESAMPLE TABLESPACE TEMP TEMPLATE TEMPORARY TEXT_P THEN TIES TIME TIMESTAMP TO TRAILING TRANSACTION TRANSFORM TREAT TRIGGER TRIM TRUE_P TRUNCATE TRUSTED TYPE_P TYPES_P UESCAPE 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 XMLNAMESPACES XMLPARSE XMLPI XMLROOT XMLSERIALIZE XMLTABLE 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). * * NOT_LA exists so that productions such as NOT LIKE can be given the same * precedence as LIKE; otherwise they'd effectively have the same precedence * as NOT, at least with respect to their left-hand subexpression. * FORMAT_LA, NULLS_LA, WITH_LA, and WITHOUT_LA are needed to make the grammar * LALR(1). */ %token FORMAT_LA NOT_LA NULLS_LA WITH_LA WITHOUT_LA /* * The grammar likewise thinks these tokens are keywords, but they are never * generated by the scanner. Rather, they can be injected by parser.c as * the initial token of the string (using the lookahead-token mechanism * implemented there). This provides a way to tell the grammar to parse * something other than the usual list of SQL commands. */ %token MODE_TYPE_NAME %token MODE_PLPGSQL_EXPR %token MODE_PLPGSQL_ASSIGN1 %token MODE_PLPGSQL_ASSIGN2 %token MODE_PLPGSQL_ASSIGN3 /* Precedence: lowest to highest */ %nonassoc SET /* see relation_expr_opt_alias */ %left UNION EXCEPT %left INTERSECT %left OR %left AND %right NOT %nonassoc IS ISNULL NOTNULL /* IS sets precedence for IS NULL, etc */ %nonassoc '<' '>' '=' LESS_EQUALS GREATER_EQUALS NOT_EQUALS %nonassoc BETWEEN IN_P LIKE ILIKE SIMILAR NOT_LA %nonassoc ESCAPE /* ESCAPE must be just above LIKE/ILIKE/SIMILAR */ /* SQL/JSON related keywords */ %nonassoc UNIQUE JSON %nonassoc KEYS OBJECT_P SCALAR VALUE_P %nonassoc WITH WITHOUT /* * To support target_el without AS, it used to be necessary to assign IDENT an * explicit precedence just less than Op. While that's not really necessary * since we removed postfix operators, it's still helpful to do so because * there are some other unreserved keywords that need precedence assignments. * If those keywords have the same precedence as IDENT then they clearly act * the same as non-keywords, reducing the risk of unwanted precedence effects. * * We need to do this for PARTITION, RANGE, ROWS, and GROUPS to support * opt_existing_window_name (see comment there). * * 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. * * To support CUBE and ROLLUP in GROUP BY without reserving them, we give them * an explicit priority lower than '(', so that a rule with CUBE '(' will shift * rather than reducing a conflicting rule that takes CUBE as a function name. * Using the same precedence as IDENT seems right for the reasons given above. */ %nonassoc UNBOUNDED /* ideally would have same precedence as IDENT */ %nonassoc IDENT PARTITION RANGE ROWS GROUPS PRECEDING FOLLOWING CUBE ROLLUP %left Op OPERATOR /* multi-character ops and user-defined operators */ %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 %% /* * The target production for the whole parse. * * Ordinarily we parse a list of statements, but if we see one of the * special MODE_XXX symbols as first token, we parse something else. * The options here correspond to enum RawParseMode, which see for details. */ parse_toplevel: stmtmulti { pg_yyget_extra(yyscanner)->parsetree = $1; (void) yynerrs; /* suppress compiler warning */ } | MODE_TYPE_NAME Typename { pg_yyget_extra(yyscanner)->parsetree = list_make1($2); } | MODE_PLPGSQL_EXPR PLpgSQL_Expr { pg_yyget_extra(yyscanner)->parsetree = list_make1(makeRawStmt($2, 0)); } | MODE_PLPGSQL_ASSIGN1 PLAssignStmt { PLAssignStmt *n = (PLAssignStmt *) $2; n->nnames = 1; pg_yyget_extra(yyscanner)->parsetree = list_make1(makeRawStmt((Node *) n, 0)); } | MODE_PLPGSQL_ASSIGN2 PLAssignStmt { PLAssignStmt *n = (PLAssignStmt *) $2; n->nnames = 2; pg_yyget_extra(yyscanner)->parsetree = list_make1(makeRawStmt((Node *) n, 0)); } | MODE_PLPGSQL_ASSIGN3 PLAssignStmt { PLAssignStmt *n = (PLAssignStmt *) $2; n->nnames = 3; pg_yyget_extra(yyscanner)->parsetree = list_make1(makeRawStmt((Node *) n, 0)); } ; /* * At top level, we wrap each stmt with a RawStmt node carrying start location * and length of the stmt's text. Notice that the start loc/len are driven * entirely from semicolon locations (@2). It would seem natural to use * @1 or @3 to get the true start location of a stmt, but that doesn't work * for statements that can start with empty nonterminals (opt_with_clause is * the main offender here); as noted in the comments for YYLLOC_DEFAULT, * we'd get -1 for the location in such cases. * We also take care to discard empty statements entirely. */ stmtmulti: stmtmulti ';' toplevel_stmt { if ($1 != NIL) { /* update length of previous stmt */ updateRawStmtEnd(llast_node(RawStmt, $1), @2); } if ($3 != NULL) $$ = lappend($1, makeRawStmt($3, @2 + 1)); else $$ = $1; } | toplevel_stmt { if ($1 != NULL) $$ = list_make1(makeRawStmt($1, 0)); else $$ = NIL; } ; /* * toplevel_stmt includes BEGIN and END. stmt does not include them, because * those words have different meanings in function bodies. */ toplevel_stmt: stmt | TransactionStmtLegacy ; stmt: AlterEventTrigStmt | AlterCollationStmt | AlterDatabaseStmt | AlterDatabaseSetStmt | AlterDefaultPrivilegesStmt | AlterDomainStmt | AlterEnumStmt | AlterExtensionStmt | AlterExtensionContentsStmt | AlterFdwStmt | AlterForeignServerStmt | AlterFunctionStmt | AlterGroupStmt | AlterObjectDependsStmt | AlterObjectSchemaStmt | AlterOwnerStmt | AlterOperatorStmt | AlterTypeStmt | AlterPolicyStmt | AlterSeqStmt | AlterSystemStmt | AlterTableStmt | AlterTblSpcStmt | AlterCompositeTypeStmt | AlterPublicationStmt | AlterRoleSetStmt | AlterRoleStmt | AlterSubscriptionStmt | AlterStatsStmt | AlterTSConfigurationStmt | AlterTSDictionaryStmt | AlterUserMappingStmt | AnalyzeStmt | CallStmt | CheckPointStmt | ClosePortalStmt | ClusterStmt | CommentStmt | ConstraintsSetStmt | CopyStmt | CreateAmStmt | CreateAsStmt | CreateAssertionStmt | CreateCastStmt | CreateConversionStmt | CreateDomainStmt | CreateExtensionStmt | CreateFdwStmt | CreateForeignServerStmt | CreateForeignTableStmt | CreateFunctionStmt | CreateGroupStmt | CreateMatViewStmt | CreateOpClassStmt | CreateOpFamilyStmt | CreatePublicationStmt | AlterOpFamilyStmt | CreatePolicyStmt | CreatePLangStmt | CreateSchemaStmt | CreateSeqStmt | CreateStmt | CreateSubscriptionStmt | CreateStatsStmt | CreateTableSpaceStmt | CreateTransformStmt | CreateTrigStmt | CreateEventTrigStmt | CreateRoleStmt | CreateUserStmt | CreateUserMappingStmt | CreatedbStmt | DeallocateStmt | DeclareCursorStmt | DefineStmt | DeleteStmt | DiscardStmt | DoStmt | DropCastStmt | DropOpClassStmt | DropOpFamilyStmt | DropOwnedStmt | DropStmt | DropSubscriptionStmt | DropTableSpaceStmt | DropTransformStmt | DropRoleStmt | DropUserMappingStmt | DropdbStmt | ExecuteStmt | ExplainStmt | FetchStmt | GrantStmt | GrantRoleStmt | ImportForeignSchemaStmt | IndexStmt | InsertStmt | ListenStmt | RefreshMatViewStmt | LoadStmt | LockStmt | MergeStmt | NotifyStmt | PrepareStmt | ReassignOwnedStmt | ReindexStmt | RemoveAggrStmt | RemoveFuncStmt | RemoveOperStmt | RenameStmt | RevokeStmt | RevokeRoleStmt | RuleStmt | SecLabelStmt | SelectStmt | TransactionStmt | TruncateStmt | UnlistenStmt | UpdateStmt | VacuumStmt | VariableResetStmt | VariableSetStmt | VariableShowStmt | ViewStmt | /*EMPTY*/ { $$ = NULL; } ; /* * Generic supporting productions for DDL */ opt_single_name: ColId { $$ = $1; } | /* EMPTY */ { $$ = NULL; } ; opt_qualified_name: any_name { $$ = $1; } | /*EMPTY*/ { $$ = NIL; } ; opt_concurrently: CONCURRENTLY { $$ = true; } | /*EMPTY*/ { $$ = false; } ; opt_drop_behavior: CASCADE { $$ = DROP_CASCADE; } | RESTRICT { $$ = DROP_RESTRICT; } | /* EMPTY */ { $$ = DROP_RESTRICT; /* default */ } ; /***************************************************************************** * * CALL statement * *****************************************************************************/ CallStmt: CALL func_application { CallStmt *n = makeNode(CallStmt); n->funccall = castNode(FuncCall, $2); $$ = (Node *) n; } ; /***************************************************************************** * * 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), @1); } | PASSWORD NULL_P { $$ = makeDefElem("password", NULL, @1); } | ENCRYPTED PASSWORD Sconst { /* * These days, passwords are always stored in encrypted * form, so there is no difference between PASSWORD and * ENCRYPTED PASSWORD. */ $$ = makeDefElem("password", (Node *) makeString($3), @1); } | UNENCRYPTED PASSWORD Sconst { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("UNENCRYPTED PASSWORD is no longer supported"), errhint("Remove UNENCRYPTED to store the password in encrypted form instead."), parser_errposition(@1))); } | INHERIT { $$ = makeDefElem("inherit", (Node *) makeBoolean(true), @1); } | CONNECTION LIMIT SignedIconst { $$ = makeDefElem("connectionlimit", (Node *) makeInteger($3), @1); } | VALID UNTIL Sconst { $$ = makeDefElem("validUntil", (Node *) makeString($3), @1); } /* Supported but not documented for roles, for use by ALTER GROUP. */ | USER role_list { $$ = makeDefElem("rolemembers", (Node *) $2, @1); } | 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 *) makeBoolean(true), @1); else if (strcmp($1, "nosuperuser") == 0) $$ = makeDefElem("superuser", (Node *) makeBoolean(false), @1); else if (strcmp($1, "createrole") == 0) $$ = makeDefElem("createrole", (Node *) makeBoolean(true), @1); else if (strcmp($1, "nocreaterole") == 0) $$ = makeDefElem("createrole", (Node *) makeBoolean(false), @1); else if (strcmp($1, "replication") == 0) $$ = makeDefElem("isreplication", (Node *) makeBoolean(true), @1); else if (strcmp($1, "noreplication") == 0) $$ = makeDefElem("isreplication", (Node *) makeBoolean(false), @1); else if (strcmp($1, "createdb") == 0) $$ = makeDefElem("createdb", (Node *) makeBoolean(true), @1); else if (strcmp($1, "nocreatedb") == 0) $$ = makeDefElem("createdb", (Node *) makeBoolean(false), @1); else if (strcmp($1, "login") == 0) $$ = makeDefElem("canlogin", (Node *) makeBoolean(true), @1); else if (strcmp($1, "nologin") == 0) $$ = makeDefElem("canlogin", (Node *) makeBoolean(false), @1); else if (strcmp($1, "bypassrls") == 0) $$ = makeDefElem("bypassrls", (Node *) makeBoolean(true), @1); else if (strcmp($1, "nobypassrls") == 0) $$ = makeDefElem("bypassrls", (Node *) makeBoolean(false), @1); 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 *) makeBoolean(false), @1); } 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), @1); } | ADMIN role_list { $$ = makeDefElem("adminmembers", (Node *) $2, @1); } | ROLE role_list { $$ = makeDefElem("rolemembers", (Node *) $2, @1); } | IN_P ROLE role_list { $$ = makeDefElem("addroleto", (Node *) $3, @1); } | IN_P GROUP_P role_list { $$ = makeDefElem("addroleto", (Node *) $3, @1); } ; /***************************************************************************** * * 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 RoleSpec opt_with AlterOptRoleList { AlterRoleStmt *n = makeNode(AlterRoleStmt); n->role = $3; n->action = +1; /* add, if there are members */ n->options = $5; $$ = (Node *) n; } | ALTER USER RoleSpec 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 name { $$ = $3; } ; AlterRoleSetStmt: ALTER ROLE RoleSpec 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 USER RoleSpec opt_in_database SetResetClause { AlterRoleSetStmt *n = makeNode(AlterRoleSetStmt); n->role = $3; n->database = $4; n->setstmt = $5; $$ = (Node *) n; } | ALTER USER ALL opt_in_database SetResetClause { AlterRoleSetStmt *n = makeNode(AlterRoleSetStmt); n->role = NULL; n->database = $4; n->setstmt = $5; $$ = (Node *) n; } ; /***************************************************************************** * * Drop a postgresql DBMS role * * XXX Ideally this would have CASCADE/RESTRICT options, but a role * might own objects in multiple databases, and there is presently no way to * implement cascading to other databases. So we always behave as RESTRICT. *****************************************************************************/ 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 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; } | 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; } ; /***************************************************************************** * * 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 RoleSpec add_drop USER role_list { AlterRoleStmt *n = makeNode(AlterRoleStmt); n->role = $3; n->action = $4; n->options = list_make1(makeDefElem("rolemembers", (Node *) $6, @6)); $$ = (Node *) n; } ; add_drop: ADD_P { $$ = +1; } | DROP { $$ = -1; } ; /***************************************************************************** * * Manipulate a schema * *****************************************************************************/ CreateSchemaStmt: CREATE SCHEMA opt_single_name AUTHORIZATION RoleSpec OptSchemaEltList { CreateSchemaStmt *n = makeNode(CreateSchemaStmt); /* One can omit the schema name or the authorization id. */ n->schemaname = $3; n->authrole = $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->authrole = NULL; n->schemaElts = $4; n->if_not_exists = false; $$ = (Node *) n; } | CREATE SCHEMA IF_P NOT EXISTS opt_single_name AUTHORIZATION RoleSpec OptSchemaEltList { CreateSchemaStmt *n = makeNode(CreateSchemaStmt); /* schema name can be omitted here, too */ n->schemaname = $6; n->authrole = $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 here */ n->schemaname = $6; n->authrole = 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; } ; 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.ival.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 | FOREIGN TABLE ] variations * * Note: we accept all subcommands for each of the 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->objtype = 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->objtype = OBJECT_TABLE; n->missing_ok = true; $$ = (Node *) n; } | ALTER TABLE relation_expr partition_cmd { AlterTableStmt *n = makeNode(AlterTableStmt); n->relation = $3; n->cmds = list_make1($4); n->objtype = OBJECT_TABLE; n->missing_ok = false; $$ = (Node *) n; } | ALTER TABLE IF_P EXISTS relation_expr partition_cmd { AlterTableStmt *n = makeNode(AlterTableStmt); n->relation = $5; n->cmds = list_make1($6); n->objtype = 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->objtype = 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->objtype = OBJECT_INDEX; n->missing_ok = true; $$ = (Node *) n; } | ALTER INDEX qualified_name index_partition_cmd { AlterTableStmt *n = makeNode(AlterTableStmt); n->relation = $3; n->cmds = list_make1($4); n->objtype = OBJECT_INDEX; n->missing_ok = false; $$ = (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->objtype = 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->objtype = 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->objtype = 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->objtype = 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->objtype = 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->objtype = 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 FOREIGN TABLE relation_expr alter_table_cmds { AlterTableStmt *n = makeNode(AlterTableStmt); n->relation = $4; n->cmds = $5; n->objtype = OBJECT_FOREIGN_TABLE; n->missing_ok = false; $$ = (Node *) n; } | ALTER FOREIGN TABLE IF_P EXISTS relation_expr alter_table_cmds { AlterTableStmt *n = makeNode(AlterTableStmt); n->relation = $6; n->cmds = $7; n->objtype = OBJECT_FOREIGN_TABLE; n->missing_ok = true; $$ = (Node *) n; } ; alter_table_cmds: alter_table_cmd { $$ = list_make1($1); } | alter_table_cmds ',' alter_table_cmd { $$ = lappend($1, $3); } ; partition_cmd: /* ALTER TABLE ATTACH PARTITION FOR VALUES */ ATTACH PARTITION qualified_name PartitionBoundSpec { AlterTableCmd *n = makeNode(AlterTableCmd); PartitionCmd *cmd = makeNode(PartitionCmd); n->subtype = AT_AttachPartition; cmd->name = $3; cmd->bound = $4; cmd->concurrent = false; n->def = (Node *) cmd; $$ = (Node *) n; } /* ALTER TABLE DETACH PARTITION [CONCURRENTLY] */ | DETACH PARTITION qualified_name opt_concurrently { AlterTableCmd *n = makeNode(AlterTableCmd); PartitionCmd *cmd = makeNode(PartitionCmd); n->subtype = AT_DetachPartition; cmd->name = $3; cmd->bound = NULL; cmd->concurrent = $4; n->def = (Node *) cmd; $$ = (Node *) n; } | DETACH PARTITION qualified_name FINALIZE { AlterTableCmd *n = makeNode(AlterTableCmd); PartitionCmd *cmd = makeNode(PartitionCmd); n->subtype = AT_DetachPartitionFinalize; cmd->name = $3; cmd->bound = NULL; cmd->concurrent = false; n->def = (Node *) cmd; $$ = (Node *) n; } ; index_partition_cmd: /* ALTER INDEX ATTACH PARTITION */ ATTACH PARTITION qualified_name { AlterTableCmd *n = makeNode(AlterTableCmd); PartitionCmd *cmd = makeNode(PartitionCmd); n->subtype = AT_AttachPartition; cmd->name = $3; cmd->bound = NULL; cmd->concurrent = false; n->def = (Node *) cmd; $$ = (Node *) n; } ; alter_table_cmd: /* ALTER TABLE ADD */ ADD_P columnDef { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_AddColumn; n->def = $2; n->missing_ok = false; $$ = (Node *) n; } /* ALTER TABLE ADD IF NOT EXISTS */ | ADD_P IF_P NOT EXISTS columnDef { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_AddColumn; n->def = $5; n->missing_ok = true; $$ = (Node *) n; } /* ALTER TABLE ADD COLUMN */ | ADD_P COLUMN columnDef { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_AddColumn; n->def = $3; n->missing_ok = false; $$ = (Node *) n; } /* ALTER TABLE ADD COLUMN IF NOT EXISTS */ | ADD_P COLUMN IF_P NOT EXISTS columnDef { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_AddColumn; n->def = $6; n->missing_ok = true; $$ = (Node *) n; } /* ALTER TABLE ALTER [COLUMN] {SET DEFAULT |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 ALTER [COLUMN] 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 ALTER [COLUMN] 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 ALTER [COLUMN] DROP EXPRESSION */ | ALTER opt_column ColId DROP EXPRESSION { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_DropExpression; n->name = $3; $$ = (Node *) n; } /* ALTER TABLE ALTER [COLUMN] DROP EXPRESSION IF EXISTS */ | ALTER opt_column ColId DROP EXPRESSION IF_P EXISTS { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_DropExpression; n->name = $3; n->missing_ok = true; $$ = (Node *) n; } /* ALTER TABLE ALTER [COLUMN] SET STATISTICS */ | 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 ALTER [COLUMN] SET STATISTICS */ | ALTER opt_column Iconst SET STATISTICS SignedIconst { AlterTableCmd *n = makeNode(AlterTableCmd); if ($3 <= 0 || $3 > PG_INT16_MAX) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("column number must be in range from 1 to %d", PG_INT16_MAX), parser_errposition(@3))); n->subtype = AT_SetStatistics; n->num = (int16) $3; n->def = (Node *) makeInteger($6); $$ = (Node *) n; } /* ALTER TABLE ALTER [COLUMN] 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 ALTER [COLUMN] RESET ( column_parameter [, ... ] ) */ | 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 ALTER [COLUMN] SET STORAGE */ | ALTER opt_column ColId SET column_storage { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_SetStorage; n->name = $3; n->def = (Node *) makeString($5); $$ = (Node *) n; } /* ALTER TABLE ALTER [COLUMN] SET COMPRESSION */ | ALTER opt_column ColId SET column_compression { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_SetCompression; n->name = $3; n->def = (Node *) makeString($5); $$ = (Node *) n; } /* ALTER TABLE ALTER [COLUMN] ADD GENERATED ... AS IDENTITY ... */ | ALTER opt_column ColId ADD_P GENERATED generated_when AS IDENTITY_P OptParenthesizedSeqOptList { AlterTableCmd *n = makeNode(AlterTableCmd); Constraint *c = makeNode(Constraint); c->contype = CONSTR_IDENTITY; c->generated_when = $6; c->options = $9; c->location = @5; n->subtype = AT_AddIdentity; n->name = $3; n->def = (Node *) c; $$ = (Node *) n; } /* ALTER TABLE ALTER [COLUMN] SET /RESET */ | ALTER opt_column ColId alter_identity_column_option_list { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_SetIdentity; n->name = $3; n->def = (Node *) $4; $$ = (Node *) n; } /* ALTER TABLE ALTER [COLUMN] DROP IDENTITY */ | ALTER opt_column ColId DROP IDENTITY_P { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_DropIdentity; n->name = $3; n->missing_ok = false; $$ = (Node *) n; } /* ALTER TABLE ALTER [COLUMN] DROP IDENTITY IF EXISTS */ | ALTER opt_column ColId DROP IDENTITY_P IF_P EXISTS { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_DropIdentity; n->name = $3; n->missing_ok = true; $$ = (Node *) n; } /* ALTER TABLE DROP [COLUMN] IF EXISTS [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 DROP [COLUMN] [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 ALTER [COLUMN] [SET DATA] TYPE * [ USING ] */ | 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 ALTER [COLUMN] 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 ADD CONSTRAINT ... */ | ADD_P TableConstraint { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_AddConstraint; n->def = $2; $$ = (Node *) n; } /* ALTER TABLE 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 VALIDATE CONSTRAINT ... */ | VALIDATE CONSTRAINT name { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_ValidateConstraint; n->name = $3; $$ = (Node *) n; } /* ALTER TABLE DROP CONSTRAINT IF EXISTS [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 DROP CONSTRAINT [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 SET WITHOUT OIDS, for backward compat */ | SET WITHOUT OIDS { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_DropOids; $$ = (Node *) n; } /* ALTER TABLE CLUSTER ON */ | CLUSTER ON name { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_ClusterOn; n->name = $3; $$ = (Node *) n; } /* ALTER TABLE SET WITHOUT CLUSTER */ | SET WITHOUT CLUSTER { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_DropCluster; n->name = NULL; $$ = (Node *) n; } /* ALTER TABLE SET LOGGED */ | SET LOGGED { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_SetLogged; $$ = (Node *) n; } /* ALTER TABLE SET UNLOGGED */ | SET UNLOGGED { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_SetUnLogged; $$ = (Node *) n; } /* ALTER TABLE ENABLE TRIGGER */ | ENABLE_P TRIGGER name { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_EnableTrig; n->name = $3; $$ = (Node *) n; } /* ALTER TABLE ENABLE ALWAYS TRIGGER */ | ENABLE_P ALWAYS TRIGGER name { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_EnableAlwaysTrig; n->name = $4; $$ = (Node *) n; } /* ALTER TABLE ENABLE REPLICA TRIGGER */ | ENABLE_P REPLICA TRIGGER name { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_EnableReplicaTrig; n->name = $4; $$ = (Node *) n; } /* ALTER TABLE ENABLE TRIGGER ALL */ | ENABLE_P TRIGGER ALL { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_EnableTrigAll; $$ = (Node *) n; } /* ALTER TABLE ENABLE TRIGGER USER */ | ENABLE_P TRIGGER USER { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_EnableTrigUser; $$ = (Node *) n; } /* ALTER TABLE DISABLE TRIGGER */ | DISABLE_P TRIGGER name { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_DisableTrig; n->name = $3; $$ = (Node *) n; } /* ALTER TABLE DISABLE TRIGGER ALL */ | DISABLE_P TRIGGER ALL { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_DisableTrigAll; $$ = (Node *) n; } /* ALTER TABLE DISABLE TRIGGER USER */ | DISABLE_P TRIGGER USER { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_DisableTrigUser; $$ = (Node *) n; } /* ALTER TABLE ENABLE RULE */ | ENABLE_P RULE name { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_EnableRule; n->name = $3; $$ = (Node *) n; } /* ALTER TABLE ENABLE ALWAYS RULE */ | ENABLE_P ALWAYS RULE name { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_EnableAlwaysRule; n->name = $4; $$ = (Node *) n; } /* ALTER TABLE ENABLE REPLICA RULE */ | ENABLE_P REPLICA RULE name { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_EnableReplicaRule; n->name = $4; $$ = (Node *) n; } /* ALTER TABLE DISABLE RULE */ | DISABLE_P RULE name { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_DisableRule; n->name = $3; $$ = (Node *) n; } /* ALTER TABLE INHERIT */ | INHERIT qualified_name { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_AddInherit; n->def = (Node *) $2; $$ = (Node *) n; } /* ALTER TABLE NO INHERIT */ | NO INHERIT qualified_name { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_DropInherit; n->def = (Node *) $3; $$ = (Node *) n; } /* ALTER TABLE OF */ | 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 NOT OF */ | NOT OF { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_DropOf; $$ = (Node *) n; } /* ALTER TABLE OWNER TO RoleSpec */ | OWNER TO RoleSpec { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_ChangeOwner; n->newowner = $3; $$ = (Node *) n; } /* ALTER TABLE SET ACCESS METHOD */ | SET ACCESS METHOD name { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_SetAccessMethod; n->name = $4; $$ = (Node *) n; } /* ALTER TABLE SET TABLESPACE */ | SET TABLESPACE name { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_SetTableSpace; n->name = $3; $$ = (Node *) n; } /* ALTER TABLE SET (...) */ | SET reloptions { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_SetRelOptions; n->def = (Node *) $2; $$ = (Node *) n; } /* ALTER TABLE RESET (...) */ | RESET reloptions { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_ResetRelOptions; n->def = (Node *) $2; $$ = (Node *) n; } /* ALTER TABLE REPLICA IDENTITY */ | REPLICA IDENTITY_P replica_identity { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_ReplicaIdentity; n->def = $3; $$ = (Node *) n; } /* ALTER TABLE ENABLE ROW LEVEL SECURITY */ | ENABLE_P ROW LEVEL SECURITY { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_EnableRowSecurity; $$ = (Node *) n; } /* ALTER TABLE DISABLE ROW LEVEL SECURITY */ | DISABLE_P ROW LEVEL SECURITY { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_DisableRowSecurity; $$ = (Node *) n; } /* ALTER TABLE FORCE ROW LEVEL SECURITY */ | FORCE ROW LEVEL SECURITY { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_ForceRowSecurity; $$ = (Node *) n; } /* ALTER TABLE NO FORCE ROW LEVEL SECURITY */ | NO FORCE ROW LEVEL SECURITY { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_NoForceRowSecurity; $$ = (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_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, @1); } | ColLabel { $$ = makeDefElem($1, NULL, @1); } | ColLabel '.' ColLabel '=' def_arg { $$ = makeDefElemExtended($1, $3, (Node *) $5, DEFELEM_UNSPEC, @1); } | ColLabel '.' ColLabel { $$ = makeDefElemExtended($1, $3, NULL, DEFELEM_UNSPEC, @1); } ; alter_identity_column_option_list: alter_identity_column_option { $$ = list_make1($1); } | alter_identity_column_option_list alter_identity_column_option { $$ = lappend($1, $2); } ; alter_identity_column_option: RESTART { $$ = makeDefElem("restart", NULL, @1); } | RESTART opt_with NumericOnly { $$ = makeDefElem("restart", (Node *) $3, @1); } | SET SeqOptElem { if (strcmp($2->defname, "as") == 0 || strcmp($2->defname, "restart") == 0 || strcmp($2->defname, "owned_by") == 0) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("sequence option \"%s\" not supported here", $2->defname), parser_errposition(@2))); $$ = $2; } | SET GENERATED generated_when { $$ = makeDefElem("generated", (Node *) makeInteger($3), @1); } ; PartitionBoundSpec: /* a HASH partition */ FOR VALUES WITH '(' hash_partbound ')' { ListCell *lc; PartitionBoundSpec *n = makeNode(PartitionBoundSpec); n->strategy = PARTITION_STRATEGY_HASH; n->modulus = n->remainder = -1; foreach (lc, $5) { DefElem *opt = lfirst_node(DefElem, lc); if (strcmp(opt->defname, "modulus") == 0) { if (n->modulus != -1) ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("modulus for hash partition provided more than once"), parser_errposition(opt->location))); n->modulus = defGetInt32(opt); } else if (strcmp(opt->defname, "remainder") == 0) { if (n->remainder != -1) ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("remainder for hash partition provided more than once"), parser_errposition(opt->location))); n->remainder = defGetInt32(opt); } else ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("unrecognized hash partition bound specification \"%s\"", opt->defname), parser_errposition(opt->location))); } if (n->modulus == -1) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("modulus for hash partition must be specified"))); if (n->remainder == -1) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("remainder for hash partition must be specified"))); n->location = @3; $$ = n; } /* a LIST partition */ | FOR VALUES IN_P '(' expr_list ')' { PartitionBoundSpec *n = makeNode(PartitionBoundSpec); n->strategy = PARTITION_STRATEGY_LIST; n->is_default = false; n->listdatums = $5; n->location = @3; $$ = n; } /* a RANGE partition */ | FOR VALUES FROM '(' expr_list ')' TO '(' expr_list ')' { PartitionBoundSpec *n = makeNode(PartitionBoundSpec); n->strategy = PARTITION_STRATEGY_RANGE; n->is_default = false; n->lowerdatums = $5; n->upperdatums = $9; n->location = @3; $$ = n; } /* a DEFAULT partition */ | DEFAULT { PartitionBoundSpec *n = makeNode(PartitionBoundSpec); n->is_default = true; n->location = @1; $$ = n; } ; hash_partbound_elem: NonReservedWord Iconst { $$ = makeDefElem($1, (Node *) makeInteger($2), @1); } ; hash_partbound: hash_partbound_elem { $$ = list_make1($1); } | hash_partbound ',' hash_partbound_elem { $$ = lappend($1, $3); } ; /***************************************************************************** * * 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->objtype = 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 ADD ATTRIBUTE [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 DROP ATTRIBUTE IF EXISTS [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 DROP ATTRIBUTE [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 ALTER ATTRIBUTE [SET DATA] TYPE [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 * *****************************************************************************/ 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 ( query ) TO file [WITH] [(options)] * * where 'query' can be one of: * { SELECT | UPDATE | INSERT | DELETE } * * and '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 FROM/TO file * [ [ USING ] DELIMITERS 'delimiter' ] ] * [ WITH NULL AS 'null string' ] * This option placement is not supported with COPY (query...). * *****************************************************************************/ CopyStmt: COPY opt_binary qualified_name opt_column_list copy_from opt_program copy_file_name copy_delimiter opt_with copy_options where_clause { CopyStmt *n = makeNode(CopyStmt); n->relation = $3; n->query = NULL; n->attlist = $4; n->is_from = $5; n->is_program = $6; n->filename = $7; n->whereClause = $11; if (n->is_program && n->filename == NULL) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("STDIN/STDOUT not allowed with PROGRAM"), parser_errposition(@8))); if (!n->is_from && n->whereClause != NULL) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("WHERE clause not allowed with COPY TO"), parser_errposition(@11))); n->options = NIL; /* Concatenate user-supplied flags */ if ($2) n->options = lappend(n->options, $2); if ($8) n->options = lappend(n->options, $8); if ($10) n->options = list_concat(n->options, $10); $$ = (Node *) n; } | COPY '(' PreparableStmt ')' TO opt_program copy_file_name opt_with copy_options { CopyStmt *n = makeNode(CopyStmt); n->relation = NULL; n->query = $3; n->attlist = NIL; n->is_from = false; n->is_program = $6; n->filename = $7; n->options = $9; if (n->is_program && n->filename == NULL) ereport(ERROR, (errcode(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"), @1); } | FREEZE { $$ = makeDefElem("freeze", (Node *) makeBoolean(true), @1); } | DELIMITER opt_as Sconst { $$ = makeDefElem("delimiter", (Node *) makeString($3), @1); } | NULL_P opt_as Sconst { $$ = makeDefElem("null", (Node *) makeString($3), @1); } | CSV { $$ = makeDefElem("format", (Node *) makeString("csv"), @1); } | HEADER_P { $$ = makeDefElem("header", (Node *) makeBoolean(true), @1); } | QUOTE opt_as Sconst { $$ = makeDefElem("quote", (Node *) makeString($3), @1); } | ESCAPE opt_as Sconst { $$ = makeDefElem("escape", (Node *) makeString($3), @1); } | FORCE QUOTE columnList { $$ = makeDefElem("force_quote", (Node *) $3, @1); } | FORCE QUOTE '*' { $$ = makeDefElem("force_quote", (Node *) makeNode(A_Star), @1); } | FORCE NOT NULL_P columnList { $$ = makeDefElem("force_not_null", (Node *) $4, @1); } | FORCE NULL_P columnList { $$ = makeDefElem("force_null", (Node *) $3, @1); } | ENCODING Sconst { $$ = makeDefElem("encoding", (Node *) makeString($2), @1); } ; /* The following exist for backward compatibility with very old versions */ opt_binary: BINARY { $$ = makeDefElem("format", (Node *) makeString("binary"), @1); } | /*EMPTY*/ { $$ = NULL; } ; copy_delimiter: opt_using DELIMITERS Sconst { $$ = makeDefElem("delimiter", (Node *) makeString($3), @2); } | /*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, @1); } ; 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 OptPartitionSpec table_access_method_clause OptWith OnCommitOption OptTableSpace { CreateStmt *n = makeNode(CreateStmt); $4->relpersistence = $2; n->relation = $4; n->tableElts = $6; n->inhRelations = $8; n->partspec = $9; n->ofTypename = NULL; n->constraints = NIL; n->accessMethod = $10; n->options = $11; n->oncommit = $12; n->tablespacename = $13; n->if_not_exists = false; $$ = (Node *) n; } | CREATE OptTemp TABLE IF_P NOT EXISTS qualified_name '(' OptTableElementList ')' OptInherit OptPartitionSpec table_access_method_clause OptWith OnCommitOption OptTableSpace { CreateStmt *n = makeNode(CreateStmt); $7->relpersistence = $2; n->relation = $7; n->tableElts = $9; n->inhRelations = $11; n->partspec = $12; n->ofTypename = NULL; n->constraints = NIL; n->accessMethod = $13; n->options = $14; n->oncommit = $15; n->tablespacename = $16; n->if_not_exists = true; $$ = (Node *) n; } | CREATE OptTemp TABLE qualified_name OF any_name OptTypedTableElementList OptPartitionSpec table_access_method_clause OptWith OnCommitOption OptTableSpace { CreateStmt *n = makeNode(CreateStmt); $4->relpersistence = $2; n->relation = $4; n->tableElts = $7; n->inhRelations = NIL; n->partspec = $8; n->ofTypename = makeTypeNameFromNameList($6); n->ofTypename->location = @6; n->constraints = NIL; n->accessMethod = $9; n->options = $10; n->oncommit = $11; n->tablespacename = $12; n->if_not_exists = false; $$ = (Node *) n; } | CREATE OptTemp TABLE IF_P NOT EXISTS qualified_name OF any_name OptTypedTableElementList OptPartitionSpec table_access_method_clause OptWith OnCommitOption OptTableSpace { CreateStmt *n = makeNode(CreateStmt); $7->relpersistence = $2; n->relation = $7; n->tableElts = $10; n->inhRelations = NIL; n->partspec = $11; n->ofTypename = makeTypeNameFromNameList($9); n->ofTypename->location = @9; n->constraints = NIL; n->accessMethod = $12; n->options = $13; n->oncommit = $14; n->tablespacename = $15; n->if_not_exists = true; $$ = (Node *) n; } | CREATE OptTemp TABLE qualified_name PARTITION OF qualified_name OptTypedTableElementList PartitionBoundSpec OptPartitionSpec table_access_method_clause OptWith OnCommitOption OptTableSpace { CreateStmt *n = makeNode(CreateStmt); $4->relpersistence = $2; n->relation = $4; n->tableElts = $8; n->inhRelations = list_make1($7); n->partbound = $9; n->partspec = $10; n->ofTypename = NULL; n->constraints = NIL; n->accessMethod = $11; n->options = $12; n->oncommit = $13; n->tablespacename = $14; n->if_not_exists = false; $$ = (Node *) n; } | CREATE OptTemp TABLE IF_P NOT EXISTS qualified_name PARTITION OF qualified_name OptTypedTableElementList PartitionBoundSpec OptPartitionSpec table_access_method_clause OptWith OnCommitOption OptTableSpace { CreateStmt *n = makeNode(CreateStmt); $7->relpersistence = $2; n->relation = $7; n->tableElts = $11; n->inhRelations = list_make1($10); n->partbound = $12; n->partspec = $13; n->ofTypename = NULL; n->constraints = NIL; n->accessMethod = $14; n->options = $15; n->oncommit = $16; n->tablespacename = $17; 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 opt_column_storage opt_column_compression create_generic_options ColQualList { ColumnDef *n = makeNode(ColumnDef); n->colname = $1; n->typeName = $2; n->storage_name = $3; n->compression = $4; 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 = $5; SplitColQualList($6, &n->constraints, &n->collClause, yyscanner); n->location = @1; $$ = (Node *) n; } ; columnOptions: ColId 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($2, &n->constraints, &n->collClause, yyscanner); n->location = @1; $$ = (Node *) n; } | 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; } ; column_compression: COMPRESSION ColId { $$ = $2; } | COMPRESSION DEFAULT { $$ = pstrdup("default"); } ; opt_column_compression: column_compression { $$ = $1; } | /*EMPTY*/ { $$ = NULL; } ; column_storage: STORAGE ColId { $$ = $2; } | STORAGE DEFAULT { $$ = pstrdup("default"); } ; opt_column_storage: column_storage { $$ = $1; } | /*EMPTY*/ { $$ = NULL; } ; ColQualList: ColQualList ColConstraint { $$ = lappend($1, $2); } | /*EMPTY*/ { $$ = NIL; } ; ColConstraint: CONSTRAINT name ColConstraintElem { Constraint *n = castNode(Constraint, $3); 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_unique_null_treatment opt_definition OptConsTableSpace { Constraint *n = makeNode(Constraint); n->contype = CONSTR_UNIQUE; n->location = @1; n->nulls_not_distinct = !$2; n->keys = NULL; n->options = $3; n->indexname = NULL; n->indexspace = $4; $$ = (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; n->skip_validation = false; n->initially_valid = true; $$ = (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; } | GENERATED generated_when AS IDENTITY_P OptParenthesizedSeqOptList { Constraint *n = makeNode(Constraint); n->contype = CONSTR_IDENTITY; n->generated_when = $2; n->options = $5; n->location = @1; $$ = (Node *) n; } | GENERATED generated_when AS '(' a_expr ')' STORED { Constraint *n = makeNode(Constraint); n->contype = CONSTR_GENERATED; n->generated_when = $2; n->raw_expr = $5; n->cooked_expr = NULL; n->location = @1; /* * Can't do this in the grammar because of shift/reduce * conflicts. (IDENTITY allows both ALWAYS and BY * DEFAULT, but generated columns only allow ALWAYS.) We * can also give a more useful error message and location. */ if ($2 != ATTRIBUTE_IDENTITY_ALWAYS) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("for a generated column, GENERATED ALWAYS must be specified"), parser_errposition(@2))); $$ = (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 = ($5)->updateAction->action; n->fk_del_action = ($5)->deleteAction->action; n->fk_del_set_cols = ($5)->deleteAction->cols; n->skip_validation = false; n->initially_valid = true; $$ = (Node *) n; } ; opt_unique_null_treatment: NULLS_P DISTINCT { $$ = true; } | NULLS_P NOT DISTINCT { $$ = false; } | /*EMPTY*/ { $$ = true; } ; generated_when: ALWAYS { $$ = ATTRIBUTE_IDENTITY_ALWAYS; } | BY DEFAULT { $$ = ATTRIBUTE_IDENTITY_BY_DEFAULT; } ; /* * 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; n->relationOid = InvalidOid; $$ = (Node *) n; } ; TableLikeOptionList: TableLikeOptionList INCLUDING TableLikeOption { $$ = $1 | $3; } | TableLikeOptionList EXCLUDING TableLikeOption { $$ = $1 & ~$3; } | /* EMPTY */ { $$ = 0; } ; TableLikeOption: COMMENTS { $$ = CREATE_TABLE_LIKE_COMMENTS; } | COMPRESSION { $$ = CREATE_TABLE_LIKE_COMPRESSION; } | CONSTRAINTS { $$ = CREATE_TABLE_LIKE_CONSTRAINTS; } | DEFAULTS { $$ = CREATE_TABLE_LIKE_DEFAULTS; } | IDENTITY_P { $$ = CREATE_TABLE_LIKE_IDENTITY; } | GENERATED { $$ = CREATE_TABLE_LIKE_GENERATED; } | INDEXES { $$ = CREATE_TABLE_LIKE_INDEXES; } | STATISTICS { $$ = CREATE_TABLE_LIKE_STATISTICS; } | STORAGE { $$ = CREATE_TABLE_LIKE_STORAGE; } | 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 = castNode(Constraint, $3); 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 opt_unique_null_treatment '(' columnList ')' opt_c_include opt_definition OptConsTableSpace ConstraintAttributeSpec { Constraint *n = makeNode(Constraint); n->contype = CONSTR_UNIQUE; n->location = @1; n->nulls_not_distinct = !$2; n->keys = $4; n->including = $6; n->options = $7; n->indexname = NULL; n->indexspace = $8; processCASbits($9, @9, "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->including = 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_c_include opt_definition OptConsTableSpace ConstraintAttributeSpec { Constraint *n = makeNode(Constraint); n->contype = CONSTR_PRIMARY; n->location = @1; n->keys = $4; n->including = $6; n->options = $7; n->indexname = NULL; n->indexspace = $8; processCASbits($9, @9, "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->including = 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_c_include opt_definition OptConsTableSpace OptWhereClause ConstraintAttributeSpec { Constraint *n = makeNode(Constraint); n->contype = CONSTR_EXCLUSION; n->location = @1; n->access_method = $2; n->exclusions = $4; n->including = $6; n->options = $7; n->indexname = NULL; n->indexspace = $8; n->where_clause = $9; processCASbits($10, @10, "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 = ($10)->updateAction->action; n->fk_del_action = ($10)->deleteAction->action; n->fk_del_set_cols = ($10)->deleteAction->cols; 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); } ; opt_c_include: INCLUDE '(' columnList ')' { $$ = $3; } | /* EMPTY */ { $$ = NIL; } ; 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); } ; OptWhereClause: WHERE '(' a_expr ')' { $$ = $3; } | /*EMPTY*/ { $$ = NULL; } ; key_actions: key_update { KeyActions *n = palloc(sizeof(KeyActions)); n->updateAction = $1; n->deleteAction = palloc(sizeof(KeyAction)); n->deleteAction->action = FKCONSTR_ACTION_NOACTION; n->deleteAction->cols = NIL; $$ = n; } | key_delete { KeyActions *n = palloc(sizeof(KeyActions)); n->updateAction = palloc(sizeof(KeyAction)); n->updateAction->action = FKCONSTR_ACTION_NOACTION; n->updateAction->cols = NIL; n->deleteAction = $1; $$ = n; } | key_update key_delete { KeyActions *n = palloc(sizeof(KeyActions)); n->updateAction = $1; n->deleteAction = $2; $$ = n; } | key_delete key_update { KeyActions *n = palloc(sizeof(KeyActions)); n->updateAction = $2; n->deleteAction = $1; $$ = n; } | /*EMPTY*/ { KeyActions *n = palloc(sizeof(KeyActions)); n->updateAction = palloc(sizeof(KeyAction)); n->updateAction->action = FKCONSTR_ACTION_NOACTION; n->updateAction->cols = NIL; n->deleteAction = palloc(sizeof(KeyAction)); n->deleteAction->action = FKCONSTR_ACTION_NOACTION; n->deleteAction->cols = NIL; $$ = n; } ; key_update: ON UPDATE key_action { if (($3)->cols) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("a column list with %s is only supported for ON DELETE actions", ($3)->action == FKCONSTR_ACTION_SETNULL ? "SET NULL" : "SET DEFAULT"), parser_errposition(@1))); $$ = $3; } ; key_delete: ON DELETE_P key_action { $$ = $3; } ; key_action: NO ACTION { KeyAction *n = palloc(sizeof(KeyAction)); n->action = FKCONSTR_ACTION_NOACTION; n->cols = NIL; $$ = n; } | RESTRICT { KeyAction *n = palloc(sizeof(KeyAction)); n->action = FKCONSTR_ACTION_RESTRICT; n->cols = NIL; $$ = n; } | CASCADE { KeyAction *n = palloc(sizeof(KeyAction)); n->action = FKCONSTR_ACTION_CASCADE; n->cols = NIL; $$ = n; } | SET NULL_P opt_column_list { KeyAction *n = palloc(sizeof(KeyAction)); n->action = FKCONSTR_ACTION_SETNULL; n->cols = $3; $$ = n; } | SET DEFAULT opt_column_list { KeyAction *n = palloc(sizeof(KeyAction)); n->action = FKCONSTR_ACTION_SETDEFAULT; n->cols = $3; $$ = n; } ; OptInherit: INHERITS '(' qualified_name_list ')' { $$ = $3; } | /*EMPTY*/ { $$ = NIL; } ; /* Optional partition key specification */ OptPartitionSpec: PartitionSpec { $$ = $1; } | /*EMPTY*/ { $$ = NULL; } ; PartitionSpec: PARTITION BY ColId '(' part_params ')' { PartitionSpec *n = makeNode(PartitionSpec); n->strategy = parsePartitionStrategy($3); n->partParams = $5; n->location = @1; $$ = n; } ; part_params: part_elem { $$ = list_make1($1); } | part_params ',' part_elem { $$ = lappend($1, $3); } ; part_elem: ColId opt_collate opt_qualified_name { PartitionElem *n = makeNode(PartitionElem); n->name = $1; n->expr = NULL; n->collation = $2; n->opclass = $3; n->location = @1; $$ = n; } | func_expr_windowless opt_collate opt_qualified_name { PartitionElem *n = makeNode(PartitionElem); n->name = NULL; n->expr = $1; n->collation = $2; n->opclass = $3; n->location = @1; $$ = n; } | '(' a_expr ')' opt_collate opt_qualified_name { PartitionElem *n = makeNode(PartitionElem); n->name = NULL; n->expr = $2; n->collation = $4; n->opclass = $5; n->location = @1; $$ = n; } ; table_access_method_clause: USING name { $$ = $2; } | /*EMPTY*/ { $$ = NULL; } ; /* WITHOUT OIDS is legacy only */ OptWith: WITH reloptions { $$ = $2; } | WITHOUT OIDS { $$ = NIL; } | /*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 name { $$ = $3; } ; /***************************************************************************** * * QUERY : * CREATE STATISTICS [[IF NOT EXISTS] stats_name] [(stat types)] * ON expression-list FROM from_list * * Note: the expectation here is that the clauses after ON are a subset of * SELECT syntax, allowing for expressions and joined tables, and probably * someday a WHERE clause. Much less than that is currently implemented, * but the grammar accepts it and then we'll throw FEATURE_NOT_SUPPORTED * errors as necessary at execution. * * Statistics name is optional unless IF NOT EXISTS is specified. * *****************************************************************************/ CreateStatsStmt: CREATE STATISTICS opt_qualified_name opt_name_list ON stats_params FROM from_list { CreateStatsStmt *n = makeNode(CreateStatsStmt); n->defnames = $3; n->stat_types = $4; n->exprs = $6; n->relations = $8; n->stxcomment = NULL; n->if_not_exists = false; $$ = (Node *) n; } | CREATE STATISTICS IF_P NOT EXISTS any_name opt_name_list ON stats_params FROM from_list { CreateStatsStmt *n = makeNode(CreateStatsStmt); n->defnames = $6; n->stat_types = $7; n->exprs = $9; n->relations = $11; n->stxcomment = NULL; n->if_not_exists = true; $$ = (Node *) n; } ; /* * Statistics attributes can be either simple column references, or arbitrary * expressions in parens. For compatibility with index attributes permitted * in CREATE INDEX, we allow an expression that's just a function call to be * written without parens. */ stats_params: stats_param { $$ = list_make1($1); } | stats_params ',' stats_param { $$ = lappend($1, $3); } ; stats_param: ColId { $$ = makeNode(StatsElem); $$->name = $1; $$->expr = NULL; } | func_expr_windowless { $$ = makeNode(StatsElem); $$->name = NULL; $$->expr = $1; } | '(' a_expr ')' { $$ = makeNode(StatsElem); $$->name = NULL; $$->expr = $2; } ; /***************************************************************************** * * QUERY : * ALTER STATISTICS [IF EXISTS] stats_name * SET STATISTICS * *****************************************************************************/ AlterStatsStmt: ALTER STATISTICS any_name SET STATISTICS SignedIconst { AlterStatsStmt *n = makeNode(AlterStatsStmt); n->defnames = $3; n->missing_ok = false; n->stxstattarget = $6; $$ = (Node *) n; } | ALTER STATISTICS IF_P EXISTS any_name SET STATISTICS SignedIconst { AlterStatsStmt *n = makeNode(AlterStatsStmt); n->defnames = $5; n->missing_ok = true; n->stxstattarget = $8; $$ = (Node *) n; } ; /***************************************************************************** * * 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->objtype = 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->objtype = 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 table_access_method_clause OptWith OnCommitOption OptTableSpace { $$ = makeNode(IntoClause); $$->rel = $1; $$->colNames = $2; $$->accessMethod = $3; $$->options = $4; $$->onCommit = $5; $$->tableSpaceName = $6; $$->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->objtype = 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->objtype = 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 table_access_method_clause opt_reloptions OptTableSpace { $$ = makeNode(IntoClause); $$->rel = $1; $$->colNames = $2; $$->accessMethod = $3; $$->options = $4; $$->onCommit = ONCOMMIT_NOOP; $$->tableSpaceName = $5; $$->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; } ; OptParenthesizedSeqOptList: '(' SeqOptList ')' { $$ = $2; } | /*EMPTY*/ { $$ = NIL; } ; SeqOptList: SeqOptElem { $$ = list_make1($1); } | SeqOptList SeqOptElem { $$ = lappend($1, $2); } ; SeqOptElem: AS SimpleTypename { $$ = makeDefElem("as", (Node *) $2, @1); } | CACHE NumericOnly { $$ = makeDefElem("cache", (Node *) $2, @1); } | CYCLE { $$ = makeDefElem("cycle", (Node *) makeBoolean(true), @1); } | NO CYCLE { $$ = makeDefElem("cycle", (Node *) makeBoolean(false), @1); } | INCREMENT opt_by NumericOnly { $$ = makeDefElem("increment", (Node *) $3, @1); } | MAXVALUE NumericOnly { $$ = makeDefElem("maxvalue", (Node *) $2, @1); } | MINVALUE NumericOnly { $$ = makeDefElem("minvalue", (Node *) $2, @1); } | NO MAXVALUE { $$ = makeDefElem("maxvalue", NULL, @1); } | NO MINVALUE { $$ = makeDefElem("minvalue", NULL, @1); } | OWNED BY any_name { $$ = makeDefElem("owned_by", (Node *) $3, @1); } | SEQUENCE NAME_P any_name { /* not documented, only used by pg_dump */ $$ = makeDefElem("sequence_name", (Node *) $3, @1); } | START opt_with NumericOnly { $$ = makeDefElem("start", (Node *) $3, @1); } | RESTART { $$ = makeDefElem("restart", NULL, @1); } | RESTART opt_with NumericOnly { $$ = makeDefElem("restart", (Node *) $3, @1); } ; opt_by: BY | /* EMPTY */ ; NumericOnly: FCONST { $$ = (Node *) makeFloat($1); } | '+' FCONST { $$ = (Node *) makeFloat($2); } | '-' FCONST { Float *f = makeFloat($2); doNegateFloat(f); $$ = (Node *) f; } | SignedIconst { $$ = (Node *) 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 name { /* * We now interpret parameterless CREATE LANGUAGE as * CREATE EXTENSION. "OR REPLACE" is silently translated * to "IF NOT EXISTS", which isn't quite the same, but * seems more useful than throwing an error. We just * ignore TRUSTED, as the previous code would have too. */ CreateExtensionStmt *n = makeNode(CreateExtensionStmt); n->if_not_exists = $2; n->extname = $6; n->options = NIL; $$ = (Node *) n; } | CREATE opt_or_replace opt_trusted opt_procedural LANGUAGE name 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; } | /*EMPTY*/ { $$ = NIL; } ; opt_procedural: PROCEDURAL | /*EMPTY*/ ; /***************************************************************************** * * QUERY: * CREATE TABLESPACE tablespace LOCATION '/path/to/tablespace/' * *****************************************************************************/ CreateTableSpaceStmt: CREATE TABLESPACE name OptTableSpaceOwner LOCATION Sconst opt_reloptions { CreateTableSpaceStmt *n = makeNode(CreateTableSpaceStmt); n->tablespacename = $3; n->owner = $4; n->location = $6; n->options = $7; $$ = (Node *) n; } ; OptTableSpaceOwner: OWNER RoleSpec { $$ = $2; } | /*EMPTY */ { $$ = NULL; } ; /***************************************************************************** * * QUERY : * DROP TABLESPACE * * No need for drop behaviour as we cannot implement dependencies for * objects in other databases; we can only support RESTRICT. * ****************************************************************************/ DropTableSpaceStmt: DROP TABLESPACE name { DropTableSpaceStmt *n = makeNode(DropTableSpaceStmt); n->tablespacename = $3; n->missing_ok = false; $$ = (Node *) n; } | DROP TABLESPACE IF_P EXISTS name { DropTableSpaceStmt *n = makeNode(DropTableSpaceStmt); n->tablespacename = $5; n->missing_ok = true; $$ = (Node *) n; } ; /***************************************************************************** * * QUERY: * CREATE EXTENSION extension * [ WITH ] [ SCHEMA schema ] [ VERSION version ] * *****************************************************************************/ CreateExtensionStmt: CREATE EXTENSION name opt_with create_extension_opt_list { CreateExtensionStmt *n = makeNode(CreateExtensionStmt); n->extname = $3; n->if_not_exists = false; n->options = $5; $$ = (Node *) n; } | CREATE EXTENSION IF_P NOT EXISTS name opt_with create_extension_opt_list { CreateExtensionStmt *n = makeNode(CreateExtensionStmt); n->extname = $6; n->if_not_exists = true; n->options = $8; $$ = (Node *) n; } ; create_extension_opt_list: create_extension_opt_list create_extension_opt_item { $$ = lappend($1, $2); } | /* EMPTY */ { $$ = NIL; } ; create_extension_opt_item: SCHEMA name { $$ = makeDefElem("schema", (Node *) makeString($2), @1); } | VERSION_P NonReservedWord_or_Sconst { $$ = makeDefElem("new_version", (Node *) makeString($2), @1); } | FROM NonReservedWord_or_Sconst { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("CREATE EXTENSION ... FROM is no longer supported"), parser_errposition(@1))); } | CASCADE { $$ = makeDefElem("cascade", (Node *) makeBoolean(true), @1); } ; /***************************************************************************** * * ALTER EXTENSION name UPDATE [ TO version ] * *****************************************************************************/ AlterExtensionStmt: ALTER EXTENSION name UPDATE alter_extension_opt_list { AlterExtensionStmt *n = makeNode(AlterExtensionStmt); n->extname = $3; n->options = $5; $$ = (Node *) n; } ; alter_extension_opt_list: alter_extension_opt_list alter_extension_opt_item { $$ = lappend($1, $2); } | /* EMPTY */ { $$ = NIL; } ; alter_extension_opt_item: TO NonReservedWord_or_Sconst { $$ = makeDefElem("new_version", (Node *) makeString($2), @1); } ; /***************************************************************************** * * ALTER EXTENSION name ADD/DROP object-identifier * *****************************************************************************/ AlterExtensionContentsStmt: ALTER EXTENSION name add_drop object_type_name name { AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt); n->extname = $3; n->action = $4; n->objtype = $5; n->object = (Node *) makeString($6); $$ = (Node *) n; } | ALTER EXTENSION name add_drop object_type_any_name any_name { AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt); n->extname = $3; n->action = $4; n->objtype = $5; n->object = (Node *) $6; $$ = (Node *) n; } | ALTER EXTENSION name add_drop AGGREGATE aggregate_with_argtypes { AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt); n->extname = $3; n->action = $4; n->objtype = OBJECT_AGGREGATE; n->object = (Node *) $6; $$ = (Node *) n; } | ALTER EXTENSION name add_drop CAST '(' Typename AS Typename ')' { AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt); n->extname = $3; n->action = $4; n->objtype = OBJECT_CAST; n->object = (Node *) list_make2($7, $9); $$ = (Node *) n; } | ALTER EXTENSION name add_drop DOMAIN_P Typename { AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt); n->extname = $3; n->action = $4; n->objtype = OBJECT_DOMAIN; n->object = (Node *) $6; $$ = (Node *) n; } | ALTER EXTENSION name add_drop FUNCTION function_with_argtypes { AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt); n->extname = $3; n->action = $4; n->objtype = OBJECT_FUNCTION; n->object = (Node *) $6; $$ = (Node *) n; } | ALTER EXTENSION name add_drop OPERATOR operator_with_argtypes { AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt); n->extname = $3; n->action = $4; n->objtype = OBJECT_OPERATOR; n->object = (Node *) $6; $$ = (Node *) n; } | ALTER EXTENSION name add_drop OPERATOR CLASS any_name USING name { AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt); n->extname = $3; n->action = $4; n->objtype = OBJECT_OPCLASS; n->object = (Node *) lcons(makeString($9), $7); $$ = (Node *) n; } | ALTER EXTENSION name add_drop OPERATOR FAMILY any_name USING name { AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt); n->extname = $3; n->action = $4; n->objtype = OBJECT_OPFAMILY; n->object = (Node *) lcons(makeString($9), $7); $$ = (Node *) n; } | ALTER EXTENSION name add_drop PROCEDURE function_with_argtypes { AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt); n->extname = $3; n->action = $4; n->objtype = OBJECT_PROCEDURE; n->object = (Node *) $6; $$ = (Node *) n; } | ALTER EXTENSION name add_drop ROUTINE function_with_argtypes { AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt); n->extname = $3; n->action = $4; n->objtype = OBJECT_ROUTINE; n->object = (Node *) $6; $$ = (Node *) n; } | ALTER EXTENSION name add_drop TRANSFORM FOR Typename LANGUAGE name { AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt); n->extname = $3; n->action = $4; n->objtype = OBJECT_TRANSFORM; n->object = (Node *) list_make2($7, makeString($9)); $$ = (Node *) n; } | ALTER EXTENSION name add_drop TYPE_P Typename { AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt); n->extname = $3; n->action = $4; n->objtype = OBJECT_TYPE; n->object = (Node *) $6; $$ = (Node *) n; } ; /***************************************************************************** * * QUERY: * CREATE FOREIGN DATA WRAPPER name options * *****************************************************************************/ CreateFdwStmt: CREATE FOREIGN DATA_P WRAPPER name opt_fdw_options create_generic_options { CreateFdwStmt *n = makeNode(CreateFdwStmt); n->fdwname = $5; n->func_options = $6; n->options = $7; $$ = (Node *) n; } ; fdw_option: HANDLER handler_name { $$ = makeDefElem("handler", (Node *) $2, @1); } | NO HANDLER { $$ = makeDefElem("handler", NULL, @1); } | VALIDATOR handler_name { $$ = makeDefElem("validator", (Node *) $2, @1); } | NO VALIDATOR { $$ = makeDefElem("validator", NULL, @1); } ; fdw_options: fdw_option { $$ = list_make1($1); } | fdw_options fdw_option { $$ = lappend($1, $2); } ; opt_fdw_options: fdw_options { $$ = $1; } | /*EMPTY*/ { $$ = NIL; } ; /***************************************************************************** * * QUERY : * ALTER FOREIGN DATA WRAPPER name options * ****************************************************************************/ AlterFdwStmt: ALTER FOREIGN DATA_P WRAPPER name opt_fdw_options alter_generic_options { AlterFdwStmt *n = makeNode(AlterFdwStmt); n->fdwname = $5; n->func_options = $6; n->options = $7; $$ = (Node *) n; } | ALTER FOREIGN DATA_P WRAPPER name fdw_options { AlterFdwStmt *n = makeNode(AlterFdwStmt); n->fdwname = $5; n->func_options = $6; n->options = NIL; $$ = (Node *) n; } ; /* Options definition for CREATE FDW, SERVER and USER MAPPING */ create_generic_options: OPTIONS '(' generic_option_list ')' { $$ = $3; } | /*EMPTY*/ { $$ = NIL; } ; generic_option_list: generic_option_elem { $$ = list_make1($1); } | generic_option_list ',' generic_option_elem { $$ = lappend($1, $3); } ; /* Options definition for ALTER FDW, SERVER and USER MAPPING */ alter_generic_options: OPTIONS '(' alter_generic_option_list ')' { $$ = $3; } ; alter_generic_option_list: alter_generic_option_elem { $$ = list_make1($1); } | alter_generic_option_list ',' alter_generic_option_elem { $$ = lappend($1, $3); } ; alter_generic_option_elem: generic_option_elem { $$ = $1; } | SET generic_option_elem { $$ = $2; $$->defaction = DEFELEM_SET; } | ADD_P generic_option_elem { $$ = $2; $$->defaction = DEFELEM_ADD; } | DROP generic_option_name { $$ = makeDefElemExtended(NULL, $2, NULL, DEFELEM_DROP, @2); } ; generic_option_elem: generic_option_name generic_option_arg { $$ = makeDefElem($1, $2, @1); } ; generic_option_name: ColLabel { $$ = $1; } ; /* We could use def_arg here, but the spec only requires string literals */ generic_option_arg: Sconst { $$ = (Node *) makeString($1); } ; /***************************************************************************** * * QUERY: * CREATE SERVER name [TYPE] [VERSION] [OPTIONS] * *****************************************************************************/ CreateForeignServerStmt: CREATE SERVER name opt_type opt_foreign_server_version FOREIGN DATA_P WRAPPER name create_generic_options { CreateForeignServerStmt *n = makeNode(CreateForeignServerStmt); n->servername = $3; n->servertype = $4; n->version = $5; n->fdwname = $9; n->options = $10; n->if_not_exists = false; $$ = (Node *) n; } | CREATE SERVER IF_P NOT EXISTS name opt_type opt_foreign_server_version FOREIGN DATA_P WRAPPER name create_generic_options { CreateForeignServerStmt *n = makeNode(CreateForeignServerStmt); n->servername = $6; n->servertype = $7; n->version = $8; n->fdwname = $12; n->options = $13; n->if_not_exists = true; $$ = (Node *) n; } ; opt_type: TYPE_P Sconst { $$ = $2; } | /*EMPTY*/ { $$ = NULL; } ; foreign_server_version: VERSION_P Sconst { $$ = $2; } | VERSION_P NULL_P { $$ = NULL; } ; opt_foreign_server_version: foreign_server_version { $$ = $1; } | /*EMPTY*/ { $$ = NULL; } ; /***************************************************************************** * * QUERY : * ALTER SERVER name [VERSION] [OPTIONS] * ****************************************************************************/ AlterForeignServerStmt: ALTER SERVER name foreign_server_version alter_generic_options { AlterForeignServerStmt *n = makeNode(AlterForeignServerStmt); n->servername = $3; n->version = $4; n->options = $5; n->has_version = true; $$ = (Node *) n; } | ALTER SERVER name foreign_server_version { AlterForeignServerStmt *n = makeNode(AlterForeignServerStmt); n->servername = $3; n->version = $4; n->has_version = true; $$ = (Node *) n; } | ALTER SERVER name alter_generic_options { AlterForeignServerStmt *n = makeNode(AlterForeignServerStmt); n->servername = $3; n->options = $4; $$ = (Node *) n; } ; /***************************************************************************** * * QUERY: * CREATE FOREIGN TABLE relname (...) SERVER name (...) * *****************************************************************************/ CreateForeignTableStmt: CREATE FOREIGN TABLE qualified_name '(' OptTableElementList ')' OptInherit SERVER name create_generic_options { CreateForeignTableStmt *n = makeNode(CreateForeignTableStmt); $4->relpersistence = RELPERSISTENCE_PERMANENT; n->base.relation = $4; n->base.tableElts = $6; n->base.inhRelations = $8; n->base.ofTypename = NULL; n->base.constraints = NIL; n->base.options = NIL; n->base.oncommit = ONCOMMIT_NOOP; n->base.tablespacename = NULL; n->base.if_not_exists = false; /* FDW-specific data */ n->servername = $10; n->options = $11; $$ = (Node *) n; } | CREATE FOREIGN TABLE IF_P NOT EXISTS qualified_name '(' OptTableElementList ')' OptInherit SERVER name create_generic_options { CreateForeignTableStmt *n = makeNode(CreateForeignTableStmt); $7->relpersistence = RELPERSISTENCE_PERMANENT; n->base.relation = $7; n->base.tableElts = $9; n->base.inhRelations = $11; n->base.ofTypename = NULL; n->base.constraints = NIL; n->base.options = NIL; n->base.oncommit = ONCOMMIT_NOOP; n->base.tablespacename = NULL; n->base.if_not_exists = true; /* FDW-specific data */ n->servername = $13; n->options = $14; $$ = (Node *) n; } | CREATE FOREIGN TABLE qualified_name PARTITION OF qualified_name OptTypedTableElementList PartitionBoundSpec SERVER name create_generic_options { CreateForeignTableStmt *n = makeNode(CreateForeignTableStmt); $4->relpersistence = RELPERSISTENCE_PERMANENT; n->base.relation = $4; n->base.inhRelations = list_make1($7); n->base.tableElts = $8; n->base.partbound = $9; n->base.ofTypename = NULL; n->base.constraints = NIL; n->base.options = NIL; n->base.oncommit = ONCOMMIT_NOOP; n->base.tablespacename = NULL; n->base.if_not_exists = false; /* FDW-specific data */ n->servername = $11; n->options = $12; $$ = (Node *) n; } | CREATE FOREIGN TABLE IF_P NOT EXISTS qualified_name PARTITION OF qualified_name OptTypedTableElementList PartitionBoundSpec SERVER name create_generic_options { CreateForeignTableStmt *n = makeNode(CreateForeignTableStmt); $7->relpersistence = RELPERSISTENCE_PERMANENT; n->base.relation = $7; n->base.inhRelations = list_make1($10); n->base.tableElts = $11; n->base.partbound = $12; n->base.ofTypename = NULL; n->base.constraints = NIL; n->base.options = NIL; n->base.oncommit = ONCOMMIT_NOOP; n->base.tablespacename = NULL; n->base.if_not_exists = true; /* FDW-specific data */ n->servername = $14; n->options = $15; $$ = (Node *) n; } ; /***************************************************************************** * * QUERY: * IMPORT FOREIGN SCHEMA remote_schema * [ { LIMIT TO | EXCEPT } ( table_list ) ] * FROM SERVER server_name INTO local_schema [ OPTIONS (...) ] * ****************************************************************************/ ImportForeignSchemaStmt: IMPORT_P FOREIGN SCHEMA name import_qualification FROM SERVER name INTO name create_generic_options { ImportForeignSchemaStmt *n = makeNode(ImportForeignSchemaStmt); n->server_name = $8; n->remote_schema = $4; n->local_schema = $10; n->list_type = $5->type; n->table_list = $5->table_names; n->options = $11; $$ = (Node *) n; } ; import_qualification_type: LIMIT TO { $$ = FDW_IMPORT_SCHEMA_LIMIT_TO; } | EXCEPT { $$ = FDW_IMPORT_SCHEMA_EXCEPT; } ; import_qualification: import_qualification_type '(' relation_expr_list ')' { ImportQual *n = (ImportQual *) palloc(sizeof(ImportQual)); n->type = $1; n->table_names = $3; $$ = n; } | /*EMPTY*/ { ImportQual *n = (ImportQual *) palloc(sizeof(ImportQual)); n->type = FDW_IMPORT_SCHEMA_ALL; n->table_names = NIL; $$ = n; } ; /***************************************************************************** * * QUERY: * CREATE USER MAPPING FOR auth_ident SERVER name [OPTIONS] * *****************************************************************************/ CreateUserMappingStmt: CREATE USER MAPPING FOR auth_ident SERVER name create_generic_options { CreateUserMappingStmt *n = makeNode(CreateUserMappingStmt); n->user = $5; n->servername = $7; n->options = $8; n->if_not_exists = false; $$ = (Node *) n; } | CREATE USER MAPPING IF_P NOT EXISTS FOR auth_ident SERVER name create_generic_options { CreateUserMappingStmt *n = makeNode(CreateUserMappingStmt); n->user = $8; n->servername = $10; n->options = $11; n->if_not_exists = true; $$ = (Node *) n; } ; /* User mapping authorization identifier */ auth_ident: RoleSpec { $$ = $1; } | USER { $$ = makeRoleSpec(ROLESPEC_CURRENT_USER, @1); } ; /***************************************************************************** * * QUERY : * DROP USER MAPPING FOR auth_ident SERVER name * * XXX you'd think this should have a CASCADE/RESTRICT option, even if it's * only pro forma; but the SQL standard doesn't show one. ****************************************************************************/ DropUserMappingStmt: DROP USER MAPPING FOR auth_ident SERVER name { DropUserMappingStmt *n = makeNode(DropUserMappingStmt); n->user = $5; n->servername = $7; n->missing_ok = false; $$ = (Node *) n; } | DROP USER MAPPING IF_P EXISTS FOR auth_ident SERVER name { DropUserMappingStmt *n = makeNode(DropUserMappingStmt); n->user = $7; n->servername = $9; n->missing_ok = true; $$ = (Node *) n; } ; /***************************************************************************** * * QUERY : * ALTER USER MAPPING FOR auth_ident SERVER name OPTIONS * ****************************************************************************/ AlterUserMappingStmt: ALTER USER MAPPING FOR auth_ident SERVER name alter_generic_options { AlterUserMappingStmt *n = makeNode(AlterUserMappingStmt); n->user = $5; n->servername = $7; n->options = $8; $$ = (Node *) n; } ; /***************************************************************************** * * QUERIES: * CREATE POLICY name ON table * [AS { PERMISSIVE | RESTRICTIVE } ] * [FOR { SELECT | INSERT | UPDATE | DELETE } ] * [TO role, ...] * [USING (qual)] [WITH CHECK (with check qual)] * ALTER POLICY name ON table [TO role, ...] * [USING (qual)] [WITH CHECK (with check qual)] * *****************************************************************************/ CreatePolicyStmt: CREATE POLICY name ON qualified_name RowSecurityDefaultPermissive RowSecurityDefaultForCmd RowSecurityDefaultToRole RowSecurityOptionalExpr RowSecurityOptionalWithCheck { CreatePolicyStmt *n = makeNode(CreatePolicyStmt); n->policy_name = $3; n->table = $5; n->permissive = $6; n->cmd_name = $7; n->roles = $8; n->qual = $9; n->with_check = $10; $$ = (Node *) n; } ; AlterPolicyStmt: ALTER POLICY name ON qualified_name RowSecurityOptionalToRole RowSecurityOptionalExpr RowSecurityOptionalWithCheck { AlterPolicyStmt *n = makeNode(AlterPolicyStmt); n->policy_name = $3; n->table = $5; n->roles = $6; n->qual = $7; n->with_check = $8; $$ = (Node *) n; } ; RowSecurityOptionalExpr: USING '(' a_expr ')' { $$ = $3; } | /* EMPTY */ { $$ = NULL; } ; RowSecurityOptionalWithCheck: WITH CHECK '(' a_expr ')' { $$ = $4; } | /* EMPTY */ { $$ = NULL; } ; RowSecurityDefaultToRole: TO role_list { $$ = $2; } | /* EMPTY */ { $$ = list_make1(makeRoleSpec(ROLESPEC_PUBLIC, -1)); } ; RowSecurityOptionalToRole: TO role_list { $$ = $2; } | /* EMPTY */ { $$ = NULL; } ; RowSecurityDefaultPermissive: AS IDENT { if (strcmp($2, "permissive") == 0) $$ = true; else if (strcmp($2, "restrictive") == 0) $$ = false; else ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("unrecognized row security option \"%s\"", $2), errhint("Only PERMISSIVE or RESTRICTIVE policies are supported currently."), parser_errposition(@2))); } | /* EMPTY */ { $$ = true; } ; RowSecurityDefaultForCmd: FOR row_security_cmd { $$ = $2; } | /* EMPTY */ { $$ = "all"; } ; row_security_cmd: ALL { $$ = "all"; } | SELECT { $$ = "select"; } | INSERT { $$ = "insert"; } | UPDATE { $$ = "update"; } | DELETE_P { $$ = "delete"; } ; /***************************************************************************** * * QUERY: * CREATE ACCESS METHOD name HANDLER handler_name * *****************************************************************************/ CreateAmStmt: CREATE ACCESS METHOD name TYPE_P am_type HANDLER handler_name { CreateAmStmt *n = makeNode(CreateAmStmt); n->amname = $4; n->handler_name = $8; n->amtype = $6; $$ = (Node *) n; } ; am_type: INDEX { $$ = AMTYPE_INDEX; } | TABLE { $$ = AMTYPE_TABLE; } ; /***************************************************************************** * * QUERIES : * CREATE TRIGGER ... * *****************************************************************************/ CreateTrigStmt: CREATE opt_or_replace TRIGGER name TriggerActionTime TriggerEvents ON qualified_name TriggerReferencing TriggerForSpec TriggerWhen EXECUTE FUNCTION_or_PROCEDURE func_name '(' TriggerFuncArgs ')' { CreateTrigStmt *n = makeNode(CreateTrigStmt); n->replace = $2; n->isconstraint = false; n->trigname = $4; n->relation = $8; n->funcname = $14; n->args = $16; n->row = $10; n->timing = $5; n->events = intVal(linitial($6)); n->columns = (List *) lsecond($6); n->whenClause = $11; n->transitionRels = $9; n->deferrable = false; n->initdeferred = false; n->constrrel = NULL; $$ = (Node *) n; } | CREATE opt_or_replace CONSTRAINT TRIGGER name AFTER TriggerEvents ON qualified_name OptConstrFromTable ConstraintAttributeSpec FOR EACH ROW TriggerWhen EXECUTE FUNCTION_or_PROCEDURE func_name '(' TriggerFuncArgs ')' { CreateTrigStmt *n = makeNode(CreateTrigStmt); n->replace = $2; if (n->replace) /* not supported, see CreateTrigger */ ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("CREATE OR REPLACE CONSTRAINT TRIGGER is not supported"))); n->isconstraint = true; n->trigname = $5; n->relation = $9; n->funcname = $18; n->args = $20; n->row = true; n->timing = TRIGGER_TYPE_AFTER; n->events = intVal(linitial($7)); n->columns = (List *) lsecond($7); n->whenClause = $15; n->transitionRels = NIL; processCASbits($11, @11, "TRIGGER", &n->deferrable, &n->initdeferred, NULL, NULL, yyscanner); n->constrrel = $10; $$ = (Node *) n; } ; TriggerActionTime: BEFORE { $$ = TRIGGER_TYPE_BEFORE; } | AFTER { $$ = TRIGGER_TYPE_AFTER; } | INSTEAD OF { $$ = TRIGGER_TYPE_INSTEAD; } ; TriggerEvents: TriggerOneEvent { $$ = $1; } | TriggerEvents OR TriggerOneEvent { int events1 = intVal(linitial($1)); int events2 = intVal(linitial($3)); List *columns1 = (List *) lsecond($1); List *columns2 = (List *) lsecond($3); if (events1 & events2) parser_yyerror("duplicate trigger events specified"); /* * concat'ing the columns lists loses information about * which columns went with which event, but so long as * only UPDATE carries columns and we disallow multiple * UPDATE items, it doesn't matter. Command execution * should just ignore the columns for non-UPDATE events. */ $$ = list_make2(makeInteger(events1 | events2), list_concat(columns1, columns2)); } ; TriggerOneEvent: INSERT { $$ = list_make2(makeInteger(TRIGGER_TYPE_INSERT), NIL); } | DELETE_P { $$ = list_make2(makeInteger(TRIGGER_TYPE_DELETE), NIL); } | UPDATE { $$ = list_make2(makeInteger(TRIGGER_TYPE_UPDATE), NIL); } | UPDATE OF columnList { $$ = list_make2(makeInteger(TRIGGER_TYPE_UPDATE), $3); } | TRUNCATE { $$ = list_make2(makeInteger(TRIGGER_TYPE_TRUNCATE), NIL); } ; TriggerReferencing: REFERENCING TriggerTransitions { $$ = $2; } | /*EMPTY*/ { $$ = NIL; } ; TriggerTransitions: TriggerTransition { $$ = list_make1($1); } | TriggerTransitions TriggerTransition { $$ = lappend($1, $2); } ; TriggerTransition: TransitionOldOrNew TransitionRowOrTable opt_as TransitionRelName { TriggerTransition *n = makeNode(TriggerTransition); n->name = $4; n->isNew = $1; n->isTable = $2; $$ = (Node *) n; } ; TransitionOldOrNew: NEW { $$ = true; } | OLD { $$ = false; } ; TransitionRowOrTable: TABLE { $$ = true; } /* * According to the standard, lack of a keyword here implies ROW. * Support for that would require prohibiting ROW entirely here, * reserving the keyword ROW, and/or requiring AS (instead of * allowing it to be optional, as the standard specifies) as the * next token. Requiring ROW seems cleanest and easiest to * explain. */ | ROW { $$ = false; } ; TransitionRelName: ColId { $$ = $1; } ; TriggerForSpec: FOR TriggerForOptEach TriggerForType { $$ = $3; } | /* EMPTY */ { /* * If ROW/STATEMENT not specified, default to * STATEMENT, per SQL */ $$ = false; } ; TriggerForOptEach: EACH | /*EMPTY*/ ; TriggerForType: ROW { $$ = true; } | STATEMENT { $$ = false; } ; TriggerWhen: WHEN '(' a_expr ')' { $$ = $3; } | /*EMPTY*/ { $$ = NULL; } ; FUNCTION_or_PROCEDURE: FUNCTION | PROCEDURE ; TriggerFuncArgs: TriggerFuncArg { $$ = list_make1($1); } | TriggerFuncArgs ',' TriggerFuncArg { $$ = lappend($1, $3); } | /*EMPTY*/ { $$ = NIL; } ; TriggerFuncArg: Iconst { $$ = (Node *) makeString(psprintf("%d", $1)); } | FCONST { $$ = (Node *) makeString($1); } | Sconst { $$ = (Node *) makeString($1); } | ColLabel { $$ = (Node *) makeString($1); } ; OptConstrFromTable: FROM qualified_name { $$ = $2; } | /*EMPTY*/ { $$ = NULL; } ; ConstraintAttributeSpec: /*EMPTY*/ { $$ = 0; } | ConstraintAttributeSpec ConstraintAttributeElem { /* * We must complain about conflicting options. * We could, but choose not to, complain about redundant * options (ie, where $2's bit is already set in $1). */ int newspec = $1 | $2; /* special message for this case */ if ((newspec & (CAS_NOT_DEFERRABLE | CAS_INITIALLY_DEFERRED)) == (CAS_NOT_DEFERRABLE | CAS_INITIALLY_DEFERRED)) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE"), parser_errposition(@2))); /* generic message for other conflicts */ if ((newspec & (CAS_NOT_DEFERRABLE | CAS_DEFERRABLE)) == (CAS_NOT_DEFERRABLE | CAS_DEFERRABLE) || (newspec & (CAS_INITIALLY_IMMEDIATE | CAS_INITIALLY_DEFERRED)) == (CAS_INITIALLY_IMMEDIATE | CAS_INITIALLY_DEFERRED)) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting constraint properties"), parser_errposition(@2))); $$ = newspec; } ; ConstraintAttributeElem: NOT DEFERRABLE { $$ = CAS_NOT_DEFERRABLE; } | DEFERRABLE { $$ = CAS_DEFERRABLE; } | INITIALLY IMMEDIATE { $$ = CAS_INITIALLY_IMMEDIATE; } | INITIALLY DEFERRED { $$ = CAS_INITIALLY_DEFERRED; } | NOT VALID { $$ = CAS_NOT_VALID; } | NO INHERIT { $$ = CAS_NO_INHERIT; } ; /***************************************************************************** * * QUERIES : * CREATE EVENT TRIGGER ... * ALTER EVENT TRIGGER ... * *****************************************************************************/ CreateEventTrigStmt: CREATE EVENT TRIGGER name ON ColLabel EXECUTE FUNCTION_or_PROCEDURE func_name '(' ')' { CreateEventTrigStmt *n = makeNode(CreateEventTrigStmt); n->trigname = $4; n->eventname = $6; n->whenclause = NULL; n->funcname = $9; $$ = (Node *) n; } | CREATE EVENT TRIGGER name ON ColLabel WHEN event_trigger_when_list EXECUTE FUNCTION_or_PROCEDURE func_name '(' ')' { CreateEventTrigStmt *n = makeNode(CreateEventTrigStmt); n->trigname = $4; n->eventname = $6; n->whenclause = $8; n->funcname = $11; $$ = (Node *) n; } ; event_trigger_when_list: event_trigger_when_item { $$ = list_make1($1); } | event_trigger_when_list AND event_trigger_when_item { $$ = lappend($1, $3); } ; event_trigger_when_item: ColId IN_P '(' event_trigger_value_list ')' { $$ = makeDefElem($1, (Node *) $4, @1); } ; event_trigger_value_list: SCONST { $$ = list_make1(makeString($1)); } | event_trigger_value_list ',' SCONST { $$ = lappend($1, makeString($3)); } ; AlterEventTrigStmt: ALTER EVENT TRIGGER name enable_trigger { AlterEventTrigStmt *n = makeNode(AlterEventTrigStmt); n->trigname = $4; n->tgenabled = $5; $$ = (Node *) n; } ; enable_trigger: ENABLE_P { $$ = TRIGGER_FIRES_ON_ORIGIN; } | ENABLE_P REPLICA { $$ = TRIGGER_FIRES_ON_REPLICA; } | ENABLE_P ALWAYS { $$ = TRIGGER_FIRES_ALWAYS; } | DISABLE_P { $$ = TRIGGER_DISABLED; } ; /***************************************************************************** * * QUERY : * CREATE ASSERTION ... * *****************************************************************************/ CreateAssertionStmt: CREATE ASSERTION any_name CHECK '(' a_expr ')' ConstraintAttributeSpec { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("CREATE ASSERTION is not yet implemented"))); $$ = NULL; } ; /***************************************************************************** * * QUERY : * define (aggregate,operator,type) * *****************************************************************************/ DefineStmt: CREATE opt_or_replace AGGREGATE func_name aggr_args definition { DefineStmt *n = makeNode(DefineStmt); n->kind = OBJECT_AGGREGATE; n->oldstyle = false; n->replace = $2; n->defnames = $4; n->args = $5; n->definition = $6; $$ = (Node *) n; } | CREATE opt_or_replace AGGREGATE func_name old_aggr_definition { /* old-style (pre-8.2) syntax for CREATE AGGREGATE */ DefineStmt *n = makeNode(DefineStmt); n->kind = OBJECT_AGGREGATE; n->oldstyle = true; n->replace = $2; n->defnames = $4; n->args = NIL; n->definition = $5; $$ = (Node *) n; } | CREATE OPERATOR any_operator definition { DefineStmt *n = makeNode(DefineStmt); n->kind = OBJECT_OPERATOR; n->oldstyle = false; n->defnames = $3; n->args = NIL; n->definition = $4; $$ = (Node *) n; } | CREATE TYPE_P any_name definition { DefineStmt *n = makeNode(DefineStmt); n->kind = OBJECT_TYPE; n->oldstyle = false; n->defnames = $3; n->args = NIL; n->definition = $4; $$ = (Node *) n; } | CREATE TYPE_P any_name { /* Shell type (identified by lack of definition) */ DefineStmt *n = makeNode(DefineStmt); n->kind = OBJECT_TYPE; n->oldstyle = false; n->defnames = $3; n->args = NIL; n->definition = NIL; $$ = (Node *) n; } | CREATE TYPE_P any_name AS '(' OptTableFuncElementList ')' { CompositeTypeStmt *n = makeNode(CompositeTypeStmt); /* can't use qualified_name, sigh */ n->typevar = makeRangeVarFromAnyName($3, @3, yyscanner); n->coldeflist = $6; $$ = (Node *) n; } | CREATE TYPE_P any_name AS ENUM_P '(' opt_enum_val_list ')' { CreateEnumStmt *n = makeNode(CreateEnumStmt); n->typeName = $3; n->vals = $7; $$ = (Node *) n; } | CREATE TYPE_P any_name AS RANGE definition { CreateRangeStmt *n = makeNode(CreateRangeStmt); n->typeName = $3; n->params = $6; $$ = (Node *) n; } | CREATE TEXT_P SEARCH PARSER any_name definition { DefineStmt *n = makeNode(DefineStmt); n->kind = OBJECT_TSPARSER; n->args = NIL; n->defnames = $5; n->definition = $6; $$ = (Node *) n; } | CREATE TEXT_P SEARCH DICTIONARY any_name definition { DefineStmt *n = makeNode(DefineStmt); n->kind = OBJECT_TSDICTIONARY; n->args = NIL; n->defnames = $5; n->definition = $6; $$ = (Node *) n; } | CREATE TEXT_P SEARCH TEMPLATE any_name definition { DefineStmt *n = makeNode(DefineStmt); n->kind = OBJECT_TSTEMPLATE; n->args = NIL; n->defnames = $5; n->definition = $6; $$ = (Node *) n; } | CREATE TEXT_P SEARCH CONFIGURATION any_name definition { DefineStmt *n = makeNode(DefineStmt); n->kind = OBJECT_TSCONFIGURATION; n->args = NIL; n->defnames = $5; n->definition = $6; $$ = (Node *) n; } | CREATE COLLATION any_name definition { DefineStmt *n = makeNode(DefineStmt); n->kind = OBJECT_COLLATION; n->args = NIL; n->defnames = $3; n->definition = $4; $$ = (Node *) n; } | CREATE COLLATION IF_P NOT EXISTS any_name definition { DefineStmt *n = makeNode(DefineStmt); n->kind = OBJECT_COLLATION; n->args = NIL; n->defnames = $6; n->definition = $7; n->if_not_exists = true; $$ = (Node *) n; } | CREATE COLLATION any_name FROM any_name { DefineStmt *n = makeNode(DefineStmt); n->kind = OBJECT_COLLATION; n->args = NIL; n->defnames = $3; n->definition = list_make1(makeDefElem("from", (Node *) $5, @5)); $$ = (Node *) n; } | CREATE COLLATION IF_P NOT EXISTS any_name FROM any_name { DefineStmt *n = makeNode(DefineStmt); n->kind = OBJECT_COLLATION; n->args = NIL; n->defnames = $6; n->definition = list_make1(makeDefElem("from", (Node *) $8, @8)); n->if_not_exists = true; $$ = (Node *) n; } ; definition: '(' def_list ')' { $$ = $2; } ; def_list: def_elem { $$ = list_make1($1); } | def_list ',' def_elem { $$ = lappend($1, $3); } ; def_elem: ColLabel '=' def_arg { $$ = makeDefElem($1, (Node *) $3, @1); } | ColLabel { $$ = makeDefElem($1, NULL, @1); } ; /* Note: any simple identifier will be returned as a type name! */ def_arg: func_type { $$ = (Node *) $1; } | reserved_keyword { $$ = (Node *) makeString(pstrdup($1)); } | qual_all_Op { $$ = (Node *) $1; } | NumericOnly { $$ = (Node *) $1; } | Sconst { $$ = (Node *) makeString($1); } | NONE { $$ = (Node *) makeString(pstrdup($1)); } ; old_aggr_definition: '(' old_aggr_list ')' { $$ = $2; } ; old_aggr_list: old_aggr_elem { $$ = list_make1($1); } | old_aggr_list ',' old_aggr_elem { $$ = lappend($1, $3); } ; /* * Must use IDENT here to avoid reduce/reduce conflicts; fortunately none of * the item names needed in old aggregate definitions are likely to become * SQL keywords. */ old_aggr_elem: IDENT '=' def_arg { $$ = makeDefElem($1, (Node *) $3, @1); } ; opt_enum_val_list: enum_val_list { $$ = $1; } | /*EMPTY*/ { $$ = NIL; } ; enum_val_list: Sconst { $$ = list_make1(makeString($1)); } | enum_val_list ',' Sconst { $$ = lappend($1, makeString($3)); } ; /***************************************************************************** * * ALTER TYPE enumtype ADD ... * *****************************************************************************/ AlterEnumStmt: ALTER TYPE_P any_name ADD_P VALUE_P opt_if_not_exists Sconst { AlterEnumStmt *n = makeNode(AlterEnumStmt); n->typeName = $3; n->oldVal = NULL; n->newVal = $7; n->newValNeighbor = NULL; n->newValIsAfter = true; n->skipIfNewValExists = $6; $$ = (Node *) n; } | ALTER TYPE_P any_name ADD_P VALUE_P opt_if_not_exists Sconst BEFORE Sconst { AlterEnumStmt *n = makeNode(AlterEnumStmt); n->typeName = $3; n->oldVal = NULL; n->newVal = $7; n->newValNeighbor = $9; n->newValIsAfter = false; n->skipIfNewValExists = $6; $$ = (Node *) n; } | ALTER TYPE_P any_name ADD_P VALUE_P opt_if_not_exists Sconst AFTER Sconst { AlterEnumStmt *n = makeNode(AlterEnumStmt); n->typeName = $3; n->oldVal = NULL; n->newVal = $7; n->newValNeighbor = $9; n->newValIsAfter = true; n->skipIfNewValExists = $6; $$ = (Node *) n; } | ALTER TYPE_P any_name RENAME VALUE_P Sconst TO Sconst { AlterEnumStmt *n = makeNode(AlterEnumStmt); n->typeName = $3; n->oldVal = $6; n->newVal = $8; n->newValNeighbor = NULL; n->newValIsAfter = false; n->skipIfNewValExists = false; $$ = (Node *) n; } ; opt_if_not_exists: IF_P NOT EXISTS { $$ = true; } | /* EMPTY */ { $$ = false; } ; /***************************************************************************** * * QUERIES : * CREATE OPERATOR CLASS ... * CREATE OPERATOR FAMILY ... * ALTER OPERATOR FAMILY ... * DROP OPERATOR CLASS ... * DROP OPERATOR FAMILY ... * *****************************************************************************/ CreateOpClassStmt: CREATE OPERATOR CLASS any_name opt_default FOR TYPE_P Typename USING name opt_opfamily AS opclass_item_list { CreateOpClassStmt *n = makeNode(CreateOpClassStmt); n->opclassname = $4; n->isDefault = $5; n->datatype = $8; n->amname = $10; n->opfamilyname = $11; n->items = $13; $$ = (Node *) n; } ; opclass_item_list: opclass_item { $$ = list_make1($1); } | opclass_item_list ',' opclass_item { $$ = lappend($1, $3); } ; opclass_item: OPERATOR Iconst any_operator opclass_purpose opt_recheck { CreateOpClassItem *n = makeNode(CreateOpClassItem); ObjectWithArgs *owa = makeNode(ObjectWithArgs); owa->objname = $3; owa->objargs = NIL; n->itemtype = OPCLASS_ITEM_OPERATOR; n->name = owa; n->number = $2; n->order_family = $4; $$ = (Node *) n; } | OPERATOR Iconst operator_with_argtypes opclass_purpose opt_recheck { CreateOpClassItem *n = makeNode(CreateOpClassItem); n->itemtype = OPCLASS_ITEM_OPERATOR; n->name = $3; n->number = $2; n->order_family = $4; $$ = (Node *) n; } | FUNCTION Iconst function_with_argtypes { CreateOpClassItem *n = makeNode(CreateOpClassItem); n->itemtype = OPCLASS_ITEM_FUNCTION; n->name = $3; n->number = $2; $$ = (Node *) n; } | FUNCTION Iconst '(' type_list ')' function_with_argtypes { CreateOpClassItem *n = makeNode(CreateOpClassItem); n->itemtype = OPCLASS_ITEM_FUNCTION; n->name = $6; n->number = $2; n->class_args = $4; $$ = (Node *) n; } | STORAGE Typename { CreateOpClassItem *n = makeNode(CreateOpClassItem); n->itemtype = OPCLASS_ITEM_STORAGETYPE; n->storedtype = $2; $$ = (Node *) n; } ; opt_default: DEFAULT { $$ = true; } | /*EMPTY*/ { $$ = false; } ; opt_opfamily: FAMILY any_name { $$ = $2; } | /*EMPTY*/ { $$ = NIL; } ; opclass_purpose: FOR SEARCH { $$ = NIL; } | FOR ORDER BY any_name { $$ = $4; } | /*EMPTY*/ { $$ = NIL; } ; opt_recheck: RECHECK { /* * RECHECK no longer does anything in opclass definitions, * but we still accept it to ease porting of old database * dumps. */ ereport(NOTICE, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("RECHECK is no longer required"), errhint("Update your data type."), parser_errposition(@1))); $$ = true; } | /*EMPTY*/ { $$ = false; } ; CreateOpFamilyStmt: CREATE OPERATOR FAMILY any_name USING name { CreateOpFamilyStmt *n = makeNode(CreateOpFamilyStmt); n->opfamilyname = $4; n->amname = $6; $$ = (Node *) n; } ; AlterOpFamilyStmt: ALTER OPERATOR FAMILY any_name USING name ADD_P opclass_item_list { AlterOpFamilyStmt *n = makeNode(AlterOpFamilyStmt); n->opfamilyname = $4; n->amname = $6; n->isDrop = false; n->items = $8; $$ = (Node *) n; } | ALTER OPERATOR FAMILY any_name USING name DROP opclass_drop_list { AlterOpFamilyStmt *n = makeNode(AlterOpFamilyStmt); n->opfamilyname = $4; n->amname = $6; n->isDrop = true; n->items = $8; $$ = (Node *) n; } ; opclass_drop_list: opclass_drop { $$ = list_make1($1); } | opclass_drop_list ',' opclass_drop { $$ = lappend($1, $3); } ; opclass_drop: OPERATOR Iconst '(' type_list ')' { CreateOpClassItem *n = makeNode(CreateOpClassItem); n->itemtype = OPCLASS_ITEM_OPERATOR; n->number = $2; n->class_args = $4; $$ = (Node *) n; } | FUNCTION Iconst '(' type_list ')' { CreateOpClassItem *n = makeNode(CreateOpClassItem); n->itemtype = OPCLASS_ITEM_FUNCTION; n->number = $2; n->class_args = $4; $$ = (Node *) n; } ; DropOpClassStmt: DROP OPERATOR CLASS any_name USING name opt_drop_behavior { DropStmt *n = makeNode(DropStmt); n->objects = list_make1(lcons(makeString($6), $4)); n->removeType = OBJECT_OPCLASS; n->behavior = $7; n->missing_ok = false; n->concurrent = false; $$ = (Node *) n; } | DROP OPERATOR CLASS IF_P EXISTS any_name USING name opt_drop_behavior { DropStmt *n = makeNode(DropStmt); n->objects = list_make1(lcons(makeString($8), $6)); n->removeType = OBJECT_OPCLASS; n->behavior = $9; n->missing_ok = true; n->concurrent = false; $$ = (Node *) n; } ; DropOpFamilyStmt: DROP OPERATOR FAMILY any_name USING name opt_drop_behavior { DropStmt *n = makeNode(DropStmt); n->objects = list_make1(lcons(makeString($6), $4)); n->removeType = OBJECT_OPFAMILY; n->behavior = $7; n->missing_ok = false; n->concurrent = false; $$ = (Node *) n; } | DROP OPERATOR FAMILY IF_P EXISTS any_name USING name opt_drop_behavior { DropStmt *n = makeNode(DropStmt); n->objects = list_make1(lcons(makeString($8), $6)); n->removeType = OBJECT_OPFAMILY; n->behavior = $9; n->missing_ok = true; n->concurrent = false; $$ = (Node *) n; } ; /***************************************************************************** * * QUERY: * * DROP OWNED BY username [, username ...] [ RESTRICT | CASCADE ] * REASSIGN OWNED BY username [, username ...] TO username * *****************************************************************************/ DropOwnedStmt: DROP OWNED BY role_list opt_drop_behavior { DropOwnedStmt *n = makeNode(DropOwnedStmt); n->roles = $4; n->behavior = $5; $$ = (Node *) n; } ; ReassignOwnedStmt: REASSIGN OWNED BY role_list TO RoleSpec { ReassignOwnedStmt *n = makeNode(ReassignOwnedStmt); n->roles = $4; n->newrole = $6; $$ = (Node *) n; } ; /***************************************************************************** * * QUERY: * * DROP itemtype [ IF EXISTS ] itemname [, itemname ...] * [ RESTRICT | CASCADE ] * *****************************************************************************/ DropStmt: DROP object_type_any_name IF_P EXISTS any_name_list opt_drop_behavior { DropStmt *n = makeNode(DropStmt); n->removeType = $2; n->missing_ok = true; n->objects = $5; n->behavior = $6; n->concurrent = false; $$ = (Node *) n; } | DROP object_type_any_name any_name_list opt_drop_behavior { DropStmt *n = makeNode(DropStmt); n->removeType = $2; n->missing_ok = false; n->objects = $3; n->behavior = $4; n->concurrent = false; $$ = (Node *) n; } | DROP drop_type_name IF_P EXISTS name_list opt_drop_behavior { DropStmt *n = makeNode(DropStmt); n->removeType = $2; n->missing_ok = true; n->objects = $5; n->behavior = $6; n->concurrent = false; $$ = (Node *) n; } | DROP drop_type_name name_list opt_drop_behavior { DropStmt *n = makeNode(DropStmt); n->removeType = $2; n->missing_ok = false; n->objects = $3; n->behavior = $4; n->concurrent = false; $$ = (Node *) n; } | DROP object_type_name_on_any_name name ON any_name opt_drop_behavior { DropStmt *n = makeNode(DropStmt); n->removeType = $2; n->objects = list_make1(lappend($5, makeString($3))); n->behavior = $6; n->missing_ok = false; n->concurrent = false; $$ = (Node *) n; } | DROP object_type_name_on_any_name IF_P EXISTS name ON any_name opt_drop_behavior { DropStmt *n = makeNode(DropStmt); n->removeType = $2; n->objects = list_make1(lappend($7, makeString($5))); n->behavior = $8; n->missing_ok = true; n->concurrent = false; $$ = (Node *) n; } | DROP TYPE_P type_name_list opt_drop_behavior { DropStmt *n = makeNode(DropStmt); n->removeType = OBJECT_TYPE; n->missing_ok = false; n->objects = $3; n->behavior = $4; n->concurrent = false; $$ = (Node *) n; } | DROP TYPE_P IF_P EXISTS type_name_list opt_drop_behavior { DropStmt *n = makeNode(DropStmt); n->removeType = OBJECT_TYPE; n->missing_ok = true; n->objects = $5; n->behavior = $6; n->concurrent = false; $$ = (Node *) n; } | DROP DOMAIN_P type_name_list opt_drop_behavior { DropStmt *n = makeNode(DropStmt); n->removeType = OBJECT_DOMAIN; n->missing_ok = false; n->objects = $3; n->behavior = $4; n->concurrent = false; $$ = (Node *) n; } | DROP DOMAIN_P IF_P EXISTS type_name_list opt_drop_behavior { DropStmt *n = makeNode(DropStmt); n->removeType = OBJECT_DOMAIN; n->missing_ok = true; n->objects = $5; n->behavior = $6; n->concurrent = false; $$ = (Node *) n; } | DROP INDEX CONCURRENTLY any_name_list opt_drop_behavior { DropStmt *n = makeNode(DropStmt); n->removeType = OBJECT_INDEX; n->missing_ok = false; n->objects = $4; n->behavior = $5; n->concurrent = true; $$ = (Node *) n; } | DROP INDEX CONCURRENTLY IF_P EXISTS any_name_list opt_drop_behavior { DropStmt *n = makeNode(DropStmt); n->removeType = OBJECT_INDEX; n->missing_ok = true; n->objects = $6; n->behavior = $7; n->concurrent = true; $$ = (Node *) n; } ; /* object types taking any_name/any_name_list */ object_type_any_name: TABLE { $$ = OBJECT_TABLE; } | SEQUENCE { $$ = OBJECT_SEQUENCE; } | VIEW { $$ = OBJECT_VIEW; } | MATERIALIZED VIEW { $$ = OBJECT_MATVIEW; } | INDEX { $$ = OBJECT_INDEX; } | FOREIGN TABLE { $$ = OBJECT_FOREIGN_TABLE; } | COLLATION { $$ = OBJECT_COLLATION; } | CONVERSION_P { $$ = OBJECT_CONVERSION; } | STATISTICS { $$ = OBJECT_STATISTIC_EXT; } | TEXT_P SEARCH PARSER { $$ = OBJECT_TSPARSER; } | TEXT_P SEARCH DICTIONARY { $$ = OBJECT_TSDICTIONARY; } | TEXT_P SEARCH TEMPLATE { $$ = OBJECT_TSTEMPLATE; } | TEXT_P SEARCH CONFIGURATION { $$ = OBJECT_TSCONFIGURATION; } ; /* * object types taking name/name_list * * DROP handles some of them separately */ object_type_name: drop_type_name { $$ = $1; } | DATABASE { $$ = OBJECT_DATABASE; } | ROLE { $$ = OBJECT_ROLE; } | SUBSCRIPTION { $$ = OBJECT_SUBSCRIPTION; } | TABLESPACE { $$ = OBJECT_TABLESPACE; } ; drop_type_name: ACCESS METHOD { $$ = OBJECT_ACCESS_METHOD; } | EVENT TRIGGER { $$ = OBJECT_EVENT_TRIGGER; } | EXTENSION { $$ = OBJECT_EXTENSION; } | FOREIGN DATA_P WRAPPER { $$ = OBJECT_FDW; } | opt_procedural LANGUAGE { $$ = OBJECT_LANGUAGE; } | PUBLICATION { $$ = OBJECT_PUBLICATION; } | SCHEMA { $$ = OBJECT_SCHEMA; } | SERVER { $$ = OBJECT_FOREIGN_SERVER; } ; /* object types attached to a table */ object_type_name_on_any_name: POLICY { $$ = OBJECT_POLICY; } | RULE { $$ = OBJECT_RULE; } | TRIGGER { $$ = OBJECT_TRIGGER; } ; any_name_list: any_name { $$ = list_make1($1); } | any_name_list ',' any_name { $$ = lappend($1, $3); } ; any_name: ColId { $$ = list_make1(makeString($1)); } | ColId attrs { $$ = lcons(makeString($1), $2); } ; attrs: '.' attr_name { $$ = list_make1(makeString($2)); } | attrs '.' attr_name { $$ = lappend($1, makeString($3)); } ; type_name_list: Typename { $$ = list_make1($1); } | type_name_list ',' Typename { $$ = lappend($1, $3); } ; /***************************************************************************** * * QUERY: * truncate table relname1, relname2, ... * *****************************************************************************/ TruncateStmt: TRUNCATE opt_table relation_expr_list opt_restart_seqs opt_drop_behavior { TruncateStmt *n = makeNode(TruncateStmt); n->relations = $3; n->restart_seqs = $4; n->behavior = $5; $$ = (Node *) n; } ; opt_restart_seqs: CONTINUE_P IDENTITY_P { $$ = false; } | RESTART IDENTITY_P { $$ = true; } | /* EMPTY */ { $$ = false; } ; /***************************************************************************** * * COMMENT ON IS * *****************************************************************************/ CommentStmt: COMMENT ON object_type_any_name any_name IS comment_text { CommentStmt *n = makeNode(CommentStmt); n->objtype = $3; n->object = (Node *) $4; n->comment = $6; $$ = (Node *) n; } | COMMENT ON COLUMN any_name IS comment_text { CommentStmt *n = makeNode(CommentStmt); n->objtype = OBJECT_COLUMN; n->object = (Node *) $4; n->comment = $6; $$ = (Node *) n; } | COMMENT ON object_type_name name IS comment_text { CommentStmt *n = makeNode(CommentStmt); n->objtype = $3; n->object = (Node *) makeString($4); n->comment = $6; $$ = (Node *) n; } | COMMENT ON TYPE_P Typename IS comment_text { CommentStmt *n = makeNode(CommentStmt); n->objtype = OBJECT_TYPE; n->object = (Node *) $4; n->comment = $6; $$ = (Node *) n; } | COMMENT ON DOMAIN_P Typename IS comment_text { CommentStmt *n = makeNode(CommentStmt); n->objtype = OBJECT_DOMAIN; n->object = (Node *) $4; n->comment = $6; $$ = (Node *) n; } | COMMENT ON AGGREGATE aggregate_with_argtypes IS comment_text { CommentStmt *n = makeNode(CommentStmt); n->objtype = OBJECT_AGGREGATE; n->object = (Node *) $4; n->comment = $6; $$ = (Node *) n; } | COMMENT ON FUNCTION function_with_argtypes IS comment_text { CommentStmt *n = makeNode(CommentStmt); n->objtype = OBJECT_FUNCTION; n->object = (Node *) $4; n->comment = $6; $$ = (Node *) n; } | COMMENT ON OPERATOR operator_with_argtypes IS comment_text { CommentStmt *n = makeNode(CommentStmt); n->objtype = OBJECT_OPERATOR; n->object = (Node *) $4; n->comment = $6; $$ = (Node *) n; } | COMMENT ON CONSTRAINT name ON any_name IS comment_text { CommentStmt *n = makeNode(CommentStmt); n->objtype = OBJECT_TABCONSTRAINT; n->object = (Node *) lappend($6, makeString($4)); n->comment = $8; $$ = (Node *) n; } | COMMENT ON CONSTRAINT name ON DOMAIN_P any_name IS comment_text { CommentStmt *n = makeNode(CommentStmt); n->objtype = OBJECT_DOMCONSTRAINT; /* * should use Typename not any_name in the production, but * there's a shift/reduce conflict if we do that, so fix it * up here. */ n->object = (Node *) list_make2(makeTypeNameFromNameList($7), makeString($4)); n->comment = $9; $$ = (Node *) n; } | COMMENT ON object_type_name_on_any_name name ON any_name IS comment_text { CommentStmt *n = makeNode(CommentStmt); n->objtype = $3; n->object = (Node *) lappend($6, makeString($4)); n->comment = $8; $$ = (Node *) n; } | COMMENT ON PROCEDURE function_with_argtypes IS comment_text { CommentStmt *n = makeNode(CommentStmt); n->objtype = OBJECT_PROCEDURE; n->object = (Node *) $4; n->comment = $6; $$ = (Node *) n; } | COMMENT ON ROUTINE function_with_argtypes IS comment_text { CommentStmt *n = makeNode(CommentStmt); n->objtype = OBJECT_ROUTINE; n->object = (Node *) $4; n->comment = $6; $$ = (Node *) n; } | COMMENT ON TRANSFORM FOR Typename LANGUAGE name IS comment_text { CommentStmt *n = makeNode(CommentStmt); n->objtype = OBJECT_TRANSFORM; n->object = (Node *) list_make2($5, makeString($7)); n->comment = $9; $$ = (Node *) n; } | COMMENT ON OPERATOR CLASS any_name USING name IS comment_text { CommentStmt *n = makeNode(CommentStmt); n->objtype = OBJECT_OPCLASS; n->object = (Node *) lcons(makeString($7), $5); n->comment = $9; $$ = (Node *) n; } | COMMENT ON OPERATOR FAMILY any_name USING name IS comment_text { CommentStmt *n = makeNode(CommentStmt); n->objtype = OBJECT_OPFAMILY; n->object = (Node *) lcons(makeString($7), $5); n->comment = $9; $$ = (Node *) n; } | COMMENT ON LARGE_P OBJECT_P NumericOnly IS comment_text { CommentStmt *n = makeNode(CommentStmt); n->objtype = OBJECT_LARGEOBJECT; n->object = (Node *) $5; n->comment = $7; $$ = (Node *) n; } | COMMENT ON CAST '(' Typename AS Typename ')' IS comment_text { CommentStmt *n = makeNode(CommentStmt); n->objtype = OBJECT_CAST; n->object = (Node *) list_make2($5, $7); n->comment = $10; $$ = (Node *) n; } ; comment_text: Sconst { $$ = $1; } | NULL_P { $$ = NULL; } ; /***************************************************************************** * * SECURITY LABEL [FOR ] ON IS