From 7911557f0a8de43db295237d13adda8afd51a704 Mon Sep 17 00:00:00 2001 From: TotaJ Date: Mon, 6 Sep 2021 15:02:46 +0800 Subject: [PATCH] Add db_b_parser. --- contrib/db_b_parser/.gitignore | 2 + contrib/db_b_parser/Makefile | 55 + contrib/db_b_parser/README.md | 2 + contrib/db_b_parser/db_b_gram.y | 22195 +++++++++++++++++++++ contrib/db_b_parser/db_b_keywords.h | 609 + contrib/db_b_parser/db_b_parser--1.0.sql | 3 + contrib/db_b_parser/db_b_parser.control | 5 + contrib/db_b_parser/db_b_parser.cpp | 555 + contrib/db_b_parser/db_b_parser_header.h | 12 + contrib/db_b_parser/db_b_scan.l | 1749 ++ contrib/db_b_parser/help/db_b_gram.svg | 1 + contrib/db_b_parser/pl/pl_b.cpp | 18 + contrib/db_b_parser/pl/pl_b.h | 2 + contrib/db_b_parser/pl/pl_b_gram.y | 6197 ++++++ contrib/db_b_parser/pl/pl_b_scanner.cpp | 795 + contrib/db_b_parser/pl/pl_b_sql.h | 1034 + contrib/db_b_parser/pl/tool/mtlocal.pl | 102 + 17 files changed, 33336 insertions(+) create mode 100644 contrib/db_b_parser/.gitignore create mode 100644 contrib/db_b_parser/Makefile create mode 100644 contrib/db_b_parser/README.md create mode 100644 contrib/db_b_parser/db_b_gram.y create mode 100644 contrib/db_b_parser/db_b_keywords.h create mode 100644 contrib/db_b_parser/db_b_parser--1.0.sql create mode 100644 contrib/db_b_parser/db_b_parser.control create mode 100644 contrib/db_b_parser/db_b_parser.cpp create mode 100644 contrib/db_b_parser/db_b_parser_header.h create mode 100644 contrib/db_b_parser/db_b_scan.l create mode 100644 contrib/db_b_parser/help/db_b_gram.svg create mode 100644 contrib/db_b_parser/pl/pl_b.cpp create mode 100644 contrib/db_b_parser/pl/pl_b.h create mode 100644 contrib/db_b_parser/pl/pl_b_gram.y create mode 100644 contrib/db_b_parser/pl/pl_b_scanner.cpp create mode 100644 contrib/db_b_parser/pl/pl_b_sql.h create mode 100644 contrib/db_b_parser/pl/tool/mtlocal.pl diff --git a/contrib/db_b_parser/.gitignore b/contrib/db_b_parser/.gitignore new file mode 100644 index 000000000..8cd0df3a4 --- /dev/null +++ b/contrib/db_b_parser/.gitignore @@ -0,0 +1,2 @@ +.vscode +.idea \ No newline at end of file diff --git a/contrib/db_b_parser/Makefile b/contrib/db_b_parser/Makefile new file mode 100644 index 000000000..31fcca621 --- /dev/null +++ b/contrib/db_b_parser/Makefile @@ -0,0 +1,55 @@ +# contrib/db_b_parser/Makefile + +subdir = contrib/db_b_parser +top_builddir = ../.. + +MODULE_big = db_b_parser +OBJS =db_b_gram.o db_b_parser.o pl/pl_b_gram.o pl/pl_b.o pl/pl_b_scanner.o + +FLEXFLAGS = -CF -b -p -p +# Latest flex causes warnings in this file. +ifeq ($(GCC),yes) +db_b_gram.o: CXXFLAGS += -Wno-error +endif + +# scan is compiled as part of gram +db_b_gram.o: db_b_scan.inc + +# There is no correct way to write a rule that generates two files. +# Rules with two targets don't have that meaning, they are merely +# shorthand for two otherwise separate rules. To be safe for parallel +# make, we must chain the dependencies like this. The semicolon is +# important, otherwise make will choose the built-in rule for +# gram.y=>gram.cpp. + +db_b_gram.hpp: db_b_gram.cpp ; + +db_b_gram.cpp: db_b_gram.y + $(BISON) -d $(BISONFLAGS) -o $@ $< + sed -i 's/YY_NULL nullptr/YY_NULL 0/g' db_b_gram.cpp + +db_b_scan.inc: db_b_scan.l + $(FLEX) $(FLEXFLAGS) -o'$@' $< + +# Force these dependencies to be known even without dependency info built: +db_b_gram.o db_b_parser.o: db_b_gram.hpp + +db_b_hint_scan.inc: db_b_hint_scan.l | db_b_scan.inc + $(FLEX) $(FLEXFLAGS) -o'$@' $< + +pl/pl_b_scanner.o: pl/pl_b_scanner.cpp pl/pl_b_gram.o +pl/pl_b_gram.o : pl/pl_b_gram.hpp +pl/pl_b_gram.hpp: pl/pl_b_gram.cpp ; +pl/pl_b_gram.cpp: pl/pl_b_gram.y $(top_builddir)/$(subdir)/pl/tool/mtlocal.pl + $(BISON) -d $(BISONFLAGS) -o $@ $< + $(PERL) $(top_builddir)/$(subdir)/pl/tool/mtlocal.pl $(top_builddir)/$(subdir)/pl/pl_b_gram.cpp + $(PERL) $(top_builddir)/$(subdir)/pl/tool/mtlocal.pl $(top_builddir)/$(subdir)/pl/pl_b_gram.hpp + + +EXTENSION = db_b_parser +DATA = db_b_parser--1.0.sql + +override CPPFLAGS :=$(filter-out -fPIE, $(CPPFLAGS)) -fPIC + +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk diff --git a/contrib/db_b_parser/README.md b/contrib/db_b_parser/README.md new file mode 100644 index 000000000..983f432d6 --- /dev/null +++ b/contrib/db_b_parser/README.md @@ -0,0 +1,2 @@ +# db_b_parser + diff --git a/contrib/db_b_parser/db_b_gram.y b/contrib/db_b_parser/db_b_gram.y new file mode 100644 index 000000000..fc931684c --- /dev/null +++ b/contrib/db_b_parser/db_b_gram.y @@ -0,0 +1,22195 @@ +%{ + +/*#define YYDEBUG 1*/ +/* ------------------------------------------------------------------------- + * + * gram.y + * POSTGRESQL BISON rules/actions + * + * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010-2012 Postgres-XC Development Group + * + * + * 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. + * SQL92-specific syntax is separated from plain SQL/Postgres syntax + * to help isolate the non-extensible portions of the parser. + * + * In general, nothing in this file should initiate database accesses + * nor depend on changeable state (such as SET variables). If you do + * database accesses, your code will fail when we have aborted the + * current transaction and are just parsing commands to find the next + * ROLLBACK or COMMIT. If you make use of SET variables, then you + * will do the wrong thing in multi-query strings like this: + * SET SQL_inheritance TO off; SELECT * FROM foo; + * because the entire string is parsed by gram.y before the SET gets + * executed. Anything that depends on the database or changeable state + * should be handled during parse analysis so that it happens at the + * right time not the wrong time. The handling of SQL_inheritance is + * a good example. + * + * WARNINGS + * If you use a list, make sure the datum is a node so that the printing + * routines work. + * + * Sometimes we assign constants to makeStrings. Make sure we don't free + * those. + * + * ------------------------------------------------------------------------- + */ +#include "postgres.h" +#include "knl/knl_variable.h" + +#include +#include + +#include "catalog/index.h" +#include "catalog/namespace.h" +#include "catalog/pg_proc.h" +#include "catalog/pg_trigger.h" +#include "commands/defrem.h" +#ifdef ENABLE_MULTIPLE_NODES +#include "distribute_core.h" +#endif +#include "funcapi.h" +#include "miscadmin.h" +#include "nodes/makefuncs.h" +#include "nodes/nodeFuncs.h" +#include "parser/scanner.h" +#include "db_b_gram.hpp" +#include "parser/gramparse.h" +#include "parser/parse_hint.h" +#include "pgxc/pgxc.h" +#include "nodes/nodes.h" +#include "pgxc/poolmgr.h" +#include "parser/parser.h" +#include "storage/lmgr.h" +#include "utils/builtins.h" +#include "utils/date.h" +#include "utils/datetime.h" +#include "utils/numeric.h" +#include "utils/syscache.h" +#include "utils/xml.h" +#include "catalog/pg_streaming_fn.h" +#include "db_b_parser_header.h" + +#pragma GCC diagnostic ignored "-Wsign-compare" +#pragma GCC diagnostic ignored "-Wunused-variable" + +#define MAXFNAMELEN 64 + +extern int db_b_base_yylex(YYSTYPE* lvalp, YYLTYPE* llocp, core_yyscan_t yyscanner); + +#ifndef ENABLE_MULTIPLE_NODES +DB_CompatibilityAttr g_dbCompatArray[] = { + {DB_CMPT_A, "A"}, + {DB_CMPT_B, "B"}, + {DB_CMPT_C, "C"}, + {DB_CMPT_PG, "PG"} +}; + +IntervalStylePack g_interStyleVal = {"a"}; + +#endif + +/* Location tracking support --- simpler than bison's default */ + +#define YYLLOC_DEFAULT(Current, Rhs, N) \ + do { \ + if (N) \ + (Current) = (Rhs)[1]; \ + else \ + (Current) = (Rhs)[0]; \ + } while (0) + +/* + * Bison doesn't allocate anything that needs to live across parser calls, + * so we can easily have it use palloc instead of malloc. This prevents + * memory leaks if we error out during parsing. Note this only works with + * bison >= 2.0. However, in bison 1.875 the default is to use alloca() + * if possible, so there's not really much problem anyhow, at least if + * you're building with gcc. + */ +#define YYMALLOC palloc +#define YYFREE pfree +#ifdef YYLEX_PARAM +# define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM) +#else +# define YYLEX yylex (&yylval, &yylloc, yyscanner) +#endif + +/* Private struct for the result of privilege_target production */ +typedef struct PrivTarget +{ + GrantTargetType targtype; + GrantObjectType objtype; + List *objs; +} PrivTarget; + +/* 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 + +/* + * In the IntoClause structure there is a char value which will eventually be + * set to RELKIND_RELATION or RELKIND_MATVIEW based on the relkind field in + * the statement-level structure, which is an ObjectType. Define the default + * here, which should always be overridden later. + */ +#define INTO_CLAUSE_RELKIND_DEFAULT '\0' + +#define parser_yyerror(msg) scanner_yyerror(msg, yyscanner) +#define parser_errposition(pos) scanner_errposition(pos, yyscanner) + +static void db_b_base_yyerror(YYLTYPE *yylloc, core_yyscan_t yyscanner, + const char *msg); +static Node *makeColumnRef(char *colname, List *indirection, + int location, core_yyscan_t yyscanner); +static Node *makeTypeCast(Node *arg, TypeName *typname, int location); +static Node *makeStringConst(char *str, int location); +static Node *makeStringConstCast(char *str, int location, TypeName *typname); +static Node *makeIntConst(int val, int location); +static Node *makeFloatConst(char *str, int location); +static Node *makeBitStringConst(char *str, int location); +Node *makeAConst(Value *v, int location); +Node *makeBoolAConst(bool state, int location); +static void check_qualified_name(List *names, core_yyscan_t yyscanner); +static List *check_func_name(List *names, core_yyscan_t yyscanner); +static List *check_setting_name(List *names, core_yyscan_t yyscanner); +static List *check_indirection(List *indirection, core_yyscan_t yyscanner); +static List *extractArgTypes(List *parameters); +static void insertSelectOptions(SelectStmt *stmt, + List *sortClause, List *lockingClause, + Node *limitOffset, Node *limitCount, + WithClause *withClause, + core_yyscan_t yyscanner); +static Node *makeSetOp(SetOperation op, bool all, Node *larg, Node *rarg); +static Node *doNegate(Node *n, int location); +static void doNegateFloat(Value *v); +static Node *makeAArrayExpr(List *elements, int location); +static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, + List *args, int location); +static Node *makeCallFuncStmt(List* funcname, List* parameters); +static List *mergeTableFuncParameters(List *func_args, List *columns); +static TypeName *TableFuncTypeName(List *columns); +static RangeVar *makeRangeVarFromAnyName(List *names, int position, core_yyscan_t yyscanner); +static void SplitColQualList(List *qualList, + List **constraintList, CollateClause **collClause, + core_yyscan_t yyscanner); +static void SplitColQualList(List *qualList, + List **constraintList, CollateClause **collClause, ClientLogicColumnRef **clientLogicColumnRef, + 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 Expr *makeNodeDecodeCondtion(Expr* firstCond,Expr* secondCond); +static List *make_action_func(List *arguments); +static List *get_func_args(char *sid); +static char *pg_strsep(char **stringp, const char *delim); +static long long get_pid(const char *strsid); +static Node *MakeAnonyBlockFuncStmt(int flag, const char * str); +#define DECLARE_LEN 9 /* strlen(" DECLARE ") */ +#define DECLARE_STR " DECLARE " +static int get_outarg_num(List *fun_args); +static int get_table_modes(int nargs, const char *p_argmodes); +static void get_arg_mode_by_name(const char *argname, const char * const *argnames, + const char *argmodes, const int proargnum, + bool *have_assigend, char *argmode); +static void get_arg_mode_by_pos(const int pos, const char *argmodes, const int narg, + bool *have_assigend, char *argmode); +static List *append_inarg_list(const char argmode, const ListCell *cell,List *in_parameter); +static void check_outarg_info(const bool *have_assigend, + const char *argmodes,const int proargnum); +bool IsValidIdentClientKey(const char *input); +bool IsValidIdent(char *input); +bool IsValidGroupname(const char *input); +static bool checkNlssortArgs(const char *argname); +static void ParseUpdateMultiSet(List *set_target_list, SelectStmt *stmt, core_yyscan_t yyscanner); +static void parameter_check_execute_direct(const char* query); +%} + +%pure-parser +%expect 0 +%name-prefix="db_b_base_yy" +%locations + +%parse-param {core_yyscan_t yyscanner} +%lex-param {core_yyscan_t yyscanner} + +%union +{ + core_YYSTYPE core_yystype; + /* these fields must match core_YYSTYPE: */ + int ival; + char *str; + const char *keyword; + + char chr; + bool boolean; + JoinType jtype; + DropBehavior dbehavior; + OnCommitAction oncommit; + List *list; + Node *node; + Value *value; + ObjectType objtype; + TypeName *typnam; + FunctionParameter *fun_param; + FunctionParameterMode fun_param_mode; + FuncWithArgs *funwithargs; + DefElem *defelt; + SortBy *sortby; + WindowDef *windef; + JoinExpr *jexpr; + IndexElem *ielem; + Alias *alias; + RangeVar *range; + IntoClause *into; + WithClause *with; + A_Indices *aind; + ResTarget *target; + struct PrivTarget *privtarget; + AccessPriv *accesspriv; + InsertStmt *istmt; + VariableSetStmt *vsetstmt; +/* PGXC_BEGIN */ + DistributeBy *distby; + PGXCSubCluster *subclus; +/* PGXC_END */ + ForeignPartState *foreignpartby; + MergeWhenClause *mergewhen; + UpsertClause *upsert; + EncryptionType algtype; +} + +%type stmt schema_stmt + AlterDatabaseStmt AlterDatabaseSetStmt AlterDataSourceStmt AlterDomainStmt AlterEnumStmt + AlterFdwStmt AlterForeignServerStmt AlterGroupStmt + AlterObjectSchemaStmt AlterOwnerStmt AlterSeqStmt AlterTableStmt + AlterExtensionStmt AlterExtensionContentsStmt AlterForeignTableStmt + AlterCompositeTypeStmt AlterUserStmt AlterUserMappingStmt AlterUserSetStmt + AlterSystemStmt + AlterRoleStmt AlterRoleSetStmt AlterRlsPolicyStmt + AlterDefaultPrivilegesStmt DefACLAction AlterSessionStmt + AnalyzeStmt CleanConnStmt ClosePortalStmt ClusterStmt CommentStmt + ConstraintsSetStmt CopyStmt CreateAsStmt CreateCastStmt CreateContQueryStmt CreateDirectoryStmt + CreateDomainStmt CreateExtensionStmt CreateGroupStmt CreateKeyStmt CreateOpClassStmt + CreateOpFamilyStmt AlterOpFamilyStmt CreatePLangStmt + CreateSchemaStmt CreateSeqStmt CreateStmt CreateStreamStmt CreateTableSpaceStmt + CreateFdwStmt CreateForeignServerStmt CreateForeignTableStmt + CreateDataSourceStmt + CreateAssertStmt CreateTrigStmt + CreateUserStmt CreateUserMappingStmt CreateRoleStmt CreateRlsPolicyStmt CreateSynonymStmt + CreatedbStmt DeclareCursorStmt DefineStmt DeleteStmt DiscardStmt DoStmt + DropGroupStmt DropOpClassStmt DropOpFamilyStmt DropPLangStmt DropStmt + DropAssertStmt DropSynonymStmt DropTrigStmt DropRuleStmt DropCastStmt DropRoleStmt DropRlsPolicyStmt + DropUserStmt DropdbStmt DropTableSpaceStmt DropDataSourceStmt DropDirectoryStmt DropFdwStmt + DropForeignServerStmt DropUserMappingStmt ExplainStmt ExecDirectStmt FetchStmt + GrantStmt GrantRoleStmt IndexStmt InsertStmt ListenStmt LoadStmt + LockStmt NotifyStmt ExplainableStmt PreparableStmt + CreateFunctionStmt CreateProcedureStmt AlterFunctionStmt AlterProcedureStmt ReindexStmt RemoveAggrStmt + RemoveFuncStmt RemoveOperStmt RenameStmt RevokeStmt RevokeRoleStmt + RuleActionStmt RuleActionStmtOrEmpty RuleStmt + SecLabelStmt SelectStmt TransactionStmt TruncateStmt CallFuncStmt + UnlistenStmt UpdateStmt VacuumStmt + VariableResetStmt VariableSetStmt VariableShowStmt VerifyStmt ShutdownStmt + ViewStmt CheckPointStmt CreateConversionStmt + DeallocateStmt PrepareStmt ExecuteStmt + DropOwnedStmt ReassignOwnedStmt + AlterTSConfigurationStmt AlterTSDictionaryStmt AnonyBlockStmt + BarrierStmt AlterNodeStmt CreateNodeStmt DropNodeStmt AlterCoordinatorStmt + CreateNodeGroupStmt AlterNodeGroupStmt DropNodeGroupStmt + CreatePolicyLabelStmt AlterPolicyLabelStmt DropPolicyLabelStmt + CreateAuditPolicyStmt AlterAuditPolicyStmt DropAuditPolicyStmt + CreateMaskingPolicyStmt AlterMaskingPolicyStmt DropMaskingPolicyStmt + CreateResourcePoolStmt AlterResourcePoolStmt DropResourcePoolStmt + CreateWorkloadGroupStmt AlterWorkloadGroupStmt DropWorkloadGroupStmt + CreateAppWorkloadGroupMappingStmt AlterAppWorkloadGroupMappingStmt DropAppWorkloadGroupMappingStmt + MergeStmt CreateMatViewStmt RefreshMatViewStmt + CreateWeakPasswordDictionaryStmt DropWeakPasswordDictionaryStmt + +%type select_no_parens select_with_parens select_clause + simple_select values_clause + +%type alter_column_default opclass_item opclass_drop alter_using +%type add_drop opt_asc_desc opt_nulls_order +%type OptNoLog + +%type alter_table_cmd alter_partition_cmd alter_type_cmd opt_collate_clause exchange_partition_cmd move_partition_cmd + modify_column_cmd + replica_identity +%type alter_table_cmds alter_partition_cmds alter_table_or_partition alter_type_cmds add_column_cmds modify_column_cmds + +%type opt_drop_behavior + +%type createdb_opt_list alterdb_opt_list copy_opt_list + transaction_mode_list weak_password_string_list + create_extension_opt_list alter_extension_opt_list + pgxcnode_list pgxcnodes bucket_maps bucket_list + opt_pgxcnodes +%type createdb_opt_item alterdb_opt_item copy_opt_item + transaction_mode_item + create_extension_opt_item alter_extension_opt_item + +%type opt_lock lock_type cast_context +%type vacuum_option_list vacuum_option_elem opt_verify_options +%type opt_check opt_force opt_or_replace + opt_grant_grant_option opt_grant_admin_option + opt_nowait opt_if_exists opt_with_data + +%type OptRoleList AlterOptRoleList +%type CreateOptRoleElem AlterOptRoleElem + +%type opt_type +%type foreign_server_version opt_foreign_server_version +%type data_source_version opt_data_source_version data_source_type opt_data_source_type +%type auth_ident +%type opt_in_database + +%type OptSchemaName +%type OptSchemaEltList + +%type TriggerForSpec TriggerForType ForeignTblWritable +%type TriggerActionTime +%type TriggerEvents TriggerOneEvent +%type TriggerFuncArg +%type TriggerWhen + +%type copy_file_name + database_name access_method_clause access_method attr_name + name namedata_string fdwName cursor_name file_name + index_name cluster_index_specification + pgxcnode_name pgxcgroup_name resource_pool_name workload_group_name + application_name password_string hint_string +%type func_name func_name_opt_arg handler_name qual_Op qual_all_Op subquery_Op + opt_class opt_inline_handler opt_validator validator_clause + opt_collate + +%type qualified_name OptConstrFromTable opt_index_name + +%type all_Op MathOp + +%type RowLevelSecurityPolicyName row_level_security_cmd RLSDefaultForCmd row_level_security_role +%type RLSDefaultPermissive +%type RLSOptionalUsingExpr +%type row_level_security_role_list RLSDefaultToRole RLSOptionalToRole + +%type iso_level opt_encoding +%type grantee +%type grantee_list +%type privilege +%type privileges privilege_list +%type privilege_str +%type privilege_target +%type function_with_argtypes +%type function_with_argtypes_list +%type defacl_privilege_target +%type DefACLOption +%type DefACLOptionList + +%type stmtblock stmtmulti + OptTableElementList TableElementList OptInherit definition tsconf_definition + OptTypedTableElementList TypedTableElementList + OptForeignTableElementList ForeignTableElementList + reloptions opt_reloptions opt_tblspc_options tblspc_options opt_cfoptions cfoptions + OptWith opt_distinct opt_definition func_args func_args_list + func_args_with_defaults func_args_with_defaults_list proc_args + func_as createfunc_opt_list opt_createproc_opt_list alterfunc_opt_list + aggr_args old_aggr_definition old_aggr_list + oper_argtypes RuleActionList RuleActionMulti + opt_column_list columnList opt_name_list opt_analyze_column_define opt_multi_name_list + opt_include opt_c_include index_including_params + sort_clause opt_sort_clause sortby_list index_params + name_list from_clause from_list opt_array_bounds + qualified_name_list any_name any_name_list + any_operator expr_list attrs callfunc_args + target_list insert_column_list set_target_list + set_clause_list set_clause multiple_set_clause + ctext_expr_list ctext_row def_list tsconf_def_list indirection opt_indirection + reloption_list tblspc_option_list cfoption_list group_clause TriggerFuncArgs select_limit + opt_select_limit opt_delete_limit opclass_item_list opclass_drop_list + opclass_purpose opt_opfamily transaction_mode_list_or_empty + OptTableFuncElementList TableFuncElementList opt_type_modifiers + prep_type_clause + execute_param_clause using_clause returning_clause + opt_enum_val_list enum_val_list table_func_column_list + create_generic_options alter_generic_options + relation_expr_list dostmt_opt_list + merge_values_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 createproc_opt_item common_func_opt_item dostmt_opt_item +%type func_arg func_arg_with_default table_func_column +%type arg_class +%type func_return func_type + +%type opt_trusted opt_restart_seqs +%type OptTemp OptKind +%type OnCommitOption + +%type for_locking_item +%type for_locking_clause opt_for_locking_clause for_locking_items +%type locked_rels_list +%type opt_all + +%type join_outer join_qual +%type join_type + +%type extract_list timestamp_arg_list overlay_list position_list +%type substr_list trim_list +%type opt_interval interval_second +%type overlay_placing substr_from substr_for + +%type opt_instead opt_incremental +%type opt_unique opt_concurrently opt_verbose opt_full opt_deltamerge opt_compact opt_hdfsdirectory opt_verify +%type opt_freeze opt_default opt_recheck opt_cascade +%type opt_binary opt_oids copy_delimiter opt_noescaping +%type OptCopyLogError OptCopyRejectLimit + +%type opt_processed + +%type DirectStmt CleanConnDbName CleanConnUserName +/* PGXC_END */ +%type copy_from + +%type opt_column event cursor_options opt_hold opt_set_data +%type reindex_type drop_type comment_type security_label_type + +%type fetch_args limit_clause select_limit_value + offset_clause select_offset_value + select_offset_value2 opt_select_fetch_first_value +%type limit_offcnt_clause +%type row_or_rows first_or_next + +%type OptSeqOptList SeqOptList +%type SeqOptElem + +/* INSERT */ +%type insert_rest +%type upsert_clause + +%type merge_insert merge_update + +%type generic_set set_rest set_rest_more SetResetClause FunctionSetResetClause + +%type TableElement TypedTableElement ConstraintElem TableFuncElement + ForeignTableElement +%type columnDef columnOptions +%type def_elem tsconf_def_elem reloption_elem tblspc_option_elem old_aggr_elem cfoption_elem +%type def_arg columnElem where_clause where_or_current_clause + a_expr b_expr c_expr c_expr_noparen AexprConst indirection_el + columnref in_expr having_clause func_table array_expr + ExclusionWhereClause +%type ExclusionConstraintList ExclusionConstraintElem +%type func_arg_list +%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 sub_type +%type ctext_expr +%type NumericOnly +%type NumericOnly_list +%type alias_clause opt_alias_clause +%type sortby +%type index_elem +%type table_ref +%type joined_table +%type relation_expr +%type relation_expr_opt_alias +%type target_el single_set_clause set_target insert_column_item +%type tablesample_clause opt_repeatable_clause + +%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 explain_option_name +%type explain_option_arg +%type explain_option_elem +%type explain_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 client_logic_type + datatypecl +%type character +%type extract_arg +%type timestamp_units +%type opt_charset +%type opt_varying opt_timezone opt_no_inherit + +%type Iconst SignedIconst +%type Sconst comment_text notify_payload +%type RoleId TypeOwner opt_granted_by opt_boolean_or_string ColId_or_Sconst +%type var_list +%type ColId ColLabel var_name type_function_name param_name +%type var_value zone_value + +%type unreserved_keyword type_func_name_keyword +%type col_name_keyword reserved_keyword + +%type TableConstraint TableLikeClause ForeignTableLikeClause +%type excluding_option_list TableLikeOptionList TableLikeIncludingOption TableLikeExcludingOption +%type ColQualList +%type ColConstraint ColConstraintElem ConstraintAttr InformationalConstraintElem +%type key_actions key_delete key_match key_update key_action +%type ConstraintAttributeSpec ConstraintAttributeElem +%type ExistingIndex + +%type constraints_set_list +%type constraints_set_mode +%type OptRelative +%type OptGPI +%type OptTableSpace OptConsTableSpace OptTableSpaceOwner LoggingStr size_clause OptMaxSize OptDatafileSize OptReuse OptAuto OptNextStr OptDatanodeName +%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_whitespace_option + +%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 window_clause window_definition_list opt_partition_clause +%type window_definition over_clause window_specification + opt_frame_clause frame_extent frame_bound +%type opt_existing_window_name +%type opt_if_not_exists +%type OptCompress +%type KVType +%type ColCmprsMode +%type subprogram_body +%type as_is +%type column_item opt_table_partitioning_clause + opt_partition_index_def range_partition_index_item range_partition_index_list + range_partitioning_clause value_partitioning_clause opt_interval_partition_clause + interval_expr maxValueItem list_partitioning_clause hash_partitioning_clause + range_start_end_item range_less_than_item list_partition_item hash_partition_item +%type range_partition_definition_list list_partition_definition_list hash_partition_definition_list maxValueList + column_item_list tablespaceList opt_interval_tablespaceList + split_dest_partition_define_list + range_start_end_list range_less_than_list opt_range_every_list +%type partition_name + +%type opt_row_movement_clause +/* PGXC_BEGIN */ +%type opt_barrier_id OptDistributeType SliceReferenceClause +%type OptDistributeBy OptDistributeByInternal distribute_by_range_clause + distribute_by_list_clause +%type range_slice_definition_list range_slice_less_than_list range_slice_start_end_list + list_distribution_rules_list list_distribution_rule_row list_distribution_rule_single +%type range_slice_less_than_item range_slice_start_end_item + list_dist_state OptListDistribution list_dist_value + +%type OptSubCluster OptSubClusterInternal +/* PGXC_END */ + +%type OptPartitionElement +%type OptForeignTableLogError OptForeignTableLogRemote +%type ForeignPosition ForeignColDef copy_col_format_def +%type OptPerNodeRejectLimit +%type copy_foramtter_opt + +/* FOREIGN_PARTITION */ +%type OptForeignPartBy OptForeignPartAuto +%type partition_item +%type partition_item_list + +/* NODE GROUP */ +%type opt_vcgroup opt_to_elastic_group +%type opt_set_vcgroup +%type opt_redistributed opt_internal_data internal_data_body + +/* MERGE INTO */ +%type merge_when_clause opt_merge_where_condition +%type merge_when_list + +/* ENCRYPTION */ +%type algorithm_desc CreateMasterKeyStmt CreateColumnKeyStmt master_key_elem column_key_elem with_algorithm +%type master_key_params column_key_params +%type columnEncryptionKey +%type encryptionType + +/* CLIENT_LOGIC */ +%type setting_name + +/* POLICY LABEL */ +%type policy_label_name policy_label_resource_type + policy_label_filter_type policy_label_any_resource +%type resources_to_label_list filters_to_label_list + policy_label_items opt_add_resources_to_label + resources_or_filters_to_label_list policy_labels_list +%type resources_to_label_list_item filters_to_label_list_item +%type policy_label_item policy_label_any_resource_item +/* AUDIT POLICY */ +%type alter_policy_filter_list alter_policy_privileges_list alter_policy_access_list +%type policy_name policy_privilege_type policy_access_type policy_filter_type policy_filter_name policy_target_type +%type policy_target_name +%type policy_status_opt +%type policy_privilege_elem policy_access_elem policy_target_elem_opt +%type policy_filter_elem pp_policy_filter_elem filter_term pp_filter_term filter_expr pp_filter_expr filter_paren filter_expr_list filter_set policy_filter_value +%type policy_filters_list policy_filter_opt policy_privileges_list policy_access_list policy_targets_list +%type policy_names_list +%type policy_status_alter_clause +%type alter_policy_action_clause policy_comments_alter_clause + +/* MASKING POLICY */ +%type masking_func masking_policy_target_type alter_masking_policy_action_clause + masking_policy_condition_operator +%type masking_clause masking_func_params_opt masking_func_params_list + alter_masking_policy_func_items_list +%type masking_clause_elem masking_target +%type masking_func_param alter_masking_policy_func_item +%type policy_condition_opt +%type alter_policy_condition +%type masking_policy_condition_value + +/* + * Non-keyword token types. These are hard-wired into the "flex" lexer. + * They must be listed first so that their numeric codes do not depend on + * the set of keywords. PL/pgsql depends on this so that it can share the + * same lexer. If you add/change tokens here, fix PL/pgsql to match! + * + * DOT_DOT is unused in the core SQL grammar, and so will always provoke + * parse errors. It is needed by PL/pgsql. + */ +%token IDENT FCONST SCONST BCONST XCONST Op CmpOp COMMENTSTRING +%token ICONST PARAM +%token TYPECAST ORA_JOINOP DOT_DOT COLON_EQUALS PARA_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 */ +/* PGXC - added DISTRIBUTE, DIRECT, COORDINATOR, CLEAN, NODE, BARRIER, SLICE, DATANODE */ +%token ABORT_P ABSOLUTE_P ACCESS ACCOUNT ACTION ADD_P ADMIN AFTER + AGGREGATE ALGORITHM ALL ALSO ALTER ALWAYS ANALYSE ANALYZE AND ANY APP ARRAY AS ASC + ASSERTION ASSIGNMENT ASYMMETRIC AT ATTRIBUTE AUDIT AUTHID AUTHORIZATION AUTOEXTEND AUTOMAPPED + + BACKWARD BARRIER BEFORE BEGIN_NON_ANOYBLOCK BEGIN_P BETWEEN BIGINT BINARY BINARY_DOUBLE BINARY_INTEGER BIT BLOB_P BOGUS + BOOLEAN_P BOTH BUCKETS BY BYTEAWITHOUTORDER BYTEAWITHOUTORDERWITHEQUAL + + CACHE CALL CALLED CASCADE CASCADED CASE CAST CATALOG_P CHAIN CHAR_P + CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLEAN CLIENT CLIENT_MASTER_KEY CLIENT_MASTER_KEYS CLOB CLOSE + CLUSTER COALESCE COLLATE COLLATION COLUMN COLUMN_ARGS COLUMN_ENCRYPTION_KEY COLUMN_ENCRYPTION_KEYS COLUMN_FUNCTION COMMENT COMMENTS COMMIT + COMMITTED COMPACT COMPATIBLE_ILLEGAL_CHARS COMPLETE COMPRESS CONCURRENTLY CONDITION CONFIGURATION CONNECTION CONSTRAINT CONSTRAINTS + CONTENT_P CONTINUE_P CONTVIEW CONVERSION_P COORDINATOR COORDINATORS 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 DATAFILE DATANODE DATANODES DATATYPE_CL DATE_P DATE_FORMAT_P DAY_P DBCOMPATIBILITY_P DEALLOCATE DEC DECIMAL_P DECLARE DECODE DEFAULT DEFAULTS + DEFERRABLE DEFERRED DEFINER DELETE_P DELIMITER DELIMITERS DELTA DELTAMERGE DESC DETERMINISTIC +/* PGXC_BEGIN */ + DICTIONARY DIRECT DIRECTORY DISABLE_P DISCARD DISTINCT DISTRIBUTE DISTRIBUTION DO DOCUMENT_P DOMAIN_P DOUBLE_P +/* PGXC_END */ + DROP DUPLICATE DISCONNECT + + EACH ELASTIC ELSE ENABLE_P ENCODING ENCRYPTED ENCRYPTED_VALUE ENCRYPTION ENCRYPTION_TYPE END_P ENFORCED ENUM_P ERRORS ESCAPE EOL ESCAPING EVERY EXCEPT EXCHANGE + EXCLUDE EXCLUDED EXCLUDING EXCLUSIVE EXECUTE EXISTS EXPIRED_P EXPLAIN + EXTENSION EXTERNAL EXTRACT + + FALSE_P FAMILY FAST FENCED FETCH FILEHEADER_P FILL_MISSING_FIELDS FILTER FIRST_P FIXED_P FLOAT_P FOLLOWING FOR FORCE FOREIGN FORMATTER FORWARD + FREEZE FROM FULL FUNCTION FUNCTIONS + + GLOBAL GLOBAL_FUNCTION GRANT GRANTED GREATEST GROUP_P GROUPING_P + + HANDLER HAVING HDFSDIRECTORY HEADER_P HOLD HOUR_P + + IDENTIFIED IDENTITY_P IF_P IGNORE_EXTRA_DATA ILIKE IMMEDIATE IMMUTABLE IMPLICIT_P IN_P INCLUDE + INCLUDING INCREMENT INCREMENTAL INDEX INDEXES INHERIT INHERITS INITIAL_P INITIALLY INITRANS INLINE_P + + INNER_P INOUT INPUT_P INSENSITIVE INSERT INSTEAD INT_P INTEGER INTERNAL + INTERSECT INTERVAL INTO INVOKER IP IS ISNULL ISOLATION + + JOIN + + KEY KILL KEY_PATH KEY_STORE + + LABEL LANGUAGE LARGE_P LAST_P LC_COLLATE_P LC_CTYPE_P LEADING LEAKPROOF + LEAST LESS LEFT LEVEL LIKE LIMIT LIST LISTEN LOAD LOCAL LOCALTIME LOCALTIMESTAMP + LOCATION LOCK_P LOG_P LOGGING LOGIN_ANY LOGIN_FAILURE LOGIN_SUCCESS LOGOUT LOOP + MAPPING MASKING MASTER MATCH MATERIALIZED MATCHED MAXEXTENTS MAXSIZE MAXTRANS MAXVALUE MERGE MINUS_P MINUTE_P MINVALUE MINEXTENTS MODE MODIFY_P MONTH_P MOVE MOVEMENT + NAME_P NAMES NATIONAL NATURAL NCHAR NEXT NLSSORT NO NOCOMPRESS NOCYCLE NODE NOLOGGING NOMAXVALUE NOMINVALUE NONE + NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF NULLS_P NUMBER_P NUMERIC NUMSTR NVARCHAR2 NVL + + OBJECT_P OF OFF OFFSET OIDS ON ONLY OPERATOR OPTIMIZATION OPTION OPTIONS OR + ORDER OUT_P OUTER_P OVER OVERLAPS OVERLAY OWNED OWNER + + PACKAGE PARSER PARTIAL PARTITION PARTITIONS PASSING PASSWORD PCTFREE PER_P PERCENT PERFORMANCE PERM PLACING PLAN PLANS POLICY POSITION +/* PGXC_BEGIN */ + POOL PRECEDING PRECISION PREFERRED PREFIX PRESERVE PREPARE PREPARED PRIMARY +/* PGXC_END */ + PRIVATE PRIOR PRIVILEGES PRIVILEGE PROCEDURAL PROCEDURE PROFILE + + QUERY QUOTE + + RANDOMIZED RANGE RAW READ REAL REASSIGN REBUILD RECHECK RECURSIVE REDISANYVALUE REF REFERENCES REFRESH REINDEX REJECT_P + RELATIVE_P RELEASE RELOPTIONS REMOTE_P REMOVE RENAME REPEATABLE REPLACE REPLICA + RESET RESIZE RESOURCE RESTART RESTRICT RETURN RETURNING RETURNS REUSE REVOKE RIGHT ROLE ROLES ROLLBACK ROLLUP + ROW ROWNUM ROWS RULE + + SAVEPOINT SCHEMA SCROLL SEARCH SECOND_P SECURITY SELECT SEQUENCE SEQUENCES + SERIALIZABLE SERVER SESSION SESSION_USER SET SETS SETOF SHARE SHIPPABLE SHOW SHUTDOWN + SIMILAR SIMPLE SIZE SLICE SMALLDATETIME SMALLDATETIME_FORMAT_P SMALLINT SNAPSHOT SOME SOURCE_P SPACE SPILL SPLIT STABLE STANDALONE_P START + STATEMENT STATEMENT_ID STATISTICS STDIN STDOUT STORAGE STORE_P STREAM STRICT_P STRIP_P SUBSTRING + SYMMETRIC SYNONYM SYSDATE SYSID SYSTEM_P SYS_REFCURSOR + + TABLE TABLES TABLESAMPLE TABLESPACE TEMP TEMPLATE TEMPORARY TEXT_P THAN THEN TIME TIME_FORMAT_P TIMESTAMP TIMESTAMP_FORMAT_P TIMESTAMPDIFF TINYINT + TO TRAILING TRANSACTION TREAT TRIGGER TRIM TRUE_P + TRUNCATE TRUSTED TSFIELD TSTAG TSTIME TYPE_P TYPES_P + + UNBOUNDED UNCOMMITTED UNENCRYPTED UNION UNIQUE UNKNOWN UNLIMITED UNLISTEN UNLOCK UNLOGGED + UNTIL UNUSABLE UPDATE USER USING + + VACUUM VALID VALIDATE VALIDATION VALIDATOR VALUE_P VALUES VARCHAR VARCHAR2 VARIABLES VARIADIC VARRAY VARYING VCGROUP + VERBOSE VERIFY VERSION_P VIEW VOLATILE + + WEAK WHEN WHERE WHITESPACE_P WINDOW WITH WITHIN WITHOUT WORK WORKLOAD WRAPPER WRITE + + XML_P XMLATTRIBUTES XMLCONCAT XMLELEMENT XMLEXISTS XMLFOREST XMLPARSE + XMLPI XMLROOT XMLSERIALIZE + + YEAR_P YES_P + + ZONE + +/* + * The grammar thinks these are keywords, but they are not in the kwlist.h + * list and so can never be entered directly. The filter in parser.c + * creates these tokens when required. + */ +%token NULLS_FIRST NULLS_LAST WITH_TIME INCLUDING_ALL + RENAME_PARTITION + PARTITION_FOR + ADD_PARTITION + DROP_PARTITION + REBUILD_PARTITION + MODIFY_PARTITION + NOT_ENFORCED + VALID_BEGIN + DECLARE_CURSOR + +/* Precedence: lowest to highest */ +%nonassoc PARTIAL_EMPTY_PREC +%nonassoc CLUSTER +%nonassoc SET /* see relation_expr_opt_alias */ +%left UNION EXCEPT MINUS_P +%left INTERSECT +%left OR +%left AND +%right NOT +%right '=' +%nonassoc '<' '>' CmpOp +%nonassoc LIKE ILIKE SIMILAR +%nonassoc ESCAPE +%nonassoc OVERLAPS +%nonassoc BETWEEN +%nonassoc IN_P +%left POSTFIXOP /* dummy for postfix Op rules */ +/* + * To support target_el without AS, we must give IDENT an explicit priority + * between POSTFIXOP and Op. We can safely assign the same priority to + * various unreserved keywords as needed to resolve ambiguities (this can't + * have any bad effects since obviously the keywords will still behave the + * same as if they weren't keywords). We need to do this for PARTITION, + * RANGE, ROWS to support opt_existing_window_name; and for RANGE, ROWS + * so that they can follow a_expr without creating postfix-operator problems; + * and for NULL so that it can follow b_expr in ColQualList without creating + * postfix-operator problems. + * + * To support CUBE and ROLLUP in GROUP BY without reserving them, we give them + * an explicit priority lower than '(', so that a rule with CUBE '(' will shift + * rather than reducing a conflicting rule that takes CUBE as a function name. + * Using the same precedence as IDENT seems right for the reasons given above. + * + * The frame_bound productions UNBOUNDED PRECEDING and UNBOUNDED FOLLOWING + * are even messier: since UNBOUNDED is an unreserved keyword (per spec!), + * there is no principled way to distinguish these from the productions + * a_expr PRECEDING/FOLLOWING. We hack this up by giving UNBOUNDED slightly + * lower precedence than PRECEDING and FOLLOWING. At present this doesn't + * appear to cause UNBOUNDED to be treated differently from other unreserved + * keywords anywhere else in the grammar, but it's definitely risky. We can + * blame any funny behavior of UNBOUNDED on the SQL standard, though. + */ +%nonassoc UNBOUNDED /* ideally should have same precedence as IDENT */ +%nonassoc IDENT NULL_P PARTITION RANGE ROWS PRECEDING FOLLOWING CUBE ROLLUP +%left Op OPERATOR /* multi-character ops and user-defined operators */ +%nonassoc NOTNULL +%nonassoc ISNULL +%nonassoc IS /* sets precedence for IS NULL, etc */ +%left '+' '-' +%left '*' '/' '%' +%left '^' +/* Unary Operators */ +%left AT /* sets precedence for AT TIME ZONE */ +%left COLLATE +%right UMINUS +%left '[' ']' +%left '(' ')' +%left TYPECAST +%left '.' +/* + * These might seem to be low-precedence, but actually they are not part + * of the arithmetic hierarchy at all in their use as JOIN operators. + * We make them high-precedence to support their use as function names. + * They wouldn't be given a precedence at all, were it not that we need + * left-associativity among the JOIN rules themselves. + */ +%left JOIN CROSS LEFT FULL RIGHT INNER_P NATURAL ENCRYPTED +/* kluge to keep xml_whitespace_option from causing shift/reduce conflicts */ +%right PRESERVE STRIP_P + +%% + +/* + * The target production for the whole parse. + */ +stmtblock: stmtmulti + { + pg_yyget_extra(yyscanner)->parsetree = $1; + } + ; + +/* the thrashing around here is to discard "empty" statements... */ +stmtmulti: stmtmulti ';' stmt + { + if ($3 != NULL) + { + if (IsA($3, List)) + { + $$ = list_concat($1, (List*)$3); + } + else + { + $$ = lappend($1, $3); + } + } + else + $$ = $1; + } + | stmt + { + if ($1 != NULL) + { + if (IsA($1, List)) + { + $$ = (List*)$1; + } + else + { + $$ = list_make1($1); + } + } + else + $$ = NIL; + } + ; +stmt : + AlterAppWorkloadGroupMappingStmt + | AlterCoordinatorStmt + | AlterDatabaseStmt + | AlterDatabaseSetStmt + | AlterDataSourceStmt + | AlterDefaultPrivilegesStmt + | AlterDomainStmt + | AlterEnumStmt + | AlterExtensionStmt + | AlterExtensionContentsStmt + | AlterFdwStmt + | AlterForeignServerStmt + | AlterForeignTableStmt + | AlterFunctionStmt + | AlterProcedureStmt + | AlterGroupStmt + | AlterNodeGroupStmt + | AlterNodeStmt + | AlterObjectSchemaStmt + | AlterOwnerStmt + | AlterRlsPolicyStmt + | AlterResourcePoolStmt + | AlterSeqStmt + | AlterTableStmt + | AlterSystemStmt + | AlterCompositeTypeStmt + | AlterRoleSetStmt + | AlterRoleStmt + | AlterSessionStmt + | AlterTSConfigurationStmt + | AlterTSDictionaryStmt + | AlterUserMappingStmt + | AlterUserSetStmt + | AlterUserStmt + | AlterWorkloadGroupStmt + | AnalyzeStmt + | AnonyBlockStmt + | BarrierStmt + | CreateAppWorkloadGroupMappingStmt + | CallFuncStmt + | CheckPointStmt + | CleanConnStmt + | ClosePortalStmt + | ClusterStmt + | CommentStmt + | ConstraintsSetStmt + | CopyStmt + | CreateAsStmt + | CreateAssertStmt + | CreateCastStmt + | CreateContQueryStmt + | CreateStreamStmt + | CreateConversionStmt + | CreateDomainStmt + | CreateDirectoryStmt + | CreateExtensionStmt + | CreateFdwStmt + | CreateForeignServerStmt + | CreateForeignTableStmt + | CreateDataSourceStmt + | CreateFunctionStmt + | CreateGroupStmt + | CreateMatViewStmt + | CreateNodeGroupStmt + | CreateNodeStmt + | CreateOpClassStmt + | CreateOpFamilyStmt + | AlterOpFamilyStmt + | CreateRlsPolicyStmt + | CreatePLangStmt + | CreateProcedureStmt + | CreateKeyStmt + | CreatePolicyLabelStmt + | CreateWeakPasswordDictionaryStmt + | DropWeakPasswordDictionaryStmt + | AlterPolicyLabelStmt + | DropPolicyLabelStmt + | CreateAuditPolicyStmt + | AlterAuditPolicyStmt + | DropAuditPolicyStmt + | CreateMaskingPolicyStmt + | AlterMaskingPolicyStmt + | DropMaskingPolicyStmt + | CreateResourcePoolStmt + | CreateSchemaStmt + | CreateSeqStmt + | CreateStmt + | CreateSynonymStmt + | CreateTableSpaceStmt + | CreateTrigStmt + | CreateRoleStmt + | CreateUserStmt + | CreateUserMappingStmt + | CreateWorkloadGroupStmt + | CreatedbStmt + | DeallocateStmt + | DeclareCursorStmt + | DefineStmt + | DeleteStmt + | DiscardStmt + | DoStmt + | DropAppWorkloadGroupMappingStmt + | DropAssertStmt + | DropCastStmt + | DropDataSourceStmt + | DropDirectoryStmt + | DropFdwStmt + | DropForeignServerStmt + | DropGroupStmt + | DropNodeGroupStmt + | DropNodeStmt + | DropOpClassStmt + | DropOpFamilyStmt + | DropOwnedStmt + | DropRlsPolicyStmt + | DropPLangStmt + | DropResourcePoolStmt + | DropRuleStmt + | DropStmt + | DropSynonymStmt + | DropTableSpaceStmt + | DropTrigStmt + | DropRoleStmt + | DropUserStmt + | DropUserMappingStmt + | DropWorkloadGroupStmt + | DropdbStmt + | ExecuteStmt + | ExecDirectStmt + | ExplainStmt + | FetchStmt + | GrantStmt + | GrantRoleStmt + | IndexStmt + | InsertStmt + | ListenStmt + | RefreshMatViewStmt + | LoadStmt + | LockStmt + | MergeStmt + | NotifyStmt + | PrepareStmt + | ReassignOwnedStmt + | ReindexStmt + | RemoveAggrStmt + | RemoveFuncStmt + | RemoveOperStmt + | RenameStmt + | RevokeStmt + | RevokeRoleStmt + | RuleStmt + | SecLabelStmt + | SelectStmt + | ShutdownStmt + | TransactionStmt + | TruncateStmt + | UnlistenStmt + | UpdateStmt + | VacuumStmt + | VariableResetStmt + | VariableSetStmt + | VariableShowStmt + | VerifyStmt + | ViewStmt + | /*EMPTY*/ + { $$ = NULL; } + ; + +/***************************************************************************** + * + * Create a new Postgres DBMS role + * + *****************************************************************************/ + +CreateRoleStmt: + CREATE ROLE RoleId opt_with OptRoleList + { + CreateRoleStmt *n = makeNode(CreateRoleStmt); + n->stmt_type = ROLESTMT_ROLE; + if (!isRestoreMode) + IsValidIdent($3); + n->role = $3; + n->options = $5; + $$ = (Node *)n; + } + ; + + +opt_with: WITH {} + | /*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; } + ; + +password_string: + Sconst + { + t_thrd.postgres_cxt.clear_key_memory = true; + $$ = $1; + } + | IDENT + { + t_thrd.postgres_cxt.clear_key_memory = true; + core_yy_extra_type yyextra = pg_yyget_extra(yyscanner)->core_yy_extra; + if (yyextra.ident_quoted) + $$ = $1; + else + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Password must be quoted"))); + } +namedata_string: + Sconst + { + $$ = pg_strtolower($1); + } + | IDENT + { + core_yy_extra_type yyextra = pg_yyget_extra(yyscanner)->core_yy_extra; + if (yyextra.ident_quoted) + $$ = $1; + else + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("name data must be quoted"))); + } + ; +AlterOptRoleElem: + PASSWORD password_string + { + $$ = makeDefElem("password", + (Node *)list_make1(makeStringConst($2, @2))); + } + | IDENTIFIED BY password_string + { + $$ = makeDefElem("password", + (Node *)list_make1(makeStringConst($3, @3))); + } + | ENCRYPTED IDENTIFIED BY password_string + { + $$ = makeDefElem("encryptedPassword", + (Node *)list_make1(makeStringConst($4, @4))); + } + | UNENCRYPTED IDENTIFIED BY password_string + { + $$ = makeDefElem("unencryptedPassword", + (Node *)list_make1(makeStringConst($4, @4))); + } + | IDENTIFIED BY password_string REPLACE password_string + { + $$ = makeDefElem("password", + (Node *)list_make2(makeStringConst($3, @3), makeStringConst($5, @5))); + } + | ENCRYPTED IDENTIFIED BY password_string REPLACE password_string + { + $$ = makeDefElem("encryptedPassword", + (Node *)list_make2(makeStringConst($4, @4), makeStringConst($6, @6))); + } + | UNENCRYPTED IDENTIFIED BY password_string REPLACE password_string + { + $$ = makeDefElem("unencryptedPassword", + (Node *)list_make2(makeStringConst($4, @4), makeStringConst($6, @6))); + } + | IDENTIFIED BY DISABLE_P + { + $$ = makeDefElem("password", NULL); + } + | PASSWORD DISABLE_P + { + $$ = makeDefElem("password", NULL); + } + | PASSWORD EXPIRED_P + { + $$ = makeDefElem("expired", (Node *)makeInteger(TRUE)); + } + | PASSWORD password_string EXPIRED_P + { + $$ = makeDefElem("expiredPassword", (Node *)list_make1(makeStringConst($2, @2))); + } + | IDENTIFIED BY password_string EXPIRED_P + { + $$ = makeDefElem("expiredPassword", (Node *)list_make1(makeStringConst($3, @3))); + } + | ENCRYPTED PASSWORD password_string + { + $$ = makeDefElem("encryptedPassword", + (Node *)list_make1(makeStringConst($3, @3))); + } + | UNENCRYPTED PASSWORD password_string + { + $$ = makeDefElem("unencryptedPassword", + (Node *)list_make1(makeStringConst($3, @3))); + } + | DEFAULT TABLESPACE name + { + $$ = makeDefElem("tablespace", (Node *)makeString($3)); + } + | PROFILE DEFAULT + { + $$ = makeDefElem("profile", NULL); + } + | PROFILE name + { + $$ = makeDefElem("profile", + (Node *)list_make1(makeStringConst($2, @2))); + } + | INHERIT + { + $$ = makeDefElem("inherit", (Node *)makeInteger(TRUE)); + } + | CONNECTION LIMIT SignedIconst + { + $$ = makeDefElem("connectionlimit", (Node *)makeInteger($3)); + } + | RESOURCE POOL namedata_string + { + $$ = makeDefElem("respool", (Node *)makeString($3)); + } + | NODE GROUP_P pgxcgroup_name + { + $$ = makeDefElem("node_group", (Node *)makeString($3)); + } + | USER GROUP_P namedata_string + { + $$ = makeDefElem("parent", (Node *)makeString($3)); + } + | USER GROUP_P DEFAULT + { + $$ = makeDefElem("parent_default", NULL); + } + | PERM SPACE Sconst + { + $$ = makeDefElem("space_limit", (Node *)makeString($3)); + } + | TEMP SPACE Sconst + { + $$ = makeDefElem("temp_space_limit", (Node *)makeString($3)); + } + | SPILL SPACE Sconst + { + $$ = makeDefElem("spill_space_limit", (Node *)makeString($3)); + } + /* VALID and BEGIN is treated as a token to avoid confilict with BEGIN TRANSACTIOn and BEGIN ANONYMOUD BLOCK */ + | VALID_BEGIN Sconst + { + $$ = makeDefElem("validBegin", (Node *)makeString($2)); + } + | VALID UNTIL Sconst + { + $$ = makeDefElem("validUntil", (Node *)makeString($3)); + } + /* Supported but not documented for roles, for use by ALTER GROUP. */ + | USER name_list + { + $$ = makeDefElem("rolemembers", (Node *)$2); + } + | IDENT + { + /* + * We handle identifiers that aren't parser keywords with + * the following special-case codes, to avoid bloating the + * size of the main parser. + */ + if (strcmp($1, "createrole") == 0) + $$ = makeDefElem("createrole", (Node *)makeInteger(TRUE)); + else if (strcmp($1, "nocreaterole") == 0) + $$ = makeDefElem("createrole", (Node *)makeInteger(FALSE)); + else if (strcmp($1, "replication") == 0) + $$ = makeDefElem("isreplication", (Node *)makeInteger(TRUE)); + else if (strcmp($1, "noreplication") == 0) + $$ = makeDefElem("isreplication", (Node *)makeInteger(FALSE)); + /* add audit admin privilege */ + else if (strcmp($1, "auditadmin") == 0) + $$ = makeDefElem("isauditadmin", (Node *)makeInteger(TRUE)); + else if (strcmp($1, "noauditadmin") == 0) + $$ = makeDefElem("isauditadmin", (Node *)makeInteger(FALSE)); + /* END */ + else if (strcmp($1, "sysadmin") == 0) + $$ = makeDefElem("issystemadmin", (Node *)makeInteger(TRUE)); + else if (strcmp($1, "nosysadmin") == 0) + $$ = makeDefElem("issystemadmin", (Node *)makeInteger(FALSE)); + /* Add system monitor privilege, operator privilege. */ + else if (strcmp($1, "monadmin") == 0) + $$ = makeDefElem("ismonitoradmin", (Node *)makeInteger(TRUE)); + else if (strcmp($1, "nomonadmin") == 0) + $$ = makeDefElem("ismonitoradmin", (Node *)makeInteger(FALSE)); + else if (strcmp($1, "opradmin") == 0) + $$ = makeDefElem("isoperatoradmin", (Node *)makeInteger(TRUE)); + else if (strcmp($1, "noopradmin") == 0) + $$ = makeDefElem("isoperatoradmin", (Node *)makeInteger(FALSE)); + else if (strcmp($1, "poladmin") == 0) + $$ = makeDefElem("ispolicyadmin", (Node *)makeInteger(TRUE)); + else if (strcmp($1, "nopoladmin") == 0) + $$ = makeDefElem("ispolicyadmin", (Node *)makeInteger(FALSE)); + /* End */ + else if (strcmp($1, "vcadmin") == 0) + $$ = makeDefElem("isvcadmin", (Node *)makeInteger(TRUE)); + else if (strcmp($1, "novcadmin") == 0) + $$ = makeDefElem("isvcadmin", (Node *)makeInteger(FALSE)); + else if (strcmp($1, "createdb") == 0) + $$ = makeDefElem("createdb", (Node *)makeInteger(TRUE)); + else if (strcmp($1, "nocreatedb") == 0) + $$ = makeDefElem("createdb", (Node *)makeInteger(FALSE)); + else if (strcmp($1, "useft") == 0) + $$ = makeDefElem("useft", (Node *)makeInteger(TRUE)); + else if (strcmp($1, "nouseft") == 0) + $$ = makeDefElem("useft", (Node *)makeInteger(FALSE)); + else if (strcmp($1, "login") == 0) + $$ = makeDefElem("canlogin", (Node *)makeInteger(TRUE)); + else if (strcmp($1, "nologin") == 0) + $$ = makeDefElem("canlogin", (Node *)makeInteger(FALSE)); + else if (strcmp($1, "independent") == 0) + $$ = makeDefElem("independent", (Node *)makeInteger(TRUE)); + else if (strcmp($1, "noindependent") == 0) + $$ = makeDefElem("independent", (Node *)makeInteger(FALSE)); + else if (strcmp($1, "persistence") == 0) + $$ = makeDefElem("persistence", (Node *)makeInteger(TRUE)); + else if (strcmp($1, "nopersistence") == 0) + $$ = makeDefElem("persistence", (Node *)makeInteger(FALSE)); + else if (strcmp($1, "noinherit") == 0) + { + /* + * Note that INHERIT is a keyword, so it's handled by main parser, but + * NOINHERIT is handled here. + */ + $$ = makeDefElem("inherit", (Node *)makeInteger(FALSE)); + } + else if (strcmp($1, "pguser") == 0) + { + $$ = makeDefElem("pguser", (Node *)makeInteger(TRUE)); + } + else + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("unrecognized role option \"%s\"", $1), + parser_errposition(@1))); + } + ; + +CreateOptRoleElem: + AlterOptRoleElem { $$ = $1; } + /* The following are not supported by ALTER ROLE/USER/GROUP */ + | SYSID Iconst + { + $$ = makeDefElem("sysid", (Node *)makeInteger($2)); + } + | ADMIN name_list + { + $$ = makeDefElem("adminmembers", (Node *)$2); + } + | ROLE name_list + { + $$ = makeDefElem("rolemembers", (Node *)$2); + } + | IN_P ROLE name_list + { + $$ = makeDefElem("addroleto", (Node *)$3); + } + | IN_P GROUP_P name_list + { + $$ = makeDefElem("addroleto", (Node *)$3); + } + ; + + +/***************************************************************************** + * + * Create a new Postgres DBMS user (role with implied login ability) + * + *****************************************************************************/ + +CreateUserStmt: + CREATE USER RoleId opt_with OptRoleList + { + CreateRoleStmt *n = makeNode(CreateRoleStmt); + n->stmt_type = ROLESTMT_USER; + IsValidIdent($3); + n->role = $3; + n->options = $5; + $$ = (Node *)n; + } + ; + + +/***************************************************************************** + * + * Alter a postgresql DBMS role + * + *****************************************************************************/ + +AlterRoleStmt: + ALTER ROLE RoleId opt_with AlterOptRoleList + { + AlterRoleStmt *n = makeNode(AlterRoleStmt); + n->role = $3; + n->action = +1; /* add, if there are members */ + n->options = $5; + n->lockstatus = DO_NOTHING; + $$ = (Node *)n; + } + | ALTER ROLE RoleId opt_with ACCOUNT LOCK_P + { + AlterRoleStmt *n = makeNode(AlterRoleStmt); + n->role = $3; + n->action = +1; /* add, if there are members */ + n->options = NIL; + n->lockstatus = LOCK_ROLE; + $$ = (Node *)n; + } + | ALTER ROLE RoleId opt_with ACCOUNT UNLOCK + { + AlterRoleStmt *n = makeNode(AlterRoleStmt); + n->role = $3; + n->action = +1; /* add, if there are members */ + n->options = NIL; + n->lockstatus = UNLOCK_ROLE; + $$ = (Node *)n; + } + ; + +opt_in_database: + /* EMPTY */ { $$ = NULL; } + | IN_P DATABASE database_name { $$ = $3; } + ; + +AlterRoleSetStmt: + ALTER ROLE RoleId opt_in_database SetResetClause + { + AlterRoleSetStmt *n = makeNode(AlterRoleSetStmt); + n->role = $3; + n->database = $4; + n->setstmt = $5; + $$ = (Node *)n; + } + ; + + +/***************************************************************************** + * + * Alter a postgresql DBMS user + * + *****************************************************************************/ + +AlterUserStmt: + ALTER USER RoleId opt_with AlterOptRoleList + { + AlterRoleStmt *n = makeNode(AlterRoleStmt); + n->role = $3; + n->action = +1; /* add, if there are members */ + n->options = $5; + n->lockstatus = DO_NOTHING; + $$ = (Node *)n; + } + | ALTER USER RoleId opt_with ACCOUNT LOCK_P + { + AlterRoleStmt *n = makeNode(AlterRoleStmt); + n->role = $3; + n->action = +1; /* add, if there are members */ + n->options = NIL; + n->lockstatus = LOCK_ROLE; + $$ = (Node *)n; + } + | ALTER USER RoleId opt_with ACCOUNT UNLOCK + { + AlterRoleStmt *n = makeNode(AlterRoleStmt); + n->role = $3; + n->action = +1; /* add, if there are members */ + n->options = NIL; + n->lockstatus = UNLOCK_ROLE; + $$ = (Node *)n; + } + ; + + +AlterUserSetStmt: + ALTER USER RoleId opt_in_database SetResetClause + { + AlterRoleSetStmt *n = makeNode(AlterRoleSetStmt); + n->role = $3; + n->database = $4; + n->setstmt = $5; + $$ = (Node *)n; + } + ; + + +/***************************************************************************** + * + * Drop a postgresql DBMS role + * + * XXX Ideally this would have CASCADE/RESTRICT options, but since a role + * might own objects in multiple databases, there is presently no way to + * implement either cascading or restricting. Caveat DBA. + *****************************************************************************/ + +DropRoleStmt: + DROP ROLE name_list + { + DropRoleStmt *n = makeNode(DropRoleStmt); + n->missing_ok = FALSE; + n->roles = $3; + $$ = (Node *)n; + } + | DROP ROLE IF_P EXISTS name_list + { + DropRoleStmt *n = makeNode(DropRoleStmt); + n->missing_ok = TRUE; + n->roles = $5; + $$ = (Node *)n; + } + ; + +/***************************************************************************** + * + * Drop a postgresql DBMS user + * + * XXX Ideally this would have CASCADE/RESTRICT options, but since a user + * might own objects in multiple databases, there is presently no way to + * implement either cascading or restricting. Caveat DBA. + *****************************************************************************/ + +DropUserStmt: + DROP USER name_list opt_drop_behavior + { + DropRoleStmt *n = makeNode(DropRoleStmt); + n->missing_ok = FALSE; + n->is_user = TRUE; + n->roles = $3; + n->behavior = $4; + $$ = (Node *)n; + } + | DROP USER IF_P EXISTS name_list opt_drop_behavior + { + DropRoleStmt *n = makeNode(DropRoleStmt); + n->roles = $5; + n->missing_ok = true; + n->is_user = TRUE; + n->behavior = $6; + n->is_user = TRUE; + n->behavior = $6; + $$ = (Node *)n; + } + ; + +/***************************************************************************** + * + * Create a postgresql group (role without login ability) + * + *****************************************************************************/ + +CreateGroupStmt: + CREATE GROUP_P RoleId opt_with OptRoleList + { + CreateRoleStmt *n = makeNode(CreateRoleStmt); + n->stmt_type = ROLESTMT_GROUP; + n->role = $3; + n->options = $5; + $$ = (Node *)n; + } + ; + + +/***************************************************************************** + * + * Alter a postgresql group + * + *****************************************************************************/ + +AlterGroupStmt: + ALTER GROUP_P RoleId add_drop USER name_list + { + AlterRoleStmt *n = makeNode(AlterRoleStmt); + n->role = $3; + n->action = $4; + n->options = list_make1(makeDefElem("rolemembers", + (Node *)$6)); + $$ = (Node *)n; + } + ; + +add_drop: ADD_P { $$ = +1; } + | DROP { $$ = -1; } + ; + +/***************************************************************************** + * + * Alter SESSION + * + *****************************************************************************/ + +AlterSessionStmt: + ALTER SESSION SET set_rest + { + VariableSetStmt *n = $4; + n->is_local = false; + $$ = (Node *) n; + } + ; + +/* "alter system" */ +/***************************************************************************** + * + * Alter SYSTEM + * (1. kill a session by "select pg_terminate_backend(pid)", so it only needs a SelectStmt node.) + * (2. disconnect a session. unsupported currently.) + * (3. set system parameter to, this is used to change configuration parameters persistently.) + * + *****************************************************************************/ + +AlterSystemStmt: + ALTER SYSTEM_P KILL SESSION Sconst altersys_option + { + SelectStmt *n = NULL; + List *pid = NULL; + + pid = get_func_args($5); + + n = makeNode(SelectStmt); + n->distinctClause = NIL; + n->targetList = make_action_func(pid); + n->intoClause = NULL; + n->fromClause = NIL; + n->whereClause = NULL; + n->groupClause = NIL; + n->havingClause = NULL; + n->windowClause = NIL; + $$ = (Node *)n; + } + + | ALTER SYSTEM_P DISCONNECT SESSION Sconst altersys_option + { + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("unsupported action \"DISCONNECT\" for statement \" alter system \""))); + } + + | ALTER SYSTEM_P SET generic_set + { +#ifdef ENABLE_MULTIPLE_NODES + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("ALTER SYSTEM SET is not supported in distributed mode."))); +#else + AlterSystemStmt *n = makeNode(AlterSystemStmt); + n->setstmt = $4; + $$ = (Node *)n; +#endif + } + ; + +altersys_option: + IMMEDIATE {/* empty */} + | {/* empty */} + ; + +/***************************************************************************** + * + * Drop a postgresql group + * + * XXX see above notes about cascading DROP USER; groups have same problem. + *****************************************************************************/ + +DropGroupStmt: + DROP GROUP_P name_list + { + DropRoleStmt *n = makeNode(DropRoleStmt); + n->missing_ok = FALSE; + n->roles = $3; + $$ = (Node *)n; + } + | DROP GROUP_P IF_P EXISTS name_list + { + DropRoleStmt *n = makeNode(DropRoleStmt); + n->missing_ok = TRUE; + n->roles = $5; + $$ = (Node *)n; + } + ; + + +/***************************************************************************** + * + * Manipulate a schema + * + *****************************************************************************/ + +CreateSchemaStmt: + CREATE SCHEMA OptSchemaName AUTHORIZATION RoleId OptSchemaEltList + { + CreateSchemaStmt *n = makeNode(CreateSchemaStmt); + /* One can omit the schema name or the authorization id. */ + if ($3 != NULL) + n->schemaname = $3; + else + n->schemaname = $5; + n->authid = $5; + n->schemaElts = $6; + $$ = (Node *)n; + } + | CREATE SCHEMA ColId OptSchemaEltList + { + CreateSchemaStmt *n = makeNode(CreateSchemaStmt); + /* ...but not both */ + n->schemaname = $3; + n->authid = NULL; + n->schemaElts = $4; + $$ = (Node *)n; + } + ; + +OptSchemaName: + ColId { $$ = $1; } + | /* EMPTY */ { $$ = NULL; } + ; + +OptSchemaEltList: + OptSchemaEltList schema_stmt { $$ = 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 + | CreateKeyStmt + | IndexStmt + | CreateSeqStmt + | CreateTrigStmt + | GrantStmt + | ViewStmt + ; + + +/***************************************************************************** + * + * Set PG internal variable + * SET name TO 'var_value' + * Include SQL92 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; + /* if we are setting role, we switch to the new syntax which check the password of role */ + if(!strcmp("role", n->name) || !pg_strcasecmp("session_authorization", n->name)) + { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("\"SET %s TO rolename\" not yet supported", n->name), + errhint("Use \"SET %s rolename\" clauses.", n->name))); + } + else + { + n->kind = VAR_SET_VALUE; + } + $$ = n; + } + | var_name '=' var_list + { + VariableSetStmt *n = makeNode(VariableSetStmt); + n->kind = VAR_SET_VALUE; + n->name = $1; + n->args = $3; + /* if we are setting role, we switch to the new syntax which check the password of role */ + if(!strcmp("role", n->name) || !pg_strcasecmp("session_authorization", n->name)) + { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("\"SET %s = rolename\" not yet supported", n->name), + errhint("Use \"SET %s rolename\" clauses.", n->name))); + } + else + { + n->kind = VAR_SET_VALUE; + } + $$ = 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; + } + | CURRENT_SCHEMA TO var_list + { + VariableSetStmt *n = makeNode(VariableSetStmt); + n->kind = VAR_SET_VALUE; + n->name = "current_schema"; + n->args = $3; + $$ = n; + } + | CURRENT_SCHEMA '=' var_list + { + VariableSetStmt *n = makeNode(VariableSetStmt); + n->kind = VAR_SET_VALUE; + n->name = "current_schema"; + n->args = $3; + $$ = n; + } + | CURRENT_SCHEMA TO DEFAULT + { + VariableSetStmt *n = makeNode(VariableSetStmt); + n->kind = VAR_SET_DEFAULT; + n->name = "current_schema"; + $$ = n; + } + | CURRENT_SCHEMA '=' DEFAULT + { + VariableSetStmt *n = makeNode(VariableSetStmt); + n->kind = VAR_SET_DEFAULT; + n->name = "current_schema"; + $$ = 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 ColId_or_Sconst + { + VariableSetStmt *n = makeNode(VariableSetStmt); + n->kind = VAR_SET_ROLEPWD; + n->name = "role"; + n->args = list_make1(makeStringConst($2, @2)); + $$ = n; + } + | ROLE ColId_or_Sconst PASSWORD password_string + { + VariableSetStmt *n = makeNode(VariableSetStmt); + n->kind = VAR_SET_ROLEPWD; + n->name = "role"; + n->args = list_make2(makeStringConst($2, @2), makeStringConst($4, @4)); + $$ = n; + } + | SESSION AUTHORIZATION ColId_or_Sconst PASSWORD password_string + { + VariableSetStmt *n = makeNode(VariableSetStmt); + n->kind = VAR_SET_ROLEPWD; + n->name = "session_authorization"; + n->args = list_make2(makeStringConst($3, @3), makeStringConst($5,@5)); + $$ = 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(const_cast($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 + { + int rc = EOK; + int len = strlen($1) + strlen($3) + 2; + $$ = (char *)palloc(len); + rc = sprintf_s($$, len, "%s.%s", $1, $3); + securec_check_ss(rc, "\0", "\0"); + } + ; + +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 ColId rule below. The action for booleans and strings + * is the same, so we don't need to distinguish them here. + */ + | ColId_or_Sconst { $$ = $1; } + ; + +/* Timezone values can be: + * - a string such as 'pst8pdt' + * - an identifier such as "pst8pdt" + * - an integer or floating point number + * - a time interval per SQL99 + * ColId gives reduce/reduce errors against ConstInterval and LOCAL, + * so use IDENT (meaning we reject anything that is a key word). + */ +zone_value: + Sconst + { + $$ = makeStringConst($1, @1); + } + | IDENT + { + $$ = makeStringConst($1, @1); + } + | ConstInterval Sconst opt_interval + { + TypeName *t = $1; + if ($3 != NIL) + { + A_Const *n = (A_Const *) linitial($3); + if ((n->val.val.ival & ~(INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE))) != 0) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("time zone interval must be HOUR or HOUR TO MINUTE"), + parser_errposition(@3))); + } + t->typmods = $3; + $$ = makeStringConstCast($2, @2, t); + } + | ConstInterval '(' Iconst ')' Sconst opt_interval + { + TypeName *t = $1; + if ($6 != NIL) + { + A_Const *n = (A_Const *) linitial($6); + if ((n->val.val.ival & ~(INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE))) != 0) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("time zone interval must be HOUR or HOUR TO MINUTE"), + parser_errposition(@6))); + if (list_length($6) != 1) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("interval precision specified twice"), + parser_errposition(@1))); + t->typmods = lappend($6, makeIntConst($3, @3)); + } + else + 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; } + ; + +ColId_or_Sconst: + ColId { $$ = $1; } + | Sconst { $$ = $1; } + ; + +VariableResetStmt: + RESET var_name + { + VariableSetStmt *n = makeNode(VariableSetStmt); + n->kind = VAR_RESET; + n->name = $2; + $$ = (Node *) n; + } + | RESET TIME ZONE + { + VariableSetStmt *n = makeNode(VariableSetStmt); + n->kind = VAR_RESET; + n->name = "timezone"; + $$ = (Node *) n; + } + | RESET CURRENT_SCHEMA + { + VariableSetStmt *n = makeNode(VariableSetStmt); + n->kind = VAR_RESET; + n->name = "current_schema"; + $$ = (Node *) n; + } + | RESET TRANSACTION ISOLATION LEVEL + { + VariableSetStmt *n = makeNode(VariableSetStmt); + n->kind = VAR_RESET; + n->name = "transaction_isolation"; + $$ = (Node *) n; + } + | RESET SESSION AUTHORIZATION + { + VariableSetStmt *n = makeNode(VariableSetStmt); + n->kind = VAR_RESET; + n->name = "session_authorization"; + $$ = (Node *) n; + } + | RESET ALL + { + VariableSetStmt *n = makeNode(VariableSetStmt); + n->kind = VAR_RESET_ALL; + $$ = (Node *) 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 CURRENT_SCHEMA + { + VariableShowStmt *n = makeNode(VariableShowStmt); + n->name = "current_schema"; + $$ = (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 VARIABLES LIKE var_name + { + VariableShowStmt *n = makeNode(VariableShowStmt); + n->name = "all"; + n->likename = $4; + $$ = (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; } + ; + +/***************************************************************************** + * + * SHUTDOWN STATEMENT + * + *****************************************************************************/ +ShutdownStmt: + SHUTDOWN + { + ShutdownStmt *n = makeNode(ShutdownStmt); + n->mode = NULL; + $$ = (Node *) n; + } + | SHUTDOWN var_name + { + ShutdownStmt *n = makeNode(ShutdownStmt); + n->mode = $2; + $$ = (Node *) n; + } + ; + +/* + * Checkpoint statement + */ +CheckPointStmt: + CHECKPOINT + { + CheckPointStmt *n = makeNode(CheckPointStmt); + $$ = (Node *)n; + } + ; + + +/***************************************************************************** + * + * DISCARD { ALL | TEMP | PLANS } + * + *****************************************************************************/ + +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; + } + ; + + +/***************************************************************************** + * + * ALTER [ TABLE | INDEX | SEQUENCE | VIEW | MATERIALIZED VIEW| STREAM] variations + * + * Note: we accept all subcommands for each of the five variants, and sort + * out what's really legal at execution time. + *****************************************************************************/ + +AlterTableStmt: + ALTER TABLE relation_expr MODIFY_P '(' modify_column_cmds ')' + { + AlterTableStmt *n = makeNode(AlterTableStmt); + n->relation = $3; + n->cmds = $6; + n->relkind = OBJECT_TABLE; + n->missing_ok = false; + n->need_rewrite_sql = false; + $$ = (Node *)n; + } + | ALTER TABLE relation_expr ADD_P '(' add_column_cmds ')' + { + AlterTableStmt *n = makeNode(AlterTableStmt); + n->relation = $3; + n->cmds = $6; + n->relkind = OBJECT_TABLE; + n->missing_ok = false; + n->need_rewrite_sql = false; + $$ = (Node *)n; + } + /* REDISANYVALUE key value only used in tsdb redis command, it is used in OM code */ + | ALTER TABLE relation_expr REDISANYVALUE + { + AlterTableStmt *n = makeNode(AlterTableStmt); + n->relation = $3; + n->cmds = NIL; + n->relkind = OBJECT_TABLE; + n->missing_ok = false; + n->need_rewrite_sql = false; + $$ = (Node *)n; + } + /* + * ALTER TABLE IF_P EXISTS MODIFY_P '(' modify_column_cmds ')' + */ + | ALTER TABLE IF_P EXISTS relation_expr MODIFY_P '(' modify_column_cmds ')' + { + AlterTableStmt *n = makeNode(AlterTableStmt); + n->relation = $5; + n->cmds = $8; + n->relkind = OBJECT_TABLE; + n->missing_ok = true; + n->need_rewrite_sql = false; + $$ = (Node *)n; + } + /* + * ALTER TABLE IF_P EXISTS ADD_P '(' add_column_cmds ')' + */ + | ALTER TABLE IF_P EXISTS relation_expr ADD_P '(' add_column_cmds ')' + { + AlterTableStmt *n = makeNode(AlterTableStmt); + n->relation = $5; + n->cmds = $8; + n->relkind = OBJECT_TABLE; + n->missing_ok = true; + n->need_rewrite_sql = false; + $$ = (Node *)n; + } + | ALTER TABLE relation_expr alter_table_or_partition + { + if ($4->length == 1 && ((AlterTableCmd*)lfirst($4->head))->subtype == AT_RebuildAllIndexOnPartition) + { + ReindexStmt *n = makeNode(ReindexStmt); + n->kind = OBJECT_TABLE_PARTITION; + n->relation = $3; + n->name = ((AlterTableCmd*)lfirst($4->head))->name; + $$ = (Node *)n; + } + else + { + AlterTableStmt *n = makeNode(AlterTableStmt); + n->relation = $3; + n->cmds = $4; + n->relkind = OBJECT_TABLE; + n->missing_ok = false; + n->need_rewrite_sql = false; + $$ = (Node *)n; + } + } + | ALTER TABLE IF_P EXISTS relation_expr alter_table_or_partition + { + if ($6->length == 1 && ((AlterTableCmd*)lfirst($6->head))->subtype == AT_RebuildAllIndexOnPartition) + { + ReindexStmt *n = makeNode(ReindexStmt); + n->kind = OBJECT_TABLE_PARTITION; + n->relation = $5; + n->name = ((AlterTableCmd*)lfirst($6->head))->name; + $$ = (Node *)n; + } + else + { + AlterTableStmt *n = makeNode(AlterTableStmt); + n->relation = $5; + n->cmds = $6; + n->relkind = OBJECT_TABLE; + n->missing_ok = true; + n->need_rewrite_sql = false; + $$ = (Node *)n; + } + } + | ALTER INDEX qualified_name alter_table_or_partition + { + if ($4->length == 1 && ((AlterTableCmd*)lfirst($4->head))->subtype == AT_RebuildIndex) + { + ReindexStmt *n = makeNode(ReindexStmt); + n->kind = OBJECT_INDEX; + n->relation = $3; + n->name = NULL; + $$ = (Node *)n; + } + else if ($4->length == 1 && ((AlterTableCmd*)lfirst($4->head))->subtype == AT_RebuildIndexPartition) + { + ReindexStmt *n = makeNode(ReindexStmt); + n->kind = OBJECT_INDEX_PARTITION; + n->relation = $3; + n->name = ((AlterTableCmd*)lfirst($4->head))->name; + $$ = (Node *)n; + } + else + { + ListCell *cell; + foreach(cell, $4) + { + AlterTableCmd* cmd = (AlterTableCmd*) lfirst(cell); + if (cmd->subtype == AT_RebuildIndex + || cmd->subtype == AT_RebuildIndexPartition) + { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("REBUILD is not supported for multiple commands"))); + } + } + + AlterTableStmt *n = makeNode(AlterTableStmt); + n->relation = $3; + n->cmds = $4; + n->relkind = OBJECT_INDEX; + n->missing_ok = false; + $$ = (Node *)n; + } + } + | ALTER INDEX IF_P EXISTS qualified_name alter_table_or_partition + { + ListCell *cell; + foreach(cell, $6) + { + AlterTableCmd* cmd = (AlterTableCmd*) lfirst(cell); + if (cmd->subtype == AT_RebuildIndex + || cmd->subtype == AT_RebuildIndexPartition) + { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("IF EXISTS is not supported for REBUILD"))); + } + } + + AlterTableStmt *n = makeNode(AlterTableStmt); + n->relation = $5; + n->cmds = $6; + n->relkind = OBJECT_INDEX; + n->missing_ok = true; + $$ = (Node *)n; + } + | ALTER SEQUENCE qualified_name alter_table_cmds + { + AlterTableStmt *n = makeNode(AlterTableStmt); + n->relation = $3; + n->cmds = $4; + n->relkind = OBJECT_SEQUENCE; + n->missing_ok = false; + $$ = (Node *)n; + } + | ALTER SEQUENCE IF_P EXISTS qualified_name alter_table_cmds + { + AlterTableStmt *n = makeNode(AlterTableStmt); + n->relation = $5; + n->cmds = $6; + n->relkind = OBJECT_SEQUENCE; + n->missing_ok = true; + $$ = (Node *)n; + } + | ALTER VIEW qualified_name alter_table_cmds + { + AlterTableStmt *n = makeNode(AlterTableStmt); + n->relation = $3; + n->cmds = $4; + n->relkind = OBJECT_VIEW; + n->missing_ok = false; + $$ = (Node *)n; + } + | ALTER VIEW IF_P EXISTS qualified_name alter_table_cmds + { + AlterTableStmt *n = makeNode(AlterTableStmt); + n->relation = $5; + n->cmds = $6; + n->relkind = OBJECT_VIEW; + n->missing_ok = true; + $$ = (Node *)n; + } + | ALTER MATERIALIZED VIEW qualified_name alter_table_cmds + { + AlterTableStmt *n = makeNode(AlterTableStmt); + n->relation = $4; + n->cmds = $5; + n->relkind = OBJECT_MATVIEW; + n->missing_ok = false; + $$ = (Node *)n; + } + | ALTER MATERIALIZED VIEW IF_P EXISTS qualified_name alter_table_cmds + { + AlterTableStmt *n = makeNode(AlterTableStmt); + n->relation = $6; + n->cmds = $7; + n->relkind = OBJECT_MATVIEW; + n->missing_ok = true; + $$ = (Node *)n; + } + | ALTER STREAM qualified_name alter_table_cmds + { + AlterTableStmt *n = makeNode(AlterTableStmt); + n->relation = $3; + n->cmds = $4; + n->relkind = OBJECT_STREAM; + n->missing_ok = false; + $$ = (Node *)n; + } + ; + +modify_column_cmds: + modify_column_cmd { $$ = list_make1($1); } + | modify_column_cmds ',' modify_column_cmd { $$ = lappend($$, $3); } + ; +modify_column_cmd: + ColId Typename + { + AlterTableCmd *n = makeNode(AlterTableCmd); + ColumnDef *def = makeNode(ColumnDef); + n->subtype = AT_AlterColumnType; + n->name = $1; + n->def = (Node *) def; + /* We only use these three fields of the ColumnDef node */ + def->typname = $2; + def->collClause = NULL; + def->raw_default = NULL; + def->clientLogicColumnRef=NULL; + $$ = (Node *)n; + } + | ColId NOT NULL_P opt_enable + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_SetNotNull; + n->name = $1; + $$ = (Node *)n; + } + | ColId NULL_P + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_DropNotNull; + n->name = $1; + $$ = (Node *)n; + } + | ColId CONSTRAINT name NOT NULL_P opt_enable + { + AlterTableCmd *n = makeNode(AlterTableCmd); + ColumnDef *def = makeNode(ColumnDef); + Constraint *cons = makeNode(Constraint); + n->subtype = AT_SetNotNull; + n->name = $1; + n->def = (Node *) def; + def->constraints = list_make1(cons); + cons->contype = CONSTR_NOTNULL; + cons->conname = $3; + cons->location = @2; + $$ = (Node *)n; + } + | ColId CONSTRAINT name NULL_P + { + AlterTableCmd *n = makeNode(AlterTableCmd); + ColumnDef *def = makeNode(ColumnDef); + Constraint *cons = makeNode(Constraint); + n->subtype = AT_DropNotNull; + n->name = $1; + n->def = (Node *) def; + def->constraints = list_make1(cons); + cons->contype = CONSTR_NULL; + cons->conname = $3; + cons->location = @2; + $$ = (Node *)n; + } + ; +opt_enable: ENABLE_P {} + | /* empty */ {} + ; +add_column_cmds: + columnDef + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_AddColumn; + n->def = $1; + $$ = list_make1(n); + } + | add_column_cmds ',' columnDef + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_AddColumn; + n->def = $3; + $$ = lappend($1, n); + } + ; + +/* ALTER TABLE sql clause both for PARTITION and ordinary table */ +alter_table_or_partition: + alter_table_cmds { $$ = ($1); } + | alter_partition_cmds { $$ = ($1); } + ; + +/* ALTER TABLE sql clauses for ordinary table */ +alter_table_cmds: + alter_table_cmd { $$ = list_make1($1); } + | alter_table_cmds ',' alter_table_cmd { $$ = lappend($1, $3); } + ; + +/* ALTER TABLE PARTITION sql clauses */ +alter_partition_cmds: + alter_partition_cmd { $$ = list_make1($1); } + | alter_partition_cmds ',' alter_partition_cmd { $$ = lappend($1, $3); } + | move_partition_cmd { $$ = list_make1($1); } + | exchange_partition_cmd { $$ = list_make1($1); } + ; + +alter_partition_cmd: + /* ALTER INDEX index_name MODIFY PARTITION partition_name UNUSABLE */ + MODIFY_PARTITION ColId UNUSABLE + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_UnusableIndexPartition; + n->name = $2; + $$ = (Node *)n; + } + /* ALTER TABLE table_name MODIFY PARTITION partition_name UNUSABLE ALL INDEX */ + | MODIFY_PARTITION ColId UNUSABLE LOCAL INDEXES + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_UnusableAllIndexOnPartition; + n->name = $2; + $$ = (Node *)n; + } + /* ALTER INDEX index_name REBUILD PARTITION partition_name */ + | REBUILD_PARTITION ColId + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_RebuildIndexPartition; + n->name = $2; + $$ = (Node *)n; + } + /* ALTER TABLE table_name MODIFY PARTITION partition_name REBUILD ALL INDEX */ + | MODIFY_PARTITION ColId REBUILD UNUSABLE LOCAL INDEXES + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_RebuildAllIndexOnPartition; + n->name = $2; + $$ = (Node *)n; + } + /* ALTER TABLE ADD PARTITION: use less/than */ + | ADD_PARTITION name VALUES LESS THAN + '(' maxValueList ')' OptTableSpace + { + RangePartitionDefState *p = makeNode(RangePartitionDefState); + AlterTableCmd *n = makeNode(AlterTableCmd); + AddPartitionState *s = makeNode(AddPartitionState); + p->partitionName = $2; + p->boundary = $7; + p->tablespacename = $9; + s->partitionList = list_make1(p); + s->isStartEnd = false; + n->subtype = AT_AddPartition; + n->def = (Node*)s; + $$ = (Node *)n; + } + /* ALTER TABLE ADD PARTITION: use START/END */ + | ADD_PARTITION name START '(' maxValueList ')' END_P '(' maxValueList ')' opt_range_every_list OptTableSpace + { + RangePartitionStartEndDefState *p = makeNode(RangePartitionStartEndDefState); + AlterTableCmd *n = makeNode(AlterTableCmd); + AddPartitionState *s = makeNode(AddPartitionState); + p->partitionName = $2; + p->startValue = $5; + p->endValue = $9; + p->everyValue = $11; + p->tableSpaceName = $12; + s->partitionList = list_make1(p); + s->isStartEnd = true; + n->subtype = AT_AddPartition; + n->def = (Node*)s; + $$ = (Node *)n; + } + | ADD_PARTITION name END_P '(' maxValueList ')' OptTableSpace + { + RangePartitionStartEndDefState *p = makeNode(RangePartitionStartEndDefState); + AlterTableCmd *n = makeNode(AlterTableCmd); + AddPartitionState *s = makeNode(AddPartitionState); + p->partitionName = $2; + p->startValue = NIL; + p->endValue = $5; + p->everyValue = NIL; + p->tableSpaceName = $7; + s->partitionList = list_make1(p); + s->isStartEnd = true; + n->subtype = AT_AddPartition; + n->def = (Node*)s; + $$ = (Node *)n; + } + | ADD_PARTITION name START '(' maxValueList ')' OptTableSpace + { + RangePartitionStartEndDefState *p = makeNode(RangePartitionStartEndDefState); + AlterTableCmd *n = makeNode(AlterTableCmd); + AddPartitionState *s = makeNode(AddPartitionState); + p->partitionName = $2; + p->startValue = $5; + p->endValue = NIL; + p->everyValue = NIL; + p->tableSpaceName = $7; + s->partitionList = list_make1(p); + s->isStartEnd = true; + n->subtype = AT_AddPartition; + n->def = (Node*)s; + $$ = (Node *)n; + } + | ADD_PARTITION name VALUES '(' expr_list ')' OptTableSpace + { + ListPartitionDefState *p = makeNode(ListPartitionDefState); + AlterTableCmd *n = makeNode(AlterTableCmd); + AddPartitionState *s = makeNode(AddPartitionState); + p->partitionName = $2; + p->boundary = $5; + p->tablespacename = $7; + s->partitionList = list_make1(p); + s->isStartEnd = false; + n->subtype = AT_AddPartition; + n->def = (Node*)s; + $$ = (Node *)n; + } + /* ALTER TABLE DROP PARTITION */ + | DROP_PARTITION ColId OptGPI + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_DropPartition; + n->name = $2; + n->behavior = DROP_CASCADE; + n->missing_ok = FALSE; + n->alterGPI = $3; + $$ = (Node *)n; + } + /* ALTER TABLE DROP PARTITION */ + | DROP_PARTITION FOR '(' maxValueList ')' OptGPI + { + RangePartitionDefState *p = makeNode(RangePartitionDefState); + AlterTableCmd *n = makeNode(AlterTableCmd); + + p->boundary = $4; + n->subtype = AT_DropPartition; + n->def = (Node*)p; + n->behavior = DROP_CASCADE; + n->missing_ok = FALSE; + n->alterGPI = $6; + $$ = (Node *)n; + } + /* merge 2 or more partitions into 1 partition */ + | MERGE PARTITIONS name_list INTO PARTITION name OptTableSpace OptGPI + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->def = (Node*)$3; + n->name = $6; + n->target_partition_tablespace = $7; + n->subtype = AT_MergePartition; + n->alterGPI = $8; + $$ = (Node*)n; + } + /* split one partition into two partition */ + | SPLIT PARTITION name AT '(' maxValueList ')' INTO + '(' split_dest_partition_define_list ')' OptGPI + { + AlterTableCmd *n = makeNode(AlterTableCmd); + SplitPartitionState *s = makeNode(SplitPartitionState); + + s->src_partition_name = $3; + s->split_point = $6; + s->dest_partition_define_list = $10; + s->partition_for_values = NULL; + + n->def = (Node*)s; + n->subtype = AT_SplitPartition; + n->alterGPI = $12; + $$ = (Node*)n; + } + /* split one partition into two partition */ + | SPLIT PARTITION_FOR '(' maxValueList ')' AT '(' maxValueList ')' INTO + '(' split_dest_partition_define_list ')' OptGPI + { + AlterTableCmd *n = makeNode(AlterTableCmd); + SplitPartitionState *s = makeNode(SplitPartitionState); + + s->partition_for_values = $4; + s->split_point = $8; + s->dest_partition_define_list = $12; + s->src_partition_name = NULL; + + n->def = (Node*)s; + n->subtype = AT_SplitPartition; + n->alterGPI = $14; + $$ = (Node*)n; + } + /*split one partition into multiple partition*/ + | SPLIT PARTITION name INTO '(' range_partition_definition_list ')' OptGPI + { + AlterTableCmd *n = makeNode(AlterTableCmd); + SplitPartitionState *s = makeNode(SplitPartitionState); + + s->src_partition_name = $3; + s->dest_partition_define_list = $6; + s->split_point = NULL; + s->partition_for_values = NULL; + + n->def = (Node*)s; + n->subtype = AT_SplitPartition; + n->alterGPI = $8; + $$ = (Node*)n; + } + | SPLIT PARTITION_FOR '(' maxValueList ')' INTO '(' range_partition_definition_list ')' OptGPI + { + AlterTableCmd *n = makeNode(AlterTableCmd); + SplitPartitionState *s = makeNode(SplitPartitionState); + + s->partition_for_values = $4; + s->dest_partition_define_list = $8; + s->src_partition_name = NULL; + s->split_point = NULL; + + n->def = (Node*)s; + n->subtype = AT_SplitPartition; + n->alterGPI = 10; + $$ = (Node*)n; + } + /* truncate partition */ + | TRUNCATE PARTITION ColId OptGPI + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_TruncatePartition; + n->missing_ok = FALSE; + n->alterGPI = $4; + $$ = (Node *)n; + + n->name = $3; + + } + /* truncate partition */ + | TRUNCATE PARTITION_FOR '(' maxValueList ')' OptGPI + { + + RangePartitionDefState *p = makeNode(RangePartitionDefState); + AlterTableCmd *n = makeNode(AlterTableCmd); + + p->boundary = $4; + n->subtype = AT_TruncatePartition; + n->def = (Node*)p; + n->missing_ok = FALSE; + n->alterGPI = $6; + $$ = (Node *)n; + + } + /* ENABLE ROW MOVEMENT */ + | ENABLE_P ROW MOVEMENT + { + AlterTableCmd *n = makeNode(AlterTableCmd); + + n->subtype = AT_EnableRowMoveMent; + n->missing_ok = FALSE; + $$ = (Node *) n; + } + /* DISABLE ROW MOVEMENT */ + | DISABLE_P ROW MOVEMENT + { + AlterTableCmd *n = makeNode(AlterTableCmd); + + n->subtype = AT_DisableRowMoveMent; + n->missing_ok = FALSE; + $$ = (Node *) n; + + } + ; + +move_partition_cmd: + /* ALTER TABLE MOVE PARTITION TABLESPACE */ + MOVE PARTITION partition_name TABLESPACE name + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_SetPartitionTableSpace; + n->def = (Node*)$3; + n->name = $5; + $$ = (Node *)n; + } + /* ALTER TABLE MOVE PARTITION FOR (...) TABLESPACE */ + | MOVE PARTITION_FOR '(' maxValueList ')' TABLESPACE name + { + RangePartitionDefState *p = makeNode(RangePartitionDefState); + AlterTableCmd *n = makeNode(AlterTableCmd); + + p->boundary = $4; + + n->subtype = AT_SetPartitionTableSpace; + n->def = (Node*)p; + n->name = $7; + $$ = (Node *)n; + } + ; + +exchange_partition_cmd: + /* exchange partition */ + EXCHANGE PARTITION '(' ColId ')' + WITH TABLE relation_expr opt_verbose OptGPI + { + AlterTableCmd *n = makeNode(AlterTableCmd); + + n->subtype = AT_ExchangePartition; + n->name = $4; + n->exchange_with_rel = $8; + n->check_validation = TRUE; + n->exchange_verbose = $9; + n->missing_ok = FALSE; + n->alterGPI = $10; + $$ = (Node *)n; + } + /* exchange partition */ + | EXCHANGE PARTITION '(' ColId ')' + WITH TABLE relation_expr WITH VALIDATION opt_verbose OptGPI + { + AlterTableCmd *n = makeNode(AlterTableCmd); + + n->subtype = AT_ExchangePartition; + n->name = $4; + n->exchange_with_rel = $8; + n->check_validation = TRUE; + n->exchange_verbose = $11; + n->missing_ok = FALSE; + n->alterGPI = $12; + $$ = (Node *)n; + } + /* exchange partition */ + | EXCHANGE PARTITION '(' ColId ')' + WITH TABLE relation_expr WITHOUT VALIDATION OptGPI + { + AlterTableCmd *n = makeNode(AlterTableCmd); + + n->subtype = AT_ExchangePartition; + n->name = $4; + n->exchange_with_rel = $8; + n->check_validation = FALSE; + n->missing_ok = FALSE; + n->alterGPI = $11; + $$ = (Node *)n; + } + + /* exchange partition */ + | EXCHANGE PARTITION_FOR '(' maxValueList ')' + WITH TABLE relation_expr opt_verbose OptGPI + { + AlterTableCmd *n = makeNode(AlterTableCmd); + RangePartitionDefState *p = makeNode(RangePartitionDefState); + + p->boundary = $4; + + n->subtype = AT_ExchangePartition; + n->exchange_with_rel = $8; + n->check_validation = TRUE; + n->exchange_verbose = $9; + n->def = (Node*)p; + n->missing_ok = FALSE; + n->alterGPI = $10; + $$ = (Node *)n; + } + + | EXCHANGE PARTITION_FOR '(' maxValueList ')' + WITH TABLE relation_expr WITH VALIDATION opt_verbose OptGPI + { + AlterTableCmd *n = makeNode(AlterTableCmd); + RangePartitionDefState *p = makeNode(RangePartitionDefState); + + p->boundary = $4; + + n->subtype = AT_ExchangePartition; + n->exchange_with_rel = $8; + n->check_validation = TRUE; + n->exchange_verbose = $11; + n->def = (Node*)p; + n->missing_ok = FALSE; + n->alterGPI = $12; + $$ = (Node *)n; + } + + | EXCHANGE PARTITION_FOR '(' maxValueList ')' + WITH TABLE relation_expr WITHOUT VALIDATION OptGPI + { + AlterTableCmd *n = makeNode(AlterTableCmd); + RangePartitionDefState *p = makeNode(RangePartitionDefState); + + p->boundary = $4; + + n->subtype = AT_ExchangePartition; + n->exchange_with_rel = $8; + n->check_validation = FALSE; + n->def = (Node*)p; + n->missing_ok = FALSE; + n->alterGPI = $11; + $$ = (Node *)n; + } + ; + +alter_table_cmd: + /*ALTER INDEX index_name UNUSABLE*/ + UNUSABLE + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_UnusableIndex; + $$ = (Node *)n; + } + | + /*ALTER INDEX index_name REBUILD*/ + REBUILD + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_RebuildIndex; + $$ = (Node *)n; + } + + | + /* ALTER TABLE ADD */ + ADD_P columnDef + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_AddColumn; + n->def = $2; + $$ = (Node *)n; + } + /* ALTER TABLE ADD COLUMN */ + | ADD_P COLUMN columnDef + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_AddColumn; + n->def = $3; + $$ = (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] 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); + n->additional_property = AT_CMD_WithoutPercent; + $$ = (Node *)n; + } + /* ALTER TABLE ALTER [COLUMN] SET STATISTICS PERCENT */ + | ALTER opt_column ColId SET STATISTICS PERCENT SignedIconst + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_SetStatistics; + n->name = $3; + n->def = (Node *) makeInteger($7); + n->additional_property = AT_CMD_WithPercent; + $$ = (Node *)n; + } + | ADD_P STATISTICS '(' opt_multi_name_list ')' + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_AddStatistics; + n->def = (Node *) $4; + $$ = (Node *)n; + } + | DELETE_P STATISTICS '(' opt_multi_name_list ')' + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_DeleteStatistics; + n->def = (Node *) $4; + $$ = (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] SET ( column_parameter = value [, ... ] ) */ + | ALTER opt_column ColId RESET reloptions + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_ResetOptions; + n->name = $3; + n->def = (Node *) $5; + $$ = (Node *)n; + } + /* ALTER TABLE ALTER [COLUMN] SET STORAGE */ + | ALTER opt_column ColId SET STORAGE ColId + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_SetStorage; + n->name = $3; + n->def = (Node *) makeString($6); + $$ = (Node *)n; + } + /* ALTER TABLE 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 three fields of the ColumnDef node */ + def->typname = $6; + def->collClause = (CollateClause *) $7; + def->raw_default = $8; + def->clientLogicColumnRef=NULL; + $$ = (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 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; + } + | MODIFY_P modify_column_cmd + { + $$ = $2; + } + /* ALTER TABLE SET WITH OIDS */ + | SET WITH OIDS + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_AddOids; + $$ = (Node *)n; + } + /* ALTER TABLE SET WITHOUT OIDS */ + | 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 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 RoleId */ + | OWNER TO RoleId + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_ChangeOwner; + n->name = $3; + $$ = (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 COMPRESS/NOCOMPRESS */ + | SET COMPRESS + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_SET_COMPRESS; + n->name = "COMPRESS"; + $$ = (Node *)n; + } + | SET NOCOMPRESS + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_SET_COMPRESS; + n->name = "NOCOMPRESS"; + $$ = (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_generic_options + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_GenericOptions; + n->def = (Node *)$1; + $$ = (Node *) n; + } + +/* PGXC_BEGIN */ + /* ALTER TABLE DISTRIBUTE BY ... */ + | OptDistributeByInternal + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_DistributeBy; + n->def = (Node *)$1; + $$ = (Node *)n; + } + /* ALTER TABLE TO [ NODE (nodelist) | GROUP groupname ] */ + | OptSubClusterInternal + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_SubCluster; + n->def = (Node *)$1; + $$ = (Node *)n; + } + /* ALTER TABLE ADD NODE (nodelist) */ + | ADD_P NODE pgxcnodes + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_AddNodeList; + n->def = (Node *)$3; + $$ = (Node *)n; + } + /* ALTER TABLE DELETE NODE (nodelist) */ + | DELETE_P NODE pgxcnodes + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_DeleteNodeList; + n->def = (Node *)$3; + $$ = (Node *)n; + } + /* ALTER TABLE ENABLE ROW LEVEL SECURITY */ + | ENABLE_P ROW LEVEL SECURITY + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_EnableRls; + $$ = (Node *)n; + } + /* ALTER TABLE DISABLE ROW LEVEL SECURITY */ + | DISABLE_P ROW LEVEL SECURITY + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_DisableRls; + $$ = (Node *)n; + } + /* ALTER TABLE FORCE ROW LEVEL SECURITY */ + | FORCE ROW LEVEL SECURITY + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_ForceRls; + $$ = (Node *)n; + } + /* ALTER TABLE NO FORCE ROW LEVEL SECURITY */ + | NO FORCE ROW LEVEL SECURITY + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_NoForceRls; + $$ = (Node *)n; + } +/* PGXC_END */ + ; + +alter_column_default: + SET DEFAULT a_expr { $$ = $3; } + | DROP DEFAULT { $$ = NULL; } + ; + +opt_drop_behavior: + CASCADE { $$ = DROP_CASCADE; } + | RESTRICT { $$ = DROP_RESTRICT; } + | CASCADE CONSTRAINTS { $$ = DROP_CASCADE; } + | /* EMPTY */ { $$ = DROP_RESTRICT; /* default */ } + ; + +opt_collate_clause: + COLLATE any_name + { + CollateClause *n = makeNode(CollateClause); + n->arg = NULL; + n->collname = $2; + n->location = @1; + $$ = (Node *) n; + } + | /* EMPTY */ { $$ = NULL; } + ; + +alter_using: + USING a_expr { $$ = $2; } + | /* EMPTY */ { $$ = NULL; } + ; + +reloptions: + '(' reloption_list ')' { $$ = $2; } + ; + +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; + } + ; + +opt_reloptions: WITH reloptions { $$ = $2; } + | /* EMPTY */ { $$ = NIL; } + ; + +reloption_list: + reloption_elem { $$ = list_make1($1); } + | reloption_list ',' reloption_elem { $$ = lappend($1, $3); } + ; + +/* This should match def_elem and also allow qualified names */ +reloption_elem: + ColLabel '=' def_arg + { + $$ = makeDefElem($1, (Node *) $3); + } + | ColLabel '=' ROW + { + $$ = makeDefElem($1, (Node *) makeString(pstrdup($3))); + } + | ColLabel + { + $$ = makeDefElem($1, NULL); + } + | ColLabel '.' ColLabel '=' def_arg + { + $$ = makeDefElemExtended($1, $3, (Node *) $5, + DEFELEM_UNSPEC); + } + | ColLabel '.' ColLabel + { + $$ = makeDefElemExtended($1, $3, NULL, DEFELEM_UNSPEC); + } + ; + +split_dest_partition_define_list: + PARTITION name OptTableSpace ',' PARTITION name OptTableSpace + { + List *result = NULL; + RangePartitionDefState *p1 = makeNode(RangePartitionDefState); + RangePartitionDefState *p2 = makeNode(RangePartitionDefState); + + p1->partitionName = $2; + p1->tablespacename = $3; + p1->boundary = NULL; + + p2->partitionName = $6; + p2->tablespacename = $7; + p2->boundary = NULL; + + result = lappend(result, p1); + result = lappend(result, p2); + + $$ = result; + } + ; + +/***************************************************************************** + * + * ALTER TYPE + * + * really variants of the ALTER TABLE subcommands with different spellings + *****************************************************************************/ + +AlterCompositeTypeStmt: + ALTER TYPE_P any_name alter_type_cmds + { + AlterTableStmt *n = makeNode(AlterTableStmt); + + /* can't use qualified_name, sigh */ + n->relation = makeRangeVarFromAnyName($3, @3, yyscanner); + n->cmds = $4; + n->relkind = OBJECT_TYPE; + $$ = (Node *)n; + } + ; + +alter_type_cmds: + alter_type_cmd { $$ = list_make1($1); } + | alter_type_cmds ',' alter_type_cmd { $$ = lappend($1, $3); } + ; + +alter_type_cmd: + /* ALTER TYPE 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 three fields of the ColumnDef node */ + def->typname = $6; + def->clientLogicColumnRef=NULL; + def->collClause = (CollateClause *) $7; + def->raw_default = NULL; + $$ = (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 ( SELECT ... ) TO file [WITH] [(options)] + * + * In the preferred syntax the options are comma-separated + * and use generic identifiers instead of keywords. The pre-9.0 + * syntax had a hard-wired, space-separated set of options. + * + * Really old syntax, from versions 7.2 and prior: + * COPY [ BINARY ] table [ WITH OIDS ] FROM/TO file + * [ [ USING ] DELIMITERS 'delimiter' ] ] + * [ WITH NULL AS 'null string' ] + * This option placement is not supported with COPY (SELECT...). + * + *****************************************************************************/ + +CopyStmt: COPY opt_binary qualified_name opt_column_list opt_oids + copy_from copy_file_name copy_delimiter opt_noescaping OptCopyLogError OptCopyRejectLimit opt_with copy_options + opt_processed + { + CopyStmt *n = makeNode(CopyStmt); + n->relation = $3; + n->query = NULL; + n->attlist = $4; + n->is_from = $6; + n->filename = $7; + if ($4) + n->relation->length = @4; + else if ($5) + n->relation->length = @5; + else + n->relation->length = @6; + n->options = NIL; + /* Concatenate user-supplied flags */ + if ($2) + n->options = lappend(n->options, $2); + if ($5) + n->options = lappend(n->options, $5); + if ($8) + n->options = lappend(n->options, $8); + if ($9) + n->options = lappend(n->options, $9); + if ($10) + n->options = lappend(n->options, $10); + if ($11) + n->options = lappend(n->options, $11); + if ($13) + n->options = list_concat(n->options, $13); + $$ = (Node *)n; + } + | COPY select_with_parens TO copy_file_name opt_noescaping opt_with copy_options opt_processed + { + CopyStmt *n = makeNode(CopyStmt); + n->relation = NULL; + n->query = $2; + n->attlist = NIL; + n->is_from = false; + n->filename = $4; + n->options = $7; + if ($5) + n->options = lappend(n->options, $5); + $$ = (Node *)n; + } + ; + +opt_processed: + ENCRYPTED {$$=TRUE;} + | /*EMPTY*/ { $$ = FALSE; } + +copy_from: + FROM { $$ = TRUE; } + | TO { $$ = 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; } + | REDISANYVALUE { $$ = NULL; } + ; + +copy_options: copy_opt_list { $$ = $1; } + | '(' copy_generic_opt_list ')' { $$ = $2; } + ; + +/* old COPY option syntax */ +copy_opt_list: + copy_opt_list copy_opt_item { $$ = lappend($1, $2); } + | /* EMPTY */ { $$ = NIL; } + ; + +copy_opt_item: + BINARY + { + $$ = makeDefElem("format", (Node *)makeString("binary")); + } + | OIDS + { + $$ = makeDefElem("oids", (Node *)makeInteger(TRUE)); + } + |FREEZE + { + $$ = makeDefElem("freeze", (Node *)makeInteger(TRUE)); + } + | DELIMITER opt_as Sconst + { + $$ = makeDefElem("delimiter", (Node *)makeString($3)); + } + | NULL_P opt_as Sconst + { + $$ = makeDefElem("null", (Node *)makeString($3)); + } + | CSV + { + $$ = makeDefElem("format", (Node *)makeString("csv")); + } + | FIXED_P + { + $$ = makeDefElem("format", (Node *)makeString("fixed")); + } + | HEADER_P + { + $$ = makeDefElem("header", (Node *)makeInteger(TRUE)); + } + | QUOTE opt_as Sconst + { + $$ = makeDefElem("quote", (Node *)makeString($3)); + } + | ESCAPE opt_as Sconst + { + $$ = makeDefElem("escape", (Node *)makeString($3)); + } + | FORCE QUOTE columnList + { + $$ = makeDefElem("force_quote", (Node *)$3); + } + | FORCE QUOTE '*' + { + $$ = makeDefElem("force_quote", (Node *)makeNode(A_Star)); + } + | FORCE NOT NULL_P columnList + { + $$ = makeDefElem("force_not_null", (Node *)$4); + } + | ENCODING Sconst + { + $$ = makeDefElem("encoding", (Node *)makeString($2)); + } + | EOL Sconst + { + $$ = makeDefElem("eol", (Node*)makeString($2)); + } + | FILEHEADER_P Sconst + { + $$ = makeDefElem("fileheader", (Node*)makeString($2)); + } + | FORMATTER '(' copy_foramtter_opt ')' + { + $$ = makeDefElem("formatter", (Node*)$3); + } + | IGNORE_EXTRA_DATA + { + $$ = makeDefElem("ignore_extra_data", (Node *)makeInteger(TRUE)); + } + | DATE_FORMAT_P Sconst + { + $$ = makeDefElem("date_format", (Node *)makeString($2)); + } + | TIME_FORMAT_P Sconst + { + $$ = makeDefElem("time_format", (Node *)makeString($2)); + } + | TIMESTAMP_FORMAT_P Sconst + { + $$ = makeDefElem("timestamp_format", (Node *)makeString($2)); + } + | SMALLDATETIME_FORMAT_P Sconst + { + $$ = makeDefElem("smalldatetime_format", (Node *)makeString($2)); + } + | COMPATIBLE_ILLEGAL_CHARS + { + $$ = makeDefElem("compatible_illegal_chars", (Node *)makeInteger(TRUE)); + } + | FILL_MISSING_FIELDS + { + $$ = makeDefElem("fill_missing_fields", (Node *)makeInteger(TRUE)); + } + ; + +/* The following exist for backward compatibility with very old versions */ + +opt_binary: + BINARY + { + $$ = makeDefElem("format", (Node *)makeString("binary")); + } + | /*EMPTY*/ { $$ = NULL; } + ; + +opt_oids: + WITH OIDS + { + $$ = makeDefElem("oids", (Node *)makeInteger(TRUE)); + } + | /*EMPTY*/ { $$ = NULL; } + ; + +copy_delimiter: + opt_using DELIMITERS Sconst + { + $$ = makeDefElem("delimiter", (Node *)makeString($3)); + } + | /*EMPTY*/ { $$ = NULL; } + ; + +opt_using: + USING {} + | /*EMPTY*/ {} + ; + +opt_noescaping: + WITHOUT ESCAPING + { + $$ = makeDefElem("noescaping", (Node *)makeInteger(TRUE)); + } + | /*EMPTY*/ {$$ = NULL;} + ; + +OptCopyLogError: + LOG_P ERRORS DATA_P + { + $$ = makeDefElem("log_errors_data", (Node *)makeInteger(TRUE)); + } + | LOG_P ERRORS + { + $$ = makeDefElem("log_errors", (Node *)makeInteger(TRUE)); + } + | /*EMPTY*/ { $$ = NULL; } + ; + +OptCopyRejectLimit: + REJECT_P LIMIT Sconst + { + $$ = makeDefElem("reject_limit", (Node*)makeString($3)); + } + | /*EMPTY*/ { $$ = NULL; } + ; + +/* new COPY option syntax */ +copy_generic_opt_list: + copy_generic_opt_elem + { + $$ = list_make1($1); + } + | copy_generic_opt_list ',' copy_generic_opt_elem + { + $$ = lappend($1, $3); + } + ; + +copy_generic_opt_elem: + ColLabel copy_generic_opt_arg + { + $$ = makeDefElem($1, $2); + } + ; + +copy_generic_opt_arg: + opt_boolean_or_string { $$ = (Node *) makeString($1); } + | NumericOnly { $$ = (Node *) $1; } + | '*' { $$ = (Node *) makeNode(A_Star); } + | '(' copy_generic_opt_arg_list ')' { $$ = (Node *) $2; } + | /* EMPTY */ { $$ = NULL; } + ; + +copy_generic_opt_arg_list: + copy_generic_opt_arg_list_item + { + $$ = list_make1($1); + } + | copy_generic_opt_arg_list ',' copy_generic_opt_arg_list_item + { + $$ = lappend($1, $3); + } + ; + +/* beware of emitting non-string list elements here; see commands/define.c */ +copy_generic_opt_arg_list_item: + opt_boolean_or_string { $$ = (Node *) makeString($1); } + ; + +copy_foramtter_opt: + copy_col_format_def + { + $$ = list_make1($1); + } + | copy_foramtter_opt ',' copy_col_format_def + { + $$ = lappend($1, $3); + } + ; + +copy_col_format_def: + ColId '(' Iconst ',' Iconst ')' + { + Position *arg = makeNode(Position); + arg->colname = $1; + arg->position = $3; + arg->fixedlen = $5; + $$ = (Node*)arg; + } + ; +/***************************************************************************** + * + * QUERY : + * CREATE STREAM relname + * + * feature: + * 1) create foreign table for streaming server + * + * + *****************************************************************************/ + +CreateStreamStmt: + CREATE STREAM qualified_name '(' OptTableElementList ')' + { + CreateForeignTableStmt *n = makeNode(CreateForeignTableStmt); + n->servername = STREAMING_SERVER; + n->base.if_not_exists = false; + n->base.relation = $3; + n->base.tableElts = $5; + $$ = (Node *)n; + } + | CREATE STREAM IF_P NOT EXISTS qualified_name '(' OptTableElementList ')' + { + CreateForeignTableStmt *n = makeNode(CreateForeignTableStmt); + n->servername = STREAMING_SERVER; + n->base.if_not_exists = true; + n->base.relation = $6; + n->base.tableElts = $8; + $$ = (Node *)n; + } + ; + +/***************************************************************************** + * + * QUERY : + * CREATE TABLE relname + * + * PGXC-related extensions: + * 1) Distribution type of a table: + * DISTRIBUTE BY ( HASH(column) | MODULO(column) | + * REPLICATION | ROUNDROBIN ) + * 2) Subcluster for table + * TO ( GROUP groupname | NODE nodename1,...,nodenameN ) + * + * 3) Internal additional data from CN to CN and CN to DN; the clause must be the last clause. + * INTERNAL DATA xxxxxxxx + * + *****************************************************************************/ + +CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' + OptInherit OptWith OnCommitOption OptCompress OptPartitionElement +/* PGXC_BEGIN */ + OptDistributeBy OptSubCluster +/* PGXC_END */ + opt_table_partitioning_clause + opt_internal_data OptKind + { + CreateStmt *n = makeNode(CreateStmt); + $4->relpersistence = $2; + n->relkind = $17; + n->relation = $4; + n->tableElts = $6; + n->inhRelations = $8; + n->constraints = NIL; + n->options = $9; + n->oncommit = $10; + n->row_compress = $11; + n->tablespacename = $12; + n->if_not_exists = false; +/* PGXC_BEGIN */ + n->distributeby = $13; + n->subcluster = $14; +/* PGXC_END */ + n->partTableState = (PartitionState *)$15; + n->internalData = $16; + $$ = (Node *)n; + } + | CREATE OptTemp TABLE IF_P NOT EXISTS qualified_name '(' + OptTableElementList ')' OptInherit OptWith OnCommitOption + OptCompress OptPartitionElement +/* PGXC_BEGIN */ + OptDistributeBy OptSubCluster +/* PGXC_END */ + opt_table_partitioning_clause + opt_internal_data + { + CreateStmt *n = makeNode(CreateStmt); + $7->relpersistence = $2; + n->relation = $7; + n->tableElts = $9; + n->inhRelations = $11; + n->constraints = NIL; + n->options = $12; + n->oncommit = $13; + n->row_compress = $14; + n->tablespacename = $15; + n->if_not_exists = true; +/* PGXC_BEGIN */ + n->distributeby = $16; + n->subcluster = $17; +/* PGXC_END */ + n->partTableState = (PartitionState *)$18; + n->internalData = $19; + $$ = (Node *)n; + } + | CREATE OptTemp TABLE qualified_name OF any_name + OptTypedTableElementList OptWith OnCommitOption OptCompress OptPartitionElement +/* PGXC_BEGIN */ + OptDistributeBy OptSubCluster +/* PGXC_END */ + { + CreateStmt *n = makeNode(CreateStmt); + $4->relpersistence = $2; + n->relation = $4; + n->tableElts = $7; + n->ofTypename = makeTypeNameFromNameList($6); + n->ofTypename->location = @6; + n->constraints = NIL; + n->options = $8; + n->oncommit = $9; + n->row_compress = $10; + n->tablespacename = $11; + n->if_not_exists = false; +/* PGXC_BEGIN */ + n->distributeby = $12; + n->subcluster = $13; +/* PGXC_END */ + n->partTableState = NULL; + n->internalData = NULL; + $$ = (Node *)n; + } + | CREATE OptTemp TABLE IF_P NOT EXISTS qualified_name OF any_name + OptTypedTableElementList OptWith OnCommitOption OptCompress OptPartitionElement +/* PGXC_BEGIN */ + OptDistributeBy OptSubCluster +/* PGXC_END */ + { + CreateStmt *n = makeNode(CreateStmt); + $7->relpersistence = $2; + n->relation = $7; + n->tableElts = $10; + n->ofTypename = makeTypeNameFromNameList($9); + n->ofTypename->location = @9; + n->constraints = NIL; + n->options = $11; + n->oncommit = $12; + n->row_compress = $13; + n->tablespacename = $14; + n->if_not_exists = true; +/* PGXC_BEGIN */ + n->distributeby = $15; + n->subcluster = $16; +/* PGXC_END */ + n->partTableState = NULL; + n->internalData = NULL; + $$ = (Node *)n; + } + ; + +OptKind: + FOR MATERIALIZED VIEW + { + $$ = OBJECT_MATVIEW; + } + | /* empty */ + { + $$ = OBJECT_TABLE; + } + ; + +opt_table_partitioning_clause: + range_partitioning_clause + { + $$ = $1; + } + |hash_partitioning_clause + { + $$ = $1; + } + |list_partitioning_clause + { + $$ = $1; + } + |value_partitioning_clause + { + $$ = $1; + } + | /* empty */ { $$ = NULL; } + ; + +range_partitioning_clause: + PARTITION BY RANGE '(' column_item_list ')' + opt_interval_partition_clause '(' range_partition_definition_list ')' opt_row_movement_clause + { + PartitionState *n = makeNode(PartitionState); + n->partitionKey = $5; + n->intervalPartDef = (IntervalPartitionDefState *)$7; + n->partitionList = $9; + + if (n->intervalPartDef) + n->partitionStrategy = 'i'; + else + n->partitionStrategy = 'r'; + + n->rowMovement = (RowMovementValue)$11; + + $$ = (Node *)n; + } + ; + +list_partitioning_clause: + PARTITION BY LIST '(' column_item_list ')' + '(' list_partition_definition_list ')' + { +#ifdef ENABLE_MULTIPLE_NODES + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("Un-support feature"), + errdetail("The distributed capability is not supported currently."))); +#endif + if (list_length($5) != 1) { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("Un-support feature"), + errdetail("The partition key's length should be 1."))); + } + if (list_length($8) > 64) { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("Un-support feature"), + errdetail("The partition's length should be less than 65."))); + } + PartitionState *n = makeNode(PartitionState); + n->partitionKey = $5; + n->intervalPartDef = NULL; + n->partitionList = $8; + n->partitionStrategy = 'l'; + $$ = (Node *)n; + + } + ; + +hash_partitioning_clause: + PARTITION BY IDENT '(' column_item_list ')' + '(' hash_partition_definition_list ')' + { +#ifdef ENABLE_MULTIPLE_NODES + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("Un-support feature"), + errdetail("The distributed capability is not supported currently."))); +#endif + if (list_length($5) != 1) { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("Un-support feature"), + errdetail("The partition key's length should be 1."))); + } + if (strcmp($3, "hash") != 0) { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("unrecognized option \"%s\"", $3))); + } + if (list_length($8) > 64) { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("Un-support feature"), + errdetail("The partition's length should be less than 65."))); + } + PartitionState *n = makeNode(PartitionState); + n->partitionKey = $5; + n->intervalPartDef = NULL; + n->partitionList = $8; + n->partitionStrategy = 'h'; + int i = 0; + ListCell *elem = NULL; + List *parts = n->partitionList; + foreach(elem, parts) { + HashPartitionDefState *hashPart = (HashPartitionDefState*)lfirst(elem); + hashPart->boundary = list_make1(makeIntConst(i, -1)); + i++; + } + $$ = (Node *)n; + + } + ; + +value_partitioning_clause: + PARTITION BY VALUES '(' column_item_list ')' + { + PartitionState *n = makeNode(PartitionState); + n->partitionKey = $5; + n->partitionStrategy = 'v'; + + $$ = (Node *)n; + } + ; + +column_item_list: + column_item + { + $$ = list_make1($1); + } + | column_item_list ',' column_item + { + $$ = lappend($1, $3); + } + ; + +column_item: + ColId + { + $$ = makeColumnRef($1, NIL, @1, yyscanner); + } + ; + +opt_interval_partition_clause: + INTERVAL '(' interval_expr ')' opt_interval_tablespaceList + { + IntervalPartitionDefState* n = makeNode(IntervalPartitionDefState); + n->partInterval = $3; + n->intervalTablespaces = $5; + + $$ = (Node *)n; + } + | /* empty */ + { + $$ = NULL; + } + ; + +opt_interval_tablespaceList: + STORE_P IN_P '(' tablespaceList ')' + { + $$= $4; + } + | + { + $$ = NIL; + } + ; + +interval_expr: + a_expr + { + $$ = $1; + } + ; + +tablespaceList: + name_list + { + $$ = $1; + } + ; + +range_partition_definition_list: /* general range partition syntax: start/end or less/than */ + range_less_than_list + { + $$ = $1; + } + | range_start_end_list + { + $$ = $1; + } + ; + +list_partition_definition_list: + list_partition_item + { + $$ = list_make1($1); + } + | list_partition_definition_list ',' list_partition_item + { + $$ = lappend($1, $3); + } + ; + +hash_partition_definition_list: + hash_partition_item + { + $$ = list_make1($1); + } + | hash_partition_definition_list ',' hash_partition_item + { + $$ = lappend($1, $3); + } + ; + +range_less_than_list: + range_less_than_item + { + $$ = list_make1($1); + } + | range_less_than_list ',' range_less_than_item + { + $$ = lappend($1, $3); + } + ; + +list_partition_item: + PARTITION name VALUES '(' expr_list ')' OptTableSpace + { + ListPartitionDefState *n = makeNode(ListPartitionDefState); + n->partitionName = $2; + n->boundary = $5; + n->tablespacename = $7; + + $$ = (Node *)n; + } + | PARTITION name VALUES '(' DEFAULT ')' OptTableSpace + { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("Un-support feature"), + errdetail("The default list's partition is not supported currently."))); + ListPartitionDefState *n = makeNode(ListPartitionDefState); + n->partitionName = $2; + Const *n_default = makeNode(Const); + n_default->ismaxvalue = true; + n_default->location = -1; + n->boundary = list_make1(n_default); + n->tablespacename = $7; + $$ = (Node *)n; + } + ; + +hash_partition_item: + PARTITION name OptTableSpace + { + HashPartitionDefState *n = makeNode(HashPartitionDefState); + n->partitionName = $2; + n->tablespacename = $3; + + $$ = (Node*)n; + } + +range_less_than_item: + PARTITION name VALUES LESS THAN + '(' maxValueList ')' OptTableSpace + { + RangePartitionDefState *n = makeNode(RangePartitionDefState); + n->partitionName = $2; + n->boundary = $7; + n->tablespacename = $9; + + $$ = (Node *)n; + } + ; + +range_start_end_list: + range_start_end_item + { + $$ = list_make1($1); + } + | range_start_end_list ',' range_start_end_item + { + $$ = lappend($1, $3); + } + ; + +range_start_end_item: + PARTITION name START '(' maxValueList ')' END_P '(' maxValueList ')' opt_range_every_list OptTableSpace + { + RangePartitionStartEndDefState *n = makeNode(RangePartitionStartEndDefState); + n->partitionName = $2; + n->startValue = $5; + n->endValue = $9; + n->everyValue = $11; + n->tableSpaceName = $12; + + $$ = (Node *)n; + } + | PARTITION name END_P '(' maxValueList ')' OptTableSpace + { + RangePartitionStartEndDefState *n = makeNode(RangePartitionStartEndDefState); + n->partitionName = $2; + n->startValue = NIL; + n->endValue = $5; + n->everyValue = NIL; + n->tableSpaceName = $7; + + $$ = (Node *)n; + } + | PARTITION name START '(' maxValueList ')' OptTableSpace + { + RangePartitionStartEndDefState *n = makeNode(RangePartitionStartEndDefState); + n->partitionName = $2; + n->startValue = $5; + n->endValue = NIL; + n->everyValue = NIL; + n->tableSpaceName = $7; + + $$ = (Node *)n; + } + ; + +opt_range_every_list: + EVERY '(' maxValueList ')' + { + $$ = $3; + } + | /* empty */ { $$ = NIL; } + +partition_name: + ColId + { + $$ = makeRangeVar(NULL, $1, @1); + } + ; + +maxValueList: + maxValueItem + { + $$ = list_make1($1); + } + | maxValueList ',' maxValueItem + { + $$ = lappend($1, $3); + } + ; + +maxValueItem: + a_expr + { + $$ = $1; + } + | MAXVALUE + { + Const *n = makeNode(Const); + + n->ismaxvalue = true; + n->location = @1; + + $$ = (Node *)n; + } + ; + + +opt_row_movement_clause: ENABLE_P ROW MOVEMENT { $$ = ROWMOVEMENT_ENABLE; } + | DISABLE_P ROW MOVEMENT { $$ = ROWMOVEMENT_DISABLE; } + | /*EMPTY*/ { $$ = ROWMOVEMENT_DEFAULT; } + ; + +/* + * 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 + { +#ifdef ENABLE_MULTIPLE_NODES + ereport(WARNING, + (errmsg("GLOBAL is deprecated in temporary table creation"), + parser_errposition(@1))); + $$ = RELPERSISTENCE_TEMP; +#else + $$ = RELPERSISTENCE_GLOBAL_TEMP; +#endif + } + | GLOBAL TEMP + { +#ifdef ENABLE_MULTIPLE_NODES + ereport(WARNING, + (errmsg("GLOBAL is deprecated in temporary table creation"), + parser_errposition(@1))); + $$ = RELPERSISTENCE_TEMP; +#else + $$ = RELPERSISTENCE_GLOBAL_TEMP; +#endif + } + | 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 KVType ColCmprsMode create_generic_options ColQualList + { + ColumnDef *n = makeNode(ColumnDef); + n->colname = $1; + n->typname = $2; + n->kvtype = $3; + n->inhcount = 0; + n->is_local = true; + n->is_not_null = false; + n->is_from_type = false; + n->storage = 0; + n->cmprs_mode = $4; + n->raw_default = NULL; + n->cooked_default = NULL; + n->collOid = InvalidOid; + n->fdwoptions = $5; + SplitColQualList($6, &n->constraints, &n->collClause, &n->clientLogicColumnRef, + yyscanner); + $$ = (Node *)n; + } + ; + +KVType: TSTAG {$$ = ATT_KV_TAG;} /* tag for kv storage */ + | TSFIELD {$$ = ATT_KV_FIELD;} /* field for kv storage */ + | TSTIME {$$ = ATT_KV_TIMETAG;} /* field for kv storage */ + | /* EMPTY */ {$$ = ATT_KV_UNDEFINED;} /* not using kv storage */ +; + +ColCmprsMode: DELTA {$$ = ATT_CMPR_DELTA;} /* delta compression */ + | PREFIX {$$ = ATT_CMPR_PREFIX;} /* prefix compression */ + | DICTIONARY {$$ = ATT_CMPR_DICTIONARY;} /* dictionary compression */ + | NUMSTR {$$ = ATT_CMPR_NUMSTR;} /* number-string compression */ + | NOCOMPRESS {$$ = ATT_CMPR_NOCOMPRESS;} /* don't compress */ + | /* EMPTY */ {$$ = ATT_CMPR_UNDEFINED;} /* not specified by user */ +; + +columnOptions: ColId WITH OPTIONS ColQualList + { + ColumnDef *n = makeNode(ColumnDef); + n->colname = $1; + n->typname = 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, &n->clientLogicColumnRef, + yyscanner); + $$ = (Node *)n; + } + ; + +ColQualList: + ColQualList ColConstraint { $$ = lappend($1, $2); } + | /*EMPTY*/ { $$ = NIL; } + ; + +ColConstraint: + CONSTRAINT name ColConstraintElem + { + Constraint *n = (Constraint *) $3; + AssertEreport(IsA(n, Constraint), + MOD_OPT, + "check node type inconsistant"); + 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; + } + | ENCRYPTED with_algorithm + { + $$=$2; + } + ; +with_algorithm: + WITH '(' algorithm_desc ')' + { + $$=$3; + } + | /*EMPTY*/ { + ClientLogicColumnRef *n = makeNode(ClientLogicColumnRef); + n->column_key_name=NULL; + n->columnEncryptionAlgorithmType = EncryptionType::DETERMINISTIC_TYPE; + n->orig_typname=NULL; + n->location=0; + $$ = (Node *) n; + } + ; +algorithm_desc: + datatypecl columnEncryptionKey ',' encryptionType + { + ClientLogicColumnRef *n = makeNode(ClientLogicColumnRef); + n->column_key_name=$2; + n->columnEncryptionAlgorithmType = $4; + n->orig_typname=NULL; + n->dest_typname=$1; + n->location=@2; + $$ = (Node *) n; + } + | datatypecl encryptionType ',' columnEncryptionKey + { + ClientLogicColumnRef *n = makeNode(ClientLogicColumnRef); + n->column_key_name=$4; + n->columnEncryptionAlgorithmType = $2; + n->orig_typname=NULL; + n->dest_typname=$1; + n->location=@2; + $$ = (Node *) n; + } + ; +columnEncryptionKey: COLUMN_ENCRYPTION_KEY '=' setting_name {$$=$3; }; +encryptionType: + ENCRYPTION_TYPE '=' RANDOMIZED {$$ =EncryptionType::RANDOMIZED_TYPE;} + | ENCRYPTION_TYPE '=' DETERMINISTIC {$$ =EncryptionType::DETERMINISTIC_TYPE; } +; +setting_name: + ColId { $$ = check_setting_name(list_make1(makeString($1)), yyscanner); } + | ColId indirection + { + $$ = check_setting_name(lcons(makeString($1), $2), yyscanner); + } + ; + +CreateKeyStmt: + CreateMasterKeyStmt { $$ = $1; } + | CreateColumnKeyStmt { $$ = $1; } + ; + +CreateMasterKeyStmt: + CREATE CLIENT MASTER KEY setting_name WITH '(' master_key_params ')' + { + CreateClientLogicGlobal *n = makeNode(CreateClientLogicGlobal); + n->global_key_name = $5; + + ClientLogicGlobalParam *n1 = makeNode (ClientLogicGlobalParam); + n1->key = ClientLogicGlobalProperty::CLIENT_GLOBAL_FUNCTION; + n1->value = "encryption"; + // len is not filled on purpose ?? + + n->global_setting_params = lappend($8, (Node*)n1); + $$=(Node*) n; + } + ; + +master_key_params: + master_key_elem { $$ = list_make1($1); } + | master_key_params ',' master_key_elem { $$ = lappend($1, $3); } + ; + +master_key_elem: + KEY_STORE '=' ColId + { + ClientLogicGlobalParam *n = makeNode (ClientLogicGlobalParam); + n->key = ClientLogicGlobalProperty::CMK_KEY_STORE; + n->value = $3; + // len is not filled on purpose ?? + $$ = (Node*) n; + } + | KEY_PATH '=' ColId + { + ClientLogicGlobalParam *n = makeNode (ClientLogicGlobalParam); + n->key = ClientLogicGlobalProperty::CMK_KEY_PATH; + n->value =$3; + // len is not filled on purpose ?? + $$ = (Node*) n; + } + | ALGORITHM '=' ColId + { + ClientLogicGlobalParam *n = makeNode (ClientLogicGlobalParam); + n->key = ClientLogicGlobalProperty::CMK_ALGORITHM; + n->value=$3; + // len is not filled on purpose ?? + $$ = (Node*) n; + } + ; + +CreateColumnKeyStmt: + CREATE COLUMN ENCRYPTION KEY setting_name WITH VALUES '(' column_key_params ')' + { + CreateClientLogicColumn *n = makeNode(CreateClientLogicColumn); + n->column_key_name = $5; + + ClientLogicColumnParam *n1 = makeNode (ClientLogicColumnParam); + n1->key = ClientLogicColumnProperty::COLUMN_COLUMN_FUNCTION; + n1->value = "encryption"; + // len is not filled on purpose ?? + + n->column_setting_params = lappend($9, (Node*)n1);; + $$=(Node*)n; + } + ; + +column_key_params: + column_key_elem { $$ = list_make1($1); } + | column_key_params ',' column_key_elem { $$ = lappend($1, $3); } + ; + +column_key_elem: + CLIENT_MASTER_KEY '=' setting_name { + ClientLogicColumnParam *n = makeNode (ClientLogicColumnParam); + n->key = ClientLogicColumnProperty::CLIENT_GLOBAL_SETTING; + n->value = NULL; + n->qualname = $3; + $$ = (Node*) n; + } + | ALGORITHM '=' ColId + { + ClientLogicColumnParam *n = makeNode (ClientLogicColumnParam); + n->key = ClientLogicColumnProperty::CEK_ALGORITHM; + n->value =$3; + n->qualname = NIL; + $$ = (Node*) n; + } + | ENCRYPTED_VALUE '=' Sconst + { + ClientLogicColumnParam *n = makeNode (ClientLogicColumnParam); + n->key = ClientLogicColumnProperty::CEK_EXPECTED_VALUE; + n->value=$3; + n->qualname = NIL; + $$ = (Node*) n; + } + ; + +datatypecl: + DATATYPE_CL '=' client_logic_type',' + { + $$ = $3; + } + | {$$= NULL;} + ; + +/* + * @HDFS + * InformationalConstraintElem is used for informational constraint. + */ +InformationalConstraintElem: + NOT_ENFORCED + { + InformationalConstraint *n = makeNode(InformationalConstraint); + n->nonforced = true; + n->enableOpt = true; + $$ = (Node *) n; + } + | NOT_ENFORCED DISABLE_P QUERY OPTIMIZATION + { + InformationalConstraint *n = makeNode(InformationalConstraint); + n->nonforced = true; + n->enableOpt = false; + $$ = (Node *) n; + } + | NOT_ENFORCED ENABLE_P QUERY OPTIMIZATION + { + InformationalConstraint *n = makeNode(InformationalConstraint); + n->nonforced = true; + n->enableOpt = true; + $$ = (Node *) n; + } + | ENFORCED + { + InformationalConstraint *n = makeNode(InformationalConstraint); + n->nonforced = false; + n->enableOpt = false; + $$ = (Node *) n; + } + | /*EMPTY*/ + { + InformationalConstraint *n = makeNode(InformationalConstraint); + n->nonforced = false; + n->enableOpt = false; + $$ = (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 SQL92-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; + } + | NOT NULL_P ENABLE_P + { + Constraint *n = makeNode(Constraint); + n->contype = CONSTR_NOTNULL; + n->location = @1; + $$ = (Node *)n; + } + | NULL_P + { + Constraint *n = makeNode(Constraint); + n->contype = CONSTR_NULL; + n->location = @1; + $$ = (Node *)n; + } + | UNIQUE opt_definition OptConsTableSpace InformationalConstraintElem + { + Constraint *n = makeNode(Constraint); + n->contype = CONSTR_UNIQUE; + n->location = @1; + n->keys = NULL; + n->options = $2; + n->indexname = NULL; + n->indexspace = $3; + n->inforConstraint = (InformationalConstraint *) $4; + $$ = (Node *)n; + } + | UNIQUE opt_definition OptConsTableSpace ENABLE_P InformationalConstraintElem + { + Constraint *n = makeNode(Constraint); + n->contype = CONSTR_UNIQUE; + n->location = @1; + n->keys = NULL; + n->options = $2; + n->indexname = NULL; + n->indexspace = $3; + n->inforConstraint = (InformationalConstraint *) $5; + $$ = (Node *)n; + } + | PRIMARY KEY opt_definition OptConsTableSpace InformationalConstraintElem + { + Constraint *n = makeNode(Constraint); + n->contype = CONSTR_PRIMARY; + n->location = @1; + n->keys = NULL; + n->options = $3; + n->indexname = NULL; + n->indexspace = $4; + n->inforConstraint = (InformationalConstraint *) $5; + $$ = (Node *)n; + } + | PRIMARY KEY opt_definition OptConsTableSpace ENABLE_P InformationalConstraintElem + { + Constraint *n = makeNode(Constraint); + n->contype = CONSTR_PRIMARY; + n->location = @1; + n->keys = NULL; + n->options = $3; + n->indexname = NULL; + n->indexspace = $4; + n->inforConstraint = (InformationalConstraint *) $6; + $$ = (Node *)n; + } + | CHECK '(' a_expr ')' opt_no_inherit + { + Constraint *n = makeNode(Constraint); + n->contype = CONSTR_CHECK; + n->location = @1; + n->is_no_inherit = $5; + n->raw_expr = $3; + n->cooked_expr = NULL; + $$ = (Node *)n; + } + | CHECK '(' a_expr ')' opt_no_inherit ENABLE_P + { + Constraint *n = makeNode(Constraint); + n->contype = CONSTR_CHECK; + n->location = @1; + n->is_no_inherit = $5; + n->raw_expr = $3; + n->cooked_expr = NULL; + $$ = (Node *)n; + } + | DEFAULT b_expr + { + Constraint *n = makeNode(Constraint); + n->contype = CONSTR_DEFAULT; + n->location = @1; + n->raw_expr = $2; + n->cooked_expr = NULL; + $$ = (Node *)n; + } + | REFERENCES qualified_name opt_column_list key_match key_actions + { +#ifdef ENABLE_MULTIPLE_NODES + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("REFERENCES constraint is not yet supported."))); +#endif + Constraint *n = makeNode(Constraint); + n->contype = CONSTR_FOREIGN; + n->location = @1; + n->pktable = $2; + n->fk_attrs = NIL; + n->pk_attrs = $3; + n->fk_matchtype = $4; + n->fk_upd_action = (char) ($5 >> 8); + n->fk_del_action = (char) ($5 & 0xFF); + n->skip_validation = false; + n->initially_valid = true; + $$ = (Node *)n; + } + | REFERENCES qualified_name opt_column_list key_match key_actions ENABLE_P + { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("REFERENCES constraint is not yet supported."))); + Constraint *n = makeNode(Constraint); + n->contype = CONSTR_FOREIGN; + n->location = @1; + n->pktable = $2; + n->fk_attrs = NIL; + n->pk_attrs = $3; + n->fk_matchtype = $4; + n->fk_upd_action = (char) ($5 >> 8); + n->fk_del_action = (char) ($5 & 0xFF); + n->skip_validation = false; + n->initially_valid = true; + $$ = (Node *)n; + } + ; + +/* + * ConstraintAttr represents constraint attributes, which we parse as if + * they were independent constraint clauses, in order to avoid shift/reduce + * conflicts (since NOT might start either an independent NOT NULL clause + * or an attribute). parse_utilcmd.c is responsible for attaching the + * attribute information to the preceding "real" constraint node, and for + * complaining if attribute clauses appear in the wrong place or wrong + * combinations. + * + * See also ConstraintAttributeSpec, which can be used in places where + * there is no parsing conflict. (Note: currently, NOT VALID and NO INHERIT + * are allowed clauses in ConstraintAttributeSpec, but not here. Someday we + * might need to allow them here too, but for the moment it doesn't seem + * useful in the statements that use ConstraintAttr.) + */ +ConstraintAttr: + DEFERRABLE + { + Constraint *n = makeNode(Constraint); + n->contype = CONSTR_ATTR_DEFERRABLE; + n->location = @1; + $$ = (Node *)n; + } + | NOT DEFERRABLE + { + Constraint *n = makeNode(Constraint); + n->contype = CONSTR_ATTR_NOT_DEFERRABLE; + n->location = @1; + $$ = (Node *)n; + } + | INITIALLY DEFERRED + { + Constraint *n = makeNode(Constraint); + n->contype = CONSTR_ATTR_DEFERRED; + n->location = @1; + $$ = (Node *)n; + } + | INITIALLY IMMEDIATE + { + Constraint *n = makeNode(Constraint); + n->contype = CONSTR_ATTR_IMMEDIATE; + n->location = @1; + $$ = (Node *)n; + } + ; + + +TableLikeClause: + LIKE qualified_name TableLikeOptionList + { + TableLikeClause *n = makeNode(TableLikeClause); + n->relation = $2; + n->options = $3; +#ifndef ENABLE_MULTIPLE_NODES + if (IS_SINGLE_NODE && (n->options & CREATE_TABLE_LIKE_DISTRIBUTION)) + { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("Un-support feature"), + errdetail("The distributed capability is not supported currently."))); + } +#endif + $$ = (Node *)n; + } + | LIKE qualified_name INCLUDING_ALL excluding_option_list + { + TableLikeClause *n = makeNode(TableLikeClause); + n->relation = $2; + n->options = CREATE_TABLE_LIKE_ALL & ~$4; +#ifndef ENABLE_MULTIPLE_NODES + if (IS_SINGLE_NODE) + { + n->options = n->options & ~CREATE_TABLE_LIKE_DISTRIBUTION; + } +#endif + $$ = (Node *)n; + } + ; + +excluding_option_list: + excluding_option_list EXCLUDING TableLikeExcludingOption { $$ = $1 | $3; } + | /* EMPTY */ { $$ = 0; } + ; + +TableLikeOptionList: + TableLikeOptionList INCLUDING TableLikeIncludingOption { $$ = $1 | $3; } + | TableLikeOptionList EXCLUDING TableLikeExcludingOption { $$ = $1 & ~$3; } + | /* EMPTY */ { $$ = CREATE_TABLE_LIKE_DEFAULTS_SERIAL; } + ; + +TableLikeIncludingOption: + DEFAULTS { $$ = CREATE_TABLE_LIKE_DEFAULTS | CREATE_TABLE_LIKE_DEFAULTS_SERIAL; } + | CONSTRAINTS { $$ = CREATE_TABLE_LIKE_CONSTRAINTS; } + | INDEXES { $$ = CREATE_TABLE_LIKE_INDEXES; } + | STORAGE { $$ = CREATE_TABLE_LIKE_STORAGE; } + | COMMENTS { $$ = CREATE_TABLE_LIKE_COMMENTS; } + | PARTITION { $$ = CREATE_TABLE_LIKE_PARTITION; } + | RELOPTIONS { $$ = CREATE_TABLE_LIKE_RELOPTIONS; } + | DISTRIBUTION { $$ = CREATE_TABLE_LIKE_DISTRIBUTION; } + | OIDS { $$ = CREATE_TABLE_LIKE_OIDS;} + ; + +TableLikeExcludingOption: + DEFAULTS { $$ = CREATE_TABLE_LIKE_DEFAULTS | CREATE_TABLE_LIKE_DEFAULTS_SERIAL; } + | CONSTRAINTS { $$ = CREATE_TABLE_LIKE_CONSTRAINTS; } + | INDEXES { $$ = CREATE_TABLE_LIKE_INDEXES; } + | STORAGE { $$ = CREATE_TABLE_LIKE_STORAGE; } + | COMMENTS { $$ = CREATE_TABLE_LIKE_COMMENTS; } + | PARTITION { $$ = CREATE_TABLE_LIKE_PARTITION; } + | RELOPTIONS { $$ = CREATE_TABLE_LIKE_RELOPTIONS; } + | DISTRIBUTION { $$ = CREATE_TABLE_LIKE_DISTRIBUTION; } + | OIDS { $$ = CREATE_TABLE_LIKE_OIDS; } + | ALL { $$ = CREATE_TABLE_LIKE_ALL; } + ; + +opt_internal_data: + INTERNAL DATA_P internal_data_body {$$ = $3;} + | /* EMPTY */ {$$ = NULL;} + ; + +internal_data_body: { + int begin = 0; + int end = 0; + char *body = NULL; + int body_len = 0; + + int tok = YYEMPTY; + base_yy_extra_type *yyextra = pg_yyget_extra(yyscanner); + + if (yychar == YYEOF || yychar == YYEMPTY) + tok = YYLEX; + + begin = yylloc; + while(tok != YYEOF) + { + if (tok == ';') + { + end = yylloc; + } + tok = YYLEX; + } + + if (end == 0) + parser_yyerror("internal data of create statment is not ended correctly"); + + body_len = end - begin + 1 ; + + body = (char *)palloc0(body_len + 1); + strncpy(body, + yyextra->core_yy_extra.scanbuf + begin - 1, body_len); + + body[body_len] = '\0'; + $$ = body; + } + ; + +/* ConstraintElem specifies constraint syntax which is not embedded into + * a column definition. ColConstraintElem specifies the embedded form. + * - thomas 1997-12-03 + */ +TableConstraint: + CONSTRAINT name ConstraintElem + { + Constraint *n = (Constraint *) $3; + Assert(IsA(n, Constraint)); + n->conname = $2; + n->location = @1; + $$ = (Node *) n; + } + | ConstraintElem { $$ = $1; } + ; + +ConstraintElem: + CHECK '(' a_expr ')' ConstraintAttributeSpec + { + Constraint *n = makeNode(Constraint); + n->contype = CONSTR_CHECK; + n->location = @1; + n->raw_expr = $3; + n->cooked_expr = NULL; + processCASbits($5, @5, "CHECK", + NULL, NULL, &n->skip_validation, + &n->is_no_inherit, yyscanner); + n->initially_valid = !n->skip_validation; + $$ = (Node *)n; + } + | UNIQUE '(' columnList ')' opt_c_include opt_definition OptConsTableSpace + ConstraintAttributeSpec InformationalConstraintElem + { + Constraint *n = makeNode(Constraint); + n->contype = CONSTR_UNIQUE; + n->location = @1; + n->keys = $3; + n->including = $5; + n->options = $6; + n->indexname = NULL; + n->indexspace = $7; + processCASbits($8, @8, "UNIQUE", + &n->deferrable, &n->initdeferred, NULL, + NULL, yyscanner); + n->inforConstraint = (InformationalConstraint *) $9; /* informational constraint info */ + $$ = (Node *)n; + } + | UNIQUE ExistingIndex ConstraintAttributeSpec InformationalConstraintElem + { + 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); + n->inforConstraint = (InformationalConstraint *) $4; /* informational constraint info */ + $$ = (Node *)n; + } + | PRIMARY KEY '(' columnList ')' opt_c_include opt_definition OptConsTableSpace + ConstraintAttributeSpec InformationalConstraintElem + { + 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); + n->inforConstraint = (InformationalConstraint *) $10; /* informational constraint info */ + $$ = (Node *)n; + } + | PRIMARY KEY ExistingIndex ConstraintAttributeSpec InformationalConstraintElem + { + 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); + n->inforConstraint = (InformationalConstraint*) $5; /* informational constraint info */ + $$ = (Node *)n; + } + | EXCLUDE access_method_clause '(' ExclusionConstraintList ')' + opt_c_include opt_definition OptConsTableSpace ExclusionWhereClause + ConstraintAttributeSpec + { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("EXCLUDE constraint is not yet supported."))); + 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 + { +#ifdef ENABLE_MULTIPLE_NODES + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("FOREIGN KEY ... REFERENCES constraint is not yet supported."))); +#endif + Constraint *n = makeNode(Constraint); + n->contype = CONSTR_FOREIGN; + n->location = @1; + n->pktable = $7; + n->fk_attrs = $4; + n->pk_attrs = $8; + n->fk_matchtype = $9; + n->fk_upd_action = (char) ($10 >> 8); + n->fk_del_action = (char) ($10 & 0xFF); + processCASbits($11, @11, "FOREIGN KEY", + &n->deferrable, &n->initdeferred, + &n->skip_validation, NULL, + yyscanner); + n->initially_valid = !n->skip_validation; + $$ = (Node *)n; + } + | PARTIAL CLUSTER KEY '(' columnList ')' ConstraintAttributeSpec + { + Constraint *n = makeNode(Constraint); + n->contype = CONSTR_CLUSTER; + n->location = @1; + n->keys = $5; + processCASbits($7, @7, "PARTIAL CLUSTER KEY", + NULL, NULL, NULL, NULL, + yyscanner); + $$ = (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_UNSPECIFIED; + } + | /*EMPTY*/ + { + $$ = FKCONSTR_MATCH_UNSPECIFIED; + } + ; + +ExclusionConstraintList: + ExclusionConstraintElem { $$ = list_make1($1); } + | ExclusionConstraintList ',' ExclusionConstraintElem + { $$ = lappend($1, $3); } + ; + +ExclusionConstraintElem: index_elem WITH any_operator + { + $$ = list_make2($1, $3); + } + /* allow OPERATOR() decoration for the benefit of ruleutils.c */ + | index_elem WITH OPERATOR '(' any_operator ')' + { + $$ = list_make2($1, $5); + } + ; + +ExclusionWhereClause: + WHERE '(' a_expr ')' { $$ = $3; } + | /*EMPTY*/ { $$ = NULL; } + ; + +/* + * We combine the update and delete actions into one value temporarily + * for simplicity of parsing, and then break them down again in the + * calling production. update is in the left 8 bits, delete in the right. + * Note that NOACTION is the default. + */ +key_actions: + key_update + { $$ = ($1 << 8) | (FKCONSTR_ACTION_NOACTION & 0xFF); } + | key_delete + { $$ = (FKCONSTR_ACTION_NOACTION << 8) | ($1 & 0xFF); } + | key_update key_delete + { $$ = ($1 << 8) | ($2 & 0xFF); } + | key_delete key_update + { $$ = ($2 << 8) | ($1 & 0xFF); } + | /*EMPTY*/ + { $$ = (FKCONSTR_ACTION_NOACTION << 8) | (FKCONSTR_ACTION_NOACTION & 0xFF); } + ; + +key_update: ON UPDATE key_action { $$ = $3; } + ; + +key_delete: ON DELETE_P key_action { $$ = $3; } + ; + +key_action: + NO ACTION { $$ = FKCONSTR_ACTION_NOACTION; } + | RESTRICT { $$ = FKCONSTR_ACTION_RESTRICT; } + | CASCADE { $$ = FKCONSTR_ACTION_CASCADE; } + | SET NULL_P { $$ = FKCONSTR_ACTION_SETNULL; } + | SET DEFAULT { $$ = FKCONSTR_ACTION_SETDEFAULT; } + ; + +OptInherit: INHERITS '(' qualified_name_list ')' + { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("CREATE TABLE ... INHERITS is not yet supported."))); + $$ = $3; + } + | /*EMPTY*/ { $$ = NIL; } + ; + +/* WITH (options) is preferred, WITH OIDS and WITHOUT OIDS are legacy forms */ +OptWith: + WITH reloptions { $$ = $2; } + | WITH OIDS + { + if (!u_sess->attr.attr_common.IsInplaceUpgrade) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("CREATE TABLE ... WITH OIDS is not yet supported."))); + $$ = list_make1(defWithOids(true)); + } + | WITHOUT OIDS { $$ = list_make1(defWithOids(false)); } + | /*EMPTY*/ { $$ = NIL; } + ; + +OnCommitOption: ON COMMIT DROP { $$ = ONCOMMIT_DROP; } + | ON COMMIT DELETE_P ROWS { $$ = ONCOMMIT_DELETE_ROWS; } + | ON COMMIT PRESERVE ROWS { $$ = ONCOMMIT_PRESERVE_ROWS; } + | /*EMPTY*/ { $$ = ONCOMMIT_NOOP; } + ; + +OptTableSpace: TABLESPACE name { $$ = $2; } + | /*EMPTY*/ { $$ = NULL; } + ; +OptGPI: UPDATE GLOBAL INDEX { $$ = TRUE; } + | /*EMPTY*/ { $$ = FALSE; } + ; +OptCompress: COMPRESS { $$ = REL_CMPRS_FIELDS_EXTRACT; } + | NOCOMPRESS { $$ = REL_CMPRS_PAGE_PLAIN; } + | /* EMPTY */ { $$ = REL_CMPRS_PAGE_PLAIN; } + ; + +/* PGXC_BEGIN */ +OptDistributeBy: OptDistributeByInternal { $$ = $1; } + | /* EMPTY */ { $$ = NULL; } + ; +OptDatanodeName: DATANODE name { $$ = $2; } + | /*EMPTY*/ { $$ = NULL; } + ; + +/* + * For the distribution type, we use IDENT to limit the impact of keywords + * related to distribution on other commands and to allow extensibility for + * new distributions. + */ +OptDistributeType: IDENT { $$ = $1; } + ; + +OptDistributeByInternal: DISTRIBUTE BY OptDistributeType '(' name_list ')' + { + DistributeBy *n = makeNode(DistributeBy); +#ifndef ENABLE_MULTIPLE_NODES + if (IS_SINGLE_NODE) + { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("Un-support feature"), + errdetail("The distributed capability is not supported currently."))); + } +#endif + if (strcmp($3, "modulo") == 0) + n->disttype = DISTTYPE_MODULO; + else if (strcmp($3, "hash") == 0) + n->disttype = DISTTYPE_HASH; + else if (strcmp($3, "list") == 0 || strcmp($3, "range") == 0) { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("%s distribution needs user-defined slice clause", $3))); + } else + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("unrecognized distribution option \"%s\"", $3))); + n->colname = $5; + if (list_length(n->colname) > 1 && strcmp($3, "hash") != 0) + { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("The number of %s distribute key can not exceed 1", $3))); + + } + $$ = n; + } + | DISTRIBUTE BY OptDistributeType + { + DistributeBy *n = makeNode(DistributeBy); +#ifndef ENABLE_MULTIPLE_NODES + if (IS_SINGLE_NODE) + { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("Un-support feature"), + errdetail("The distributed capability is not supported currently."))); + } +#endif + if (strcmp($3, "replication") == 0) + n->disttype = DISTTYPE_REPLICATION; + else if (strcmp($3, "roundrobin") == 0) + n->disttype = DISTTYPE_ROUNDROBIN; + else if (strcmp($3, "hidetag") == 0) + n->disttype = DISTTYPE_HIDETAG; + else + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("unrecognized distribution option \"%s\"", $3))); + n->colname = NULL; + $$ = n; + } + | distribute_by_range_clause + { + $$ = $1; + } + | distribute_by_list_clause + { + $$ = $1; + } + ; + + +distribute_by_list_clause: /* distribute by list ..., or distribute by list ... slice reference base_table */ + DISTRIBUTE BY LIST '(' name_list ')' OptListDistribution + { +#ifndef ENABLE_MULTIPLE_NODES + + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("Un-support feature"), + errdetail("The distributed capability is not supported currently."))); + +#endif + + DistributeBy *n = makeNode(DistributeBy); + n->disttype = DISTTYPE_LIST; + n->colname = $5; + n->distState = (DistState *)$7; + + if (list_length(n->colname) > 4) + { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("The number of LIST distribution keys can not exceed 4"))); + + } + $$ = n; + } + ; + +OptListDistribution: + '(' list_dist_state ')' + { + $$ = $2; + } + | SliceReferenceClause + { + DistState *n = makeNode(DistState); + n->strategy = 'l'; + n->refTableName = $1; + $$ = (Node *)n; + } + ; + +list_dist_state: /* DistState Struct for LIST distribution syntax */ + list_distribution_rules_list + { + DistState *n = makeNode(DistState); + n->strategy = 'l'; + n->sliceList = $1; + $$ = (Node *)n; + } + ; + +list_distribution_rules_list: /* list of DistSliceValue Struct for LIST distribution syntax */ + list_dist_value + { + $$ = list_make1($1); + } + | list_distribution_rules_list ',' list_dist_value + { + $$ = lappend($1, $3); + } + ; + +list_dist_value: + SLICE name VALUES '(' list_distribution_rule_row ')' OptDatanodeName + { + ListSliceDefState *n = makeNode(ListSliceDefState); + n->name = $2; + n->boundaries = $5; + n->datanode_name = $7; + $$ = (Node *)n; + } + | SLICE name VALUES '(' DEFAULT ')' OptDatanodeName + { + Const *m = makeNode(Const); + m->ismaxvalue = true; + m->location = @1; + + ListSliceDefState *n = makeNode(ListSliceDefState); + List *boundary = list_make1((void *)m); + n->boundaries = list_make1((void *)boundary); + n->name = $2; + n->datanode_name = $7; + $$ = (Node *)n; + } + ; + +list_distribution_rule_row: /* ListSliceDefState Struct for LIST distribution syntax */ + list_distribution_rule_single + { + $$ = list_make1($1); + } + | list_distribution_rule_row ',' list_distribution_rule_single + { + $$ = lappend($1, $3); + } + ; + +list_distribution_rule_single: + '(' expr_list ')' + { + $$ = $2; + } + | c_expr_noparen + { + $$ = list_make1($1); + } + ; + + + +distribute_by_range_clause: + DISTRIBUTE BY RANGE '(' name_list ')' '(' range_slice_definition_list ')' + { +#ifndef ENABLE_MULTIPLE_NODES + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("Un-support feature"), + errdetail("The distributed capability is not supported currently."))); +#endif + DistributeBy *n = makeNode(DistributeBy); + n->disttype = DISTTYPE_RANGE; + n->colname = $5; + DistState *n1 = makeNode(DistState); + n1->strategy = 'r'; + n1->sliceList = $8; + n->distState = n1; + + if (list_length(n->colname) > 4) { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("The number of range distribution key can not exceed 4"))); + } + + $$ = n; + } + | DISTRIBUTE BY RANGE '(' name_list ')' SliceReferenceClause + { +#ifndef ENABLE_MULTIPLE_NODES + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("Un-support feature"), + errdetail("The distributed capability is not supported currently."))); +#endif + DistributeBy *n = makeNode(DistributeBy); + n->disttype = DISTTYPE_RANGE; + n->colname = $5; + DistState *n1 = makeNode(DistState); + n1->strategy = 'r'; + n1->refTableName = $7; + n->distState = n1; + $$ = n; + } + ; + +SliceReferenceClause: + SLICE REFERENCES name + { + $$ = $3; + } + ; + +range_slice_definition_list: /* general range slice syntax: values less than or start .. end */ + range_slice_less_than_list + { + $$ = $1; + } + | range_slice_start_end_list + { + $$ = $1; + } + ; + +range_slice_less_than_list: + range_slice_less_than_item + { + $$ = list_make1($1); + } + | range_slice_less_than_list ',' range_slice_less_than_item + { + $$ = lappend($1, $3); + } + ; + +range_slice_less_than_item: + SLICE name VALUES LESS THAN '(' maxValueList ')' OptDatanodeName + { + RangePartitionDefState *n = makeNode(RangePartitionDefState); + n->partitionName = $2; + n->boundary = $7; + n->tablespacename = $9; + + $$ = (Node *)n; + } + ; + +range_slice_start_end_list: + range_slice_start_end_item + { + $$ = list_make1($1); + } + | range_slice_start_end_list ',' range_slice_start_end_item + { + $$ = lappend($1, $3); + } + ; + +range_slice_start_end_item: + SLICE name START '(' maxValueList ')' END_P '(' maxValueList ')' opt_range_every_list + { + RangePartitionStartEndDefState *n = makeNode(RangePartitionStartEndDefState); + n->partitionName = $2; + n->startValue = $5; + n->endValue = $9; + n->everyValue = $11; + + $$ = (Node *)n; + } + | SLICE name END_P '(' maxValueList ')' + { + RangePartitionStartEndDefState *n = makeNode(RangePartitionStartEndDefState); + n->partitionName = $2; + n->startValue = NIL; + n->endValue = $5; + n->everyValue = NIL; + + $$ = (Node *)n; + } + | SLICE name START '(' maxValueList ')' + { + RangePartitionStartEndDefState *n = makeNode(RangePartitionStartEndDefState); + n->partitionName = $2; + n->startValue = $5; + n->endValue = NIL; + n->everyValue = NIL; + + $$ = (Node *)n; + } + ; + +OptSubCluster: + OptSubClusterInternal + { + $$ = $1; + } + | /* EMPTY */ { $$ = NULL; } + ; + +OptSubClusterInternal: + TO NODE pgxcnodes + { + PGXCSubCluster *n = makeNode(PGXCSubCluster); + n->clustertype = SUBCLUSTER_NODE; + n->members = $3; + $$ = n; + } + | TO GROUP_P pgxcgroup_name + { + PGXCSubCluster *n = makeNode(PGXCSubCluster); + n->clustertype = SUBCLUSTER_GROUP; + n->members = list_make1(makeString($3)); + $$ = n; + } + ; +/* PGXC_END */ + +OptConsTableSpace: USING INDEX OptPartitionElement { $$ = $3; } + | /*EMPTY*/ { $$ = NULL; } + ; + +OptPartitionElement: + OptTableSpace OptPctFree OptInitRans OptMaxTrans OptStorage + { + $$ = $1; + } + ; + +OptPctFree: + PCTFREE Iconst + | /* empty */ + ; + +OptInitRans: + INITRANS Iconst + | /* empty */ + ; + +OptMaxTrans: + MAXTRANS Iconst + | /* empty */ + ; + +OptStorage: + STORAGE '(' OptInitial OptNext OptMinextents OptMaxextents ')' + | /* empty */ + ; +OptInitial: + INITIAL_P Iconst IDENT + | /* empty */ + ; + +OptNext: + NEXT Iconst IDENT + | /*empty*/ + ; + +OptMinextents: + MINEXTENTS Iconst + | /*empty*/ + ; + +OptMaxextents: + MAXEXTENTS UNLIMITED + | MAXEXTENTS Iconst + | /*empty*/ + ; + +ExistingIndex: USING INDEX index_name { $$ = $3; } + ; + + +/***************************************************************************** + * + * QUERY : + * CREATE TABLE relname AS SelectStmt [ WITH [NO] DATA ] + * + * + * Note: SELECT ... INTO is a now-deprecated alternative for this. + * + *****************************************************************************/ + +CreateAsStmt: + CREATE OptTemp TABLE create_as_target AS SelectStmt opt_with_data + { + CreateTableAsStmt *ctas = makeNode(CreateTableAsStmt); + ctas->query = $6; + ctas->into = $4; + ctas->relkind = OBJECT_TABLE; + ctas->is_select_into = false; + /* cram additional flags into the IntoClause */ + $4->rel->relpersistence = $2; + $4->skipData = !($7); + $$ = (Node *) ctas; + } + ; + +create_as_target: + qualified_name opt_column_list OptWith OnCommitOption OptCompress OptTableSpace +/* PGXC_BEGIN */ + OptDistributeBy OptSubCluster +/* PGXC_END */ + { + $$ = makeNode(IntoClause); + $$->rel = $1; + $$->colNames = $2; + $$->options = $3; + $$->onCommit = $4; + $$->row_compress = $5; + $$->tableSpaceName = $6; + $$->skipData = false; /* might get changed later */ +/* PGXC_BEGIN */ + $$->distributeby = $7; + $$->subcluster = $8; + $$->relkind = INTO_CLAUSE_RELKIND_DEFAULT; +/* PGXC_END */ + } + ; + +opt_with_data: + WITH DATA_P { $$ = TRUE; } + | WITH NO DATA_P { $$ = FALSE; } + | /*EMPTY*/ { $$ = TRUE; } + ; + +/***************************************************************************** + * + * QUERY : + * CREATE MATERIALIZED VIEW relname AS SelectStmt + * + *****************************************************************************/ + +CreateMatViewStmt: + CREATE OptNoLog opt_incremental MATERIALIZED VIEW create_mv_target AS SelectStmt opt_with_data + { + CreateTableAsStmt *ctas = makeNode(CreateTableAsStmt); + ctas->query = $8; + ctas->into = $6; + ctas->relkind = OBJECT_MATVIEW; + ctas->is_select_into = false; + /* cram additional flags into the IntoClause */ + $6->rel->relpersistence = $2; + $6->skipData = !($9); + if ($6->skipData) { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("WITH NO DATA for materialized views not yet supported"))); + } + if ($3 && $6->options) { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("options for incremental materialized views not yet supported"))); + } +#ifndef ENABLE_MULTIPLE_NODES + if ($3 && $6->distributeby) { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("It's not supported to specify distribute key on incremental materialized views"))); + } +#endif + $6->ivm = $3; + $$ = (Node *) ctas; + } + ; + +create_mv_target: + qualified_name opt_column_list +/* PGXC_BEGIN */ + OptDistributeBy +/* PGXC_END */ + opt_reloptions OptTableSpace + { + $$ = makeNode(IntoClause); + $$->rel = $1; + $$->colNames = $2; + $$->options = $4; + $$->onCommit = ONCOMMIT_NOOP; + $$->tableSpaceName = $5; + $$->skipData = false; /* might get changed later */ + $$->ivm = false; +/* PGXC_BEGIN */ + $$->distributeby = $3; +/* PGXC_END */ + $$->relkind = INTO_CLAUSE_RELKIND_DEFAULT; + } + ; + +OptNoLog: UNLOGGED { $$ = RELPERSISTENCE_UNLOGGED; } + | /*EMPTY*/ { $$ = RELPERSISTENCE_PERMANENT; } + ; + +opt_incremental: + INCREMENTAL { $$ = TRUE; } + | /*EMPTY*/ { $$ = FALSE; } + ; + + +/***************************************************************************** + * + * QUERY : + * REFRESH MATERIALIZED VIEW qualified_name + * + *****************************************************************************/ + +RefreshMatViewStmt: + REFRESH opt_incremental MATERIALIZED VIEW qualified_name opt_with_data + { + RefreshMatViewStmt *n = makeNode(RefreshMatViewStmt); + n->relation = $5; + n->incremental = $2; + n->skipData = !($6); + if (n->skipData) { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("WITH NO DATA for materialized views not yet supported"))); + } + $$ = (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; +/* PGXC_BEGIN */ + n->is_serial = false; +/* PGXC_END */ + n->uuid = 0; + n->canCreateTempSeq = false; + $$ = (Node *)n; + } + ; + +AlterSeqStmt: + ALTER SEQUENCE qualified_name SeqOptList + { + AlterSeqStmt *n = makeNode(AlterSeqStmt); + n->sequence = $3; + n->options = $4; + n->missing_ok = false; +/* PGXC_BEGIN */ + n->is_serial = false; +/* PGXC_END */ + $$ = (Node *)n; + } + | ALTER SEQUENCE IF_P EXISTS qualified_name SeqOptList + { + AlterSeqStmt *n = makeNode(AlterSeqStmt); + n->sequence = $5; + n->options = $6; + n->missing_ok = true; + $$ = (Node *)n; + } + + ; + +OptSeqOptList: SeqOptList { $$ = $1; } + | /*EMPTY*/ { $$ = NIL; } + ; + +SeqOptList: SeqOptElem { $$ = list_make1($1); } + | SeqOptList SeqOptElem { $$ = lappend($1, $2); } + ; + +SeqOptElem: CACHE NumericOnly + { + $$ = makeDefElem("cache", (Node *)$2); + } + | CYCLE + { + $$ = makeDefElem("cycle", (Node *)makeInteger(TRUE)); + } + | NO CYCLE + { + $$ = makeDefElem("cycle", (Node *)makeInteger(FALSE)); + } + | INCREMENT opt_by NumericOnly + { + $$ = makeDefElem("increment", (Node *)$3); + } + | MAXVALUE NumericOnly + { + $$ = makeDefElem("maxvalue", (Node *)$2); + } + | MINVALUE NumericOnly + { + $$ = makeDefElem("minvalue", (Node *)$2); + } + | NO MAXVALUE + { + $$ = makeDefElem("maxvalue", NULL); + } + | NO MINVALUE + { + $$ = makeDefElem("minvalue", NULL); + } + | OWNED BY any_name + { + $$ = makeDefElem("owned_by", (Node *)$3); + } + | START opt_with NumericOnly + { + $$ = makeDefElem("start", (Node *)$3); + } + | RESTART + { + $$ = makeDefElem("restart", NULL); + } + | RESTART opt_with NumericOnly + { + $$ = makeDefElem("restart", (Node *)$3); + } + | NOCYCLE + { + $$ = makeDefElem("cycle", (Node *)makeInteger(FALSE)); + } + | NOMAXVALUE + { + $$ = makeDefElem("maxvalue", NULL); + } + | NOMINVALUE + { + $$ = makeDefElem("minvalue", NULL); + } + ; + +opt_by: BY {} + | /* empty */ {} + ; + +NumericOnly: + FCONST { $$ = makeFloat($1); } + | '+' FCONST { $$ = makeFloat($2); } + | '-' FCONST + { + $$ = makeFloat($2); + doNegateFloat($$); + } + | SignedIconst { $$ = makeInteger($1); } + ; + +NumericOnly_list: NumericOnly { $$ = list_make1($1); } + | NumericOnly_list ',' NumericOnly { $$ = lappend($1, $3); } + ; + +/***************************************************************************** + * + * QUERIES : + * CREATE [OR REPLACE] [TRUSTED] [PROCEDURAL] LANGUAGE ... + * DROP [PROCEDURAL] LANGUAGE ... + * + *****************************************************************************/ + +CreatePLangStmt: + CREATE opt_or_replace opt_trusted opt_procedural LANGUAGE ColId_or_Sconst + { + CreatePLangStmt *n = makeNode(CreatePLangStmt); + n->replace = $2; + n->plname = $6; + /* parameters are all to be supplied by system */ + n->plhandler = NIL; + n->plinline = NIL; + n->plvalidator = NIL; + n->pltrusted = false; + $$ = (Node *)n; + } + | CREATE opt_or_replace opt_trusted opt_procedural LANGUAGE ColId_or_Sconst + HANDLER handler_name opt_inline_handler opt_validator + { + CreatePLangStmt *n = makeNode(CreatePLangStmt); + n->replace = $2; + n->plname = $6; + n->plhandler = $8; + n->plinline = $9; + n->plvalidator = $10; + n->pltrusted = $3; + $$ = (Node *)n; + } + ; + +opt_trusted: + TRUSTED { $$ = TRUE; } + | /*EMPTY*/ { $$ = FALSE; } + ; + +/* This ought to be just func_name, but that causes reduce/reduce conflicts + * (CREATE LANGUAGE is the only place where func_name isn't followed by '('). + * Work around by using simple names, instead. + */ +handler_name: + name { $$ = list_make1(makeString($1)); } + | name attrs { $$ = lcons(makeString($1), $2); } + ; + +opt_inline_handler: + INLINE_P handler_name { $$ = $2; } + | /*EMPTY*/ { $$ = NIL; } + ; + +validator_clause: + VALIDATOR handler_name { $$ = $2; } + | NO VALIDATOR { $$ = NIL; } + ; + +opt_validator: + validator_clause { $$ = $1; } + | /*EMPTY*/ { $$ = NIL; } + ; + +DropPLangStmt: + DROP opt_procedural LANGUAGE ColId_or_Sconst opt_drop_behavior + { + DropStmt *n = makeNode(DropStmt); + n->removeType = OBJECT_LANGUAGE; + n->objects = list_make1(list_make1(makeString($4))); + n->arguments = NIL; + n->behavior = $5; + n->missing_ok = false; + n->concurrent = false; + $$ = (Node *)n; + } + | DROP opt_procedural LANGUAGE IF_P EXISTS ColId_or_Sconst opt_drop_behavior + { + DropStmt *n = makeNode(DropStmt); + n->removeType = OBJECT_LANGUAGE; + n->objects = list_make1(list_make1(makeString($6))); + n->behavior = $7; + n->missing_ok = true; + n->concurrent = false; + $$ = (Node *)n; + } + ; + +opt_procedural: + PROCEDURAL {} + | /*EMPTY*/ {} + ; + +tblspc_options: + '(' tblspc_option_list ')' { $$ = $2; } + ; +opt_tblspc_options: WITH tblspc_options { $$ = $2; } + | /* EMPTY */ { $$ = NIL; } + ; + +tblspc_option_list: + tblspc_option_elem { $$ = list_make1($1); } + | tblspc_option_list ',' tblspc_option_elem { $$ = lappend($1, $3); } + ; + +tblspc_option_elem: + ColLabel '=' Sconst + { + $$ = makeDefElem($1, (Node *) makeString($3)); + } + | ColLabel '=' func_type + { + if(0 != pg_strcasecmp($1, "filesystem")) + { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Must use single quoted string for \"%s\" option.", $1))); + } + $$ = makeDefElem($1, (Node *) $3); + } + | ColLabel '=' NumericOnly + { + $$ = makeDefElem($1, (Node *) $3); + } + ; +/***************************************************************************** + * + * QUERY: + * CREATE TABLESPACE tablespace LOCATION '/path/to/tablespace/' + * + *****************************************************************************/ + +CreateTableSpaceStmt: CREATE TABLESPACE name OptTableSpaceOwner OptRelative LOCATION Sconst OptMaxSize opt_tblspc_options + { + CreateTableSpaceStmt *n = makeNode(CreateTableSpaceStmt); + n->tablespacename = $3; + n->owner = $4; + n->location = $7; + n->maxsize = $8; + n->options = $9; + n->relative = $5; + $$ = (Node *) n; + } + | CREATE TABLESPACE name LoggingStr DATAFILE Sconst OptDatafileSize OptReuse OptAuto + { + CreateTableSpaceStmt *n = makeNode(CreateTableSpaceStmt); + n->tablespacename = $3; + n->owner = NULL; + n->location = $6; + n->maxsize = $7; + $$ = (Node *) n; + } + | CREATE TABLESPACE name DATAFILE Sconst OptDatafileSize OptReuse OptAuto LoggingStr + { + CreateTableSpaceStmt *n = makeNode(CreateTableSpaceStmt); + n->tablespacename = $3; + n->owner = NULL; + n->location = $5; + n->maxsize = $6; + $$ = (Node *) n; + } + | CREATE TABLESPACE name DATAFILE Sconst OptDatafileSize OptReuse OptAuto + { + CreateTableSpaceStmt *n = makeNode(CreateTableSpaceStmt); + n->tablespacename = $3; + n->owner = NULL; + n->location = $5; + n->maxsize = $6; + $$ = (Node *) n; + } + ; + +LoggingStr: + LOGGING { $$ = NULL ;} + | NOLOGGING { $$ = NULL ;} + ; + +OptDatafileSize: + SIZE Iconst IDENT { $$ = NULL; } + | /*EMPTY */ { $$ = NULL; } + ; + +OptReuse: + REUSE { $$ = NULL; } + | /*EMPTY */ { $$ = NULL; } + ; + +OptAuto: + AUTOEXTEND ON OptNextStr OptMaxSize { $$ = NULL; } + | AUTOEXTEND OFF { $$ = NULL; } + | /*EMPTY */ { $$ = NULL; } + ; + +OptNextStr: + NEXT Iconst IDENT { $$ = NULL; } + | /*EMPTY */ { $$ = NULL; } + ; + +OptMaxSize: + MAXSIZE Sconst { $$ = $2; } + | /*EMPTY */ { $$ = NULL;} + ; +size_clause: + Sconst { $$ = $1; } + | UNLIMITED { $$ = "unlimited"; } + ; + +OptRelative: + RELATIVE_P { $$ = true; } + | /*EMPTY */ { $$ = false; } + + +OptTableSpaceOwner: OWNER name { $$ = $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 ] [ FROM oldversion ] + * + *****************************************************************************/ + +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)); + } + | VERSION_P ColId_or_Sconst + { + $$ = makeDefElem("new_version", (Node *)makeString($2)); + } + | FROM ColId_or_Sconst + { + $$ = makeDefElem("old_version", (Node *)makeString($2)); + } + ; +/***************************************************************************** + * + * QUERY: + * CREATE OR REPLACE DIRECTORY directory AS '/path/to/directory/' + * + *****************************************************************************/ + +CreateDirectoryStmt: CREATE opt_or_replace DIRECTORY name AS Sconst + { + CreateDirectoryStmt *n = makeNode(CreateDirectoryStmt); + n->replace = $2; + n->directoryname = $4; + n->location = $6; + n->owner = NULL; + $$ = (Node *)n; + } + ; + +/***************************************************************************** + * + * QUERY : + * DROP DIRECTORY [IF EXISTS] directory + * + ****************************************************************************/ + +DropDirectoryStmt: DROP DIRECTORY name + { + DropDirectoryStmt *n = makeNode(DropDirectoryStmt); + n->directoryname = $3; + n->missing_ok = false; + $$ = (Node *) n; + } + | DROP DIRECTORY IF_P EXISTS name + { + DropDirectoryStmt *n = makeNode(DropDirectoryStmt); + n->directoryname = $5; + n->missing_ok = true; + $$ = (Node *) n; + } + ; + +/***************************************************************************** + * + * 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 ColId_or_Sconst + { + $$ = makeDefElem("new_version", (Node *)makeString($2)); + } + ; + +/***************************************************************************** + * + * ALTER EXTENSION name ADD/DROP object-identifier + * + *****************************************************************************/ + +AlterExtensionContentsStmt: + ALTER EXTENSION name add_drop AGGREGATE func_name aggr_args + { + AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt); + n->extname = $3; + n->action = $4; + n->objtype = OBJECT_AGGREGATE; + n->objname = $6; + n->objargs = $7; + $$ = (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->objname = list_make1($7); + n->objargs = list_make1($9); + $$ = (Node *) n; + } + | ALTER EXTENSION name add_drop COLLATION any_name + { + AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt); + n->extname = $3; + n->action = $4; + n->objtype = OBJECT_COLLATION; + n->objname = $6; + $$ = (Node *)n; + } + | ALTER EXTENSION name add_drop CONVERSION_P any_name + { + AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt); + n->extname = $3; + n->action = $4; + n->objtype = OBJECT_CONVERSION; + n->objname = $6; + $$ = (Node *)n; + } + | ALTER EXTENSION name add_drop DOMAIN_P any_name + { + AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt); + n->extname = $3; + n->action = $4; + n->objtype = OBJECT_DOMAIN; + n->objname = $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->objname = $6->funcname; + n->objargs = $6->funcargs; + $$ = (Node *)n; + } + | ALTER EXTENSION name add_drop opt_procedural LANGUAGE name + { + AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt); + n->extname = $3; + n->action = $4; + n->objtype = OBJECT_LANGUAGE; + n->objname = list_make1(makeString($7)); + $$ = (Node *)n; + } + | ALTER EXTENSION name add_drop OPERATOR any_operator oper_argtypes + { + AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt); + n->extname = $3; + n->action = $4; + n->objtype = OBJECT_OPERATOR; + n->objname = $6; + n->objargs = $7; + $$ = (Node *)n; + } + | ALTER EXTENSION name add_drop OPERATOR CLASS any_name USING access_method + { + AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt); + n->extname = $3; + n->action = $4; + n->objtype = OBJECT_OPCLASS; + n->objname = $7; + n->objargs = list_make1(makeString($9)); + $$ = (Node *)n; + } + | ALTER EXTENSION name add_drop OPERATOR FAMILY any_name USING access_method + { + AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt); + n->extname = $3; + n->action = $4; + n->objtype = OBJECT_OPFAMILY; + n->objname = $7; + n->objargs = list_make1(makeString($9)); + $$ = (Node *)n; + } + | ALTER EXTENSION name add_drop SCHEMA name + { + AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt); + n->extname = $3; + n->action = $4; + n->objtype = OBJECT_SCHEMA; + n->objname = list_make1(makeString($6)); + $$ = (Node *)n; + } + | ALTER EXTENSION name add_drop TABLE any_name + { + AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt); + n->extname = $3; + n->action = $4; + n->objtype = OBJECT_TABLE; + n->objname = $6; + $$ = (Node *)n; + } + | ALTER EXTENSION name add_drop TEXT_P SEARCH PARSER any_name + { + AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt); + n->extname = $3; + n->action = $4; + n->objtype = OBJECT_TSPARSER; + n->objname = $8; + $$ = (Node *)n; + } + | ALTER EXTENSION name add_drop TEXT_P SEARCH DICTIONARY any_name + { + AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt); + n->extname = $3; + n->action = $4; + n->objtype = OBJECT_TSDICTIONARY; + n->objname = $8; + $$ = (Node *)n; + } + | ALTER EXTENSION name add_drop TEXT_P SEARCH TEMPLATE any_name + { + AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt); + n->extname = $3; + n->action = $4; + n->objtype = OBJECT_TSTEMPLATE; + n->objname = $8; + $$ = (Node *)n; + } + | ALTER EXTENSION name add_drop TEXT_P SEARCH CONFIGURATION any_name + { + AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt); + n->extname = $3; + n->action = $4; + n->objtype = OBJECT_TSCONFIGURATION; + n->objname = $8; + $$ = (Node *)n; + } + | ALTER EXTENSION name add_drop SEQUENCE any_name + { + AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt); + n->extname = $3; + n->action = $4; + n->objtype = OBJECT_SEQUENCE; + n->objname = $6; + $$ = (Node *)n; + } + | ALTER EXTENSION name add_drop VIEW any_name + { + AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt); + n->extname = $3; + n->action = $4; + n->objtype = OBJECT_VIEW; + n->objname = $6; + $$ = (Node *)n; + } + | ALTER EXTENSION name add_drop MATERIALIZED VIEW any_name + { + AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt); + n->extname = $3; + n->action = $4; + n->objtype = OBJECT_MATVIEW; + n->objname = $7; + $$ = (Node *)n; + } + | ALTER EXTENSION name add_drop FOREIGN TABLE any_name + { + AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt); + n->extname = $3; + n->action = $4; + n->objtype = OBJECT_FOREIGN_TABLE; + n->objname = $7; + $$ = (Node *)n; + } + | ALTER EXTENSION name add_drop FOREIGN DATA_P WRAPPER name + { + AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt); + n->extname = $3; + n->action = $4; + n->objtype = OBJECT_FDW; + n->objname = list_make1(makeString($8)); + $$ = (Node *)n; + } + | ALTER EXTENSION name add_drop SERVER name + { + AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt); + n->extname = $3; + n->action = $4; + n->objtype = OBJECT_FOREIGN_SERVER; + n->objname = list_make1(makeString($6)); + $$ = (Node *)n; + } + | ALTER EXTENSION name add_drop TYPE_P any_name + { + AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt); + n->extname = $3; + n->action = $4; + n->objtype = OBJECT_TYPE; + n->objname = $6; + $$ = (Node *)n; + } + ; +/***************************************************************************** + * + * QUERY: + * CREATE WEAK PASSWORD DICTIONARY + * + *****************************************************************************/ + +CreateWeakPasswordDictionaryStmt: + CREATE WEAK PASSWORD DICTIONARY opt_vals weak_password_string_list + { + CreateWeakPasswordDictionaryStmt *n = makeNode(CreateWeakPasswordDictionaryStmt); + n->weak_password_string_list = $6; + $$ = (Node*)n; + } + ; + +opt_vals: WITH VALUES {} + | /*EMPTY*/ {} + ; + +weak_password_string_list: '(' password_string ')' { $$ = list_make1(makeString($2)); } + | weak_password_string_list ',' '(' password_string ')' { $$ = lappend($1, makeString($4)); } + ; + +/***************************************************************************** + * + * QUERY: + * DROP WEAK PASSWORD DICTIONARY + * + *****************************************************************************/ + +DropWeakPasswordDictionaryStmt: + DROP WEAK PASSWORD DICTIONARY + { + DropWeakPasswordDictionaryStmt *n = makeNode(DropWeakPasswordDictionaryStmt); + $$ = (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); } + | NO HANDLER { $$ = makeDefElem("handler", NULL); } + | VALIDATOR handler_name { $$ = makeDefElem("validator", (Node *)$2); } + | NO VALIDATOR { $$ = makeDefElem("validator", NULL); } + ; + +fdw_options: + fdw_option { $$ = list_make1($1); } + | fdw_options fdw_option { $$ = lappend($1, $2); } + ; + +opt_fdw_options: + fdw_options { $$ = $1; } + | /*EMPTY*/ { $$ = NIL; } + ; + +/***************************************************************************** + * + * QUERY : + * DROP FOREIGN DATA WRAPPER name + * + ****************************************************************************/ + +DropFdwStmt: DROP FOREIGN DATA_P WRAPPER name opt_drop_behavior + { + DropStmt *n = makeNode(DropStmt); + n->removeType = OBJECT_FDW; + n->objects = list_make1(list_make1(makeString($5))); + n->arguments = NIL; + n->missing_ok = false; + n->behavior = $6; + n->concurrent = false; + $$ = (Node *) n; + } + | DROP FOREIGN DATA_P WRAPPER IF_P EXISTS name opt_drop_behavior + { + DropStmt *n = makeNode(DropStmt); + n->removeType = OBJECT_FDW; + n->objects = list_make1(list_make1(makeString($7))); + n->arguments = NIL; + n->missing_ok = true; + n->behavior = $8; + n->concurrent = false; + $$ = (Node *) n; + } + ; + +/***************************************************************************** + * + * 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); + } + ; + +generic_option_elem: + generic_option_name generic_option_arg + { + if (strcmp($1, "error_table") == 0) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Invalid option %s", $1))); + + $$ = makeDefElem($1, $2); + } + ; + +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] + * + *****************************************************************************/ +fdwName: IDENT {$$ = $1;}; + +CreateForeignServerStmt: CREATE SERVER name opt_type opt_foreign_server_version + FOREIGN DATA_P WRAPPER fdwName create_generic_options + { + CreateForeignServerStmt *n = makeNode(CreateForeignServerStmt); + n->servername = $3; + n->servertype = $4; + n->version = $5; + n->fdwname = $9; + n->options = $10; + $$ = (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 : + * DROP SERVER name + * + ****************************************************************************/ + +DropForeignServerStmt: DROP SERVER name opt_drop_behavior + { + DropStmt *n = makeNode(DropStmt); + n->removeType = OBJECT_FOREIGN_SERVER; + n->objects = list_make1(list_make1(makeString($3))); + n->arguments = NIL; + n->missing_ok = false; + n->behavior = $4; + n->concurrent = false; + $$ = (Node *) n; + } + | DROP SERVER IF_P EXISTS name opt_drop_behavior + { + DropStmt *n = makeNode(DropStmt); + n->removeType = OBJECT_FOREIGN_SERVER; + n->objects = list_make1(list_make1(makeString($5))); + n->arguments = NIL; + n->missing_ok = true; + n->behavior = $6; + n->concurrent = false; + $$ = (Node *) n; + } + ; + +/***************************************************************************** + * + * 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 + OptForeignTableElementList + SERVER name create_generic_options ForeignTblWritable + OptForeignTableLogError OptForeignTableLogRemote OptPerNodeRejectLimit OptDistributeBy +/* PGXC_BEGIN */ + OptSubCluster +/* PGXC_END */ + OptForeignPartBy + { + CreateForeignTableStmt *n = makeNode(CreateForeignTableStmt); + $4->relpersistence = RELPERSISTENCE_PERMANENT; + n->base.relation = $4; + n->base.tableElts = $5; + n->base.inhRelations = NIL; + n->base.if_not_exists = false; + /* FDW-specific data */ + n->servername = $7; + n->options = $8; + + n->write_only = $9; + n->error_relation = (Node*)$10; + if ($11 != NULL) + n->extOptions = lappend(n->extOptions, $11); + if ($12 != NULL) + n->extOptions = lappend(n->extOptions, $12); + n->base.distributeby = $13; +/* PGXC_BEGIN */ + n->base.subcluster = $14; +/* PGXC_END */ + if ($15 != NULL) + n->part_state = $15; + + $$ = (Node *) n; + } + | CREATE FOREIGN TABLE IF_P NOT EXISTS qualified_name + OptForeignTableElementList + SERVER name create_generic_options ForeignTblWritable + OptForeignTableLogError OptForeignTableLogRemote OptPerNodeRejectLimit OptDistributeBy +/* PGXC_BEGIN */ + OptSubCluster +/* PGXC_END */ + OptForeignPartBy + { + CreateForeignTableStmt *n = makeNode(CreateForeignTableStmt); + $7->relpersistence = RELPERSISTENCE_PERMANENT; + n->base.relation = $7; + n->base.tableElts = $8; + n->base.inhRelations = NIL; + n->base.if_not_exists = true; + /* FDW-specific data */ + n->servername = $10; + n->options = $11; + + n->write_only = $12; + n->error_relation = (Node*)$13; + if ($14 != NULL) + n->extOptions = lappend(n->extOptions, $14); + if ($15 != NULL) + n->extOptions = lappend(n->extOptions, $15); + n->base.distributeby = $16; +/* PGXC_BEGIN */ + n->base.subcluster = $17; +/* PGXC_END */ + if ($18 != NULL) + n->part_state = $18; + + $$ = (Node *) n; + } +/* ENABLE_MOT BEGIN */ + | CREATE FOREIGN TABLE qualified_name + OptForeignTableElementList + create_generic_options ForeignTblWritable + OptForeignTableLogError OptForeignTableLogRemote OptPerNodeRejectLimit OptDistributeBy +/* PGXC_BEGIN */ + OptSubCluster +/* PGXC_END */ + OptForeignPartBy + { + CreateForeignTableStmt *n = makeNode(CreateForeignTableStmt); + $4->relpersistence = RELPERSISTENCE_PERMANENT; + n->base.relation = $4; + n->base.tableElts = $5; + n->base.inhRelations = NIL; + n->base.if_not_exists = false; + /* FDW-specific data */ +#ifdef ENABLE_MOT + n->servername = pstrdup("mot_server"); +#else + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Foreign server is not specified"))); +#endif + n->options = $6; + + n->write_only = $7; + n->error_relation = (Node*)$8; + if ($9 != NULL) + n->extOptions = lappend(n->extOptions, $9); + if ($10 != NULL) + n->extOptions = lappend(n->extOptions, $10); + n->base.distributeby = $11; +/* PGXC_BEGIN */ + n->base.subcluster = $12; +/* PGXC_END */ + if ($13 != NULL) + n->part_state = $13; + + $$ = (Node *) n; + } + | CREATE FOREIGN TABLE IF_P NOT EXISTS qualified_name + OptForeignTableElementList + create_generic_options ForeignTblWritable + OptForeignTableLogError OptForeignTableLogRemote OptPerNodeRejectLimit OptDistributeBy +/* PGXC_BEGIN */ + OptSubCluster +/* PGXC_END */ + OptForeignPartBy + { + CreateForeignTableStmt *n = makeNode(CreateForeignTableStmt); + $7->relpersistence = RELPERSISTENCE_PERMANENT; + n->base.relation = $7; + n->base.tableElts = $8; + n->base.inhRelations = NIL; + n->base.if_not_exists = true; + /* FDW-specific data */ +#ifdef ENABLE_MOT + n->servername = pstrdup("mot_server"); +#else + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Foreign server is not specified"))); +#endif + n->options = $9; + + n->write_only = $10; + n->error_relation = (Node*)$11; + if ($12 != NULL) + n->extOptions = lappend(n->extOptions, $12); + if ($13 != NULL) + n->extOptions = lappend(n->extOptions, $13); + n->base.distributeby = $14; +/* PGXC_BEGIN */ + n->base.subcluster = $15; +/* PGXC_END */ + if ($16 != NULL) + n->part_state = $16; + + $$ = (Node *) n; + } +/* ENABLE_MOT END */ + ; + +ForeignTblWritable : WRITE ONLY { $$ = true; } + | READ ONLY { $$ = false; } + | /* EMPTY */ { $$ = false; } + ; + +OptForeignTableElementList: + '(' ForeignTableElementList ')' { $$ = $2; } + | '(' ')' { $$ = NIL; } + ; + +ForeignTableElementList: + ForeignTableElement + { + $$ = list_make1($1); + } + | ForeignTableElementList ',' ForeignTableElement + { + $$ = lappend($1, $3); + } + ; + +ForeignTableElement: + ForeignColDef { $$ = $1; } + |ForeignTableLikeClause { $$ = $1; } + |TableConstraint { $$ = $1; } /* @hdfs Add informational constraint syntax on the HDFS foreign table. */ + ; +ForeignColDef: ColId Typename ForeignPosition create_generic_options ColQualList + { + ColumnDef *n = makeNode(ColumnDef); + n->colname = $1; + n->typname = $2; + n->inhcount = 0; + n->is_local = true; + n->is_not_null = false; + n->is_from_type = false; + n->storage = 0; + n->raw_default = NULL; + n->cooked_default = NULL; + n->collOid = InvalidOid; + n->fdwoptions = $4; + n->clientLogicColumnRef=NULL; + SplitColQualList($5, &n->constraints, &n->collClause, + yyscanner); + if ($3) + { + ((Position*)$3)->colname = pstrdup($1); + n->position = (Position*)$3; + } + $$ = (Node*)n; + } + ; + +ForeignPosition: + POSITION '(' Iconst ',' Iconst ')' + { + Position *n = makeNode(Position); + n->position = $3; + n->fixedlen = $5; + $$ = (Node*)n; + } + | /*EMPTY*/ { $$ = NULL; } + ; + +ForeignTableLikeClause: + LIKE qualified_name + { + TableLikeClause *n = makeNode(TableLikeClause); + n->relation = $2; + $$ = (Node *)n; + } + ; + +OptForeignTableLogError: + LOG_P INTO qualified_name { $$ = (Node*)$3; } + | WITH qualified_name { $$ = (Node*)$2; } + | /*EMPTY*/ { $$ = NULL;} + ; + +OptForeignTableLogRemote: + REMOTE_P LOG_P Sconst + { + $$ = (Node*)makeDefElem("log_remote", (Node *)makeString($3)); + } + |REMOTE_P LOG_P + { + $$ = (Node*)makeDefElem("log_remote", (Node*)makeString("")); + } + | /* EMPTY */ { $$ = NULL; } + ; + +OptPerNodeRejectLimit: + PER_P NODE REJECT_P LIMIT Sconst + { + $$ = (Node*)makeDefElem("reject_limit", (Node*)makeString($5)); + } + | /*EMPTY*/ { $$ = NULL; } + ; + +OptForeignPartBy: + OptForeignPartAuto { $$ = $1; } + | /*EMPTY*/ { $$ = NULL; } + ; + +OptForeignPartAuto: PARTITION BY '(' partition_item_list ')' AUTOMAPPED + { + ForeignPartState *n = makeNode(ForeignPartState); + n->partitionKey = $4; + $$ = n; + } + | PARTITION BY '(' partition_item_list ')' + { + ForeignPartState *n = makeNode(ForeignPartState); + n->partitionKey = $4; + $$ = n; + } + ; + +partition_item_list: + partition_item + { + $$ = list_make1($1); + } + | partition_item_list ',' partition_item + { + $$ = lappend($1, $3); + } + ; + +partition_item: + ColId + { + $$ = makeColumnRef($1, NIL, @1, yyscanner); + } + ; + +/***************************************************************************** + * + * QUERY: + * ALTER FOREIGN TABLE relname [...] + * + *****************************************************************************/ + +AlterForeignTableStmt: + ALTER FOREIGN TABLE relation_expr alter_table_cmds + { + AlterTableStmt *n = makeNode(AlterTableStmt); + n->relation = $4; + n->cmds = $5; + n->relkind = 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->relkind = OBJECT_FOREIGN_TABLE; + n->missing_ok = true; + $$ = (Node *)n; + } + | ALTER FOREIGN TABLE relation_expr MODIFY_P '(' modify_column_cmds ')' + { + AlterTableStmt *n = makeNode(AlterTableStmt); + n->relation = $4; + n->cmds = $7; + n->relkind = OBJECT_FOREIGN_TABLE; + n->missing_ok = false; + $$ = (Node *)n; + } + | ALTER FOREIGN TABLE IF_P EXISTS relation_expr MODIFY_P '(' modify_column_cmds ')' + { + AlterTableStmt *n = makeNode(AlterTableStmt); + n->relation = $6; + n->cmds = $9; + n->relkind = OBJECT_FOREIGN_TABLE; + n->missing_ok = true; + $$ = (Node *)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->username = $5; + n->servername = $7; + n->options = $8; + $$ = (Node *) n; + } + ; + +/* User mapping authorization identifier */ +auth_ident: + CURRENT_USER { $$ = "current_user"; } + | USER { $$ = "current_user"; } + | RoleId { $$ = (strcmp($1, "public") == 0) ? NULL : $1; } + ; + +/***************************************************************************** + * + * QUERY : + * DROP USER MAPPING FOR auth_ident SERVER name + * + ****************************************************************************/ + +DropUserMappingStmt: DROP USER MAPPING FOR auth_ident SERVER name + { + DropUserMappingStmt *n = makeNode(DropUserMappingStmt); + n->username = $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->username = $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->username = $5; + n->servername = $7; + n->options = $8; + $$ = (Node *) n; + } + ; + +/***************************************************************************** + * + * QUERIES For ROW LEVEL SECURITY: + * CREATE [ROW LEVEL SECURITY] POLICY name ON table + * [AS { PERMISSIVE | RESTRICTIVE }] + * [FOR { ALL | SELECT | INSERT | UPDATE | DELETE }] + * [TO role, ...] + * [USING (qual)] + * + * ALTER [ROW LEVEL SECURITY] POLICY name ON table + * [TO role, ...] + * [USING (qual)] + * + * DROP [ROW LEVEL SECURITY] POLIICY [IF EXISTS] name ON table [CASCADE | RESTRICT] + * + *****************************************************************************/ + +CreateRlsPolicyStmt: + CREATE RowLevelSecurityPolicyName ON qualified_name RLSDefaultPermissive + RLSDefaultForCmd RLSDefaultToRole + RLSOptionalUsingExpr + { + /* Did not support INSERT, MERGE yet */ + if (strcmp($6, "insert") == 0 || + strcmp($6, "merge") == 0) + { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("Row Level Security is not yet supported for INSERT and MERGE"))); + } + CreateRlsPolicyStmt *n = makeNode(CreateRlsPolicyStmt); + n->fromExternal = true; + n->policyName = $2; + n->relation = $4; + n->isPermissive = $5; + n->cmdName = $6; + n->roleList = $7; + n->usingQual = $8; + $$ = (Node *) n; + } + ; + +AlterRlsPolicyStmt: + ALTER RowLevelSecurityPolicyName ON qualified_name RLSOptionalToRole + RLSOptionalUsingExpr + { + AlterRlsPolicyStmt *n = makeNode(AlterRlsPolicyStmt); + n->policyName = $2; + n->relation = $4; + n->roleList = $5; + n->usingQual = $6; + $$ = (Node *) n; + } + ; + +DropRlsPolicyStmt: + DROP RowLevelSecurityPolicyName ON any_name opt_drop_behavior + { + DropStmt *n = makeNode(DropStmt); + n->removeType = OBJECT_RLSPOLICY; + n->objects = list_make1(lappend($4, makeString($2))); + n->arguments = NIL; + n->behavior = $5; + n->missing_ok = false; + n->concurrent = false; + $$ = (Node *) n; + } + | DROP POLICY IF_P EXISTS name ON any_name opt_drop_behavior + { + DropStmt *n = makeNode(DropStmt); + n->removeType = OBJECT_RLSPOLICY; + n->objects = list_make1(lappend($7, makeString($5))); + n->arguments = NIL; + n->behavior = $8; + n->missing_ok = true; + n->concurrent = false; + $$ = (Node *) n; + } + | DROP ROW LEVEL SECURITY POLICY IF_P EXISTS name ON any_name opt_drop_behavior + { + DropStmt *n = makeNode(DropStmt); + n->removeType = OBJECT_RLSPOLICY; + n->objects = list_make1(lappend($10, makeString($8))); + n->arguments = NIL; + n->behavior = $11; + n->missing_ok = true; + n->concurrent = false; + $$ = (Node *) n; + } + ; + +RowLevelSecurityPolicyName: + ROW LEVEL SECURITY POLICY name { $$ = $5; } + | POLICY name { $$ = $2; } + +RLSOptionalUsingExpr: + USING '(' a_expr ')' { $$ = $3; } + | /* EMPTY */ { $$ = NULL; } + ; + +RLSDefaultToRole: + TO row_level_security_role_list { $$ = $2; } + | /* EMPTY */ { $$ = list_make1(makeString("public")); } + ; + +RLSOptionalToRole: + TO row_level_security_role_list { $$ = $2; } + | /* EMPTY */ { $$ = NULL; } + ; + +row_level_security_role_list: row_level_security_role + { $$ = list_make1(makeString($1)); } + | row_level_security_role_list ',' row_level_security_role + { $$ = lappend($1, makeString($3)); } + ; + +row_level_security_role: + RoleId { $$ = $1; } + | CURRENT_USER { $$ = pstrdup($1); } + | SESSION_USER { $$ = pstrdup($1); } + ; + +RLSDefaultPermissive: + 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; } + ; + +RLSDefaultForCmd: + FOR row_level_security_cmd { $$ = $2; } + | /* EMPTY */ { $$ = "all"; } + ; + +row_level_security_cmd: + ALL { $$ = "all"; } + | SELECT { $$ = "select"; } + | UPDATE { $$ = "update"; } + | DELETE_P { $$ = "delete"; } + | INSERT { $$ = "insert"; } + | MERGE { $$ = "merge"; } + ; + +/***************************************************************************** + * + * QUERIES: + * CREATE OR REPLACE SYNONYM STATEMENTS + * + *****************************************************************************/ + +CreateSynonymStmt: + CREATE opt_or_replace SYNONYM any_name FOR any_name + { + CreateSynonymStmt *n = makeNode(CreateSynonymStmt); + n->replace = $2; + n->synName = $4; + n->objName = $6; + $$ = (Node *)n; + } + ; + +/***************************************************************************** + * + * QUERIES: + * DROP SYNONYM STATEMENTS + * + *****************************************************************************/ + +DropSynonymStmt: + DROP SYNONYM any_name opt_drop_behavior + { + DropSynonymStmt *n = makeNode(DropSynonymStmt); + n->synName = $3; + n->behavior = $4; + n->missing = false; + $$ = (Node *) n; + } + | DROP SYNONYM IF_P EXISTS any_name opt_drop_behavior + { + DropSynonymStmt *n = makeNode(DropSynonymStmt); + n->synName = $5; + n->behavior = $6; + n->missing = true; + $$ = (Node *) n; + } + ; + + +/***************************************************************************** + * + * QUERY: + * CREATE DATA SOURCE name [TYPE] [VERSION] [OPTIONS] + * + *****************************************************************************/ + +CreateDataSourceStmt: CREATE DATA_P SOURCE_P name opt_data_source_type + opt_data_source_version create_generic_options + { + CreateDataSourceStmt *n = makeNode(CreateDataSourceStmt); + n->srcname = $4; + n->srctype = $5; + n->version = $6; + n->options = $7; + $$ = (Node *) n; + } + ; + +data_source_type: + TYPE_P Sconst { $$ = $2; } + ; + +opt_data_source_type: + data_source_type { $$ = $1; } + | /*EMPTY*/ { $$ = NULL; } + ; + +data_source_version: + VERSION_P Sconst { $$ = $2; } + | VERSION_P NULL_P { $$ = NULL; } + ; + +opt_data_source_version: + data_source_version { $$ = $1; } + | /*EMPTY*/ { $$ = NULL; } + ; + +/***************************************************************************** + * + * QUERY : + * ALTER DATA SOURCE name [TYPE] [VERSION] [OPTIONS] + * + ****************************************************************************/ + +AlterDataSourceStmt: ALTER DATA_P SOURCE_P name data_source_type data_source_version alter_generic_options + { + AlterDataSourceStmt *n = makeNode(AlterDataSourceStmt); + n->srcname = $4; + n->srctype = $5; + n->version = $6; + n->options = $7; + n->has_version = true; + $$ = (Node *) n; + } + | ALTER DATA_P SOURCE_P name data_source_type data_source_version + { + AlterDataSourceStmt *n = makeNode(AlterDataSourceStmt); + n->srcname = $4; + n->srctype = $5; + n->version = $6; + n->has_version = true; + $$ = (Node *) n; + } + | ALTER DATA_P SOURCE_P name data_source_type alter_generic_options + { + AlterDataSourceStmt *n = makeNode(AlterDataSourceStmt); + n->srcname = $4; + n->srctype = $5; + n->options = $6; + n->has_version = false; + $$ = (Node *) n; + } + | ALTER DATA_P SOURCE_P name data_source_version alter_generic_options + { + AlterDataSourceStmt *n = makeNode(AlterDataSourceStmt); + n->srcname = $4; + n->version = $5; + n->options = $6; + n->has_version = true; + $$ = (Node *) n; + } + | ALTER DATA_P SOURCE_P name data_source_type + { + AlterDataSourceStmt *n = makeNode(AlterDataSourceStmt); + n->srcname = $4; + n->srctype = $5; + n->has_version = false; + $$ = (Node *) n; + } + | ALTER DATA_P SOURCE_P name data_source_version + { + AlterDataSourceStmt *n = makeNode(AlterDataSourceStmt); + n->srcname = $4; + n->version = $5; + n->has_version = true; + $$ = (Node *) n; + } + | ALTER DATA_P SOURCE_P name alter_generic_options + { + AlterDataSourceStmt *n = makeNode(AlterDataSourceStmt); + n->srcname = $4; + n->options = $5; + n->has_version = false; + $$ = (Node *) n; + } + ; + +/***************************************************************************** + * + * QUERY : + * DROP DATA SOURCE name + * + ****************************************************************************/ + +DropDataSourceStmt: DROP DATA_P SOURCE_P name opt_drop_behavior + { + DropStmt *n = makeNode(DropStmt); + n->removeType = OBJECT_DATA_SOURCE; + n->objects = list_make1(list_make1(makeString($4))); + n->arguments = NIL; + n->missing_ok = false; + n->behavior = $5; + n->concurrent = false; + $$ = (Node *) n; + } + | DROP DATA_P SOURCE_P IF_P EXISTS name opt_drop_behavior + { + DropStmt *n = makeNode(DropStmt); + n->removeType = OBJECT_DATA_SOURCE; + n->objects = list_make1(list_make1(makeString($6))); + n->arguments = NIL; + n->missing_ok = true; + n->behavior = $7; + n->concurrent = false; + $$ = (Node *) n; + } + ; + +/***************************************************************************** + * + * QUERIES : + * CREATE TRIGGER ... + * DROP TRIGGER ... + * + *****************************************************************************/ + +CreateTrigStmt: + CREATE TRIGGER name TriggerActionTime TriggerEvents ON + qualified_name TriggerForSpec TriggerWhen + EXECUTE PROCEDURE func_name '(' TriggerFuncArgs ')' + { + CreateTrigStmt *n = makeNode(CreateTrigStmt); + n->trigname = $3; + n->relation = $7; + n->funcname = $12; + n->args = $14; + n->row = $8; + n->timing = $4; + n->events = intVal(linitial($5)); + n->columns = (List *) lsecond($5); + n->whenClause = $9; + n->isconstraint = FALSE; + n->deferrable = FALSE; + n->initdeferred = FALSE; + n->constrrel = NULL; + $$ = (Node *)n; + } + | CREATE CONSTRAINT TRIGGER name AFTER TriggerEvents ON + qualified_name OptConstrFromTable ConstraintAttributeSpec + FOR EACH ROW TriggerWhen + EXECUTE PROCEDURE func_name '(' TriggerFuncArgs ')' + { + CreateTrigStmt *n = makeNode(CreateTrigStmt); + n->trigname = $4; + n->relation = $8; + n->funcname = $17; + n->args = $19; + n->row = TRUE; + n->timing = TRIGGER_TYPE_AFTER; + n->events = intVal(linitial($6)); + n->columns = (List *) lsecond($6); + n->whenClause = $14; + n->isconstraint = TRUE; + processCASbits($10, @10, "TRIGGER", + &n->deferrable, &n->initdeferred, NULL, + NULL, yyscanner); + n->constrrel = $9; + $$ = (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); } + ; + +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; } + ; + +TriggerFuncArgs: + TriggerFuncArg { $$ = list_make1($1); } + | TriggerFuncArgs ',' TriggerFuncArg { $$ = lappend($1, $3); } + | /*EMPTY*/ { $$ = NIL; } + ; + +TriggerFuncArg: + Iconst + { + char buf[64]; + snprintf(buf, sizeof(buf), "%d", $1); + $$ = makeString(pstrdup(buf)); + } + | FCONST { $$ = makeString($1); } + | Sconst { $$ = makeString($1); } + | ColLabel { $$ = 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; } + ; + + +DropTrigStmt: + DROP TRIGGER name ON any_name opt_drop_behavior + { + DropStmt *n = makeNode(DropStmt); + n->removeType = OBJECT_TRIGGER; + n->objects = list_make1(lappend($5, makeString($3))); + n->arguments = NIL; + n->behavior = $6; + n->missing_ok = false; + n->concurrent = false; + $$ = (Node *) n; + } + | DROP TRIGGER IF_P EXISTS name ON any_name opt_drop_behavior + { + DropStmt *n = makeNode(DropStmt); + n->removeType = OBJECT_TRIGGER; + n->objects = list_make1(lappend($7, makeString($5))); + n->arguments = NIL; + n->behavior = $8; + n->missing_ok = true; + n->concurrent = false; + $$ = (Node *) n; + } + ; + + +/***************************************************************************** + * + * QUERIES : + * CREATE ASSERTION ... + * DROP ASSERTION ... + * + *****************************************************************************/ + +CreateAssertStmt: + CREATE ASSERTION name CHECK '(' a_expr ')' + ConstraintAttributeSpec + { + CreateTrigStmt *n = makeNode(CreateTrigStmt); + n->trigname = $3; + n->args = list_make1($6); + n->isconstraint = TRUE; + processCASbits($8, @8, "ASSERTION", + &n->deferrable, &n->initdeferred, NULL, + NULL, yyscanner); + + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("CREATE ASSERTION is not yet implemented"))); + + $$ = (Node *)n; + } + ; + +DropAssertStmt: + DROP ASSERTION name opt_drop_behavior + { + DropStmt *n = makeNode(DropStmt); + n->objects = NIL; + n->arguments = NIL; + n->behavior = $4; + n->removeType = OBJECT_TRIGGER; /* XXX */ + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("DROP ASSERTION is not yet implemented"))); + $$ = (Node *) n; + } + ; + + +/***************************************************************************** + * + * QUERY : + * define (aggregate,operator,type) + * + *****************************************************************************/ + +DefineStmt: + CREATE AGGREGATE func_name aggr_args definition + { + DefineStmt *n = makeNode(DefineStmt); + n->kind = OBJECT_AGGREGATE; + n->oldstyle = false; + n->defnames = $3; + n->args = $4; + n->definition = $5; + $$ = (Node *)n; + } + | CREATE 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->defnames = $3; + n->args = NIL; + n->definition = $4; + $$ = (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->typname = $3; + n->vals = $7; + $$ = (Node *)n; + } + | CREATE TYPE_P any_name AS RANGE definition + { + CreateRangeStmt *n = makeNode(CreateRangeStmt); + n->typname = $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 tsconf_definition opt_cfoptions + { + DefineStmt *n = makeNode(DefineStmt); + n->kind = OBJECT_TSCONFIGURATION; + n->args = $7; /* record configuration options */ + 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 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)); + $$ = (Node *)n; + } + ; + +opt_cfoptions: WITH cfoptions { $$ = $2; } + | /* EMPTY */ { $$ = NIL; } + ; + +cfoptions:'(' cfoption_list ')' { $$ = $2; } + ; + +cfoption_list: cfoption_elem { $$ = list_make1($1); } + | cfoption_list ',' cfoption_elem { $$ = lappend($1, $3); } + ; + +cfoption_elem: ColLabel '=' def_arg { $$ = makeDefElem($1, (Node *) $3); } + | ColLabel { $$ = makeDefElem($1, NULL); } + ; + +tsconf_definition: '(' tsconf_def_list ')' { $$ = $2; } + ; + +tsconf_def_list: tsconf_def_elem { $$ = list_make1($1); } + | tsconf_def_list ',' tsconf_def_elem { $$ = lappend($1, $3); } + ; + +tsconf_def_elem: PARSER '=' any_name { $$ = makeDefElem("parser", (Node *) $3); } + | PARSER '=' DEFAULT { $$ = makeDefElem("parser", (Node *) list_make1(makeString("default"))); } + | COPY '=' any_name { $$ = makeDefElem("copy", (Node *) $3); } + ; + +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); + } + | ColLabel + { + $$ = makeDefElem($1, NULL); + } + ; + +/* 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); } + ; + +/* + * aggregate function args. + * (*) - normal agg with no args + * (aggr_arg,...) - normal agg with args + * (ORDER BY type_list,...) - ordered-set agg with no direct args + + */ +aggr_args: '(' type_list ')' { $$ = list_make2($2, makeInteger(-1)); } + | '(' '*' ')' { $$ = list_make2(NIL, makeInteger(-1)); } + | '(' ORDER BY type_list ')' + { + $$ = list_make2($4, makeInteger(0)); + } + ; + +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); + } + ; + +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->typname = $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->typname = $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->typname = $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->typname = $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 access_method 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); + n->itemtype = OPCLASS_ITEM_OPERATOR; + n->name = $3; + n->args = NIL; + n->number = $2; + n->order_family = $4; + $$ = (Node *) n; + } + | OPERATOR Iconst any_operator oper_argtypes opclass_purpose + opt_recheck + { + CreateOpClassItem *n = makeNode(CreateOpClassItem); + n->itemtype = OPCLASS_ITEM_OPERATOR; + n->name = $3; + n->args = $4; + n->number = $2; + n->order_family = $5; + $$ = (Node *) n; + } + | FUNCTION Iconst func_name func_args + { + CreateOpClassItem *n = makeNode(CreateOpClassItem); + n->itemtype = OPCLASS_ITEM_FUNCTION; + n->name = $3; + n->args = extractArgTypes($4); + n->number = $2; + $$ = (Node *) n; + } + | FUNCTION Iconst '(' type_list ')' func_name func_args + { + CreateOpClassItem *n = makeNode(CreateOpClassItem); + n->itemtype = OPCLASS_ITEM_FUNCTION; + n->name = $6; + n->args = extractArgTypes($7); + 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 access_method + { + CreateOpFamilyStmt *n = makeNode(CreateOpFamilyStmt); + n->opfamilyname = $4; + n->amname = $6; + $$ = (Node *) n; + } + ; + +AlterOpFamilyStmt: + ALTER OPERATOR FAMILY any_name USING access_method 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 access_method 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->args = $4; + $$ = (Node *) n; + } + | FUNCTION Iconst '(' type_list ')' + { + CreateOpClassItem *n = makeNode(CreateOpClassItem); + n->itemtype = OPCLASS_ITEM_FUNCTION; + n->number = $2; + n->args = $4; + $$ = (Node *) n; + } + ; + + +DropOpClassStmt: + DROP OPERATOR CLASS any_name USING access_method opt_drop_behavior + { + DropStmt *n = makeNode(DropStmt); + n->objects = list_make1($4); + n->arguments = list_make1(list_make1(makeString($6))); + 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 access_method opt_drop_behavior + { + DropStmt *n = makeNode(DropStmt); + n->objects = list_make1($6); + n->arguments = list_make1(list_make1(makeString($8))); + n->removeType = OBJECT_OPCLASS; + n->behavior = $9; + n->missing_ok = true; + n->concurrent = false; + $$ = (Node *) n; + } + ; + +DropOpFamilyStmt: + DROP OPERATOR FAMILY any_name USING access_method opt_drop_behavior + { + DropStmt *n = makeNode(DropStmt); + n->objects = list_make1($4); + n->arguments = list_make1(list_make1(makeString($6))); + 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 access_method opt_drop_behavior + { + DropStmt *n = makeNode(DropStmt); + n->objects = list_make1($6); + n->arguments = list_make1(list_make1(makeString($8))); + 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 name_list opt_drop_behavior + { + DropOwnedStmt *n = makeNode(DropOwnedStmt); + n->roles = $4; + n->behavior = $5; + $$ = (Node *)n; + } + ; + +ReassignOwnedStmt: + REASSIGN OWNED BY name_list TO name + { + ReassignOwnedStmt *n = makeNode(ReassignOwnedStmt); + n->roles = $4; + n->newrole = $6; + $$ = (Node *)n; + } + ; + +/***************************************************************************** + * + * QUERY: + * + * DROP itemtype [ IF EXISTS ] itemname [, itemname ...] + * [ RESTRICT | CASCADE ] + * + *****************************************************************************/ + +DropStmt: DROP drop_type IF_P EXISTS any_name_list opt_drop_behavior + { + DropStmt *n = makeNode(DropStmt); + n->removeType = $2; + n->missing_ok = TRUE; + n->objects = $5; + n->arguments = NIL; + n->behavior = $6; + n->concurrent = false; + $$ = (Node *)n; + } + | DROP drop_type any_name_list opt_drop_behavior + { + DropStmt *n = makeNode(DropStmt); + n->removeType = $2; + n->missing_ok = FALSE; + n->objects = $3; + n->arguments = NIL; + n->behavior = $4; + 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->arguments = NIL; + 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->arguments = NIL; + n->behavior = $7; + n->concurrent = true; + $$ = (Node *)n; + } + ; + + +drop_type: TABLE { $$ = OBJECT_TABLE; } + | CONTVIEW { $$ = OBJECT_CONTQUERY; } + | STREAM { $$ = OBJECT_STREAM; } + | SEQUENCE { $$ = OBJECT_SEQUENCE; } + | VIEW { $$ = OBJECT_VIEW; } + | MATERIALIZED VIEW { $$ = OBJECT_MATVIEW; } + | INDEX { $$ = OBJECT_INDEX; } + | FOREIGN TABLE { $$ = OBJECT_FOREIGN_TABLE; } + | TYPE_P { $$ = OBJECT_TYPE; } + | DOMAIN_P { $$ = OBJECT_DOMAIN; } + | COLLATION { $$ = OBJECT_COLLATION; } + | CONVERSION_P { $$ = OBJECT_CONVERSION; } + | SCHEMA { $$ = OBJECT_SCHEMA; } + | EXTENSION { $$ = OBJECT_EXTENSION; } + | TEXT_P SEARCH PARSER { $$ = OBJECT_TSPARSER; } + | TEXT_P SEARCH DICTIONARY { $$ = OBJECT_TSDICTIONARY; } + | TEXT_P SEARCH TEMPLATE { $$ = OBJECT_TSTEMPLATE; } + | TEXT_P SEARCH CONFIGURATION { $$ = OBJECT_TSCONFIGURATION; } + | CLIENT MASTER KEY { $$ = OBJECT_GLOBAL_SETTING; } + | COLUMN ENCRYPTION KEY { $$ = OBJECT_COLUMN_SETTING; } + ; + +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)); } + ; + + +/***************************************************************************** + * + * 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; } + ; + +/***************************************************************************** + * + * The COMMENT ON statement can take different forms based upon the type of + * the object associated with the comment. The form of the statement is: + * + * COMMENT ON [ [ DATABASE | DOMAIN | INDEX | SEQUENCE | TABLE | TYPE | VIEW | + * COLLATION | CONVERSION | LANGUAGE | OPERATOR CLASS | + * LARGE OBJECT | CAST | COLUMN | SCHEMA | TABLESPACE | + * EXTENSION | ROLE | TEXT SEARCH PARSER | + * TEXT SEARCH DICTIONARY | TEXT SEARCH TEMPLATE | + * TEXT SEARCH CONFIGURATION | FOREIGN TABLE | + * FOREIGN DATA WRAPPER | SERVER | EVENT TRIGGER | + MATERIALIZED VIEW] | + * AGGREGATE (arg1, ...) | + * FUNCTION (arg1, arg2, ...) | + * OPERATOR (leftoperand_typ, rightoperand_typ) | + * TRIGGER ON | + * CONSTRAINT ON | + * RULE ON ] + * IS 'text' + * + *****************************************************************************/ + +CommentStmt: + COMMENT ON comment_type any_name IS comment_text + { + CommentStmt *n = makeNode(CommentStmt); + n->objtype = $3; + n->objname = $4; + n->objargs = NIL; + n->comment = $6; + $$ = (Node *) n; + } + | COMMENT ON AGGREGATE func_name aggr_args IS comment_text + { + CommentStmt *n = makeNode(CommentStmt); + n->objtype = OBJECT_AGGREGATE; + n->objname = $4; + n->objargs = $5; + n->comment = $7; + $$ = (Node *) n; + } + | COMMENT ON FUNCTION func_name func_args IS comment_text + { + CommentStmt *n = makeNode(CommentStmt); + n->objtype = OBJECT_FUNCTION; + n->objname = $4; + n->objargs = extractArgTypes($5); + n->comment = $7; + $$ = (Node *) n; + } + | COMMENT ON OPERATOR any_operator oper_argtypes IS comment_text + { + CommentStmt *n = makeNode(CommentStmt); + n->objtype = OBJECT_OPERATOR; + n->objname = $4; + n->objargs = $5; + n->comment = $7; + $$ = (Node *) n; + } + | COMMENT ON CONSTRAINT name ON any_name IS comment_text + { + CommentStmt *n = makeNode(CommentStmt); + n->objtype = OBJECT_CONSTRAINT; + n->objname = lappend($6, makeString($4)); + n->objargs = NIL; + n->comment = $8; + $$ = (Node *) n; + } + | COMMENT ON RULE name ON any_name IS comment_text + { + CommentStmt *n = makeNode(CommentStmt); + n->objtype = OBJECT_RULE; + n->objname = lappend($6, makeString($4)); + n->objargs = NIL; + n->comment = $8; + $$ = (Node *) n; + } + | COMMENT ON RULE name IS comment_text + { + /* Obsolete syntax supported for awhile for compatibility */ + CommentStmt *n = makeNode(CommentStmt); + n->objtype = OBJECT_RULE; + n->objname = list_make1(makeString($4)); + n->objargs = NIL; + n->comment = $6; + $$ = (Node *) n; + } + | COMMENT ON TRIGGER name ON any_name IS comment_text + { + CommentStmt *n = makeNode(CommentStmt); + n->objtype = OBJECT_TRIGGER; + n->objname = lappend($6, makeString($4)); + n->objargs = NIL; + n->comment = $8; + $$ = (Node *) n; + } + | COMMENT ON OPERATOR CLASS any_name USING access_method IS comment_text + { + CommentStmt *n = makeNode(CommentStmt); + n->objtype = OBJECT_OPCLASS; + n->objname = $5; + n->objargs = list_make1(makeString($7)); + n->comment = $9; + $$ = (Node *) n; + } + | COMMENT ON OPERATOR FAMILY any_name USING access_method IS comment_text + { + CommentStmt *n = makeNode(CommentStmt); + n->objtype = OBJECT_OPFAMILY; + n->objname = $5; + n->objargs = list_make1(makeString($7)); + n->comment = $9; + $$ = (Node *) n; + } + | COMMENT ON LARGE_P OBJECT_P NumericOnly IS comment_text + { + CommentStmt *n = makeNode(CommentStmt); + n->objtype = OBJECT_LARGEOBJECT; + n->objname = list_make1($5); + n->objargs = NIL; + n->comment = $7; + $$ = (Node *) n; + } + | COMMENT ON CAST '(' Typename AS Typename ')' IS comment_text + { + CommentStmt *n = makeNode(CommentStmt); + n->objtype = OBJECT_CAST; + n->objname = list_make1($5); + n->objargs = list_make1($7); + n->comment = $10; + $$ = (Node *) n; + } + | COMMENT ON opt_procedural LANGUAGE any_name IS comment_text + { + CommentStmt *n = makeNode(CommentStmt); + n->objtype = OBJECT_LANGUAGE; + n->objname = $5; + n->objargs = NIL; + n->comment = $7; + $$ = (Node *) n; + } + | COMMENT ON TEXT_P SEARCH PARSER any_name IS comment_text + { + CommentStmt *n = makeNode(CommentStmt); + n->objtype = OBJECT_TSPARSER; + n->objname = $6; + n->comment = $8; + $$ = (Node *) n; + } + | COMMENT ON TEXT_P SEARCH DICTIONARY any_name IS comment_text + { + CommentStmt *n = makeNode(CommentStmt); + n->objtype = OBJECT_TSDICTIONARY; + n->objname = $6; + n->comment = $8; + $$ = (Node *) n; + } + | COMMENT ON TEXT_P SEARCH TEMPLATE any_name IS comment_text + { + CommentStmt *n = makeNode(CommentStmt); + n->objtype = OBJECT_TSTEMPLATE; + n->objname = $6; + n->comment = $8; + $$ = (Node *) n; + } + | COMMENT ON TEXT_P SEARCH CONFIGURATION any_name IS comment_text + { + CommentStmt *n = makeNode(CommentStmt); + n->objtype = OBJECT_TSCONFIGURATION; + n->objname = $6; + n->comment = $8; + $$ = (Node *) n; + } + ; + +comment_type: + COLUMN { $$ = OBJECT_COLUMN; } + | DATABASE { $$ = OBJECT_DATABASE; } + | SCHEMA { $$ = OBJECT_SCHEMA; } + | INDEX { $$ = OBJECT_INDEX; } + | SEQUENCE { $$ = OBJECT_SEQUENCE; } + | TABLE { $$ = OBJECT_TABLE; } + | DOMAIN_P { $$ = OBJECT_DOMAIN; } + | TYPE_P { $$ = OBJECT_TYPE; } + | VIEW { $$ = OBJECT_VIEW; } + | MATERIALIZED VIEW { $$ = OBJECT_MATVIEW; } + | COLLATION { $$ = OBJECT_COLLATION; } + | CONVERSION_P { $$ = OBJECT_CONVERSION; } + | TABLESPACE { $$ = OBJECT_TABLESPACE; } + | EXTENSION { $$ = OBJECT_EXTENSION; } + | ROLE { $$ = OBJECT_ROLE; } + | USER { $$ = OBJECT_USER; } + | FOREIGN TABLE { $$ = OBJECT_FOREIGN_TABLE; } + | SERVER { $$ = OBJECT_FOREIGN_SERVER; } + | FOREIGN DATA_P WRAPPER { $$ = OBJECT_FDW; } + ; + +comment_text: + Sconst { $$ = $1; } + | NULL_P { $$ = NULL; } + ; + + +/***************************************************************************** + * + * SECURITY LABEL [FOR ] ON IS