* gram.y
* POSTGRESQL BISON rules/actions
*
- * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.671 2009/07/20 02:42:28 adunstan Exp $
+ * src/backend/parser/gram.y
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
(Current) = (Rhs)[0]; \
} while (0)
-/*
- * The %name-prefix option below will make bison call base_yylex, but we
- * really want it to call filtered_base_yylex (see parser.c).
- */
-#define base_yylex filtered_base_yylex
-
/*
* 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
/* Private struct for the result of privilege_target production */
typedef struct PrivTarget
{
+ GrantTargetType targtype;
GrantObjectType objtype;
List *objs;
} PrivTarget;
#define parser_yyerror(msg) scanner_yyerror(msg, yyscanner)
#define parser_errposition(pos) scanner_errposition(pos, yyscanner)
-static void base_yyerror(YYLTYPE *yylloc, base_yyscan_t yyscanner,
+static void base_yyerror(YYLTYPE *yylloc, core_yyscan_t yyscanner,
const char *msg);
static Node *makeColumnRef(char *colname, List *indirection,
- int location, base_yyscan_t yyscanner);
+ int location, core_yyscan_t yyscanner);
static Node *makeTypeCast(Node *arg, TypeName *typename, int location);
static Node *makeStringConst(char *str, int location);
static Node *makeStringConstCast(char *str, int location, TypeName *typename);
static Node *makeAConst(Value *v, int location);
static Node *makeBoolAConst(bool state, int location);
static FuncCall *makeOverlaps(List *largs, List *rargs,
- int location, base_yyscan_t yyscanner);
-static void check_qualified_name(List *names, base_yyscan_t yyscanner);
-static List *check_func_name(List *names, base_yyscan_t yyscanner);
-static List *check_indirection(List *indirection, base_yyscan_t yyscanner);
+ int location, core_yyscan_t yyscanner);
+static void check_qualified_name(List *names, core_yyscan_t yyscanner);
+static List *check_func_name(List *names, core_yyscan_t yyscanner);
+static List *check_indirection(List *indirection, core_yyscan_t yyscanner);
static List *extractArgTypes(List *parameters);
static SelectStmt *findLeftmostSelect(SelectStmt *node);
static void insertSelectOptions(SelectStmt *stmt,
List *sortClause, List *lockingClause,
Node *limitOffset, Node *limitCount,
WithClause *withClause,
- base_yyscan_t yyscanner);
+ 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);
List *args, int location);
static List *mergeTableFuncParameters(List *func_args, List *columns);
static TypeName *TableFuncTypeName(List *columns);
+static RangeVar *makeRangeVarFromAnyName(List *names, int position, core_yyscan_t yyscanner);
%}
%name-prefix="base_yy"
%locations
-%parse-param {base_yyscan_t yyscanner}
-%lex-param {base_yyscan_t yyscanner}
+%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 chr;
char *str;
const char *keyword;
+
+ char chr;
bool boolean;
JoinType jtype;
DropBehavior dbehavior;
Node *node;
Value *value;
ObjectType objtype;
-
TypeName *typnam;
FunctionParameter *fun_param;
FunctionParameterMode fun_param_mode;
ResTarget *target;
struct PrivTarget *privtarget;
AccessPriv *accesspriv;
-
InsertStmt *istmt;
VariableSetStmt *vsetstmt;
}
AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterFdwStmt
AlterForeignServerStmt AlterGroupStmt
AlterObjectSchemaStmt AlterOwnerStmt AlterSeqStmt AlterTableStmt
- AlterUserStmt AlterUserMappingStmt AlterUserSetStmt AlterRoleStmt AlterRoleSetStmt
+ AlterCompositeTypeStmt AlterUserStmt AlterUserMappingStmt AlterUserSetStmt
+ AlterRoleStmt AlterRoleSetStmt
+ AlterDefaultPrivilegesStmt DefACLAction
AnalyzeStmt ClosePortalStmt ClusterStmt CommentStmt
ConstraintsSetStmt CopyStmt CreateAsStmt CreateCastStmt
CreateDomainStmt CreateGroupStmt CreateOpClassStmt
CreateSchemaStmt CreateSeqStmt CreateStmt CreateTableSpaceStmt
CreateFdwStmt CreateForeignServerStmt CreateAssertStmt CreateTrigStmt
CreateUserStmt CreateUserMappingStmt CreateRoleStmt
- CreatedbStmt DeclareCursorStmt DefineStmt DeleteStmt DiscardStmt
+ CreatedbStmt DeclareCursorStmt DefineStmt DeleteStmt DiscardStmt DoStmt
DropGroupStmt DropOpClassStmt DropOpFamilyStmt DropPLangStmt DropStmt
DropAssertStmt DropTrigStmt DropRuleStmt DropCastStmt DropRoleStmt
DropUserStmt DropdbStmt DropTableSpaceStmt DropFdwStmt
CreateFunctionStmt AlterFunctionStmt ReindexStmt RemoveAggrStmt
RemoveFuncStmt RemoveOperStmt RenameStmt RevokeStmt RevokeRoleStmt
RuleActionStmt RuleActionStmtOrEmpty RuleStmt
- SelectStmt TransactionStmt TruncateStmt
+ SecLabelStmt SelectStmt TransactionStmt TruncateStmt
UnlistenStmt UpdateStmt VacuumStmt
VariableResetStmt VariableSetStmt VariableShowStmt
ViewStmt CheckPointStmt CreateConversionStmt
%type <node> alter_column_default opclass_item opclass_drop alter_using
%type <ival> add_drop opt_asc_desc opt_nulls_order
-%type <node> alter_table_cmd
-%type <list> alter_table_cmds
+%type <node> alter_table_cmd alter_type_cmd
+%type <list> alter_table_cmds alter_type_cmds
%type <dbehavior> opt_drop_behavior
transaction_mode_item
%type <ival> opt_lock lock_type cast_context
+%type <ival> vacuum_option_list vacuum_option_elem
%type <boolean> opt_force opt_or_replace
opt_grant_grant_option opt_grant_admin_option
opt_nowait opt_if_exists opt_with_data
-%type <list> OptRoleList
-%type <defelt> OptRoleElem
+%type <list> OptRoleList AlterOptRoleList
+%type <defelt> CreateOptRoleElem AlterOptRoleElem
%type <str> opt_type
%type <str> foreign_server_version opt_foreign_server_version
%type <str> auth_ident
+%type <str> opt_in_database
%type <str> OptSchemaName
%type <list> OptSchemaEltList
-%type <boolean> TriggerActionTime TriggerForSpec opt_trusted opt_restart_seqs
-%type <str> opt_lancompiler
-
-%type <ival> TriggerEvents TriggerOneEvent
+%type <boolean> TriggerForSpec TriggerForType
+%type <ival> TriggerActionTime
+%type <list> TriggerEvents TriggerOneEvent
%type <value> TriggerFuncArg
+%type <node> TriggerWhen
-%type <str> relation_name copy_file_name
+%type <str> copy_file_name
database_name access_method_clause access_method attr_name
- index_name name file_name cluster_index_specification
+ name cursor_name file_name
+ index_name opt_index_name cluster_index_specification
%type <list> func_name handler_name qual_Op qual_all_Op subquery_Op
- opt_class opt_validator validator_clause
+ opt_class opt_inline_handler opt_validator validator_clause
%type <range> qualified_name OptConstrFromTable
-%type <str> all_Op MathOp SpecialRuleRelation
+%type <str> all_Op MathOp
%type <str> iso_level opt_encoding
%type <node> grantee
%type <privtarget> privilege_target
%type <funwithargs> function_with_argtypes
%type <list> function_with_argtypes_list
+%type <ival> defacl_privilege_target
+%type <defelt> DefACLOption
+%type <list> DefACLOptionList
%type <list> stmtblock stmtmulti
OptTableElementList TableElementList OptInherit definition
+ OptTypedTableElementList TypedTableElementList
reloptions opt_reloptions
OptWith opt_distinct opt_definition func_args func_args_list
func_args_with_defaults func_args_with_defaults_list
reloption_list group_clause TriggerFuncArgs select_limit
opt_select_limit opclass_item_list opclass_drop_list
opt_opfamily transaction_mode_list_or_empty
- TableFuncElementList opt_type_modifiers
+ OptTableFuncElementList TableFuncElementList opt_type_modifiers
prep_type_clause
execute_param_clause using_clause returning_clause
- enum_val_list table_func_column_list
+ opt_enum_val_list enum_val_list table_func_column_list
create_generic_options alter_generic_options
- relation_expr_list
+ relation_expr_list dostmt_opt_list
%type <range> OptTempTableName
%type <into> into_clause create_as_target
-%type <defelt> createfunc_opt_item common_func_opt_item
+%type <defelt> createfunc_opt_item common_func_opt_item dostmt_opt_item
%type <fun_param> func_arg func_arg_with_default table_func_column
%type <fun_param_mode> arg_class
%type <typnam> func_return func_type
-%type <boolean> TriggerForType OptTemp
+%type <boolean> OptTemp opt_trusted opt_restart_seqs
%type <oncommit> OnCommitOption
%type <node> for_locking_item
%type <list> opt_interval interval_second
%type <node> overlay_placing substr_from substr_for
-%type <boolean> opt_instead opt_analyze
-%type <boolean> index_opt_unique opt_verbose opt_full
+%type <boolean> opt_instead
+%type <boolean> opt_unique opt_concurrently opt_verbose opt_full
%type <boolean> opt_freeze opt_default opt_recheck
%type <defelt> opt_binary opt_oids copy_delimiter
%type <boolean> copy_from
%type <ival> opt_column event cursor_options opt_hold opt_set_data
-%type <objtype> reindex_type drop_type comment_type
+%type <objtype> reindex_type drop_type comment_type security_label_type
-%type <node> fetch_direction select_limit_value select_offset_value
+%type <node> fetch_args limit_clause select_limit_value
+ offset_clause select_offset_value
select_offset_value2 opt_select_fetch_first_value
%type <ival> row_or_rows first_or_next
%type <vsetstmt> set_rest SetResetClause
-%type <node> TableElement ConstraintElem TableFuncElement
-%type <node> columnDef
+%type <node> TableElement TypedTableElement ConstraintElem TableFuncElement
+%type <node> columnDef columnOptions
%type <defelt> def_elem reloption_elem old_aggr_elem
%type <node> def_arg columnElem where_clause where_or_current_clause
a_expr b_expr c_expr func_expr AexprConst indirection_el
columnref in_expr having_clause func_table array_expr
+ ExclusionWhereClause
+%type <list> ExclusionConstraintList ExclusionConstraintElem
+%type <list> func_arg_list
+%type <node> func_arg_expr
%type <list> row type_list array_expr_list
%type <node> case_expr case_arg when_clause case_default
%type <list> when_clause_list
%type <list> OptCreateAs CreateAsList
%type <node> CreateAsElement ctext_expr
%type <value> NumericOnly
+%type <list> NumericOnly_list
%type <alias> alias_clause
%type <sortby> sortby
%type <ielem> index_elem
%type <node> generic_option_arg
%type <defelt> generic_option_elem alter_generic_option_elem
%type <list> generic_option_list alter_generic_option_list
+%type <str> explain_option_name
+%type <node> explain_option_arg
+%type <defelt> explain_option_elem
+%type <list> explain_option_list
+%type <node> copy_generic_opt_arg copy_generic_opt_arg_list_item
+%type <defelt> copy_generic_opt_elem
+%type <list> copy_generic_opt_list copy_generic_opt_arg_list
+%type <list> copy_options
%type <typnam> Typename SimpleTypename ConstTypename
GenericType Numeric opt_float
%type <boolean> opt_varying opt_timezone
%type <ival> Iconst SignedIconst
-%type <str> Sconst comment_text
+%type <str> Sconst comment_text notify_payload
%type <str> RoleId opt_granted_by opt_boolean ColId_or_Sconst
%type <list> var_list
%type <str> ColId ColLabel var_name type_function_name param_name
%type <keyword> col_name_keyword reserved_keyword
%type <node> TableConstraint TableLikeClause
-%type <list> TableLikeOptionList
-%type <ival> TableLikeOption
+%type <ival> TableLikeOptionList TableLikeOption
%type <list> ColQualList
%type <node> ColConstraint ColConstraintElem ConstraintAttr
%type <ival> key_actions key_delete key_match key_update key_action
%type <str> OptTableSpace OptConsTableSpace OptTableSpaceOwner
%type <list> opt_check_option
+%type <str> opt_provider security_label
+
%type <target> xml_attribute_el
%type <list> xml_attribute_list xml_attributes
%type <node> xml_root_version opt_xml_root_standalone
+%type <node> xmlexists_argument
%type <ival> document_or_content
%type <boolean> xml_whitespace_option
%type <node> common_table_expr
-%type <with> with_clause
+%type <with> with_clause opt_with_clause
%type <list> cte_list
%type <list> window_clause window_definition_list opt_partition_clause
%type <windef> window_definition over_clause window_specification
+ opt_frame_clause frame_extent frame_bound
%type <str> opt_existing_window_name
-%type <ival> opt_frame_clause frame_extent frame_bound
/*
* the set of keywords. PL/pgsql depends on this so that it can share the
* same lexer. If you add/change tokens here, fix PL/pgsql to match!
*
- * DOT_DOT and COLON_EQUALS are unused in the core SQL grammar, and so will
- * always provoke parse errors. They are needed by PL/pgsql.
+ * DOT_DOT is unused in the core SQL grammar, and so will always provoke
+ * parse errors. It is needed by PL/pgsql.
*/
%token <str> IDENT FCONST SCONST BCONST XCONST Op
%token <ival> ICONST PARAM
/* ordinary key words in alphabetical order */
%token <keyword> ABORT_P ABSOLUTE_P ACCESS ACTION ADD_P ADMIN AFTER
AGGREGATE ALL ALSO ALTER ALWAYS ANALYSE ANALYZE AND ANY ARRAY AS ASC
- ASSERTION ASSIGNMENT ASYMMETRIC AT AUTHORIZATION
+ ASSERTION ASSIGNMENT ASYMMETRIC AT ATTRIBUTE AUTHORIZATION
BACKWARD BEFORE BEGIN_P BETWEEN BIGINT BINARY BIT
BOOLEAN_P BOTH BY
CACHE CALLED CASCADE CASCADED CASE CAST CATALOG_P CHAIN CHAR_P
CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLOSE
- CLUSTER COALESCE COLLATE COLUMN COMMENT COMMIT
+ CLUSTER COALESCE COLLATE COLUMN COMMENT COMMENTS COMMIT
COMMITTED CONCURRENTLY CONFIGURATION CONNECTION CONSTRAINT CONSTRAINTS
CONTENT_P CONTINUE_P CONVERSION_P COPY COST CREATE CREATEDB
CREATEROLE CREATEUSER CROSS CSV CURRENT_P
DICTIONARY DISABLE_P DISCARD DISTINCT DO DOCUMENT_P DOMAIN_P DOUBLE_P DROP
EACH ELSE ENABLE_P ENCODING ENCRYPTED END_P ENUM_P ESCAPE EXCEPT
- EXCLUDING EXCLUSIVE EXECUTE EXISTS EXPLAIN EXTERNAL EXTRACT
+ EXCLUDE EXCLUDING EXCLUSIVE EXECUTE EXISTS EXPLAIN EXTERNAL EXTRACT
FALSE_P FAMILY FETCH FIRST_P FLOAT_P FOLLOWING FOR FORCE FOREIGN FORWARD
- FREEZE FROM FULL FUNCTION
+ FREEZE FROM FULL FUNCTION FUNCTIONS
GLOBAL GRANT GRANTED GREATEST GROUP_P
HANDLER HAVING HEADER_P HOLD HOUR_P
IDENTITY_P IF_P ILIKE IMMEDIATE IMMUTABLE IMPLICIT_P IN_P
- INCLUDING INCREMENT INDEX INDEXES INHERIT INHERITS INITIALLY
+ INCLUDING INCREMENT INDEX INDEXES INHERIT INHERITS INITIALLY INLINE_P
INNER_P INOUT INPUT_P INSENSITIVE INSERT INSTEAD INT_P INTEGER
INTERSECT INTERVAL INTO INVOKER IS ISNULL ISOLATION
KEY
- LANCOMPILER LANGUAGE LARGE_P LAST_P LC_COLLATE_P LC_CTYPE_P LEADING
+ LABEL LANGUAGE LARGE_P LAST_P LC_COLLATE_P LC_CTYPE_P LEADING
LEAST LEFT LEVEL LIKE LIMIT LISTEN LOAD LOCAL LOCALTIME LOCALTIMESTAMP
LOCATION LOCK_P LOGIN_P
MAPPING MATCH MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE
- NAME_P NAMES NATIONAL NATURAL NCHAR NEW NEXT NO NOCREATEDB
+ NAME_P NAMES NATIONAL NATURAL NCHAR NEXT NO NOCREATEDB
NOCREATEROLE NOCREATEUSER NOINHERIT NOLOGIN_P NONE NOSUPERUSER
NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF NULLS_P NUMERIC
- OBJECT_P OF OFF OFFSET OIDS OLD ON ONLY OPERATOR OPTION OPTIONS OR
+ OBJECT_P OF OFF OFFSET OIDS ON ONLY OPERATOR OPTION OPTIONS OR
ORDER OUT_P OUTER_P OVER OVERLAPS OVERLAY OWNED OWNER
- PARSER PARTIAL PARTITION PASSWORD PLACING PLANS POSITION
+ PARSER PARTIAL PARTITION PASSING PASSWORD PLACING PLANS POSITION
PRECEDING PRECISION PRESERVE PREPARE PREPARED PRIMARY
PRIOR PRIVILEGES PROCEDURAL PROCEDURE
QUOTE
- RANGE READ REAL REASSIGN RECHECK RECURSIVE REFERENCES REINDEX
+ RANGE READ REAL REASSIGN RECHECK RECURSIVE REF REFERENCES REINDEX
RELATIVE_P RELEASE RENAME REPEATABLE REPLACE REPLICA RESET RESTART
RESTRICT RETURNING RETURNS REVOKE RIGHT ROLE ROLLBACK ROW ROWS RULE
- SAVEPOINT SCHEMA SCROLL SEARCH SECOND_P SECURITY SELECT SEQUENCE
+ SAVEPOINT SCHEMA SCROLL SEARCH SECOND_P SECURITY SELECT SEQUENCE SEQUENCES
SERIALIZABLE SERVER SESSION SESSION_USER SET SETOF SHARE
SHOW SIMILAR SIMPLE SMALLINT SOME STABLE STANDALONE_P START STATEMENT
STATISTICS STDIN STDOUT STORAGE STRICT_P STRIP_P SUBSTRING SUPERUSER_P
SYMMETRIC SYSID SYSTEM_P
- TABLE TABLESPACE TEMP TEMPLATE TEMPORARY TEXT_P THEN TIME TIMESTAMP
+ TABLE TABLES TABLESPACE TEMP TEMPLATE TEMPORARY TEXT_P THEN TIME TIMESTAMP
TO TRAILING TRANSACTION TREAT TRIGGER TRIM TRUE_P
TRUNCATE TRUSTED TYPE_P
WHEN WHERE WHITESPACE_P WINDOW WITH WITHOUT WORK WRAPPER WRITE
- XML_P XMLATTRIBUTES XMLCONCAT XMLELEMENT XMLFOREST XMLPARSE
+ XML_P XMLATTRIBUTES XMLCONCAT XMLELEMENT XMLEXISTS XMLFOREST XMLPARSE
XMLPI XMLROOT XMLSERIALIZE
YEAR_P YES_P
* RANGE, ROWS to support opt_existing_window_name; and for RANGE, ROWS
* so that they can follow a_expr without creating
* postfix-operator problems.
+ *
+ * The frame_bound productions UNBOUNDED PRECEDING and UNBOUNDED FOLLOWING
+ * are even messier: since UNBOUNDED is an unreserved keyword (per spec!),
+ * there is no principled way to distinguish these from the productions
+ * a_expr PRECEDING/FOLLOWING. We hack this up by giving UNBOUNDED slightly
+ * lower precedence than PRECEDING and FOLLOWING. At present this doesn't
+ * appear to cause UNBOUNDED to be treated differently from other unreserved
+ * keywords anywhere else in the grammar, but it's definitely risky. We can
+ * blame any funny behavior of UNBOUNDED on the SQL standard, though.
*/
-%nonassoc IDENT PARTITION RANGE ROWS
+%nonassoc UNBOUNDED /* ideally should have same precedence as IDENT */
+%nonassoc IDENT PARTITION RANGE ROWS PRECEDING FOLLOWING
%left Op OPERATOR /* multi-character ops and user-defined operators */
%nonassoc NOTNULL
%nonassoc ISNULL
%left JOIN CROSS LEFT FULL RIGHT INNER_P NATURAL
/* kluge to keep xml_whitespace_option from causing shift/reduce conflicts */
%right PRESERVE STRIP_P
+
%%
/*
stmt :
AlterDatabaseStmt
| AlterDatabaseSetStmt
+ | AlterDefaultPrivilegesStmt
| AlterDomainStmt
| AlterFdwStmt
| AlterForeignServerStmt
| AlterOwnerStmt
| AlterSeqStmt
| AlterTableStmt
+ | AlterCompositeTypeStmt
| AlterRoleSetStmt
| AlterRoleStmt
| AlterTSConfigurationStmt
| DefineStmt
| DeleteStmt
| DiscardStmt
+ | DoStmt
| DropAssertStmt
| DropCastStmt
| DropFdwStmt
| RevokeStmt
| RevokeRoleStmt
| RuleStmt
+ | SecLabelStmt
| SelectStmt
| TransactionStmt
| TruncateStmt
* is "WITH ADMIN name".
*/
OptRoleList:
- OptRoleList OptRoleElem { $$ = lappend($1, $2); }
+ OptRoleList CreateOptRoleElem { $$ = lappend($1, $2); }
+ | /* EMPTY */ { $$ = NIL; }
+ ;
+
+AlterOptRoleList:
+ AlterOptRoleList AlterOptRoleElem { $$ = lappend($1, $2); }
| /* EMPTY */ { $$ = NIL; }
;
-OptRoleElem:
+AlterOptRoleElem:
PASSWORD Sconst
{
$$ = makeDefElem("password",
{
$$ = makeDefElem("rolemembers", (Node *)$2);
}
- /* The following are not supported by ALTER ROLE/USER/GROUP */
+ ;
+
+CreateOptRoleElem:
+ AlterOptRoleElem { $$ = $1; }
+ /* The following are not supported by ALTER ROLE/USER/GROUP */
| SYSID Iconst
{
$$ = makeDefElem("sysid", (Node *)makeInteger($2));
*****************************************************************************/
AlterRoleStmt:
- ALTER ROLE RoleId opt_with OptRoleList
+ ALTER ROLE RoleId opt_with AlterOptRoleList
{
AlterRoleStmt *n = makeNode(AlterRoleStmt);
n->role = $3;
}
;
+opt_in_database:
+ /* EMPTY */ { $$ = NULL; }
+ | IN_P DATABASE database_name { $$ = $3; }
+ ;
+
AlterRoleSetStmt:
- ALTER ROLE RoleId SetResetClause
+ ALTER ROLE RoleId opt_in_database SetResetClause
{
AlterRoleSetStmt *n = makeNode(AlterRoleSetStmt);
n->role = $3;
- n->setstmt = $4;
+ n->database = $4;
+ n->setstmt = $5;
$$ = (Node *)n;
}
;
*****************************************************************************/
AlterUserStmt:
- ALTER USER RoleId opt_with OptRoleList
+ ALTER USER RoleId opt_with AlterOptRoleList
{
AlterRoleStmt *n = makeNode(AlterRoleStmt);
n->role = $3;
{
AlterRoleSetStmt *n = makeNode(AlterRoleSetStmt);
n->role = $3;
+ n->database = NULL;
n->setstmt = $4;
$$ = (Node *)n;
}
;
alter_table_cmd:
- /* ALTER TABLE <name> ADD [COLUMN] <coldef> */
- ADD_P opt_column columnDef
+ /* ALTER TABLE <name> ADD <coldef> */
+ ADD_P columnDef
+ {
+ AlterTableCmd *n = makeNode(AlterTableCmd);
+ n->subtype = AT_AddColumn;
+ n->def = $2;
+ $$ = (Node *)n;
+ }
+ /* ALTER TABLE <name> ADD COLUMN <coldef> */
+ | ADD_P COLUMN columnDef
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_AddColumn;
n->def = (Node *) makeInteger($6);
$$ = (Node *)n;
}
+ /* ALTER TABLE <name> ALTER [COLUMN] <colname> SET ( column_parameter = value [, ... ] ) */
+ | ALTER opt_column ColId SET reloptions
+ {
+ AlterTableCmd *n = makeNode(AlterTableCmd);
+ n->subtype = AT_SetOptions;
+ n->name = $3;
+ n->def = (Node *) $5;
+ $$ = (Node *)n;
+ }
+ /* ALTER TABLE <name> ALTER [COLUMN] <colname> SET ( column_parameter = value [, ... ] ) */
+ | ALTER opt_column ColId RESET reloptions
+ {
+ AlterTableCmd *n = makeNode(AlterTableCmd);
+ n->subtype = AT_ResetOptions;
+ n->name = $3;
+ n->def = (Node *) $5;
+ $$ = (Node *)n;
+ }
/* ALTER TABLE <name> ALTER [COLUMN] <colname> SET STORAGE <storagemode> */
| ALTER opt_column ColId SET STORAGE ColId
{
;
/* This should match def_elem and also allow qualified names */
-reloption_elem:
+reloption_elem:
ColLabel '=' def_arg
{
$$ = makeDefElem($1, (Node *) $3);
;
+/*****************************************************************************
+ *
+ * ALTER TYPE
+ *
+ * really variants of the ALTER TABLE subcommands with different spellings
+ *****************************************************************************/
+
+AlterCompositeTypeStmt:
+ ALTER TYPE_P any_name alter_type_cmds
+ {
+ AlterTableStmt *n = makeNode(AlterTableStmt);
+
+ /* can't use qualified_name, sigh */
+ n->relation = makeRangeVarFromAnyName($3, @3, yyscanner);
+ n->cmds = $4;
+ n->relkind = OBJECT_TYPE;
+ $$ = (Node *)n;
+ }
+ ;
+
+alter_type_cmds:
+ alter_type_cmd { $$ = list_make1($1); }
+ | alter_type_cmds ',' alter_type_cmd { $$ = lappend($1, $3); }
+ ;
+
+alter_type_cmd:
+ /* ALTER TYPE <name> ADD ATTRIBUTE <coldef> */
+ ADD_P ATTRIBUTE TableFuncElement
+ {
+ AlterTableCmd *n = makeNode(AlterTableCmd);
+ n->subtype = AT_AddColumn;
+ n->def = $3;
+ $$ = (Node *)n;
+ }
+ /* ALTER TYPE <name> DROP ATTRIBUTE IF EXISTS <attname> */
+ | DROP ATTRIBUTE IF_P EXISTS ColId
+ {
+ AlterTableCmd *n = makeNode(AlterTableCmd);
+ n->subtype = AT_DropColumn;
+ n->name = $5;
+ n->behavior = DROP_RESTRICT; /* currently no effect */
+ n->missing_ok = TRUE;
+ $$ = (Node *)n;
+ }
+ /* ALTER TYPE <name> DROP ATTRIBUTE <attname> */
+ | DROP ATTRIBUTE ColId opt_drop_behavior
+ {
+ AlterTableCmd *n = makeNode(AlterTableCmd);
+ n->subtype = AT_DropColumn;
+ n->name = $3;
+ n->behavior = DROP_RESTRICT; /* currently no effect */
+ n->missing_ok = FALSE;
+ $$ = (Node *)n;
+ }
+ /* ALTER TYPE <name> ALTER ATTRIBUTE <attname> [SET DATA] TYPE <typename> */
+ | ALTER ATTRIBUTE ColId opt_set_data TYPE_P Typename
+ {
+ AlterTableCmd *n = makeNode(AlterTableCmd);
+ n->subtype = AT_AlterColumnType;
+ n->name = $3;
+ n->def = (Node *) $6;
+ $$ = (Node *)n;
+ }
+ ;
+
+
/*****************************************************************************
*
* QUERY :
*****************************************************************************/
ClosePortalStmt:
- CLOSE name
+ CLOSE cursor_name
{
ClosePortalStmt *n = makeNode(ClosePortalStmt);
n->portalname = $2;
/*****************************************************************************
*
* QUERY :
- * COPY relname ['(' columnList ')'] FROM/TO file [WITH options]
+ * COPY relname [(columnList)] FROM/TO file [WITH] [(options)]
+ * COPY ( SELECT ... ) TO file [WITH] [(options)]
*
- * BINARY, OIDS, and DELIMITERS kept in old locations
- * for backward compatibility. 2002-06-18
+ * 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.
*
- * COPY ( SELECT ... ) TO file [WITH options]
- * This form doesn't have the backwards-compatible option
- * syntax.
+ * 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_with copy_opt_list
+ copy_from copy_file_name copy_delimiter opt_with copy_options
{
CopyStmt *n = makeNode(CopyStmt);
n->relation = $3;
n->options = list_concat(n->options, $10);
$$ = (Node *)n;
}
- | COPY select_with_parens TO copy_file_name opt_with
- copy_opt_list
+ | COPY select_with_parens TO copy_file_name opt_with copy_options
{
CopyStmt *n = makeNode(CopyStmt);
n->relation = NULL;
| STDOUT { $$ = NULL; }
;
+copy_options: copy_opt_list { $$ = $1; }
+ | '(' copy_generic_opt_list ')' { $$ = $2; }
+ ;
-
+/* old COPY option syntax */
copy_opt_list:
copy_opt_list copy_opt_item { $$ = lappend($1, $2); }
| /* EMPTY */ { $$ = NIL; }
;
-
copy_opt_item:
BINARY
{
- $$ = makeDefElem("binary", (Node *)makeInteger(TRUE));
+ $$ = makeDefElem("format", (Node *)makeString("binary"));
}
| OIDS
{
}
| CSV
{
- $$ = makeDefElem("csv", (Node *)makeInteger(TRUE));
+ $$ = makeDefElem("format", (Node *)makeString("csv"));
}
| HEADER_P
{
{
$$ = makeDefElem("force_quote", (Node *)$3);
}
+ | FORCE QUOTE '*'
+ {
+ $$ = makeDefElem("force_quote", (Node *)makeNode(A_Star));
+ }
| FORCE NOT NULL_P columnList
{
- $$ = makeDefElem("force_notnull", (Node *)$4);
+ $$ = makeDefElem("force_not_null", (Node *)$4);
}
;
-/* The following exist for backward compatibility */
+/* The following exist for backward compatibility with very old versions */
opt_binary:
BINARY
{
- $$ = makeDefElem("binary", (Node *)makeInteger(TRUE));
+ $$ = makeDefElem("format", (Node *)makeString("binary"));
}
| /*EMPTY*/ { $$ = NULL; }
;
;
copy_delimiter:
- /* USING DELIMITERS kept for backward compatibility. 2002-06-15 */
opt_using DELIMITERS Sconst
{
$$ = makeDefElem("delimiter", (Node *)makeString($3));
| /*EMPTY*/ {}
;
+/* new COPY option syntax */
+copy_generic_opt_list:
+ copy_generic_opt_elem
+ {
+ $$ = list_make1($1);
+ }
+ | copy_generic_opt_list ',' copy_generic_opt_elem
+ {
+ $$ = lappend($1, $3);
+ }
+ ;
+
+copy_generic_opt_elem:
+ ColLabel copy_generic_opt_arg
+ {
+ $$ = makeDefElem($1, $2);
+ }
+ ;
+
+copy_generic_opt_arg:
+ opt_boolean { $$ = (Node *) makeString($1); }
+ | ColId_or_Sconst { $$ = (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 { $$ = (Node *) makeString($1); }
+ | ColId_or_Sconst { $$ = (Node *) makeString($1); }
+ ;
+
/*****************************************************************************
*
n->options = $9;
n->oncommit = $10;
n->tablespacename = $11;
+ n->if_not_exists = false;
$$ = (Node *)n;
}
- | CREATE OptTemp TABLE qualified_name OF qualified_name
- '(' OptTableElementList ')' OptWith OnCommitOption OptTableSpace
+ | CREATE OptTemp TABLE IF_P NOT EXISTS qualified_name '('
+ OptTableElementList ')' OptInherit OptWith OnCommitOption
+ OptTableSpace
+ {
+ CreateStmt *n = makeNode(CreateStmt);
+ $7->istemp = $2;
+ n->relation = $7;
+ n->tableElts = $9;
+ n->inhRelations = $11;
+ n->constraints = NIL;
+ n->options = $12;
+ n->oncommit = $13;
+ n->tablespacename = $14;
+ n->if_not_exists = true;
+ $$ = (Node *)n;
+ }
+ | CREATE OptTemp TABLE qualified_name OF any_name
+ OptTypedTableElementList OptWith OnCommitOption OptTableSpace
{
- /* SQL99 CREATE TABLE OF <UDT> (cols) seems to be satisfied
- * by our inheritance capabilities. Let's try it...
- */
CreateStmt *n = makeNode(CreateStmt);
$4->istemp = $2;
n->relation = $4;
- n->tableElts = $8;
- n->inhRelations = list_make1($6);
+ n->tableElts = $7;
+ n->ofTypename = makeTypeNameFromNameList($6);
+ n->ofTypename->location = @6;
n->constraints = NIL;
- n->options = $10;
- n->oncommit = $11;
- n->tablespacename = $12;
+ n->options = $8;
+ n->oncommit = $9;
+ n->tablespacename = $10;
+ n->if_not_exists = false;
+ $$ = (Node *)n;
+ }
+ | CREATE OptTemp TABLE IF_P NOT EXISTS qualified_name OF any_name
+ OptTypedTableElementList OptWith OnCommitOption OptTableSpace
+ {
+ CreateStmt *n = makeNode(CreateStmt);
+ $7->istemp = $2;
+ n->relation = $7;
+ n->tableElts = $10;
+ n->ofTypename = makeTypeNameFromNameList($9);
+ n->ofTypename->location = @9;
+ n->constraints = NIL;
+ n->options = $11;
+ n->oncommit = $12;
+ n->tablespacename = $13;
+ n->if_not_exists = true;
$$ = (Node *)n;
}
;
| /*EMPTY*/ { $$ = NIL; }
;
+OptTypedTableElementList:
+ '(' TypedTableElementList ')' { $$ = $2; }
+ | /*EMPTY*/ { $$ = NIL; }
+ ;
+
TableElementList:
TableElement
{
}
;
+TypedTableElementList:
+ TypedTableElement
+ {
+ $$ = list_make1($1);
+ }
+ | TypedTableElementList ',' TypedTableElement
+ {
+ $$ = lappend($1, $3);
+ }
+ ;
+
TableElement:
columnDef { $$ = $1; }
| TableLikeClause { $$ = $1; }
| TableConstraint { $$ = $1; }
;
+TypedTableElement:
+ columnOptions { $$ = $1; }
+ | TableConstraint { $$ = $1; }
+ ;
+
columnDef: ColId Typename ColQualList
{
ColumnDef *n = makeNode(ColumnDef);
}
;
+columnOptions: ColId WITH OPTIONS ColQualList
+ {
+ ColumnDef *n = makeNode(ColumnDef);
+ n->colname = $1;
+ n->constraints = $4;
+ n->is_local = true;
+ $$ = (Node *)n;
+ }
+ ;
+
ColQualList:
ColQualList ColConstraint { $$ = lappend($1, $2); }
| /*EMPTY*/ { $$ = NIL; }
ColConstraint:
CONSTRAINT name ColConstraintElem
{
- switch (nodeTag($3))
- {
- case T_Constraint:
- {
- Constraint *n = (Constraint *)$3;
- n->name = $2;
- }
- break;
- case T_FkConstraint:
- {
- FkConstraint *n = (FkConstraint *)$3;
- n->constr_name = $2;
- }
- break;
- default:
- break;
- }
- $$ = $3;
+ Constraint *n = (Constraint *) $3;
+ Assert(IsA(n, Constraint));
+ n->conname = $2;
+ n->location = @1;
+ $$ = (Node *) n;
}
| ColConstraintElem { $$ = $1; }
| ConstraintAttr { $$ = $1; }
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_NOTNULL;
- n->name = NULL;
- n->raw_expr = NULL;
- n->cooked_expr = NULL;
- n->keys = NULL;
- n->indexspace = NULL;
+ n->location = @1;
$$ = (Node *)n;
}
| NULL_P
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_NULL;
- n->name = NULL;
- n->raw_expr = NULL;
- n->cooked_expr = NULL;
- n->keys = NULL;
- n->indexspace = NULL;
+ n->location = @1;
$$ = (Node *)n;
}
| UNIQUE opt_definition OptConsTableSpace
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_UNIQUE;
- n->name = NULL;
- n->raw_expr = NULL;
- n->cooked_expr = NULL;
+ n->location = @1;
n->keys = NULL;
n->options = $2;
n->indexspace = $3;
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_PRIMARY;
- n->name = NULL;
- n->raw_expr = NULL;
- n->cooked_expr = NULL;
+ n->location = @1;
n->keys = NULL;
n->options = $3;
n->indexspace = $4;
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_CHECK;
- n->name = NULL;
+ n->location = @1;
n->raw_expr = $3;
n->cooked_expr = NULL;
- n->keys = NULL;
- n->indexspace = NULL;
$$ = (Node *)n;
}
| DEFAULT b_expr
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_DEFAULT;
- n->name = NULL;
+ n->location = @1;
n->raw_expr = $2;
n->cooked_expr = NULL;
- n->keys = NULL;
- n->indexspace = NULL;
$$ = (Node *)n;
}
| REFERENCES qualified_name opt_column_list key_match key_actions
{
- FkConstraint *n = makeNode(FkConstraint);
- n->constr_name = NULL;
+ 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->deferrable = FALSE;
- n->initdeferred = FALSE;
+ n->skip_validation = FALSE;
$$ = (Node *)n;
}
;
{
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;
}
;
;
TableLikeOptionList:
- TableLikeOptionList TableLikeOption { $$ = lappend_int($1, $2); }
- | /* EMPTY */ { $$ = NIL; }
+ TableLikeOptionList INCLUDING TableLikeOption { $$ = $1 | $3; }
+ | TableLikeOptionList EXCLUDING TableLikeOption { $$ = $1 & ~$3; }
+ | /* EMPTY */ { $$ = 0; }
;
TableLikeOption:
- INCLUDING DEFAULTS { $$ = CREATE_TABLE_LIKE_INCLUDING_DEFAULTS; }
- | EXCLUDING DEFAULTS { $$ = CREATE_TABLE_LIKE_EXCLUDING_DEFAULTS; }
- | INCLUDING CONSTRAINTS { $$ = CREATE_TABLE_LIKE_INCLUDING_CONSTRAINTS; }
- | EXCLUDING CONSTRAINTS { $$ = CREATE_TABLE_LIKE_EXCLUDING_CONSTRAINTS; }
- | INCLUDING INDEXES { $$ = CREATE_TABLE_LIKE_INCLUDING_INDEXES; }
- | EXCLUDING INDEXES { $$ = CREATE_TABLE_LIKE_EXCLUDING_INDEXES; }
+ DEFAULTS { $$ = CREATE_TABLE_LIKE_DEFAULTS; }
+ | CONSTRAINTS { $$ = CREATE_TABLE_LIKE_CONSTRAINTS; }
+ | INDEXES { $$ = CREATE_TABLE_LIKE_INDEXES; }
+ | STORAGE { $$ = CREATE_TABLE_LIKE_STORAGE; }
+ | COMMENTS { $$ = CREATE_TABLE_LIKE_COMMENTS; }
+ | ALL { $$ = CREATE_TABLE_LIKE_ALL; }
;
TableConstraint:
CONSTRAINT name ConstraintElem
{
- switch (nodeTag($3))
- {
- case T_Constraint:
- {
- Constraint *n = (Constraint *)$3;
- n->name = $2;
- }
- break;
- case T_FkConstraint:
- {
- FkConstraint *n = (FkConstraint *)$3;
- n->constr_name = $2;
- }
- break;
- default:
- break;
- }
- $$ = $3;
+ Constraint *n = (Constraint *) $3;
+ Assert(IsA(n, Constraint));
+ n->conname = $2;
+ n->location = @1;
+ $$ = (Node *) n;
}
| ConstraintElem { $$ = $1; }
;
ConstraintElem:
- CHECK '(' a_expr ')'
+ CHECK '(' a_expr ')' ConstraintAttributeSpec
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_CHECK;
- n->name = NULL;
+ n->location = @1;
n->raw_expr = $3;
n->cooked_expr = NULL;
- n->indexspace = NULL;
+ if ($5 != 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("CHECK constraints cannot be deferred"),
+ parser_errposition(@5)));
$$ = (Node *)n;
}
| UNIQUE '(' columnList ')' opt_definition OptConsTableSpace
+ ConstraintAttributeSpec
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_UNIQUE;
- n->name = NULL;
- n->raw_expr = NULL;
- n->cooked_expr = NULL;
+ n->location = @1;
n->keys = $3;
n->options = $5;
n->indexspace = $6;
+ n->deferrable = ($7 & 1) != 0;
+ n->initdeferred = ($7 & 2) != 0;
$$ = (Node *)n;
}
| PRIMARY KEY '(' columnList ')' opt_definition OptConsTableSpace
+ ConstraintAttributeSpec
{
Constraint *n = makeNode(Constraint);
n->contype = CONSTR_PRIMARY;
- n->name = NULL;
- n->raw_expr = NULL;
- n->cooked_expr = NULL;
+ n->location = @1;
n->keys = $4;
n->options = $6;
n->indexspace = $7;
+ n->deferrable = ($8 & 1) != 0;
+ n->initdeferred = ($8 & 2) != 0;
+ $$ = (Node *)n;
+ }
+ | EXCLUDE access_method_clause '(' ExclusionConstraintList ')'
+ opt_definition OptConsTableSpace ExclusionWhereClause
+ ConstraintAttributeSpec
+ {
+ Constraint *n = makeNode(Constraint);
+ n->contype = CONSTR_EXCLUSION;
+ n->location = @1;
+ n->access_method = $2;
+ n->exclusions = $4;
+ n->options = $6;
+ n->indexspace = $7;
+ n->where_clause = $8;
+ n->deferrable = ($9 & 1) != 0;
+ n->initdeferred = ($9 & 2) != 0;
$$ = (Node *)n;
}
| FOREIGN KEY '(' columnList ')' REFERENCES qualified_name
opt_column_list key_match key_actions ConstraintAttributeSpec
{
- FkConstraint *n = makeNode(FkConstraint);
- n->constr_name = NULL;
+ 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);
+ n->skip_validation = FALSE;
n->deferrable = ($11 & 1) != 0;
n->initdeferred = ($11 & 2) != 0;
$$ = (Node *)n;
}
;
+ExclusionConstraintList:
+ ExclusionConstraintElem { $$ = list_make1($1); }
+ | ExclusionConstraintList ',' ExclusionConstraintElem
+ { $$ = lappend($1, $3); }
+ ;
+
+ExclusionConstraintElem: index_elem WITH any_operator
+ {
+ $$ = list_make2($1, $3);
+ }
+ /* allow OPERATOR() decoration for the benefit of ruleutils.c */
+ | index_elem WITH OPERATOR '(' any_operator ')'
+ {
+ $$ = list_make2($1, $5);
+ }
+ ;
+
+ExclusionWhereClause:
+ WHERE '(' a_expr ')' { $$ = $3; }
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
+
/*
* We combine the update and delete actions into one value temporarily
* for simplicity of parsing, and then break them down again in the
$4->istemp = $2;
n->sequence = $4;
n->options = $5;
+ n->ownerId = InvalidOid;
$$ = (Node *)n;
}
;
;
NumericOnly:
- FCONST { $$ = makeFloat($1); }
+ FCONST { $$ = makeFloat($1); }
| '-' FCONST
{
$$ = makeFloat($2);
doNegateFloat($$);
}
- | SignedIconst { $$ = makeInteger($1); };
+ | SignedIconst { $$ = makeInteger($1); }
+ ;
+
+NumericOnly_list: NumericOnly { $$ = list_make1($1); }
+ | NumericOnly_list ',' NumericOnly { $$ = lappend($1, $3); }
;
/*****************************************************************************
*
* QUERIES :
- * CREATE PROCEDURAL LANGUAGE ...
- * DROP PROCEDURAL LANGUAGE ...
+ * CREATE [OR REPLACE] [TRUSTED] [PROCEDURAL] LANGUAGE ...
+ * DROP [PROCEDURAL] LANGUAGE ...
*
*****************************************************************************/
CreatePLangStmt:
- CREATE opt_trusted opt_procedural LANGUAGE ColId_or_Sconst
+ CREATE opt_or_replace opt_trusted opt_procedural LANGUAGE ColId_or_Sconst
{
CreatePLangStmt *n = makeNode(CreatePLangStmt);
- n->plname = $5;
+ n->replace = $2;
+ n->plname = $6;
/* parameters are all to be supplied by system */
n->plhandler = NIL;
+ n->plinline = NIL;
n->plvalidator = NIL;
n->pltrusted = false;
$$ = (Node *)n;
}
- | CREATE opt_trusted opt_procedural LANGUAGE ColId_or_Sconst
- HANDLER handler_name opt_validator opt_lancompiler
+ | CREATE opt_or_replace opt_trusted opt_procedural LANGUAGE ColId_or_Sconst
+ HANDLER handler_name opt_inline_handler opt_validator
{
CreatePLangStmt *n = makeNode(CreatePLangStmt);
- n->plname = $5;
- n->plhandler = $7;
- n->plvalidator = $8;
- n->pltrusted = $2;
- /* LANCOMPILER is now ignored entirely */
+ n->replace = $2;
+ n->plname = $6;
+ n->plhandler = $8;
+ n->plinline = $9;
+ n->plvalidator = $10;
+ n->pltrusted = $3;
$$ = (Node *)n;
}
;
| 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; }
| /*EMPTY*/ { $$ = NIL; }
;
-opt_lancompiler:
- LANCOMPILER Sconst { $$ = $2; }
- | /*EMPTY*/ { $$ = NULL; }
- ;
-
DropPLangStmt:
DROP opt_procedural LANGUAGE ColId_or_Sconst opt_drop_behavior
{
CreateTrigStmt:
CREATE TRIGGER name TriggerActionTime TriggerEvents ON
- qualified_name TriggerForSpec EXECUTE PROCEDURE
- func_name '(' TriggerFuncArgs ')'
+ qualified_name TriggerForSpec TriggerWhen
+ EXECUTE PROCEDURE func_name '(' TriggerFuncArgs ')'
{
CreateTrigStmt *n = makeNode(CreateTrigStmt);
n->trigname = $3;
n->relation = $7;
- n->funcname = $11;
- n->args = $13;
- n->before = $4;
+ n->funcname = $12;
+ n->args = $14;
n->row = $8;
- n->events = $5;
+ n->timing = $4;
+ n->events = intVal(linitial($5));
+ n->columns = (List *) lsecond($5);
+ n->whenClause = $9;
n->isconstraint = FALSE;
n->deferrable = FALSE;
n->initdeferred = FALSE;
$$ = (Node *)n;
}
| CREATE CONSTRAINT TRIGGER name AFTER TriggerEvents ON
- qualified_name OptConstrFromTable
- ConstraintAttributeSpec
- FOR EACH ROW EXECUTE PROCEDURE
- func_name '(' TriggerFuncArgs ')'
+ qualified_name OptConstrFromTable ConstraintAttributeSpec
+ FOR EACH ROW TriggerWhen
+ EXECUTE PROCEDURE func_name '(' TriggerFuncArgs ')'
{
CreateTrigStmt *n = makeNode(CreateTrigStmt);
n->trigname = $4;
n->relation = $8;
- n->funcname = $16;
- n->args = $18;
- n->before = FALSE;
+ n->funcname = $17;
+ n->args = $19;
n->row = TRUE;
- n->events = $6;
+ n->timing = TRIGGER_TYPE_AFTER;
+ n->events = intVal(linitial($6));
+ n->columns = (List *) lsecond($6);
+ n->whenClause = $14;
n->isconstraint = TRUE;
n->deferrable = ($10 & 1) != 0;
n->initdeferred = ($10 & 2) != 0;
;
TriggerActionTime:
- BEFORE { $$ = TRUE; }
- | AFTER { $$ = FALSE; }
+ BEFORE { $$ = TRIGGER_TYPE_BEFORE; }
+ | AFTER { $$ = TRIGGER_TYPE_AFTER; }
+ | INSTEAD OF { $$ = TRIGGER_TYPE_INSTEAD; }
;
TriggerEvents:
{ $$ = $1; }
| TriggerEvents OR TriggerOneEvent
{
- if ($1 & $3)
+ 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");
- $$ = $1 | $3;
+ /*
+ * 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 { $$ = TRIGGER_TYPE_INSERT; }
- | DELETE_P { $$ = TRIGGER_TYPE_DELETE; }
- | UPDATE { $$ = TRIGGER_TYPE_UPDATE; }
- | TRUNCATE { $$ = TRIGGER_TYPE_TRUNCATE; }
+ 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 TriggerForOpt TriggerForType
+ FOR TriggerForOptEach TriggerForType
{
$$ = $3;
}
}
;
-TriggerForOpt:
+TriggerForOptEach:
EACH {}
| /*EMPTY*/ {}
;
| STATEMENT { $$ = FALSE; }
;
+TriggerWhen:
+ WHEN '(' a_expr ')' { $$ = $3; }
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
+
TriggerFuncArgs:
TriggerFuncArg { $$ = list_make1($1); }
| TriggerFuncArgs ',' TriggerFuncArg { $$ = lappend($1, $3); }
n->definition = NIL;
$$ = (Node *)n;
}
- | CREATE TYPE_P any_name AS '(' TableFuncElementList ')'
+ | CREATE TYPE_P any_name AS '(' OptTableFuncElementList ')'
{
CompositeTypeStmt *n = makeNode(CompositeTypeStmt);
- RangeVar *r = makeNode(RangeVar);
/* can't use qualified_name, sigh */
- switch (list_length($3))
- {
- case 1:
- r->catalogname = NULL;
- r->schemaname = NULL;
- r->relname = strVal(linitial($3));
- break;
- case 2:
- r->catalogname = NULL;
- r->schemaname = strVal(linitial($3));
- r->relname = strVal(lsecond($3));
- break;
- case 3:
- r->catalogname = strVal(linitial($3));
- r->schemaname = strVal(lsecond($3));
- r->relname = strVal(lthird($3));
- break;
- default:
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("improper qualified name (too many dotted names): %s",
- NameListToString($3)),
- parser_errposition(@3)));
- break;
- }
- r->location = @3;
- n->typevar = r;
+ n->typevar = makeRangeVarFromAnyName($3, @3, yyscanner);
n->coldeflist = $6;
$$ = (Node *)n;
}
- | CREATE TYPE_P any_name AS ENUM_P '(' enum_val_list ')'
+ | CREATE TYPE_P any_name AS ENUM_P '(' opt_enum_val_list ')'
{
CreateEnumStmt *n = makeNode(CreateEnumStmt);
n->typeName = $3;
}
;
+opt_enum_val_list:
+ enum_val_list { $$ = $1; }
+ | /*EMPTY*/ { $$ = NIL; }
+ ;
+
enum_val_list: Sconst
{ $$ = list_make1(makeString($1)); }
| enum_val_list ',' Sconst
| NULL_P { $$ = NULL; }
;
+
+/*****************************************************************************
+ *
+ * SECURITY LABEL [FOR <provider>] ON <object> IS <label>
+ *
+ * As with COMMENT ON, <object> can refer to various types of database
+ * objects (e.g. TABLE, COLUMN, etc.).
+ *
+ *****************************************************************************/
+
+SecLabelStmt:
+ SECURITY LABEL opt_provider ON security_label_type any_name
+ IS security_label
+ {
+ SecLabelStmt *n = makeNode(SecLabelStmt);
+ n->provider = $3;
+ n->objtype = $5;
+ n->objname = $6;
+ n->objargs = NIL;
+ n->label = $8;
+ $$ = (Node *) n;
+ }
+ | SECURITY LABEL opt_provider ON AGGREGATE func_name aggr_args
+ IS security_label
+ {
+ SecLabelStmt *n = makeNode(SecLabelStmt);
+ n->provider = $3;
+ n->objtype = OBJECT_AGGREGATE;
+ n->objname = $6;
+ n->objargs = $7;
+ n->label = $9;
+ $$ = (Node *) n;
+ }
+ | SECURITY LABEL opt_provider ON FUNCTION func_name func_args
+ IS security_label
+ {
+ SecLabelStmt *n = makeNode(SecLabelStmt);
+ n->provider = $3;
+ n->objtype = OBJECT_FUNCTION;
+ n->objname = $6;
+ n->objargs = extractArgTypes($7);
+ n->label = $9;
+ $$ = (Node *) n;
+ }
+ | SECURITY LABEL opt_provider ON LARGE_P OBJECT_P NumericOnly
+ IS security_label
+ {
+ SecLabelStmt *n = makeNode(SecLabelStmt);
+ n->provider = $3;
+ n->objtype = OBJECT_LARGEOBJECT;
+ n->objname = list_make1($7);
+ n->objargs = NIL;
+ n->label = $9;
+ $$ = (Node *) n;
+ }
+ | SECURITY LABEL opt_provider ON opt_procedural LANGUAGE any_name
+ IS security_label
+ {
+ SecLabelStmt *n = makeNode(SecLabelStmt);
+ n->provider = $3;
+ n->objtype = OBJECT_LANGUAGE;
+ n->objname = $7;
+ n->objargs = NIL;
+ n->label = $9;
+ $$ = (Node *) n;
+ }
+ ;
+
+opt_provider: FOR ColId_or_Sconst { $$ = $2; }
+ | /* empty */ { $$ = NULL; }
+ ;
+
+security_label_type:
+ COLUMN { $$ = OBJECT_COLUMN; }
+ | SCHEMA { $$ = OBJECT_SCHEMA; }
+ | SEQUENCE { $$ = OBJECT_SEQUENCE; }
+ | TABLE { $$ = OBJECT_TABLE; }
+ | DOMAIN_P { $$ = OBJECT_TYPE; }
+ | TYPE_P { $$ = OBJECT_TYPE; }
+ | VIEW { $$ = OBJECT_VIEW; }
+ ;
+
+security_label: Sconst { $$ = $1; }
+ | NULL_P { $$ = NULL; }
+ ;
+
/*****************************************************************************
*
* QUERY:
*
*****************************************************************************/
-FetchStmt: FETCH fetch_direction from_in name
+FetchStmt: FETCH fetch_args
{
FetchStmt *n = (FetchStmt *) $2;
- n->portalname = $4;
- n->ismove = FALSE;
- $$ = (Node *)n;
- }
- | FETCH name
- {
- FetchStmt *n = makeNode(FetchStmt);
- n->direction = FETCH_FORWARD;
- n->howMany = 1;
- n->portalname = $2;
n->ismove = FALSE;
$$ = (Node *)n;
}
- | MOVE fetch_direction from_in name
+ | MOVE fetch_args
{
FetchStmt *n = (FetchStmt *) $2;
- n->portalname = $4;
n->ismove = TRUE;
$$ = (Node *)n;
}
- | MOVE name
+ ;
+
+fetch_args: cursor_name
{
FetchStmt *n = makeNode(FetchStmt);
+ n->portalname = $1;
n->direction = FETCH_FORWARD;
n->howMany = 1;
- n->portalname = $2;
- n->ismove = TRUE;
$$ = (Node *)n;
}
- ;
-
-fetch_direction:
- /*EMPTY*/
+ | from_in cursor_name
{
FetchStmt *n = makeNode(FetchStmt);
+ n->portalname = $2;
n->direction = FETCH_FORWARD;
n->howMany = 1;
$$ = (Node *)n;
}
- | NEXT
+ | NEXT opt_from_in cursor_name
{
FetchStmt *n = makeNode(FetchStmt);
+ n->portalname = $3;
n->direction = FETCH_FORWARD;
n->howMany = 1;
$$ = (Node *)n;
}
- | PRIOR
+ | PRIOR opt_from_in cursor_name
{
FetchStmt *n = makeNode(FetchStmt);
+ n->portalname = $3;
n->direction = FETCH_BACKWARD;
n->howMany = 1;
$$ = (Node *)n;
}
- | FIRST_P
+ | FIRST_P opt_from_in cursor_name
{
FetchStmt *n = makeNode(FetchStmt);
+ n->portalname = $3;
n->direction = FETCH_ABSOLUTE;
n->howMany = 1;
$$ = (Node *)n;
}
- | LAST_P
+ | LAST_P opt_from_in cursor_name
{
FetchStmt *n = makeNode(FetchStmt);
+ n->portalname = $3;
n->direction = FETCH_ABSOLUTE;
n->howMany = -1;
$$ = (Node *)n;
}
- | ABSOLUTE_P SignedIconst
+ | ABSOLUTE_P SignedIconst opt_from_in cursor_name
{
FetchStmt *n = makeNode(FetchStmt);
+ n->portalname = $4;
n->direction = FETCH_ABSOLUTE;
n->howMany = $2;
$$ = (Node *)n;
}
- | RELATIVE_P SignedIconst
+ | RELATIVE_P SignedIconst opt_from_in cursor_name
{
FetchStmt *n = makeNode(FetchStmt);
+ n->portalname = $4;
n->direction = FETCH_RELATIVE;
n->howMany = $2;
$$ = (Node *)n;
}
- | SignedIconst
+ | SignedIconst opt_from_in cursor_name
{
FetchStmt *n = makeNode(FetchStmt);
+ n->portalname = $3;
n->direction = FETCH_FORWARD;
n->howMany = $1;
$$ = (Node *)n;
}
- | ALL
+ | ALL opt_from_in cursor_name
{
FetchStmt *n = makeNode(FetchStmt);
+ n->portalname = $3;
n->direction = FETCH_FORWARD;
n->howMany = FETCH_ALL;
$$ = (Node *)n;
}
- | FORWARD
+ | FORWARD opt_from_in cursor_name
{
FetchStmt *n = makeNode(FetchStmt);
+ n->portalname = $3;
n->direction = FETCH_FORWARD;
n->howMany = 1;
$$ = (Node *)n;
}
- | FORWARD SignedIconst
+ | FORWARD SignedIconst opt_from_in cursor_name
{
FetchStmt *n = makeNode(FetchStmt);
+ n->portalname = $4;
n->direction = FETCH_FORWARD;
n->howMany = $2;
$$ = (Node *)n;
}
- | FORWARD ALL
+ | FORWARD ALL opt_from_in cursor_name
{
FetchStmt *n = makeNode(FetchStmt);
+ n->portalname = $4;
n->direction = FETCH_FORWARD;
n->howMany = FETCH_ALL;
$$ = (Node *)n;
}
- | BACKWARD
+ | BACKWARD opt_from_in cursor_name
{
FetchStmt *n = makeNode(FetchStmt);
+ n->portalname = $3;
n->direction = FETCH_BACKWARD;
n->howMany = 1;
$$ = (Node *)n;
}
- | BACKWARD SignedIconst
+ | BACKWARD SignedIconst opt_from_in cursor_name
{
FetchStmt *n = makeNode(FetchStmt);
+ n->portalname = $4;
n->direction = FETCH_BACKWARD;
n->howMany = $2;
$$ = (Node *)n;
}
- | BACKWARD ALL
+ | BACKWARD ALL opt_from_in cursor_name
{
FetchStmt *n = makeNode(FetchStmt);
+ n->portalname = $4;
n->direction = FETCH_BACKWARD;
n->howMany = FETCH_ALL;
$$ = (Node *)n;
| IN_P {}
;
+opt_from_in: from_in {}
+ | /* EMPTY */ {}
+ ;
+
/*****************************************************************************
*
GrantStmt *n = makeNode(GrantStmt);
n->is_grant = true;
n->privileges = $2;
+ n->targtype = ($4)->targtype;
n->objtype = ($4)->objtype;
n->objects = ($4)->objs;
n->grantees = $6;
n->is_grant = false;
n->grant_option = false;
n->privileges = $2;
+ n->targtype = ($4)->targtype;
n->objtype = ($4)->objtype;
n->objects = ($4)->objs;
n->grantees = $6;
n->is_grant = false;
n->grant_option = true;
n->privileges = $5;
+ n->targtype = ($7)->targtype;
n->objtype = ($7)->objtype;
n->objects = ($7)->objs;
n->grantees = $9;
qualified_name_list
{
PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+ n->targtype = ACL_TARGET_OBJECT;
n->objtype = ACL_OBJECT_RELATION;
n->objs = $1;
$$ = n;
| TABLE qualified_name_list
{
PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+ n->targtype = ACL_TARGET_OBJECT;
n->objtype = ACL_OBJECT_RELATION;
n->objs = $2;
$$ = n;
| SEQUENCE qualified_name_list
{
PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+ n->targtype = ACL_TARGET_OBJECT;
n->objtype = ACL_OBJECT_SEQUENCE;
n->objs = $2;
$$ = n;
| FOREIGN DATA_P WRAPPER name_list
{
PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+ n->targtype = ACL_TARGET_OBJECT;
n->objtype = ACL_OBJECT_FDW;
n->objs = $4;
$$ = n;
| FOREIGN SERVER name_list
{
PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+ n->targtype = ACL_TARGET_OBJECT;
n->objtype = ACL_OBJECT_FOREIGN_SERVER;
n->objs = $3;
$$ = n;
| FUNCTION function_with_argtypes_list
{
PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+ n->targtype = ACL_TARGET_OBJECT;
n->objtype = ACL_OBJECT_FUNCTION;
n->objs = $2;
$$ = n;
| DATABASE name_list
{
PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+ n->targtype = ACL_TARGET_OBJECT;
n->objtype = ACL_OBJECT_DATABASE;
n->objs = $2;
$$ = n;
| LANGUAGE name_list
{
PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+ n->targtype = ACL_TARGET_OBJECT;
n->objtype = ACL_OBJECT_LANGUAGE;
n->objs = $2;
$$ = n;
}
+ | LARGE_P OBJECT_P NumericOnly_list
+ {
+ PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+ n->targtype = ACL_TARGET_OBJECT;
+ n->objtype = ACL_OBJECT_LARGEOBJECT;
+ n->objs = $3;
+ $$ = n;
+ }
| SCHEMA name_list
{
PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+ n->targtype = ACL_TARGET_OBJECT;
n->objtype = ACL_OBJECT_NAMESPACE;
n->objs = $2;
$$ = n;
| TABLESPACE name_list
{
PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+ n->targtype = ACL_TARGET_OBJECT;
n->objtype = ACL_OBJECT_TABLESPACE;
n->objs = $2;
$$ = n;
}
+ | ALL TABLES IN_P SCHEMA name_list
+ {
+ PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+ n->targtype = ACL_TARGET_ALL_IN_SCHEMA;
+ n->objtype = ACL_OBJECT_RELATION;
+ n->objs = $5;
+ $$ = n;
+ }
+ | ALL SEQUENCES IN_P SCHEMA name_list
+ {
+ PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+ n->targtype = ACL_TARGET_ALL_IN_SCHEMA;
+ n->objtype = ACL_OBJECT_SEQUENCE;
+ n->objs = $5;
+ $$ = n;
+ }
+ | ALL FUNCTIONS IN_P SCHEMA name_list
+ {
+ PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+ n->targtype = ACL_TARGET_ALL_IN_SCHEMA;
+ n->objtype = ACL_OBJECT_FUNCTION;
+ n->objs = $5;
+ $$ = n;
+ }
;
| /*EMPTY*/ { $$ = NULL; }
;
+/*****************************************************************************
+ *
+ * ALTER DEFAULT PRIVILEGES statement
+ *
+ *****************************************************************************/
+
+AlterDefaultPrivilegesStmt:
+ ALTER DEFAULT PRIVILEGES DefACLOptionList DefACLAction
+ {
+ AlterDefaultPrivilegesStmt *n = makeNode(AlterDefaultPrivilegesStmt);
+ n->options = $4;
+ n->action = (GrantStmt *) $5;
+ $$ = (Node*)n;
+ }
+ ;
+
+DefACLOptionList:
+ DefACLOptionList DefACLOption { $$ = lappend($1, $2); }
+ | /* EMPTY */ { $$ = NIL; }
+ ;
+
+DefACLOption:
+ IN_P SCHEMA name_list
+ {
+ $$ = makeDefElem("schemas", (Node *)$3);
+ }
+ | FOR ROLE name_list
+ {
+ $$ = makeDefElem("roles", (Node *)$3);
+ }
+ | FOR USER name_list
+ {
+ $$ = makeDefElem("roles", (Node *)$3);
+ }
+ ;
+
+/*
+ * This should match GRANT/REVOKE, except that individual target objects
+ * are not mentioned and we only allow a subset of object types.
+ */
+DefACLAction:
+ GRANT privileges ON defacl_privilege_target TO grantee_list
+ opt_grant_grant_option
+ {
+ GrantStmt *n = makeNode(GrantStmt);
+ n->is_grant = true;
+ n->privileges = $2;
+ n->targtype = ACL_TARGET_DEFAULTS;
+ n->objtype = $4;
+ n->objects = NIL;
+ n->grantees = $6;
+ n->grant_option = $7;
+ $$ = (Node*)n;
+ }
+ | REVOKE privileges ON defacl_privilege_target
+ FROM grantee_list opt_drop_behavior
+ {
+ GrantStmt *n = makeNode(GrantStmt);
+ n->is_grant = false;
+ n->grant_option = false;
+ n->privileges = $2;
+ n->targtype = ACL_TARGET_DEFAULTS;
+ n->objtype = $4;
+ n->objects = NIL;
+ n->grantees = $6;
+ n->behavior = $7;
+ $$ = (Node *)n;
+ }
+ | REVOKE GRANT OPTION FOR privileges ON defacl_privilege_target
+ FROM grantee_list opt_drop_behavior
+ {
+ GrantStmt *n = makeNode(GrantStmt);
+ n->is_grant = false;
+ n->grant_option = true;
+ n->privileges = $5;
+ n->targtype = ACL_TARGET_DEFAULTS;
+ n->objtype = $7;
+ n->objects = NIL;
+ n->grantees = $9;
+ n->behavior = $10;
+ $$ = (Node *)n;
+ }
+ ;
+
+defacl_privilege_target:
+ TABLES { $$ = ACL_OBJECT_RELATION; }
+ | FUNCTIONS { $$ = ACL_OBJECT_FUNCTION; }
+ | SEQUENCES { $$ = ACL_OBJECT_SEQUENCE; }
+ ;
+
/*****************************************************************************
*
* QUERY: CREATE INDEX
*
- * Note: we can't factor CONCURRENTLY into a separate production without
- * making it a reserved word.
- *
* Note: we cannot put TABLESPACE clause after WHERE clause unless we are
* willing to make TABLESPACE a fully reserved word.
*****************************************************************************/
-IndexStmt: CREATE index_opt_unique INDEX index_name
+IndexStmt: CREATE opt_unique INDEX opt_concurrently opt_index_name
ON qualified_name access_method_clause '(' index_params ')'
opt_reloptions OptTableSpace where_clause
{
IndexStmt *n = makeNode(IndexStmt);
n->unique = $2;
- n->concurrent = false;
- n->idxname = $4;
- n->relation = $6;
- n->accessMethod = $7;
- n->indexParams = $9;
- n->options = $11;
- n->tableSpace = $12;
- n->whereClause = $13;
- $$ = (Node *)n;
- }
- | CREATE index_opt_unique INDEX CONCURRENTLY index_name
- ON qualified_name access_method_clause '(' index_params ')'
- opt_reloptions OptTableSpace where_clause
- {
- IndexStmt *n = makeNode(IndexStmt);
- n->unique = $2;
- n->concurrent = true;
+ n->concurrent = $4;
n->idxname = $5;
n->relation = $7;
n->accessMethod = $8;
}
;
-index_opt_unique:
+opt_unique:
UNIQUE { $$ = TRUE; }
| /*EMPTY*/ { $$ = FALSE; }
;
+opt_concurrently:
+ CONCURRENTLY { $$ = TRUE; }
+ | /*EMPTY*/ { $$ = FALSE; }
+ ;
+
+opt_index_name:
+ index_name { $$ = $1; }
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
+
access_method_clause:
USING access_method { $$ = $2; }
| /*EMPTY*/ { $$ = DEFAULT_INDEX_TYPE; }
$$ = makeNode(IndexElem);
$$->name = $1;
$$->expr = NULL;
+ $$->indexcolname = NULL;
$$->opclass = $2;
$$->ordering = $3;
$$->nulls_ordering = $4;
$$ = makeNode(IndexElem);
$$->name = NULL;
$$->expr = $1;
+ $$->indexcolname = NULL;
$$->opclass = $2;
$$->ordering = $3;
$$->nulls_ordering = $4;
$$ = makeNode(IndexElem);
$$->name = NULL;
$$->expr = $2;
+ $$->indexcolname = NULL;
$$->opclass = $4;
$$->ordering = $5;
$$->nulls_ordering = $6;
{ $$ = lcons(makeString($1), $3); }
;
+/*****************************************************************************
+ *
+ * DO <anonymous code block> [ LANGUAGE language ]
+ *
+ * We use a DefElem list for future extensibility, and to allow flexibility
+ * in the clause order.
+ *
+ *****************************************************************************/
+
+DoStmt: DO dostmt_opt_list
+ {
+ DoStmt *n = makeNode(DoStmt);
+ n->args = $2;
+ $$ = (Node *)n;
+ }
+ ;
+
+dostmt_opt_list:
+ dostmt_opt_item { $$ = list_make1($1); }
+ | dostmt_opt_list dostmt_opt_item { $$ = lappend($1, $2); }
+ ;
+
+dostmt_opt_item:
+ Sconst
+ {
+ $$ = makeDefElem("as", (Node *)makeString($1));
+ }
+ | LANGUAGE ColId_or_Sconst
+ {
+ $$ = makeDefElem("language", (Node *)makeString($2));
+ }
+ ;
/*****************************************************************************
*
n->newname = $6;
$$ = (Node *)n;
}
+ | ALTER TABLESPACE name SET reloptions
+ {
+ AlterTableSpaceOptionsStmt *n =
+ makeNode(AlterTableSpaceOptionsStmt);
+ n->tablespacename = $3;
+ n->options = $5;
+ n->isReset = FALSE;
+ $$ = (Node *)n;
+ }
+ | ALTER TABLESPACE name RESET reloptions
+ {
+ AlterTableSpaceOptionsStmt *n =
+ makeNode(AlterTableSpaceOptionsStmt);
+ n->tablespacename = $3;
+ n->options = $5;
+ n->isReset = TRUE;
+ $$ = (Node *)n;
+ }
| ALTER TEXT_P SEARCH PARSER any_name RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
n->newname = $6;
$$ = (Node *)n;
}
+ | ALTER TYPE_P any_name RENAME ATTRIBUTE name TO name
+ {
+ RenameStmt *n = makeNode(RenameStmt);
+ n->renameType = OBJECT_ATTRIBUTE;
+ n->relation = makeRangeVarFromAnyName($3, @3, yyscanner);
+ n->subname = $6;
+ n->newname = $8;
+ $$ = (Node *)n;
+ }
;
opt_column: COLUMN { $$ = COLUMN; }
n->newowner = $7;
$$ = (Node *)n;
}
+ | ALTER LARGE_P OBJECT_P NumericOnly OWNER TO RoleId
+ {
+ AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
+ n->objectType = OBJECT_LARGEOBJECT;
+ n->object = list_make1($4);
+ n->newowner = $7;
+ $$ = (Node *)n;
+ }
| ALTER OPERATOR any_operator oper_argtypes OWNER TO RoleId
{
AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
*****************************************************************************/
RuleStmt: CREATE opt_or_replace RULE name AS
- { pg_yyget_extra(yyscanner)->QueryIsRule = TRUE; }
ON event TO qualified_name where_clause
DO opt_instead RuleActionList
{
RuleStmt *n = makeNode(RuleStmt);
n->replace = $2;
- n->relation = $10;
+ n->relation = $9;
n->rulename = $4;
- n->whereClause = $11;
- n->event = $8;
- n->instead = $13;
- n->actions = $14;
+ n->whereClause = $10;
+ n->event = $7;
+ n->instead = $12;
+ n->actions = $13;
$$ = (Node *)n;
- pg_yyget_extra(yyscanner)->QueryIsRule = FALSE;
}
;
*
*****************************************************************************/
-NotifyStmt: NOTIFY ColId
+NotifyStmt: NOTIFY ColId notify_payload
{
NotifyStmt *n = makeNode(NotifyStmt);
n->conditionname = $2;
+ n->payload = $3;
$$ = (Node *)n;
}
;
+notify_payload:
+ ',' Sconst { $$ = $2; }
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
+
ListenStmt: LISTEN ColId
{
ListenStmt *n = makeNode(ListenStmt);
VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
{
VacuumStmt *n = makeNode(VacuumStmt);
- n->vacuum = true;
- n->analyze = false;
- n->full = $2;
+ n->options = VACOPT_VACUUM;
+ if ($2)
+ n->options |= VACOPT_FULL;
+ if ($4)
+ n->options |= VACOPT_VERBOSE;
n->freeze_min_age = $3 ? 0 : -1;
n->freeze_table_age = $3 ? 0 : -1;
- n->verbose = $4;
n->relation = NULL;
n->va_cols = NIL;
$$ = (Node *)n;
| VACUUM opt_full opt_freeze opt_verbose qualified_name
{
VacuumStmt *n = makeNode(VacuumStmt);
- n->vacuum = true;
- n->analyze = false;
- n->full = $2;
+ n->options = VACOPT_VACUUM;
+ if ($2)
+ n->options |= VACOPT_FULL;
+ if ($4)
+ n->options |= VACOPT_VERBOSE;
n->freeze_min_age = $3 ? 0 : -1;
n->freeze_table_age = $3 ? 0 : -1;
- n->verbose = $4;
n->relation = $5;
n->va_cols = NIL;
$$ = (Node *)n;
| VACUUM opt_full opt_freeze opt_verbose AnalyzeStmt
{
VacuumStmt *n = (VacuumStmt *) $5;
- n->vacuum = true;
- n->full = $2;
+ n->options |= VACOPT_VACUUM;
+ if ($2)
+ n->options |= VACOPT_FULL;
+ if ($4)
+ n->options |= VACOPT_VERBOSE;
n->freeze_min_age = $3 ? 0 : -1;
n->freeze_table_age = $3 ? 0 : -1;
- n->verbose |= $4;
$$ = (Node *)n;
}
+ | VACUUM '(' vacuum_option_list ')'
+ {
+ VacuumStmt *n = makeNode(VacuumStmt);
+ n->options = VACOPT_VACUUM | $3;
+ if (n->options & VACOPT_FREEZE)
+ n->freeze_min_age = n->freeze_table_age = 0;
+ else
+ n->freeze_min_age = n->freeze_table_age = -1;
+ n->relation = NULL;
+ n->va_cols = NIL;
+ $$ = (Node *) n;
+ }
+ | VACUUM '(' vacuum_option_list ')' qualified_name opt_name_list
+ {
+ VacuumStmt *n = makeNode(VacuumStmt);
+ n->options = VACOPT_VACUUM | $3;
+ if (n->options & VACOPT_FREEZE)
+ n->freeze_min_age = n->freeze_table_age = 0;
+ else
+ n->freeze_min_age = n->freeze_table_age = -1;
+ n->relation = $5;
+ n->va_cols = $6;
+ if (n->va_cols != NIL) /* implies analyze */
+ n->options |= VACOPT_ANALYZE;
+ $$ = (Node *) n;
+ }
+ ;
+
+vacuum_option_list:
+ vacuum_option_elem { $$ = $1; }
+ | vacuum_option_list ',' vacuum_option_elem { $$ = $1 | $3; }
+ ;
+
+vacuum_option_elem:
+ analyze_keyword { $$ = VACOPT_ANALYZE; }
+ | VERBOSE { $$ = VACOPT_VERBOSE; }
+ | FREEZE { $$ = VACOPT_FREEZE; }
+ | FULL { $$ = VACOPT_FULL; }
;
AnalyzeStmt:
analyze_keyword opt_verbose
{
VacuumStmt *n = makeNode(VacuumStmt);
- n->vacuum = false;
- n->analyze = true;
- n->full = false;
+ n->options = VACOPT_ANALYZE;
+ if ($2)
+ n->options |= VACOPT_VERBOSE;
n->freeze_min_age = -1;
n->freeze_table_age = -1;
- n->verbose = $2;
n->relation = NULL;
n->va_cols = NIL;
$$ = (Node *)n;
| analyze_keyword opt_verbose qualified_name opt_name_list
{
VacuumStmt *n = makeNode(VacuumStmt);
- n->vacuum = false;
- n->analyze = true;
- n->full = false;
+ n->options = VACOPT_ANALYZE;
+ if ($2)
+ n->options |= VACOPT_VERBOSE;
n->freeze_min_age = -1;
n->freeze_table_age = -1;
- n->verbose = $2;
n->relation = $3;
n->va_cols = $4;
$$ = (Node *)n;
*
* QUERY:
* EXPLAIN [ANALYZE] [VERBOSE] query
+ * EXPLAIN ( options ) query
*
*****************************************************************************/
-ExplainStmt: EXPLAIN opt_analyze opt_verbose ExplainableStmt
+ExplainStmt:
+ EXPLAIN ExplainableStmt
+ {
+ ExplainStmt *n = makeNode(ExplainStmt);
+ n->query = $2;
+ n->options = NIL;
+ $$ = (Node *) n;
+ }
+ | EXPLAIN analyze_keyword opt_verbose ExplainableStmt
{
ExplainStmt *n = makeNode(ExplainStmt);
- n->analyze = $2;
- n->verbose = $3;
n->query = $4;
- $$ = (Node *)n;
+ n->options = list_make1(makeDefElem("analyze", NULL));
+ if ($3)
+ n->options = lappend(n->options,
+ makeDefElem("verbose", NULL));
+ $$ = (Node *) n;
+ }
+ | EXPLAIN VERBOSE ExplainableStmt
+ {
+ ExplainStmt *n = makeNode(ExplainStmt);
+ n->query = $3;
+ n->options = list_make1(makeDefElem("verbose", NULL));
+ $$ = (Node *) n;
+ }
+ | EXPLAIN '(' explain_option_list ')' ExplainableStmt
+ {
+ ExplainStmt *n = makeNode(ExplainStmt);
+ n->query = $5;
+ n->options = $3;
+ $$ = (Node *) n;
}
;
| ExecuteStmt /* by default all are $$=$1 */
;
-opt_analyze:
- analyze_keyword { $$ = TRUE; }
- | /* EMPTY */ { $$ = FALSE; }
+explain_option_list:
+ explain_option_elem
+ {
+ $$ = list_make1($1);
+ }
+ | explain_option_list ',' explain_option_elem
+ {
+ $$ = lappend($1, $3);
+ }
+ ;
+
+explain_option_elem:
+ explain_option_name explain_option_arg
+ {
+ $$ = makeDefElem($1, $2);
+ }
+ ;
+
+explain_option_name:
+ ColId { $$ = $1; }
+ | analyze_keyword { $$ = "analyze"; }
+ | VERBOSE { $$ = "verbose"; }
+ ;
+
+explain_option_arg:
+ opt_boolean { $$ = (Node *) makeString($1); }
+ | ColId_or_Sconst { $$ = (Node *) makeString($1); }
+ | NumericOnly { $$ = (Node *) $1; }
+ | /* EMPTY */ { $$ = NULL; }
;
/*****************************************************************************
*****************************************************************************/
InsertStmt:
- INSERT INTO qualified_name insert_rest returning_clause
+ opt_with_clause INSERT INTO qualified_name insert_rest returning_clause
{
- $4->relation = $3;
- $4->returningList = $5;
- $$ = (Node *) $4;
+ $5->relation = $4;
+ $5->returningList = $6;
+ $5->withClause = $1;
+ $$ = (Node *) $5;
}
;
*
*****************************************************************************/
-DeleteStmt: DELETE_P FROM relation_expr_opt_alias
+DeleteStmt: opt_with_clause DELETE_P FROM relation_expr_opt_alias
using_clause where_or_current_clause returning_clause
{
DeleteStmt *n = makeNode(DeleteStmt);
- n->relation = $3;
- n->usingClause = $4;
- n->whereClause = $5;
- n->returningList = $6;
+ n->relation = $4;
+ n->usingClause = $5;
+ n->whereClause = $6;
+ n->returningList = $7;
+ n->withClause = $1;
$$ = (Node *)n;
}
;
*
*****************************************************************************/
-UpdateStmt: UPDATE relation_expr_opt_alias
+UpdateStmt: opt_with_clause UPDATE relation_expr_opt_alias
SET set_clause_list
from_clause
where_or_current_clause
returning_clause
{
UpdateStmt *n = makeNode(UpdateStmt);
- n->relation = $2;
- n->targetList = $4;
- n->fromClause = $5;
- n->whereClause = $6;
- n->returningList = $7;
+ n->relation = $3;
+ n->targetList = $5;
+ n->fromClause = $6;
+ n->whereClause = $7;
+ n->returningList = $8;
+ n->withClause = $1;
$$ = (Node *)n;
}
;
* CURSOR STATEMENTS
*
*****************************************************************************/
-DeclareCursorStmt: DECLARE name cursor_options CURSOR opt_hold FOR SelectStmt
+DeclareCursorStmt: DECLARE cursor_name cursor_options CURSOR opt_hold FOR SelectStmt
{
DeclareCursorStmt *n = makeNode(DeclareCursorStmt);
n->portalname = $2;
}
;
+cursor_name: name { $$ = $1; }
+ ;
+
cursor_options: /*EMPTY*/ { $$ = 0; }
| cursor_options NO SCROLL { $$ = $1 | CURSOR_OPT_NO_SCROLL; }
| cursor_options SCROLL { $$ = $1 | CURSOR_OPT_SCROLL; }
}
;
+opt_with_clause:
+ with_clause { $$ = $1; }
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
+
into_clause:
INTO OptTempTableName
{
select_limit:
- LIMIT select_limit_value OFFSET select_offset_value
- { $$ = list_make2($4, $2); }
- | OFFSET select_offset_value LIMIT select_limit_value
- { $$ = list_make2($2, $4); }
- | LIMIT select_limit_value
- { $$ = list_make2(NULL, $2); }
- | OFFSET select_offset_value
- { $$ = list_make2($2, NULL); }
+ limit_clause offset_clause { $$ = list_make2($2, $1); }
+ | offset_clause limit_clause { $$ = list_make2($1, $2); }
+ | limit_clause { $$ = list_make2(NULL, $1); }
+ | offset_clause { $$ = list_make2($1, NULL); }
+ ;
+
+opt_select_limit:
+ select_limit { $$ = $1; }
+ | /* EMPTY */ { $$ = list_make2(NULL,NULL); }
+ ;
+
+limit_clause:
+ LIMIT select_limit_value
+ { $$ = $2; }
| LIMIT select_limit_value ',' select_offset_value
{
/* Disabled because it was too confusing, bjm 2002-02-18 */
errhint("Use separate LIMIT and OFFSET clauses."),
parser_errposition(@1)));
}
- /* SQL:2008 syntax variants */
- | OFFSET select_offset_value2 row_or_rows
- { $$ = list_make2($2, NULL); }
+ /* SQL:2008 syntax */
| FETCH first_or_next opt_select_fetch_first_value row_or_rows ONLY
- { $$ = list_make2(NULL, $3); }
- | OFFSET select_offset_value2 row_or_rows FETCH first_or_next opt_select_fetch_first_value row_or_rows ONLY
- { $$ = list_make2($2, $6); }
+ { $$ = $3; }
;
-opt_select_limit:
- select_limit { $$ = $1; }
- | /* EMPTY */
- { $$ = list_make2(NULL,NULL); }
+offset_clause:
+ OFFSET select_offset_value
+ { $$ = $2; }
+ /* SQL:2008 syntax */
+ | OFFSET select_offset_value2 row_or_rows
+ { $$ = $2; }
;
select_limit_value:
}
;
+select_offset_value:
+ a_expr { $$ = $1; }
+ ;
+
/*
* Allowing full expressions without parentheses causes various parsing
* problems with the trailing ROW/ROWS key words. SQL only calls for
- * constants, so we allow the rest only with parentheses.
+ * constants, so we allow the rest only with parentheses. If omitted,
+ * default to 1.
*/
opt_select_fetch_first_value:
- SignedIconst { $$ = makeIntConst($1, @1); }
- | '(' a_expr ')' { $$ = $2; }
- | /*EMPTY*/ { $$ = makeIntConst(1, -1); }
- ;
-
-select_offset_value:
- a_expr { $$ = $1; }
+ SignedIconst { $$ = makeIntConst($1, @1); }
+ | '(' a_expr ')' { $$ = $2; }
+ | /*EMPTY*/ { $$ = makeIntConst(1, -1); }
;
/*
;
/* noise words */
-row_or_rows:
- ROW { $$ = 0; }
- | ROWS { $$ = 0; }
- ;
+row_or_rows: ROW { $$ = 0; }
+ | ROWS { $$ = 0; }
+ ;
+
+first_or_next: FIRST_P { $$ = 0; }
+ | NEXT { $$ = 0; }
+ ;
-/* noise words */
-first_or_next:
- FIRST_P { $$ = 0; }
- | NEXT { $$ = 0; }
- ;
group_clause:
GROUP_P BY expr_list { $$ = $3; }
n->cursor_param = 0;
$$ = (Node *) n;
}
- | WHERE CURRENT_P OF PARAM
- {
- CurrentOfExpr *n = makeNode(CurrentOfExpr);
- /* cvarno is filled in by parse analysis */
- n->cursor_name = NULL;
- n->cursor_param = $4;
- $$ = (Node *) n;
- }
| /*EMPTY*/ { $$ = NULL; }
;
+OptTableFuncElementList:
+ TableFuncElementList { $$ = $1; }
+ | /*EMPTY*/ { $$ = NIL; }
+ ;
+
TableFuncElementList:
TableFuncElement
{
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("timezone");
n->args = list_make2($5, $1);
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("like_escape");
n->args = list_make2($3, $5);
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
- n->location = @4;
+ n->location = @2;
$$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~~", $1, (Node *) n, @2);
}
| a_expr NOT LIKE a_expr
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("like_escape");
n->args = list_make2($4, $6);
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
- n->location = @5;
+ n->location = @2;
$$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~~", $1, (Node *) n, @2);
}
| a_expr ILIKE a_expr
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("like_escape");
n->args = list_make2($3, $5);
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
- n->location = @4;
+ n->location = @2;
$$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~~*", $1, (Node *) n, @2);
}
| a_expr NOT ILIKE a_expr
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("like_escape");
n->args = list_make2($4, $6);
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
- n->location = @5;
+ n->location = @2;
$$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~~*", $1, (Node *) n, @2);
}
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("similar_escape");
n->args = list_make2($4, makeNullAConst(-1));
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("similar_escape");
n->args = list_make2($4, $6);
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
- n->location = @5;
+ n->location = @2;
$$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~", $1, (Node *) n, @2);
}
| a_expr NOT SIMILAR TO a_expr %prec SIMILAR
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("similar_escape");
n->args = list_make2($5, makeNullAConst(-1));
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
- n->location = @5;
+ n->location = @2;
$$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~", $1, (Node *) n, @2);
}
| a_expr NOT SIMILAR TO a_expr ESCAPE a_expr
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("similar_escape");
n->args = list_make2($5, $7);
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
- n->location = @6;
+ n->location = @2;
$$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~", $1, (Node *) n, @2);
}
$$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "<>", $1, (Node *) $6, @2);
}
/*
- * Ideally we would not use hard-wired operators below but instead use
- * opclasses. However, mixed data types and other issues make this
- * difficult: http://archives.postgresql.org/pgsql-hackers/2008-08/msg01142.php
- */
+ * Ideally we would not use hard-wired operators below but
+ * instead use opclasses. However, mixed data types and other
+ * issues make this difficult:
+ * http://archives.postgresql.org/pgsql-hackers/2008-08/msg01142.php
+ */
| a_expr BETWEEN opt_asymmetric b_expr AND b_expr %prec BETWEEN
{
$$ = (Node *) makeA_Expr(AEXPR_AND, NIL,
FuncCall *n = makeNode(FuncCall);
n->funcname = $1;
n->args = NIL;
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->location = @1;
$$ = (Node *)n;
}
- | func_name '(' expr_list ')' over_clause
+ | func_name '(' func_arg_list ')' over_clause
{
FuncCall *n = makeNode(FuncCall);
n->funcname = $1;
n->args = $3;
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->location = @1;
$$ = (Node *)n;
}
- | func_name '(' VARIADIC a_expr ')' over_clause
+ | func_name '(' VARIADIC func_arg_expr ')' over_clause
{
FuncCall *n = makeNode(FuncCall);
n->funcname = $1;
n->args = list_make1($4);
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = TRUE;
n->location = @1;
$$ = (Node *)n;
}
- | func_name '(' expr_list ',' VARIADIC a_expr ')' over_clause
+ | func_name '(' func_arg_list ',' VARIADIC func_arg_expr ')' over_clause
{
FuncCall *n = makeNode(FuncCall);
n->funcname = $1;
n->args = lappend($3, $6);
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = TRUE;
n->location = @1;
$$ = (Node *)n;
}
- | func_name '(' ALL expr_list ')' over_clause
+ | func_name '(' func_arg_list sort_clause ')' over_clause
+ {
+ FuncCall *n = makeNode(FuncCall);
+ n->funcname = $1;
+ n->args = $3;
+ n->agg_order = $4;
+ n->agg_star = FALSE;
+ n->agg_distinct = FALSE;
+ n->func_variadic = FALSE;
+ n->over = $6;
+ n->location = @1;
+ $$ = (Node *)n;
+ }
+ | func_name '(' ALL func_arg_list opt_sort_clause ')' over_clause
{
FuncCall *n = makeNode(FuncCall);
n->funcname = $1;
n->args = $4;
+ n->agg_order = $5;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
/* Ideally we'd mark the FuncCall node to indicate
* for that in FuncCall at the moment.
*/
n->func_variadic = FALSE;
- n->over = $6;
+ n->over = $7;
n->location = @1;
$$ = (Node *)n;
}
- | func_name '(' DISTINCT expr_list ')' over_clause
+ | func_name '(' DISTINCT func_arg_list opt_sort_clause ')' over_clause
{
FuncCall *n = makeNode(FuncCall);
n->funcname = $1;
n->args = $4;
+ n->agg_order = $5;
n->agg_star = FALSE;
n->agg_distinct = TRUE;
n->func_variadic = FALSE;
- n->over = $6;
+ n->over = $7;
n->location = @1;
$$ = (Node *)n;
}
FuncCall *n = makeNode(FuncCall);
n->funcname = $1;
n->args = NIL;
+ n->agg_order = NIL;
n->agg_star = TRUE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("now");
n->args = NIL;
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("current_user");
n->args = NIL;
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("current_user");
n->args = NIL;
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("session_user");
n->args = NIL;
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("current_user");
n->args = NIL;
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("current_database");
n->args = NIL;
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("current_schema");
n->args = NIL;
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("date_part");
n->args = $3;
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
| OVERLAY '(' overlay_list ')'
{
/* overlay(A PLACING B FROM C FOR D) is converted to
- * substring(A, 1, C-1) || B || substring(A, C+1, C+D)
+ * overlay(A, B, C, D)
* overlay(A PLACING B FROM C) is converted to
- * substring(A, 1, C-1) || B || substring(A, C+1, C+char_length(B))
+ * overlay(A, B, C)
*/
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("overlay");
n->args = $3;
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("position");
n->args = $3;
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("substring");
n->args = $3;
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
*/
n->funcname = SystemFuncName(((Value *)llast($5->names))->val.str);
n->args = list_make1($3);
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("btrim");
n->args = $4;
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("ltrim");
n->args = $4;
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("rtrim");
n->args = $4;
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("btrim");
n->args = $3;
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
{
$$ = makeXmlExpr(IS_XMLELEMENT, $4, $6, $8, @1);
}
+ | XMLEXISTS '(' c_expr xmlexists_argument ')'
+ {
+ /* xmlexists(A PASSING [BY REF] B [BY REF]) is
+ * converted to xmlexists(A, B)*/
+ FuncCall *n = makeNode(FuncCall);
+ n->funcname = SystemFuncName("xmlexists");
+ n->args = list_make2($3, $4);
+ n->agg_order = NIL;
+ n->agg_star = FALSE;
+ n->agg_distinct = FALSE;
+ n->func_variadic = FALSE;
+ n->over = NULL;
+ n->location = @1;
+ $$ = (Node *)n;
+ }
| XMLFOREST '(' xml_attribute_list ')'
{
$$ = makeXmlExpr(IS_XMLFOREST, NULL, $3, NIL, @1);
| /*EMPTY*/ { $$ = FALSE; }
;
+/* We allow several variants for SQL and other compatibility. */
+xmlexists_argument:
+ PASSING c_expr
+ {
+ $$ = $2;
+ }
+ | PASSING c_expr BY REF
+ {
+ $$ = $2;
+ }
+ | PASSING BY REF c_expr
+ {
+ $$ = $4;
+ }
+ | PASSING BY REF c_expr BY REF
+ {
+ $$ = $4;
+ }
+ ;
+
+
/*
* Window Definitions
*/
n->partitionClause = NIL;
n->orderClause = NIL;
n->frameOptions = FRAMEOPTION_DEFAULTS;
+ n->startOffset = NULL;
+ n->endOffset = NULL;
n->location = @2;
$$ = n;
}
n->refname = $2;
n->partitionClause = $3;
n->orderClause = $4;
- n->frameOptions = $5;
+ /* copy relevant fields of opt_frame_clause */
+ n->frameOptions = $5->frameOptions;
+ n->startOffset = $5->startOffset;
+ n->endOffset = $5->endOffset;
n->location = @1;
$$ = n;
}
;
/*
+ * For frame clauses, we return a WindowDef, but only some fields are used:
+ * frameOptions, startOffset, and endOffset.
+ *
* This is only a subset of the full SQL:2008 frame_clause grammar.
- * We don't support <expression> PRECEDING, <expression> FOLLOWING,
- * nor <window frame exclusion> yet.
+ * We don't support <window frame exclusion> yet.
*/
opt_frame_clause:
RANGE frame_extent
{
- $$ = FRAMEOPTION_NONDEFAULT | FRAMEOPTION_RANGE | $2;
+ WindowDef *n = $2;
+ n->frameOptions |= FRAMEOPTION_NONDEFAULT | FRAMEOPTION_RANGE;
+ if (n->frameOptions & (FRAMEOPTION_START_VALUE_PRECEDING |
+ FRAMEOPTION_END_VALUE_PRECEDING))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("RANGE PRECEDING is only supported with UNBOUNDED"),
+ parser_errposition(@1)));
+ if (n->frameOptions & (FRAMEOPTION_START_VALUE_FOLLOWING |
+ FRAMEOPTION_END_VALUE_FOLLOWING))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("RANGE FOLLOWING is only supported with UNBOUNDED"),
+ parser_errposition(@1)));
+ $$ = n;
}
| ROWS frame_extent
{
- $$ = FRAMEOPTION_NONDEFAULT | FRAMEOPTION_ROWS | $2;
+ WindowDef *n = $2;
+ n->frameOptions |= FRAMEOPTION_NONDEFAULT | FRAMEOPTION_ROWS;
+ $$ = n;
}
| /*EMPTY*/
- { $$ = FRAMEOPTION_DEFAULTS; }
+ {
+ WindowDef *n = makeNode(WindowDef);
+ n->frameOptions = FRAMEOPTION_DEFAULTS;
+ n->startOffset = NULL;
+ n->endOffset = NULL;
+ $$ = n;
+ }
;
frame_extent: frame_bound
{
+ WindowDef *n = $1;
/* reject invalid cases */
- if ($1 & FRAMEOPTION_START_UNBOUNDED_FOLLOWING)
+ if (n->frameOptions & FRAMEOPTION_START_UNBOUNDED_FOLLOWING)
ereport(ERROR,
(errcode(ERRCODE_WINDOWING_ERROR),
errmsg("frame start cannot be UNBOUNDED FOLLOWING"),
parser_errposition(@1)));
- if ($1 & FRAMEOPTION_START_CURRENT_ROW)
+ if (n->frameOptions & FRAMEOPTION_START_VALUE_FOLLOWING)
ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("frame start at CURRENT ROW is not implemented"),
+ (errcode(ERRCODE_WINDOWING_ERROR),
+ errmsg("frame starting from following row cannot end with current row"),
parser_errposition(@1)));
- $$ = $1 | FRAMEOPTION_END_CURRENT_ROW;
+ n->frameOptions |= FRAMEOPTION_END_CURRENT_ROW;
+ $$ = n;
}
| BETWEEN frame_bound AND frame_bound
{
+ WindowDef *n1 = $2;
+ WindowDef *n2 = $4;
+ /* form merged options */
+ int frameOptions = n1->frameOptions;
+ /* shift converts START_ options to END_ options */
+ frameOptions |= n2->frameOptions << 1;
+ frameOptions |= FRAMEOPTION_BETWEEN;
/* reject invalid cases */
- if ($2 & FRAMEOPTION_START_UNBOUNDED_FOLLOWING)
+ if (frameOptions & FRAMEOPTION_START_UNBOUNDED_FOLLOWING)
ereport(ERROR,
(errcode(ERRCODE_WINDOWING_ERROR),
errmsg("frame start cannot be UNBOUNDED FOLLOWING"),
parser_errposition(@2)));
- if ($2 & FRAMEOPTION_START_CURRENT_ROW)
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("frame start at CURRENT ROW is not implemented"),
- parser_errposition(@2)));
- if ($4 & FRAMEOPTION_START_UNBOUNDED_PRECEDING)
+ if (frameOptions & FRAMEOPTION_END_UNBOUNDED_PRECEDING)
ereport(ERROR,
(errcode(ERRCODE_WINDOWING_ERROR),
errmsg("frame end cannot be UNBOUNDED PRECEDING"),
parser_errposition(@4)));
- /* shift converts START_ options to END_ options */
- $$ = FRAMEOPTION_BETWEEN | $2 | ($4 << 1);
+ if ((frameOptions & FRAMEOPTION_START_CURRENT_ROW) &&
+ (frameOptions & FRAMEOPTION_END_VALUE_PRECEDING))
+ ereport(ERROR,
+ (errcode(ERRCODE_WINDOWING_ERROR),
+ errmsg("frame starting from current row cannot have preceding rows"),
+ parser_errposition(@4)));
+ if ((frameOptions & FRAMEOPTION_START_VALUE_FOLLOWING) &&
+ (frameOptions & (FRAMEOPTION_END_VALUE_PRECEDING |
+ FRAMEOPTION_END_CURRENT_ROW)))
+ ereport(ERROR,
+ (errcode(ERRCODE_WINDOWING_ERROR),
+ errmsg("frame starting from following row cannot have preceding rows"),
+ parser_errposition(@4)));
+ n1->frameOptions = frameOptions;
+ n1->endOffset = n2->startOffset;
+ $$ = n1;
}
;
frame_bound:
UNBOUNDED PRECEDING
{
- $$ = FRAMEOPTION_START_UNBOUNDED_PRECEDING;
+ WindowDef *n = makeNode(WindowDef);
+ n->frameOptions = FRAMEOPTION_START_UNBOUNDED_PRECEDING;
+ n->startOffset = NULL;
+ n->endOffset = NULL;
+ $$ = n;
}
| UNBOUNDED FOLLOWING
{
- $$ = FRAMEOPTION_START_UNBOUNDED_FOLLOWING;
+ WindowDef *n = makeNode(WindowDef);
+ n->frameOptions = FRAMEOPTION_START_UNBOUNDED_FOLLOWING;
+ n->startOffset = NULL;
+ n->endOffset = NULL;
+ $$ = n;
}
| CURRENT_P ROW
{
- $$ = FRAMEOPTION_START_CURRENT_ROW;
+ WindowDef *n = makeNode(WindowDef);
+ n->frameOptions = FRAMEOPTION_START_CURRENT_ROW;
+ n->startOffset = NULL;
+ n->endOffset = NULL;
+ $$ = n;
+ }
+ | a_expr PRECEDING
+ {
+ WindowDef *n = makeNode(WindowDef);
+ n->frameOptions = FRAMEOPTION_START_VALUE_PRECEDING;
+ n->startOffset = $1;
+ n->endOffset = NULL;
+ $$ = n;
+ }
+ | a_expr FOLLOWING
+ {
+ WindowDef *n = makeNode(WindowDef);
+ n->frameOptions = FRAMEOPTION_START_VALUE_FOLLOWING;
+ n->startOffset = $1;
+ n->endOffset = NULL;
+ $$ = n;
}
;
}
;
+/* function arguments can have names */
+func_arg_list: func_arg_expr
+ {
+ $$ = list_make1($1);
+ }
+ | func_arg_list ',' func_arg_expr
+ {
+ $$ = lappend($1, $3);
+ }
+ ;
+
+func_arg_expr: a_expr
+ {
+ $$ = $1;
+ }
+ | param_name COLON_EQUALS a_expr
+ {
+ NamedArgExpr *na = makeNode(NamedArgExpr);
+ na->name = $1;
+ na->arg = (Expr *) $3;
+ na->argnumber = -1; /* until determined */
+ na->location = @1;
+ $$ = (Node *) na;
+ }
+ ;
+
type_list: Typename { $$ = list_make1($1); }
| type_list ',' Typename { $$ = lappend($1, $3); }
;
* SQL99 defines the OVERLAY() function:
* o overlay(text placing text from int for int)
* o overlay(text placing text from int)
+ * and similarly for binary strings
*/
overlay_list:
a_expr overlay_placing substr_from substr_for
| /*EMPTY*/ { $$ = NULL; }
;
-/*
- * columnref starts with relation_name not ColId, so that OLD and NEW
- * references can be accepted. Note that when there are more than two
- * dotted names, the first name is not actually a relation name...
- */
-columnref: relation_name
+columnref: ColId
{
$$ = makeColumnRef($1, NIL, @1, yyscanner);
}
- | relation_name indirection
+ | ColId indirection
{
$$ = makeColumnRef($1, $2, @1, yyscanner);
}
*
*****************************************************************************/
-relation_name:
- SpecialRuleRelation { $$ = $1; }
- | ColId { $$ = $1; }
- ;
-
qualified_name_list:
qualified_name { $$ = list_make1($1); }
| qualified_name_list ',' qualified_name { $$ = lappend($1, $3); }
* which may contain subscripts, and reject that case in the C code.
*/
qualified_name:
- relation_name
+ ColId
{
$$ = makeNode(RangeVar);
$$->catalogname = NULL;
$$->relname = $1;
$$->location = @1;
}
- | relation_name indirection
+ | ColId indirection
{
check_qualified_name($2, yyscanner);
$$ = makeNode(RangeVar);
*/
func_name: type_function_name
{ $$ = list_make1(makeString($1)); }
- | relation_name indirection
+ | ColId indirection
{
$$ = check_func_name(lcons(makeString($1), $2),
yyscanner);
t->location = @1;
$$ = makeStringConstCast($2, @2, t);
}
- | func_name '(' expr_list ')' Sconst
+ | func_name '(' func_arg_list ')' Sconst
{
/* generic syntax with a type modifier */
TypeName *t = makeTypeNameFromNameList($1);
+ ListCell *lc;
+
+ /*
+ * We must use func_arg_list in the production to avoid
+ * reduce/reduce conflicts, but we don't actually wish
+ * to allow NamedArgExpr in this context.
+ */
+ foreach(lc, $3)
+ {
+ NamedArgExpr *arg = (NamedArgExpr *) lfirst(lc);
+
+ if (IsA(arg, NamedArgExpr))
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("type modifier cannot have parameter name"),
+ parser_errposition(arg->location)));
+ }
t->typmods = $3;
t->location = @1;
$$ = makeStringConstCast($5, @5, t);
| ASSERTION
| ASSIGNMENT
| AT
+ | ATTRIBUTE
| BACKWARD
| BEFORE
| BEGIN_P
| CLOSE
| CLUSTER
| COMMENT
+ | COMMENTS
| COMMIT
| COMMITTED
- | CONCURRENTLY
| CONFIGURATION
| CONNECTION
| CONSTRAINTS
| ENCRYPTED
| ENUM_P
| ESCAPE
+ | EXCLUDE
| EXCLUDING
| EXCLUSIVE
| EXECUTE
| FORCE
| FORWARD
| FUNCTION
+ | FUNCTIONS
| GLOBAL
| GRANTED
| HANDLER
| INDEXES
| INHERIT
| INHERITS
+ | INLINE_P
| INPUT_P
| INSENSITIVE
| INSERT
| INVOKER
| ISOLATION
| KEY
- | LANCOMPILER
+ | LABEL
| LANGUAGE
| LARGE_P
| LAST_P
| PARSER
| PARTIAL
| PARTITION
+ | PASSING
| PASSWORD
| PLANS
| PRECEDING
| REASSIGN
| RECHECK
| RECURSIVE
+ | REF
| REINDEX
| RELATIVE_P
| RELEASE
| SECOND_P
| SECURITY
| SEQUENCE
+ | SEQUENCES
| SERIALIZABLE
| SERVER
| SESSION
| SUPERUSER_P
| SYSID
| SYSTEM_P
+ | TABLES
| TABLESPACE
| TEMP
| TEMPLATE
* looks too much like a function call for an LR(1) parser.
*/
col_name_keyword:
- BIGINT
+ BETWEEN
+ | BIGINT
| BIT
| BOOLEAN_P
| CHAR_P
| XMLATTRIBUTES
| XMLCONCAT
| XMLELEMENT
+ | XMLEXISTS
| XMLFOREST
| XMLPARSE
| XMLPI
*/
type_func_name_keyword:
AUTHORIZATION
- | BETWEEN
| BINARY
+ | CONCURRENTLY
| CROSS
| CURRENT_SCHEMA
| FREEZE
| LIMIT
| LOCALTIME
| LOCALTIMESTAMP
- | NEW
| NOT
| NULL_P
| OFF
| OFFSET
- | OLD
| ON
| ONLY
| OR
| WITH
;
-
-SpecialRuleRelation:
- OLD
- {
- if (pg_yyget_extra(yyscanner)->QueryIsRule)
- $$ = "*OLD*";
- else
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("OLD used in query that is not in a rule"),
- parser_errposition(@1)));
- }
- | NEW
- {
- if (pg_yyget_extra(yyscanner)->QueryIsRule)
- $$ = "*NEW*";
- else
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("NEW used in query that is not in a rule"),
- parser_errposition(@1)));
- }
- ;
-
%%
/*
* available from the scanner.
*/
static void
-base_yyerror(YYLTYPE *yylloc, base_yyscan_t yyscanner, const char *msg)
+base_yyerror(YYLTYPE *yylloc, core_yyscan_t yyscanner, const char *msg)
{
parser_yyerror(msg);
}
static Node *
makeColumnRef(char *colname, List *indirection,
- int location, base_yyscan_t yyscanner)
+ int location, core_yyscan_t yyscanner)
{
/*
* Generate a ColumnRef node, with an A_Indirection node added if there
* Create and populate a FuncCall node to support the OVERLAPS operator.
*/
static FuncCall *
-makeOverlaps(List *largs, List *rargs, int location, base_yyscan_t yyscanner)
+makeOverlaps(List *largs, List *rargs, int location, core_yyscan_t yyscanner)
{
FuncCall *n = makeNode(FuncCall);
errmsg("wrong number of parameters on right side of OVERLAPS expression"),
parser_errposition(location)));
n->args = list_concat(largs, rargs);
+ n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
* subscripts and '*', which we then must reject here.
*/
static void
-check_qualified_name(List *names, base_yyscan_t yyscanner)
+check_qualified_name(List *names, core_yyscan_t yyscanner)
{
ListCell *i;
* and '*', which we then must reject here.
*/
static List *
-check_func_name(List *names, base_yyscan_t yyscanner)
+check_func_name(List *names, core_yyscan_t yyscanner)
{
ListCell *i;
* in the grammar, so do it here.
*/
static List *
-check_indirection(List *indirection, base_yyscan_t yyscanner)
+check_indirection(List *indirection, core_yyscan_t yyscanner)
{
ListCell *l;
List *sortClause, List *lockingClause,
Node *limitOffset, Node *limitCount,
WithClause *withClause,
- base_yyscan_t yyscanner)
+ core_yyscan_t yyscanner)
{
Assert(IsA(stmt, SelectStmt));
parser_init(base_yy_extra_type *yyext)
{
yyext->parsetree = NIL; /* in case grammar forgets to set it */
- yyext->QueryIsRule = FALSE;
}
/*
}
/*
- * Must undefine base_yylex before including scan.c, since we want it
- * to create the function base_yylex not filtered_base_yylex.
+ * Convert a list of (dotted) names to a RangeVar (like
+ * makeRangeVarFromNameList, but with position support). The
+ * "AnyName" refers to the any_name production in the grammar.
*/
-#undef base_yylex
+static RangeVar *
+makeRangeVarFromAnyName(List *names, int position, core_yyscan_t yyscanner)
+{
+ RangeVar *r = makeNode(RangeVar);
+
+ switch (list_length(names))
+ {
+ case 1:
+ r->catalogname = NULL;
+ r->schemaname = NULL;
+ r->relname = strVal(linitial(names));
+ break;
+ case 2:
+ r->catalogname = NULL;
+ r->schemaname = strVal(linitial(names));
+ r->relname = strVal(lsecond(names));
+ break;
+ case 3:
+ r->catalogname = strVal(linitial(names));;
+ r->schemaname = strVal(lsecond(names));
+ r->relname = strVal(lthird(names));
+ break;
+ default:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("improper qualified name (too many dotted names): %s",
+ NameListToString(names)),
+ parser_errposition(position)));
+ break;
+ }
+
+ r->location = position;
-/* Undefine some other stuff that would conflict in scan.c, too */
+ return r;
+}
+
+/*
+ * Must undefine this stuff before including scan.c, since it has different
+ * definitions for these macros.
+ */
#undef yyerror
#undef yylval
#undef yylloc