gram.y
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:141k
- %{ /* -*-text-*- */
- /*#define YYDEBUG 1*/
- /*-------------------------------------------------------------------------
- *
- * gram.y
- * POSTGRES SQL YACC rules/actions
- *
- * Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- * $Header: /usr/local/cvsroot/pgsql/src/backend/parser/gram.y,v 2.88.2.2 1999/09/14 06:07:35 thomas Exp $
- *
- * HISTORY
- * AUTHOR DATE MAJOR EVENT
- * Andrew Yu Sept, 1994 POSTQUEL to SQL conversion
- * Andrew Yu Oct, 1994 lispy code conversion
- *
- * NOTES
- * CAPITALS are used to represent terminal symbols.
- * non-capitals are used to represent non-terminals.
- * SQL92-specific syntax is separated from plain SQL/Postgres syntax
- * to help isolate the non-extensible portions of the parser.
- *
- * if you use list, make sure the datum is a node so that the printing
- * routines work
- *
- * WARNING
- * sometimes we assign constants to makeStrings. Make sure we don't free
- * those.
- *
- *-------------------------------------------------------------------------
- */
- #include <string.h>
- #include <ctype.h>
- #include "postgres.h"
- #include "access/htup.h"
- #include "nodes/parsenodes.h"
- #include "nodes/print.h"
- #include "parser/gramparse.h"
- #include "parser/parse_type.h"
- #include "utils/acl.h"
- #include "utils/palloc.h"
- #include "catalog/catname.h"
- #include "utils/elog.h"
- #include "access/xact.h"
- #include "storage/lmgr.h"
- #include "utils/numeric.h"
- #include "parser/analyze.h"
- #include "catalog/pg_type.h"
- #ifdef MULTIBYTE
- #include "mb/pg_wchar.h"
- #endif
- static char saved_relname[NAMEDATALEN]; /* need this for complex attributes */
- static bool QueryIsRule = FALSE;
- static List *saved_In_Expr = NIL;
- static Oid *param_type_info;
- static int pfunc_num_args;
- extern List *parsetree;
- /*
- * If you need access to certain yacc-generated variables and find that
- * they're static by default, uncomment the next line. (this is not a
- * problem, yet.)
- */
- /*#define __YYSCLASS*/
- static char *xlateSqlFunc(char *);
- static char *xlateSqlType(char *);
- static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
- static Node *makeRowExpr(char *opr, List *largs, List *rargs);
- static void mapTargetColumns(List *source, List *target);
- static List *makeConstantList( A_Const *node);
- static char *FlattenStringList(List *list);
- static char *fmtId(char *rawid);
- static Node *makeIndexable(char *opname, Node *lexpr, Node *rexpr);
- static void param_type_init(Oid *typev, int nargs);
- static Node *doNegate(Node *n);
- Oid param_type(int t); /* used in parse_expr.c */
- /* old versions of flex define this as a macro */
- #if defined(yywrap)
- #undef yywrap
- #endif /* yywrap */
- %}
- %union
- {
- double dval;
- int ival;
- char chr;
- char *str;
- bool boolean;
- bool* pboolean; /* for pg_shadow privileges */
- List *list;
- Node *node;
- Value *value;
- Attr *attr;
- TypeName *typnam;
- DefElem *defelt;
- ParamString *param;
- SortGroupBy *sortgroupby;
- JoinExpr *joinexpr;
- IndexElem *ielem;
- RangeVar *range;
- RelExpr *relexp;
- A_Indices *aind;
- ResTarget *target;
- ParamNo *paramno;
- VersionStmt *vstmt;
- DefineStmt *dstmt;
- RuleStmt *rstmt;
- InsertStmt *astmt;
- }
- %type <node> stmt,
- AddAttrStmt, ClosePortalStmt,
- CopyStmt, CreateStmt, CreateAsStmt, CreateSeqStmt, DefineStmt, DestroyStmt,
- ExtendStmt, FetchStmt, GrantStmt, CreateTrigStmt, DropTrigStmt,
- CreatePLangStmt, DropPLangStmt,
- IndexStmt, ListenStmt, UnlistenStmt, LockStmt, OptimizableStmt,
- ProcedureStmt, RemoveAggrStmt, RemoveOperStmt,
- RemoveFuncStmt, RemoveStmt,
- RenameStmt, RevokeStmt, RuleStmt, TransactionStmt, ViewStmt, LoadStmt,
- CreatedbStmt, DestroydbStmt, VacuumStmt, CursorStmt, SubSelect,
- UpdateStmt, InsertStmt, select_clause, SelectStmt, NotifyStmt, DeleteStmt,
- ClusterStmt, ExplainStmt, VariableSetStmt, VariableShowStmt, VariableResetStmt,
- CreateUserStmt, AlterUserStmt, DropUserStmt, RuleActionStmt
- %type <str> opt_database1, opt_database2, location, encoding
- %type <ival> opt_lock, lock_type
- %type <boolean> opt_lmode
- %type <pboolean> user_createdb_clause, user_createuser_clause
- %type <str> user_passwd_clause
- %type <str> user_valid_clause
- %type <list> user_group_list, user_group_clause
- %type <boolean> TriggerActionTime, TriggerForSpec, PLangTrusted
- %type <str> TriggerEvents, TriggerFuncArg
- %type <str> relation_name, copy_file_name, copy_delimiter, def_name,
- database_name, access_method_clause, access_method, attr_name,
- class, index_name, name, func_name, file_name, aggr_argtype
- %type <str> opt_id, opt_portal_name,
- all_Op, MathOp, opt_name, opt_unique,
- OptUseOp, opt_class, SpecialRuleRelation
- %type <str> opt_level
- %type <str> privileges, operation_commalist, grantee
- %type <chr> operation, TriggerOneEvent
- %type <list> stmtblock, stmtmulti,
- result, relation_name_list, OptTableElementList,
- OptInherit, definition,
- opt_with, func_args, func_args_list,
- oper_argtypes, RuleActionList, RuleActionBlock, RuleActionMulti,
- opt_column_list, columnList, opt_va_list, va_list,
- sort_clause, sortby_list, index_params, index_list, name_list,
- from_clause, from_expr, table_list, opt_array_bounds, nest_array_bounds,
- expr_list, attrs, res_target_list, res_target_list2,
- def_list, opt_indirection, group_clause, TriggerFuncArgs,
- opt_select_limit
- %type <node> func_return
- %type <boolean> set_opt
- %type <boolean> TriggerForOpt, TriggerForType, OptTemp, OptTempType, OptTempScope
- %type <list> for_update_clause, update_list
- %type <boolean> opt_union
- %type <boolean> opt_table
- %type <boolean> opt_trans
- %type <list> join_clause_with_union, join_clause, join_list, join_qual, using_list
- %type <node> join_expr, using_expr
- %type <str> join_outer
- %type <ival> join_type
- %type <node> position_expr
- %type <list> extract_list, position_list
- %type <list> substr_list, substr_from, substr_for, trim_list
- %type <list> opt_interval
- %type <boolean> opt_inh_star, opt_binary, opt_instead, opt_with_copy,
- index_opt_unique, opt_verbose, opt_analyze
- %type <boolean> opt_cursor
- %type <ival> copy_dirn, def_type, opt_direction, remove_type,
- opt_column, event
- %type <ival> fetch_how_many
- %type <node> select_limit_value, select_offset_value
- %type <list> OptSeqList
- %type <defelt> OptSeqElem
- %type <dstmt> def_rest
- %type <astmt> insert_rest
- %type <node> OptTableElement, ConstraintElem
- %type <node> columnDef, alter_clause
- %type <defelt> def_elem
- %type <node> def_arg, columnElem, where_clause,
- a_expr, a_expr_or_null, b_expr, AexprConst,
- in_expr, in_expr_nodes, not_in_expr, not_in_expr_nodes,
- having_clause
- %type <list> row_descriptor, row_list, c_list, c_expr
- %type <node> row_expr
- %type <str> row_op
- %type <node> case_expr, case_arg, when_clause, case_default
- %type <list> when_clause_list
- %type <ival> sub_type
- %type <list> OptCreateAs, CreateAsList
- %type <node> CreateAsElement
- %type <value> NumericOnly, FloatOnly, IntegerOnly
- %type <attr> event_object, attr
- %type <sortgroupby> sortby
- %type <ielem> index_elem, func_index
- %type <range> table_expr
- %type <relexp> relation_expr
- %type <target> res_target_el, res_target_el2
- %type <paramno> ParamNo
- %type <typnam> Typename, opt_type, Array, Generic, Character, Datetime, Numeric
- %type <str> generic, numeric, character, datetime
- %type <str> extract_arg
- %type <str> opt_charset, opt_collate
- %type <str> opt_float
- %type <ival> opt_numeric, opt_decimal
- %type <boolean> opt_varying, opt_timezone
- %type <ival> Iconst
- %type <str> Sconst
- %type <str> UserId, var_value, zone_value
- %type <str> ColId, ColLabel
- %type <str> TypeId
- %type <node> TableConstraint
- %type <list> constraint_list, constraint_expr
- %type <list> default_list, default_expr
- %type <list> ColPrimaryKey, ColQualList, ColQualifier
- %type <node> ColConstraint, ColConstraintElem
- %type <list> key_actions, key_action
- %type <str> key_match, key_reference
- /*
- * If you make any token changes, remember to:
- * - use "yacc -d" and update parse.h
- * - update the keyword table in parser/keywords.c
- */
- /* Reserved word tokens
- * SQL92 syntax has many type-specific constructs.
- * So, go ahead and make these types reserved words,
- * and call-out the syntax explicitly.
- * This gets annoying when trying to also retain Postgres' nice
- * type-extensible features, but we don't really have a choice.
- * - thomas 1997-10-11
- */
- /* Keywords (in SQL92 reserved words) */
- %token ABSOLUTE, ACTION, ADD, ALL, ALTER, AND, ANY, AS, ASC,
- BEGIN_TRANS, BETWEEN, BOTH, BY,
- CASCADE, CASE, CAST, CHAR, CHARACTER, CHECK, CLOSE,
- COALESCE, COLLATE, COLUMN, COMMIT,
- CONSTRAINT, CREATE, CROSS, CURRENT, CURRENT_DATE, CURRENT_TIME,
- CURRENT_TIMESTAMP, CURRENT_USER, CURSOR,
- DAY_P, DECIMAL, DECLARE, DEFAULT, DELETE, DESC, DISTINCT, DOUBLE, DROP,
- ELSE, END_TRANS, EXCEPT, EXECUTE, EXISTS, EXTRACT,
- FALSE_P, FETCH, FLOAT, FOR, FOREIGN, FROM, FULL,
- GLOBAL, GRANT, GROUP, HAVING, HOUR_P,
- IN, INNER_P, INSENSITIVE, INSERT, INTERSECT, INTERVAL, INTO, IS,
- ISOLATION, JOIN, KEY, LANGUAGE, LEADING, LEFT, LEVEL, LIKE, LOCAL,
- MATCH, MINUTE_P, MONTH_P, NAMES,
- NATIONAL, NATURAL, NCHAR, NEXT, NO, NOT, NULLIF, NULL_P, NUMERIC,
- OF, ON, ONLY, OPTION, OR, ORDER, OUTER_P,
- PARTIAL, POSITION, PRECISION, PRIMARY, PRIOR, PRIVILEGES, PROCEDURE, PUBLIC,
- READ, REFERENCES, RELATIVE, REVOKE, RIGHT, ROLLBACK,
- SCROLL, SECOND_P, SELECT, SET, SUBSTRING,
- TABLE, TEMP, TEMPORARY, THEN, TIME, TIMESTAMP, TIMEZONE_HOUR,
- TIMEZONE_MINUTE, TO, TRAILING, TRANSACTION, TRIM, TRUE_P,
- UNION, UNIQUE, UPDATE, USER, USING,
- VALUES, VARCHAR, VARYING, VIEW,
- WHEN, WHERE, WITH, WORK, YEAR_P, ZONE
- /* Keywords (in SQL3 reserved words) */
- %token TRIGGER
- /* Keywords (in SQL92 non-reserved words) */
- %token COMMITTED, SERIALIZABLE, TYPE_P
- /* Keywords for Postgres support (not in SQL92 reserved words)
- *
- * The CREATEDB and CREATEUSER tokens should go away
- * when some sort of pg_privileges relation is introduced.
- * - Todd A. Brandys 1998-01-01?
- */
- %token ABORT_TRANS, ACCESS, AFTER, AGGREGATE, ANALYZE,
- BACKWARD, BEFORE, BINARY,
- CACHE, CLUSTER, COPY, CREATEDB, CREATEUSER, CYCLE,
- DATABASE, DELIMITERS, DO,
- EACH, ENCODING, EXCLUSIVE, EXPLAIN, EXTEND,
- FORWARD, FUNCTION, HANDLER,
- INCREMENT, INDEX, INHERITS, INSTEAD, ISNULL,
- LANCOMPILER, LIMIT, LISTEN, LOAD, LOCATION, LOCK_P,
- MAXVALUE, MINVALUE, MODE, MOVE,
- NEW, NOCREATEDB, NOCREATEUSER, NONE, NOTHING, NOTIFY, NOTNULL,
- OFFSET, OIDS, OPERATOR, PASSWORD, PROCEDURAL,
- RENAME, RESET, RETURNS, ROW, RULE,
- SEQUENCE, SERIAL, SETOF, SHARE, SHOW, START, STATEMENT, STDIN, STDOUT,
- TRUSTED,
- UNLISTEN, UNTIL, VACUUM, VALID, VERBOSE, VERSION
- /* Special keywords, not in the query language - see the "lex" file */
- %token <str> IDENT, SCONST, Op
- %token <ival> ICONST, PARAM
- %token <dval> FCONST
- /* these are not real. they are here so that they get generated as #define's*/
- %token OP
- /* precedence */
- %left OR
- %left AND
- %right NOT
- %right '='
- %nonassoc '<' '>'
- %nonassoc LIKE
- %nonassoc BETWEEN
- %nonassoc IN
- %left Op /* multi-character ops and user-defined operators */
- %nonassoc NOTNULL
- %nonassoc ISNULL
- %nonassoc NULL_P
- %nonassoc IS
- %left '+' '-'
- %left '*' '/' '%'
- %left '^'
- %left '|' /* this is the relation union op, not logical or */
- /* Unary Operators */
- %right ':'
- %left ';' /* end of statement or natural log */
- %right UMINUS
- %left '.'
- %left '[' ']'
- %nonassoc TYPECAST
- %left UNION INTERSECT EXCEPT
- %%
- stmtblock: stmtmulti opt_semi
- { parsetree = $1; }
- ;
- stmtmulti: stmtmulti ';' stmt
- { $$ = lappend($1, $3); }
- | stmt
- { $$ = lcons($1,NIL); }
- ;
- opt_semi: ';'
- | /*EMPTY*/
- ;
-
- stmt : AddAttrStmt
- | AlterUserStmt
- | ClosePortalStmt
- | CopyStmt
- | CreateStmt
- | CreateAsStmt
- | CreateSeqStmt
- | CreatePLangStmt
- | CreateTrigStmt
- | CreateUserStmt
- | ClusterStmt
- | DefineStmt
- | DestroyStmt
- | DropPLangStmt
- | DropTrigStmt
- | DropUserStmt
- | ExtendStmt
- | ExplainStmt
- | FetchStmt
- | GrantStmt
- | IndexStmt
- | ListenStmt
- | UnlistenStmt
- | LockStmt
- | ProcedureStmt
- | RemoveAggrStmt
- | RemoveOperStmt
- | RemoveFuncStmt
- | RemoveStmt
- | RenameStmt
- | RevokeStmt
- | OptimizableStmt
- | RuleStmt
- | TransactionStmt
- | ViewStmt
- | LoadStmt
- | CreatedbStmt
- | DestroydbStmt
- | VacuumStmt
- | VariableSetStmt
- | VariableShowStmt
- | VariableResetStmt
- ;
- /*****************************************************************************
- *
- * Create a new Postgres DBMS user
- *
- *
- *****************************************************************************/
- CreateUserStmt: CREATE USER UserId user_passwd_clause user_createdb_clause
- user_createuser_clause user_group_clause user_valid_clause
- {
- CreateUserStmt *n = makeNode(CreateUserStmt);
- n->user = $3;
- n->password = $4;
- n->createdb = $5;
- n->createuser = $6;
- n->groupElts = $7;
- n->validUntil = $8;
- $$ = (Node *)n;
- }
- ;
- /*****************************************************************************
- *
- * Alter a postresql DBMS user
- *
- *
- *****************************************************************************/
- AlterUserStmt: ALTER USER UserId user_passwd_clause user_createdb_clause
- user_createuser_clause user_group_clause user_valid_clause
- {
- AlterUserStmt *n = makeNode(AlterUserStmt);
- n->user = $3;
- n->password = $4;
- n->createdb = $5;
- n->createuser = $6;
- n->groupElts = $7;
- n->validUntil = $8;
- $$ = (Node *)n;
- }
- ;
- /*****************************************************************************
- *
- * Drop a postresql DBMS user
- *
- *
- *****************************************************************************/
- DropUserStmt: DROP USER UserId
- {
- DropUserStmt *n = makeNode(DropUserStmt);
- n->user = $3;
- $$ = (Node *)n;
- }
- ;
- user_passwd_clause: WITH PASSWORD UserId { $$ = $3; }
- | /*EMPTY*/ { $$ = NULL; }
- ;
- user_createdb_clause: CREATEDB
- {
- bool* b;
- $$ = (b = (bool*)palloc(sizeof(bool)));
- *b = true;
- }
- | NOCREATEDB
- {
- bool* b;
- $$ = (b = (bool*)palloc(sizeof(bool)));
- *b = false;
- }
- | /*EMPTY*/ { $$ = NULL; }
- ;
- user_createuser_clause: CREATEUSER
- {
- bool* b;
- $$ = (b = (bool*)palloc(sizeof(bool)));
- *b = true;
- }
- | NOCREATEUSER
- {
- bool* b;
- $$ = (b = (bool*)palloc(sizeof(bool)));
- *b = false;
- }
- | /*EMPTY*/ { $$ = NULL; }
- ;
- user_group_list: user_group_list ',' UserId
- {
- $$ = lcons((void*)makeString($3), $1);
- }
- | UserId
- {
- $$ = lcons((void*)makeString($1), NIL);
- }
- ;
- user_group_clause: IN GROUP user_group_list { $$ = $3; }
- | /*EMPTY*/ { $$ = NULL; }
- ;
- user_valid_clause: VALID UNTIL SCONST { $$ = $3; }
- | /*EMPTY*/ { $$ = NULL; }
- ;
- /*****************************************************************************
- *
- * Set PG internal variable
- * SET name TO 'var_value'
- * Include SQL92 syntax (thomas 1997-10-22):
- * SET TIME ZONE 'var_value'
- *
- *****************************************************************************/
- VariableSetStmt: SET ColId TO var_value
- {
- VariableSetStmt *n = makeNode(VariableSetStmt);
- n->name = $2;
- n->value = $4;
- $$ = (Node *) n;
- }
- | SET ColId '=' var_value
- {
- VariableSetStmt *n = makeNode(VariableSetStmt);
- n->name = $2;
- n->value = $4;
- $$ = (Node *) n;
- }
- | SET TIME ZONE zone_value
- {
- VariableSetStmt *n = makeNode(VariableSetStmt);
- n->name = "timezone";
- n->value = $4;
- $$ = (Node *) n;
- }
- | SET TRANSACTION ISOLATION LEVEL opt_level
- {
- VariableSetStmt *n = makeNode(VariableSetStmt);
- n->name = "XactIsoLevel";
- n->value = $5;
- $$ = (Node *) n;
- }
- | SET NAMES encoding
- {
- #ifdef MULTIBYTE
- VariableSetStmt *n = makeNode(VariableSetStmt);
- n->name = "client_encoding";
- n->value = $3;
- $$ = (Node *) n;
- #else
- elog(ERROR, "SET NAMES is not supported");
- #endif
- }
- ;
- opt_level: READ COMMITTED { $$ = "committed"; }
- | SERIALIZABLE { $$ = "serializable"; }
- ;
- var_value: Sconst { $$ = $1; }
- | DEFAULT { $$ = NULL; }
- ;
- zone_value: Sconst { $$ = $1; }
- | DEFAULT { $$ = NULL; }
- | LOCAL { $$ = NULL; }
- ;
- VariableShowStmt: SHOW ColId
- {
- VariableShowStmt *n = makeNode(VariableShowStmt);
- n->name = $2;
- $$ = (Node *) n;
- }
- | SHOW TIME ZONE
- {
- VariableShowStmt *n = makeNode(VariableShowStmt);
- n->name = "timezone";
- $$ = (Node *) n;
- }
- | SHOW TRANSACTION ISOLATION LEVEL
- {
- VariableShowStmt *n = makeNode(VariableShowStmt);
- n->name = "XactIsoLevel";
- $$ = (Node *) n;
- }
- ;
- VariableResetStmt: RESET ColId
- {
- VariableResetStmt *n = makeNode(VariableResetStmt);
- n->name = $2;
- $$ = (Node *) n;
- }
- | RESET TIME ZONE
- {
- VariableResetStmt *n = makeNode(VariableResetStmt);
- n->name = "timezone";
- $$ = (Node *) n;
- }
- | RESET TRANSACTION ISOLATION LEVEL
- {
- VariableResetStmt *n = makeNode(VariableResetStmt);
- n->name = "XactIsoLevel";
- $$ = (Node *) n;
- }
- ;
- /*****************************************************************************
- *
- * QUERY :
- * addattr ( attr1 = type1 .. attrn = typen ) to <relname> [*]
- *
- *****************************************************************************/
- AddAttrStmt: ALTER TABLE relation_name opt_inh_star alter_clause
- {
- AddAttrStmt *n = makeNode(AddAttrStmt);
- n->relname = $3;
- n->inh = $4;
- n->colDef = $5;
- $$ = (Node *)n;
- }
- ;
- alter_clause: ADD opt_column columnDef
- {
- $$ = $3;
- }
- | ADD '(' OptTableElementList ')'
- {
- Node *lp = lfirst($3);
- if (length($3) != 1)
- elog(ERROR,"ALTER TABLE/ADD() allows one column only");
- $$ = lp;
- }
- | DROP opt_column ColId
- { elog(ERROR,"ALTER TABLE/DROP COLUMN not yet implemented"); }
- | ALTER opt_column ColId SET DEFAULT default_expr
- { elog(ERROR,"ALTER TABLE/ALTER COLUMN/SET DEFAULT not yet implemented"); }
- | ALTER opt_column ColId DROP DEFAULT
- { elog(ERROR,"ALTER TABLE/ALTER COLUMN/DROP DEFAULT not yet implemented"); }
- | ADD ConstraintElem
- { elog(ERROR,"ALTER TABLE/ADD CONSTRAINT not yet implemented"); }
- ;
- /*****************************************************************************
- *
- * QUERY :
- * close <optname>
- *
- *****************************************************************************/
- ClosePortalStmt: CLOSE opt_id
- {
- ClosePortalStmt *n = makeNode(ClosePortalStmt);
- n->portalname = $2;
- $$ = (Node *)n;
- }
- ;
- /*****************************************************************************
- *
- * QUERY :
- * COPY [BINARY] <relname> FROM/TO
- * [USING DELIMITERS <delimiter>]
- *
- *****************************************************************************/
- CopyStmt: COPY opt_binary relation_name opt_with_copy copy_dirn copy_file_name copy_delimiter
- {
- CopyStmt *n = makeNode(CopyStmt);
- n->binary = $2;
- n->relname = $3;
- n->oids = $4;
- n->direction = $5;
- n->filename = $6;
- n->delimiter = $7;
- $$ = (Node *)n;
- }
- ;
- copy_dirn: TO
- { $$ = TO; }
- | FROM
- { $$ = FROM; }
- ;
- /*
- * copy_file_name NULL indicates stdio is used. Whether stdin or stdout is
- * used depends on the direction. (It really doesn't make sense to copy from
- * stdout. We silently correct the "typo". - AY 9/94
- */
- copy_file_name: Sconst { $$ = $1; }
- | STDIN { $$ = NULL; }
- | STDOUT { $$ = NULL; }
- ;
- opt_binary: BINARY { $$ = TRUE; }
- | /*EMPTY*/ { $$ = FALSE; }
- ;
- opt_with_copy: WITH OIDS { $$ = TRUE; }
- | /*EMPTY*/ { $$ = FALSE; }
- ;
- /*
- * the default copy delimiter is tab but the user can configure it
- */
- copy_delimiter: USING DELIMITERS Sconst { $$ = $3; }
- | /*EMPTY*/ { $$ = "t"; }
- ;
- /*****************************************************************************
- *
- * QUERY :
- * CREATE relname
- *
- *****************************************************************************/
- CreateStmt: CREATE OptTemp TABLE relation_name '(' OptTableElementList ')'
- OptInherit
- {
- CreateStmt *n = makeNode(CreateStmt);
- n->istemp = $2;
- n->relname = $4;
- n->tableElts = $6;
- n->inhRelnames = $8;
- n->constraints = NIL;
- $$ = (Node *)n;
- }
- ;
- OptTemp: OptTempType { $$ = $1; }
- | OptTempScope OptTempType { $$ = $2; }
- ;
- OptTempType: TEMP { $$ = TRUE; }
- | TEMPORARY { $$ = TRUE; }
- | /*EMPTY*/ { $$ = FALSE; }
- ;
- OptTempScope: GLOBAL
- {
- elog(ERROR, "GLOBAL TEMPORARY TABLE is not currently supported");
- $$ = TRUE;
- }
- | LOCAL
- {
- $$ = FALSE;
- }
- ;
- OptTableElementList: OptTableElementList ',' OptTableElement
- {
- if ($3 != NULL)
- $$ = lappend($1, $3);
- else
- $$ = $1;
- }
- | OptTableElement
- {
- if ($1 != NULL)
- $$ = lcons($1, NIL);
- else
- $$ = NULL;
- }
- | /*EMPTY*/ { $$ = NULL; }
- ;
- OptTableElement: columnDef { $$ = $1; }
- | TableConstraint { $$ = $1; }
- ;
- columnDef: ColId Typename ColQualifier
- {
- ColumnDef *n = makeNode(ColumnDef);
- n->colname = $1;
- n->typename = $2;
- n->defval = NULL;
- n->is_not_null = FALSE;
- n->constraints = $3;
- $$ = (Node *)n;
- }
- | ColId SERIAL ColPrimaryKey
- {
- ColumnDef *n = makeNode(ColumnDef);
- n->colname = $1;
- n->typename = makeNode(TypeName);
- n->typename->name = xlateSqlType("integer");
- n->defval = NULL;
- n->is_not_null = TRUE;
- n->is_sequence = TRUE;
- n->constraints = $3;
- $$ = (Node *)n;
- }
- ;
- ColQualifier: ColQualList { $$ = $1; }
- | /*EMPTY*/ { $$ = NULL; }
- ;
- ColQualList: ColQualList ColConstraint
- {
- if ($2 != NULL)
- $$ = lappend($1, $2);
- else
- $$ = $1;
- }
- | ColConstraint
- {
- if ($1 != NULL)
- $$ = lcons($1, NIL);
- else
- $$ = NULL;
- }
- ;
- ColPrimaryKey: PRIMARY KEY
- {
- Constraint *n = makeNode(Constraint);
- n->contype = CONSTR_PRIMARY;
- n->name = NULL;
- n->def = NULL;
- n->keys = NULL;
- $$ = lcons((Node *)n, NIL);
- }
- | /*EMPTY*/ { $$ = NULL; }
- ;
- ColConstraint:
- CONSTRAINT name ColConstraintElem
- {
- Constraint *n = (Constraint *)$3;
- if (n != NULL) n->name = fmtId($2);
- $$ = $3;
- }
- | ColConstraintElem
- { $$ = $1; }
- ;
- /* DEFAULT NULL is already the default for Postgres.
- * Bue define it here and carry it forward into the system
- * to make it explicit.
- * - thomas 1998-09-13
- * WITH NULL and NULL are not SQL92-standard syntax elements,
- * so leave them out. Use DEFAULT NULL to explicitly indicate
- * that a column may have that value. WITH NULL leads to
- * shift/reduce conflicts with WITH TIME ZONE anyway.
- * - thomas 1999-01-08
- */
- ColConstraintElem: CHECK '(' constraint_expr ')'
- {
- Constraint *n = makeNode(Constraint);
- n->contype = CONSTR_CHECK;
- n->name = NULL;
- n->def = FlattenStringList($3);
- n->keys = NULL;
- $$ = (Node *)n;
- }
- | DEFAULT NULL_P
- {
- Constraint *n = makeNode(Constraint);
- n->contype = CONSTR_DEFAULT;
- n->name = NULL;
- n->def = NULL;
- n->keys = NULL;
- $$ = (Node *)n;
- }
- | DEFAULT default_expr
- {
- Constraint *n = makeNode(Constraint);
- n->contype = CONSTR_DEFAULT;
- n->name = NULL;
- n->def = FlattenStringList($2);
- n->keys = NULL;
- $$ = (Node *)n;
- }
- | NOT NULL_P
- {
- Constraint *n = makeNode(Constraint);
- n->contype = CONSTR_NOTNULL;
- n->name = NULL;
- n->def = NULL;
- n->keys = NULL;
- $$ = (Node *)n;
- }
- | UNIQUE
- {
- Constraint *n = makeNode(Constraint);
- n->contype = CONSTR_UNIQUE;
- n->name = NULL;
- n->def = NULL;
- n->keys = NULL;
- $$ = (Node *)n;
- }
- | PRIMARY KEY
- {
- Constraint *n = makeNode(Constraint);
- n->contype = CONSTR_PRIMARY;
- n->name = NULL;
- n->def = NULL;
- n->keys = NULL;
- $$ = (Node *)n;
- }
- | REFERENCES ColId opt_column_list key_match key_actions
- {
- elog(NOTICE,"CREATE TABLE/FOREIGN KEY clause ignored; not yet implemented");
- $$ = NULL;
- }
- ;
- default_list: default_list ',' default_expr
- {
- $$ = lappend($1,makeString(","));
- $$ = nconc($$, $3);
- }
- | default_expr
- {
- $$ = $1;
- }
- ;
- /* The Postgres default column value is NULL.
- * Rather than carrying DEFAULT NULL forward as a clause,
- * let's just have it be a no-op.
- | NULL_P
- { $$ = lcons( makeString("NULL"), NIL); }
- * - thomas 1998-09-13
- */
- default_expr: AexprConst
- { $$ = makeConstantList((A_Const *) $1); }
- | '-' default_expr %prec UMINUS
- { $$ = lcons( makeString( "-"), $2); }
- | default_expr '+' default_expr
- { $$ = nconc( $1, lcons( makeString( "+"), $3)); }
- | default_expr '-' default_expr
- { $$ = nconc( $1, lcons( makeString( "-"), $3)); }
- | default_expr '/' default_expr
- { $$ = nconc( $1, lcons( makeString( "/"), $3)); }
- | default_expr '%' default_expr
- { $$ = nconc( $1, lcons( makeString( "%"), $3)); }
- | default_expr '*' default_expr
- { $$ = nconc( $1, lcons( makeString( "*"), $3)); }
- | default_expr '^' default_expr
- { $$ = nconc( $1, lcons( makeString( "^"), $3)); }
- | default_expr '=' default_expr
- { elog(ERROR,"boolean expressions not supported in DEFAULT"); }
- | default_expr '<' default_expr
- { elog(ERROR,"boolean expressions not supported in DEFAULT"); }
- | default_expr '>' default_expr
- { elog(ERROR,"boolean expressions not supported in DEFAULT"); }
- | ':' default_expr
- { $$ = lcons( makeString( ":"), $2); }
- | ';' default_expr
- { $$ = lcons( makeString( ";"), $2); }
- | '|' default_expr
- { $$ = lcons( makeString( "|"), $2); }
- | default_expr TYPECAST Typename
- {
- $3->name = fmtId($3->name);
- $$ = nconc( lcons( makeString( "CAST"), $1), makeList( makeString("AS"), $3, -1));
- }
- | CAST '(' default_expr AS Typename ')'
- {
- $5->name = fmtId($5->name);
- $$ = nconc( lcons( makeString( "CAST"), $3), makeList( makeString("AS"), $5, -1));
- }
- | '(' default_expr ')'
- { $$ = lappend( lcons( makeString( "("), $2), makeString( ")")); }
- | func_name '(' ')'
- {
- $$ = makeList( makeString($1), makeString("("), -1);
- $$ = lappend( $$, makeString(")"));
- }
- | func_name '(' default_list ')'
- {
- $$ = makeList( makeString($1), makeString("("), -1);
- $$ = nconc( $$, $3);
- $$ = lappend( $$, makeString(")"));
- }
- | default_expr Op default_expr
- {
- if (!strcmp("<=", $2) || !strcmp(">=", $2))
- elog(ERROR,"boolean expressions not supported in DEFAULT");
- $$ = nconc( $1, lcons( makeString( $2), $3));
- }
- | Op default_expr
- { $$ = lcons( makeString( $1), $2); }
- | default_expr Op
- { $$ = lappend( $1, makeString( $2)); }
- /* XXX - thomas 1997-10-07 v6.2 function-specific code to be changed */
- | CURRENT_DATE
- { $$ = lcons( makeString( "date( 'current'::datetime + '0 sec')"), NIL); }
- | CURRENT_TIME
- { $$ = lcons( makeString( "'now'::time"), NIL); }
- | CURRENT_TIME '(' Iconst ')'
- {
- if ($3 != 0)
- elog(NOTICE,"CURRENT_TIME(%d) precision not implemented; zero used instead",$3);
- $$ = lcons( makeString( "'now'::time"), NIL);
- }
- | CURRENT_TIMESTAMP
- { $$ = lcons( makeString( "now()"), NIL); }
- | CURRENT_TIMESTAMP '(' Iconst ')'
- {
- if ($3 != 0)
- elog(NOTICE,"CURRENT_TIMESTAMP(%d) precision not implemented; zero used instead",$3);
- $$ = lcons( makeString( "now()"), NIL);
- }
- | CURRENT_USER
- { $$ = lcons( makeString( "CURRENT_USER"), NIL); }
- | USER
- { $$ = lcons( makeString( "USER"), NIL); }
- ;
- /* ConstraintElem specifies constraint syntax which is not embedded into
- * a column definition. ColConstraintElem specifies the embedded form.
- * - thomas 1997-12-03
- */
- TableConstraint: CONSTRAINT name ConstraintElem
- {
- Constraint *n = (Constraint *)$3;
- if (n != NULL) n->name = fmtId($2);
- $$ = $3;
- }
- | ConstraintElem
- { $$ = $1; }
- ;
- ConstraintElem: CHECK '(' constraint_expr ')'
- {
- Constraint *n = makeNode(Constraint);
- n->contype = CONSTR_CHECK;
- n->name = NULL;
- n->def = FlattenStringList($3);
- $$ = (Node *)n;
- }
- | UNIQUE '(' columnList ')'
- {
- Constraint *n = makeNode(Constraint);
- n->contype = CONSTR_UNIQUE;
- n->name = NULL;
- n->def = NULL;
- n->keys = $3;
- $$ = (Node *)n;
- }
- | PRIMARY KEY '(' columnList ')'
- {
- Constraint *n = makeNode(Constraint);
- n->contype = CONSTR_PRIMARY;
- n->name = NULL;
- n->def = NULL;
- n->keys = $4;
- $$ = (Node *)n;
- }
- | FOREIGN KEY '(' columnList ')' REFERENCES ColId opt_column_list key_match key_actions
- {
- elog(NOTICE,"CREATE TABLE/FOREIGN KEY clause ignored; not yet implemented");
- $$ = NULL;
- }
- ;
- constraint_list: constraint_list ',' constraint_expr
- {
- $$ = lappend($1,makeString(","));
- $$ = nconc($$, $3);
- }
- | constraint_expr
- {
- $$ = $1;
- }
- ;
- constraint_expr: AexprConst
- { $$ = makeConstantList((A_Const *) $1); }
- | NULL_P
- { $$ = lcons( makeString("NULL"), NIL); }
- | ColId
- {
- $$ = lcons( makeString(fmtId($1)), NIL);
- }
- | '-' constraint_expr %prec UMINUS
- { $$ = lcons( makeString( "-"), $2); }
- | constraint_expr '+' constraint_expr
- { $$ = nconc( $1, lcons( makeString( "+"), $3)); }
- | constraint_expr '-' constraint_expr
- { $$ = nconc( $1, lcons( makeString( "-"), $3)); }
- | constraint_expr '/' constraint_expr
- { $$ = nconc( $1, lcons( makeString( "/"), $3)); }
- | constraint_expr '%' constraint_expr
- { $$ = nconc( $1, lcons( makeString( "%"), $3)); }
- | constraint_expr '*' constraint_expr
- { $$ = nconc( $1, lcons( makeString( "*"), $3)); }
- | constraint_expr '^' constraint_expr
- { $$ = nconc( $1, lcons( makeString( "^"), $3)); }
- | constraint_expr '=' constraint_expr
- { $$ = nconc( $1, lcons( makeString( "="), $3)); }
- | constraint_expr '<' constraint_expr
- { $$ = nconc( $1, lcons( makeString( "<"), $3)); }
- | constraint_expr '>' constraint_expr
- { $$ = nconc( $1, lcons( makeString( ">"), $3)); }
- | ':' constraint_expr
- { $$ = lcons( makeString( ":"), $2); }
- | ';' constraint_expr
- { $$ = lcons( makeString( ";"), $2); }
- | '|' constraint_expr
- { $$ = lcons( makeString( "|"), $2); }
- | constraint_expr TYPECAST Typename
- {
- $3->name = fmtId($3->name);
- $$ = nconc( lcons( makeString( "CAST"), $1), makeList( makeString("AS"), $3, -1));
- }
- | CAST '(' constraint_expr AS Typename ')'
- {
- $5->name = fmtId($5->name);
- $$ = nconc( lcons( makeString( "CAST"), $3), makeList( makeString("AS"), $5, -1));
- }
- | '(' constraint_expr ')'
- { $$ = lappend( lcons( makeString( "("), $2), makeString( ")")); }
- | func_name '(' ')'
- {
- $$ = makeList( makeString($1), makeString("("), -1);
- $$ = lappend( $$, makeString(")"));
- }
- | func_name '(' constraint_list ')'
- {
- $$ = makeList( makeString($1), makeString("("), -1);
- $$ = nconc( $$, $3);
- $$ = lappend( $$, makeString(")"));
- }
- | constraint_expr Op constraint_expr
- { $$ = nconc( $1, lcons( makeString( $2), $3)); }
- | constraint_expr LIKE constraint_expr
- { $$ = nconc( $1, lcons( makeString( "LIKE"), $3)); }
- | constraint_expr NOT LIKE constraint_expr
- { $$ = nconc( $1, lcons( makeString( "NOT LIKE"), $4)); }
- | constraint_expr AND constraint_expr
- { $$ = nconc( $1, lcons( makeString( "AND"), $3)); }
- | constraint_expr OR constraint_expr
- { $$ = nconc( $1, lcons( makeString( "OR"), $3)); }
- | NOT constraint_expr
- { $$ = lcons( makeString( "NOT"), $2); }
- | Op constraint_expr
- { $$ = lcons( makeString( $1), $2); }
- | constraint_expr Op
- { $$ = lappend( $1, makeString( $2)); }
- | constraint_expr ISNULL
- { $$ = lappend( $1, makeString( "IS NULL")); }
- | constraint_expr IS NULL_P
- { $$ = lappend( $1, makeString( "IS NULL")); }
- | constraint_expr NOTNULL
- { $$ = lappend( $1, makeString( "IS NOT NULL")); }
- | constraint_expr IS NOT NULL_P
- { $$ = lappend( $1, makeString( "IS NOT NULL")); }
- | constraint_expr IS TRUE_P
- { $$ = lappend( $1, makeString( "IS TRUE")); }
- | constraint_expr IS FALSE_P
- { $$ = lappend( $1, makeString( "IS FALSE")); }
- | constraint_expr IS NOT TRUE_P
- { $$ = lappend( $1, makeString( "IS NOT TRUE")); }
- | constraint_expr IS NOT FALSE_P
- { $$ = lappend( $1, makeString( "IS NOT FALSE")); }
- | constraint_expr IN '(' c_list ')'
- {
- $$ = lappend( $1, makeString("IN"));
- $$ = lappend( $$, makeString("("));
- $$ = nconc( $$, $4);
- $$ = lappend( $$, makeString(")"));
- }
- | constraint_expr NOT IN '(' c_list ')'
- {
- $$ = lappend( $1, makeString("NOT IN"));
- $$ = lappend( $$, makeString("("));
- $$ = nconc( $$, $5);
- $$ = lappend( $$, makeString(")"));
- }
- | constraint_expr BETWEEN c_expr AND c_expr
- {
- $$ = lappend( $1, makeString("BETWEEN"));
- $$ = nconc( $$, $3);
- $$ = lappend( $$, makeString("AND"));
- $$ = nconc( $$, $5);
- }
- | constraint_expr NOT BETWEEN c_expr AND c_expr
- {
- $$ = lappend( $1, makeString("NOT BETWEEN"));
- $$ = nconc( $$, $4);
- $$ = lappend( $$, makeString("AND"));
- $$ = nconc( $$, $6);
- }
- ;
- c_list: c_list ',' c_expr
- {
- $$ = lappend($1, makeString(","));
- $$ = nconc($$, $3);
- }
- | c_expr
- {
- $$ = $1;
- }
- ;
- c_expr: AexprConst
- { $$ = makeConstantList((A_Const *) $1); }
- ;
- key_match: MATCH FULL { $$ = NULL; }
- | MATCH PARTIAL { $$ = NULL; }
- | /*EMPTY*/ { $$ = NULL; }
- ;
- key_actions: key_action key_action { $$ = NIL; }
- | key_action { $$ = NIL; }
- | /*EMPTY*/ { $$ = NIL; }
- ;
- key_action: ON DELETE key_reference { $$ = NIL; }
- | ON UPDATE key_reference { $$ = NIL; }
- ;
- key_reference: NO ACTION { $$ = NULL; }
- | CASCADE { $$ = NULL; }
- | SET DEFAULT { $$ = NULL; }
- | SET NULL_P { $$ = NULL; }
- ;
- OptInherit: INHERITS '(' relation_name_list ')' { $$ = $3; }
- | /*EMPTY*/ { $$ = NIL; }
- ;
- CreateAsStmt: CREATE OptTemp TABLE relation_name OptCreateAs AS SubSelect
- {
- SelectStmt *n = (SelectStmt *)$7;
- if ($5 != NIL)
- mapTargetColumns($5, n->targetList);
- n->istemp = $2;
- n->into = $4;
- $$ = (Node *)n;
- }
- ;
- OptCreateAs: '(' CreateAsList ')' { $$ = $2; }
- | /*EMPTY*/ { $$ = NULL; }
- ;
- CreateAsList: CreateAsList ',' CreateAsElement { $$ = lappend($1, $3); }
- | CreateAsElement { $$ = lcons($1, NIL); }
- ;
- CreateAsElement: ColId
- {
- ColumnDef *n = makeNode(ColumnDef);
- n->colname = $1;
- n->typename = NULL;
- n->defval = NULL;
- n->is_not_null = FALSE;
- n->constraints = NULL;
- $$ = (Node *)n;
- }
- ;
- /*****************************************************************************
- *
- * QUERY :
- * CREATE SEQUENCE seqname
- *
- *****************************************************************************/
- CreateSeqStmt: CREATE SEQUENCE relation_name OptSeqList
- {
- CreateSeqStmt *n = makeNode(CreateSeqStmt);
- n->seqname = $3;
- n->options = $4;
- $$ = (Node *)n;
- }
- ;
- OptSeqList: OptSeqList OptSeqElem
- { $$ = lappend($1, $2); }
- | { $$ = NIL; }
- ;
- OptSeqElem: CACHE IntegerOnly
- {
- $$ = makeNode(DefElem);
- $$->defname = "cache";
- $$->arg = (Node *)$2;
- }
- | CYCLE
- {
- $$ = makeNode(DefElem);
- $$->defname = "cycle";
- $$->arg = (Node *)NULL;
- }
- | INCREMENT IntegerOnly
- {
- $$ = makeNode(DefElem);
- $$->defname = "increment";
- $$->arg = (Node *)$2;
- }
- | MAXVALUE IntegerOnly
- {
- $$ = makeNode(DefElem);
- $$->defname = "maxvalue";
- $$->arg = (Node *)$2;
- }
- | MINVALUE IntegerOnly
- {
- $$ = makeNode(DefElem);
- $$->defname = "minvalue";
- $$->arg = (Node *)$2;
- }
- | START IntegerOnly
- {
- $$ = makeNode(DefElem);
- $$->defname = "start";
- $$->arg = (Node *)$2;
- }
- ;
- NumericOnly: FloatOnly { $$ = $1; }
- | IntegerOnly { $$ = $1; }
- FloatOnly: FCONST
- {
- $$ = makeFloat($1);
- }
- | '-' FCONST
- {
- $$ = makeFloat($2);
- $$->val.dval = - $$->val.dval;
- }
- ;
- IntegerOnly: Iconst
- {
- $$ = makeInteger($1);
- }
- | '-' Iconst
- {
- $$ = makeInteger($2);
- $$->val.ival = - $$->val.ival;
- }
- ;
- /*****************************************************************************
- *
- * QUERIES :
- * CREATE PROCEDURAL LANGUAGE ...
- * DROP PROCEDURAL LANGUAGE ...
- *
- *****************************************************************************/
- CreatePLangStmt: CREATE PLangTrusted PROCEDURAL LANGUAGE Sconst
- HANDLER def_name LANCOMPILER Sconst
- {
- CreatePLangStmt *n = makeNode(CreatePLangStmt);
- n->plname = $5;
- n->plhandler = $7;
- n->plcompiler = $9;
- n->pltrusted = $2;
- $$ = (Node *)n;
- }
- ;
- PLangTrusted: TRUSTED { $$ = TRUE; }
- | { $$ = FALSE; }
- DropPLangStmt: DROP PROCEDURAL LANGUAGE Sconst
- {
- DropPLangStmt *n = makeNode(DropPLangStmt);
- n->plname = $4;
- $$ = (Node *)n;
- }
- ;
- /*****************************************************************************
- *
- * QUERIES :
- * CREATE TRIGGER ...
- * DROP TRIGGER ...
- *
- *****************************************************************************/
- CreateTrigStmt: CREATE TRIGGER name TriggerActionTime TriggerEvents ON
- relation_name TriggerForSpec EXECUTE PROCEDURE
- name '(' TriggerFuncArgs ')'
- {
- CreateTrigStmt *n = makeNode(CreateTrigStmt);
- n->trigname = $3;
- n->relname = $7;
- n->funcname = $11;
- n->args = $13;
- n->before = $4;
- n->row = $8;
- memcpy (n->actions, $5, 4);
- $$ = (Node *)n;
- }
- ;
- TriggerActionTime: BEFORE { $$ = TRUE; }
- | AFTER { $$ = FALSE; }
- ;
- TriggerEvents: TriggerOneEvent
- {
- char *e = palloc (4);
- e[0] = $1; e[1] = 0; $$ = e;
- }
- | TriggerOneEvent OR TriggerOneEvent
- {
- char *e = palloc (4);
- e[0] = $1; e[1] = $3; e[2] = 0; $$ = e;
- }
- | TriggerOneEvent OR TriggerOneEvent OR TriggerOneEvent
- {
- char *e = palloc (4);
- e[0] = $1; e[1] = $3; e[2] = $5; e[3] = 0;
- $$ = e;
- }
- ;
- TriggerOneEvent: INSERT { $$ = 'i'; }
- | DELETE { $$ = 'd'; }
- | UPDATE { $$ = 'u'; }
- ;
- TriggerForSpec: FOR TriggerForOpt TriggerForType
- {
- $$ = $3;
- }
- ;
- TriggerForOpt: EACH { $$ = TRUE; }
- | /*EMPTY*/ { $$ = FALSE; }
- ;
- TriggerForType: ROW { $$ = TRUE; }
- | STATEMENT { $$ = FALSE; }
- ;
- TriggerFuncArgs: TriggerFuncArg
- { $$ = lcons($1, NIL); }
- | TriggerFuncArgs ',' TriggerFuncArg
- { $$ = lappend($1, $3); }
- | /*EMPTY*/
- { $$ = NIL; }
- ;
- TriggerFuncArg: ICONST
- {
- char *s = (char *) palloc (256);
- sprintf (s, "%d", $1);
- $$ = s;
- }
- | FCONST
- {
- char *s = (char *) palloc (256);
- sprintf (s, "%g", $1);
- $$ = s;
- }
- | Sconst { $$ = $1; }
- | IDENT { $$ = $1; }
- ;
- DropTrigStmt: DROP TRIGGER name ON relation_name
- {
- DropTrigStmt *n = makeNode(DropTrigStmt);
- n->trigname = $3;
- n->relname = $5;
- $$ = (Node *) n;
- }
- ;
- /*****************************************************************************
- *
- * QUERY :
- * define (type,operator,aggregate)
- *
- *****************************************************************************/
- DefineStmt: CREATE def_type def_rest
- {
- $3->defType = $2;
- $$ = (Node *)$3;
- }
- ;
- def_rest: def_name definition
- {
- $$ = makeNode(DefineStmt);
- $$->defname = $1;
- $$->definition = $2;
- }
- ;
- def_type: OPERATOR { $$ = OPERATOR; }
- | TYPE_P { $$ = TYPE_P; }
- | AGGREGATE { $$ = AGGREGATE; }
- ;
- def_name: PROCEDURE { $$ = "procedure"; }
- | JOIN { $$ = "join"; }
- | ColId { $$ = $1; }
- | MathOp { $$ = $1; }
- | Op { $$ = $1; }
- ;
- definition: '(' def_list ')' { $$ = $2; }
- ;
- def_list: def_elem { $$ = lcons($1, NIL); }
- | def_list ',' def_elem { $$ = lappend($1, $3); }
- ;
- def_elem: def_name '=' def_arg
- {
- $$ = makeNode(DefElem);
- $$->defname = $1;
- $$->arg = (Node *)$3;
- }
- | def_name
- {
- $$ = makeNode(DefElem);
- $$->defname = $1;
- $$->arg = (Node *)NULL;
- }
- | DEFAULT '=' def_arg
- {
- $$ = makeNode(DefElem);
- $$->defname = "default";
- $$->arg = (Node *)$3;
- }
- ;
- def_arg: ColId { $$ = (Node *)makeString($1); }
- | all_Op { $$ = (Node *)makeString($1); }
- | NumericOnly { $$ = (Node *)$1; }
- | Sconst { $$ = (Node *)makeString($1); }
- | SETOF ColId
- {
- TypeName *n = makeNode(TypeName);
- n->name = $2;
- n->setof = TRUE;
- n->arrayBounds = NULL;
- n->typmod = -1;
- $$ = (Node *)n;
- }
- ;
- /*****************************************************************************
- *
- * QUERY:
- * destroy <relname1> [, <relname2> .. <relnameN> ]
- *
- *****************************************************************************/
- DestroyStmt: DROP TABLE relation_name_list
- {
- DestroyStmt *n = makeNode(DestroyStmt);
- n->relNames = $3;
- n->sequence = FALSE;
- $$ = (Node *)n;
- }
- | DROP SEQUENCE relation_name_list
- {
- DestroyStmt *n = makeNode(DestroyStmt);
- n->relNames = $3;
- n->sequence = TRUE;
- $$ = (Node *)n;
- }
- ;
- /*****************************************************************************
- *
- * QUERY:
- * fetch/move [forward | backward] [ # | all ] [ in <portalname> ]
- * fetch [ forward | backward | absolute | relative ]
- * [ # | all | next | prior ] [ [ in | from ] <portalname> ]
- *
- *****************************************************************************/
- FetchStmt: FETCH opt_direction fetch_how_many opt_portal_name
- {
- FetchStmt *n = makeNode(FetchStmt);
- if ($2 == RELATIVE)
- {
- if ($3 == 0)
- elog(ERROR,"FETCH/RELATIVE at current position is not supported");
- $2 = FORWARD;
- }
- if ($3 < 0)
- {
- $3 = -$3;
- $2 = (($2 == FORWARD)? BACKWARD: FORWARD);
- }
- n->direction = $2;
- n->howMany = $3;
- n->portalname = $4;
- n->ismove = false;
- $$ = (Node *)n;
- }
- | MOVE opt_direction fetch_how_many opt_portal_name
- {
- FetchStmt *n = makeNode(FetchStmt);
- if ($3 < 0)
- {
- $3 = -$3;
- $2 = (($2 == FORWARD)? BACKWARD: FORWARD);
- }
- n->direction = $2;
- n->howMany = $3;
- n->portalname = $4;
- n->ismove = TRUE;
- $$ = (Node *)n;
- }
- ;
- opt_direction: FORWARD { $$ = FORWARD; }
- | BACKWARD { $$ = BACKWARD; }
- | RELATIVE { $$ = RELATIVE; }
- | ABSOLUTE
- {
- elog(NOTICE,"FETCH/ABSOLUTE not supported, using RELATIVE");
- $$ = RELATIVE;
- }
- | /*EMPTY*/ { $$ = FORWARD; /* default */ }
- ;
- fetch_how_many: Iconst { $$ = $1; }
- | '-' Iconst { $$ = - $2; }
- | ALL { $$ = 0; /* 0 means fetch all tuples*/ }
- | NEXT { $$ = 1; }
- | PRIOR { $$ = -1; }
- | /*EMPTY*/ { $$ = 1; /*default*/ }
- ;
- opt_portal_name: IN name { $$ = $2; }
- | FROM name { $$ = $2; }
- | /*EMPTY*/ { $$ = NULL; }
- ;
- /*****************************************************************************
- *
- * QUERY:
- * GRANT [privileges] ON [relation_name_list] TO [GROUP] grantee
- *
- *****************************************************************************/
- GrantStmt: GRANT privileges ON relation_name_list TO grantee opt_with_grant
- {
- $$ = (Node*)makeAclStmt($2,$4,$6,'+');
- }
- ;
- privileges: ALL PRIVILEGES
- {
- $$ = aclmakepriv("rwaR",0);
- }
- | ALL
- {
- $$ = aclmakepriv("rwaR",0);
- }
- | operation_commalist
- {
- $$ = $1;
- }
- ;
- operation_commalist: operation
- {
- $$ = aclmakepriv("",$1);
- }
- | operation_commalist ',' operation
- {
- $$ = aclmakepriv($1,$3);
- }
- ;
- operation: SELECT
- {
- $$ = ACL_MODE_RD_CHR;
- }
- | INSERT
- {
- $$ = ACL_MODE_AP_CHR;
- }
- | UPDATE
- {
- $$ = ACL_MODE_WR_CHR;
- }
- | DELETE
- {
- $$ = ACL_MODE_WR_CHR;
- }
- | RULE
- {
- $$ = ACL_MODE_RU_CHR;
- }
- ;
- grantee: PUBLIC
- {
- $$ = aclmakeuser("A","");
- }
- | GROUP ColId
- {
- $$ = aclmakeuser("G",$2);
- }
- | ColId
- {
- $$ = aclmakeuser("U",$1);
- }
- ;
- opt_with_grant: WITH GRANT OPTION
- {
- yyerror("WITH GRANT OPTION is not supported. Only relation owners can set privileges");
- }
- | /*EMPTY*/
- ;
- /*****************************************************************************
- *
- * QUERY:
- * REVOKE [privileges] ON [relation_name] FROM [user]
- *
- *****************************************************************************/
- RevokeStmt: REVOKE privileges ON relation_name_list FROM grantee
- {
- $$ = (Node*)makeAclStmt($2,$4,$6,'-');
- }
- ;
- /*****************************************************************************
- *
- * QUERY:
- * create index <indexname> on <relname>
- * using <access> "(" (<col> with <op>)+ ")" [with
- * <target_list>]
- *
- * [where <qual>] is not supported anymore
- *****************************************************************************/
- IndexStmt: CREATE index_opt_unique INDEX index_name ON relation_name
- access_method_clause '(' index_params ')' opt_with
- {
- /* should check that access_method is valid,
- etc ... but doesn't */
- IndexStmt *n = makeNode(IndexStmt);
- n->unique = $2;
- n->idxname = $4;
- n->relname = $6;
- n->accessMethod = $7;
- n->indexParams = $9;
- n->withClause = $11;
- n->whereClause = NULL;
- $$ = (Node *)n;
- }
- ;
- index_opt_unique: UNIQUE { $$ = TRUE; }
- | /*EMPTY*/ { $$ = FALSE; }
- ;
- access_method_clause: USING access_method { $$ = $2; }
- | /*EMPTY*/ { $$ = "btree"; }
- ;
- index_params: index_list { $$ = $1; }
- | func_index { $$ = lcons($1,NIL); }
- ;
- index_list: index_list ',' index_elem { $$ = lappend($1, $3); }
- | index_elem { $$ = lcons($1, NIL); }
- ;
- func_index: func_name '(' name_list ')' opt_type opt_class
- {
- $$ = makeNode(IndexElem);
- $$->name = $1;
- $$->args = $3;
- $$->class = $6;
- $$->typename = $5;
- }
- ;
- index_elem: attr_name opt_type opt_class
- {
- $$ = makeNode(IndexElem);
- $$->name = $1;
- $$->args = NIL;
- $$->class = $3;
- $$->typename = $2;
- }
- ;
- opt_type: ':' Typename { $$ = $2; }
- | FOR Typename { $$ = $2; }
- | /*EMPTY*/ { $$ = NULL; }
- ;
- /* opt_class "WITH class" conflicts with preceeding opt_type
- * for Typename of "TIMESTAMP WITH TIME ZONE"
- * So, remove "WITH class" from the syntax. OK??
- * - thomas 1997-10-12
- * | WITH class { $$ = $2; }
- */
- opt_class: class { $$ = $1; }
- | USING class { $$ = $2; }
- | /*EMPTY*/ { $$ = NULL; }
- ;
- /*****************************************************************************
- *
- * QUERY:
- * extend index <indexname> [where <qual>]
- *
- *****************************************************************************/
- ExtendStmt: EXTEND INDEX index_name where_clause
- {
- ExtendStmt *n = makeNode(ExtendStmt);
- n->idxname = $3;
- n->whereClause = $4;
- $$ = (Node *)n;
- }
- ;
- /*****************************************************************************
- *
- * QUERY:
- * execute recipe <recipeName>
- *
- *****************************************************************************/
- /* NOT USED
- RecipeStmt: EXECUTE RECIPE recipe_name
- {
- RecipeStmt *n;
- if (!IsTransactionBlock())
- elog(ERROR,"EXECUTE RECIPE may only be used in begin/end transaction blocks");
- n = makeNode(RecipeStmt);
- n->recipeName = $3;
- $$ = (Node *)n;
- }
- ;
- */
- /*****************************************************************************
- *
- * QUERY:
- * define function <fname>
- * (language = <lang>, returntype = <typename>
- * [, arch_pct = <percentage | pre-defined>]
- * [, disk_pct = <percentage | pre-defined>]
- * [, byte_pct = <percentage | pre-defined>]
- * [, perbyte_cpu = <int | pre-defined>]
- * [, percall_cpu = <int | pre-defined>]
- * [, iscachable])
- * [arg is (<type-1> { , <type-n>})]
- * as <filename or code in language as appropriate>
- *
- *****************************************************************************/
- ProcedureStmt: CREATE FUNCTION func_name func_args
- RETURNS func_return opt_with AS Sconst LANGUAGE Sconst
- {
- ProcedureStmt *n = makeNode(ProcedureStmt);
- n->funcname = $3;
- n->defArgs = $4;
- n->returnType = $6;
- n->withClause = $7;
- n->as = $9;
- n->language = $11;
- $$ = (Node *)n;
- };
- opt_with: WITH definition { $$ = $2; }
- | /*EMPTY*/ { $$ = NIL; }
- ;
- func_args: '(' func_args_list ')' { $$ = $2; }
- | '(' ')' { $$ = NIL; }
- ;
- func_args_list: TypeId
- { $$ = lcons(makeString($1),NIL); }
- | func_args_list ',' TypeId
- { $$ = lappend($1,makeString($3)); }
- ;
- func_return: set_opt TypeId
- {
- TypeName *n = makeNode(TypeName);
- n->name = $2;
- n->setof = $1;
- n->arrayBounds = NULL;
- $$ = (Node *)n;
- }
- ;
- set_opt: SETOF { $$ = TRUE; }
- | /*EMPTY*/ { $$ = FALSE; }
- ;
- /*****************************************************************************
- *
- * QUERY:
- *
- * remove function <funcname>
- * (REMOVE FUNCTION "funcname" (arg1, arg2, ...))
- * remove aggregate <aggname>
- * (REMOVE AGGREGATE "aggname" "aggtype")
- * remove operator <opname>
- * (REMOVE OPERATOR "opname" (leftoperand_typ rightoperand_typ))
- * remove type <typename>
- * (REMOVE TYPE "typename")
- * remove rule <rulename>
- * (REMOVE RULE "rulename")
- *
- *****************************************************************************/
- RemoveStmt: DROP remove_type name
- {
- RemoveStmt *n = makeNode(RemoveStmt);
- n->removeType = $2;
- n->name = $3;
- $$ = (Node *)n;
- }
- ;
- remove_type: TYPE_P { $$ = TYPE_P; }
- | INDEX { $$ = INDEX; }
- | RULE { $$ = RULE; }
- | VIEW { $$ = VIEW; }
- ;
- RemoveAggrStmt: DROP AGGREGATE name aggr_argtype
- {
- RemoveAggrStmt *n = makeNode(RemoveAggrStmt);
- n->aggname = $3;
- n->aggtype = $4;
- $$ = (Node *)n;
- }
- ;
- aggr_argtype: name { $$ = $1; }
- | '*' { $$ = NULL; }
- ;
- RemoveFuncStmt: DROP FUNCTION func_name func_args
- {
- RemoveFuncStmt *n = makeNode(RemoveFuncStmt);
- n->funcname = $3;
- n->args = $4;
- $$ = (Node *)n;
- }
- ;
- RemoveOperStmt: DROP OPERATOR all_Op '(' oper_argtypes ')'
- {
- RemoveOperStmt *n = makeNode(RemoveOperStmt);
- n->opname = $3;
- n->args = $5;
- $$ = (Node *)n;
- }
- ;
- all_Op: Op | MathOp;
- MathOp: '+' { $$ = "+"; }
- | '-' { $$ = "-"; }
- | '*' { $$ = "*"; }
- | '/' { $$ = "/"; }
- | '%' { $$ = "%"; }
- | '<' { $$ = "<"; }
- | '>' { $$ = ">"; }
- | '=' { $$ = "="; }
- ;
- oper_argtypes: name
- {
- elog(ERROR,"parser: argument type missing (use NONE for unary operators)");
- }
- | name ',' name
- { $$ = makeList(makeString($1), makeString($3), -1); }
- | NONE ',' name /* left unary */
- { $$ = makeList(NULL, makeString($3), -1); }
- | name ',' NONE /* right unary */
- { $$ = makeList(makeString($1), NULL, -1); }
- ;
- /*****************************************************************************
- *
- * QUERY:
- * rename <attrname1> in <relname> [*] to <attrname2>
- * rename <relname1> to <relname2>
- *
- *****************************************************************************/
- RenameStmt: ALTER TABLE relation_name opt_inh_star
- RENAME opt_column opt_name TO name
- {
- RenameStmt *n = makeNode(RenameStmt);
- n->relname = $3;
- n->inh = $4;
- n->column = $7;
- n->newname = $9;
- $$ = (Node *)n;
- }
- ;
- opt_name: name { $$ = $1; }
- | /*EMPTY*/ { $$ = NULL; }
- ;
- opt_column: COLUMN { $$ = COLUMN; }
- | /*EMPTY*/ { $$ = 0; }
- ;
- /*****************************************************************************
- *
- * QUERY: Define Rewrite Rule , Define Tuple Rule
- * Define Rule <old rules >
- *
- * only rewrite rule is supported -- ay 9/94
- *
- *****************************************************************************/
- RuleStmt: CREATE RULE name AS
- { QueryIsRule=TRUE; }
- ON event TO event_object where_clause
- DO opt_instead RuleActionList
- {
- RuleStmt *n = makeNode(RuleStmt);
- n->rulename = $3;
- n->event = $7;
- n->object = $9;
- n->whereClause = $10;
- n->instead = $12;
- n->actions = $13;
- $$ = (Node *)n;
- }
- ;
- RuleActionList: NOTHING { $$ = NIL; }
- | SelectStmt { $$ = lcons($1, NIL); }
- | RuleActionStmt { $$ = lcons($1, NIL); }
- | '[' RuleActionBlock ']' { $$ = $2; }
- | '(' RuleActionBlock ')' { $$ = $2; }
- ;
- RuleActionBlock: RuleActionMulti { $$ = $1; }
- | RuleActionStmt { $$ = lcons($1, NIL); }
- ;
- RuleActionMulti: RuleActionMulti RuleActionStmt
- { $$ = lappend($1, $2); }
- | RuleActionMulti RuleActionStmt ';'
- { $$ = lappend($1, $2); }
- | RuleActionStmt ';'
- { $$ = lcons($1, NIL); }
- ;
- RuleActionStmt: InsertStmt
- | UpdateStmt
- | DeleteStmt
- | NotifyStmt
- ;
- event_object: relation_name '.' attr_name
- {
- $$ = makeNode(Attr);
- $$->relname = $1;
- $$->paramNo = NULL;
- $$->attrs = lcons(makeString($3), NIL);
- $$->indirection = NIL;
- }
- | relation_name
- {
- $$ = makeNode(Attr);
- $$->relname = $1;
- $$->paramNo = NULL;
- $$->attrs = NIL;
- $$->indirection = NIL;
- }
- ;
- /* change me to select, update, etc. some day */
- event: SELECT { $$ = CMD_SELECT; }
- | UPDATE { $$ = CMD_UPDATE; }
- | DELETE { $$ = CMD_DELETE; }
- | INSERT { $$ = CMD_INSERT; }
- ;
- opt_instead: INSTEAD { $$ = TRUE; }
- | /*EMPTY*/ { $$ = FALSE; }
- ;
- /*****************************************************************************
- *
- * QUERY:
- * NOTIFY <relation_name> can appear both in rule bodies and
- * as a query-level command
- *
- *****************************************************************************/
- NotifyStmt: NOTIFY relation_name
- {
- NotifyStmt *n = makeNode(NotifyStmt);
- n->relname = $2;
- $$ = (Node *)n;
- }
- ;
- ListenStmt: LISTEN relation_name
- {
- ListenStmt *n = makeNode(ListenStmt);
- n->relname = $2;
- $$ = (Node *)n;
- }
- ;
- UnlistenStmt: UNLISTEN relation_name
- {
- UnlistenStmt *n = makeNode(UnlistenStmt);
- n->relname = $2;
- $$ = (Node *)n;
- }
- | UNLISTEN '*'
- {
- UnlistenStmt *n = makeNode(UnlistenStmt);
- n->relname = "*";
- $$ = (Node *)n;
- }
- ;
- /*****************************************************************************
- *
- * Transactions:
- *
- * abort transaction
- * (ABORT)
- * begin transaction
- * (BEGIN)
- * end transaction
- * (END)
- *
- *****************************************************************************/
- TransactionStmt: ABORT_TRANS opt_trans
- {
- TransactionStmt *n = makeNode(TransactionStmt);
- n->command = ABORT_TRANS;
- $$ = (Node *)n;
- }
- | BEGIN_TRANS opt_trans
- {
- TransactionStmt *n = makeNode(TransactionStmt);
- n->command = BEGIN_TRANS;
- $$ = (Node *)n;
- }
- | COMMIT opt_trans
- {
- TransactionStmt *n = makeNode(TransactionStmt);
- n->command = END_TRANS;
- $$ = (Node *)n;
- }
- | END_TRANS opt_trans
- {
- TransactionStmt *n = makeNode(TransactionStmt);
- n->command = END_TRANS;
- $$ = (Node *)n;
- }
- | ROLLBACK opt_trans
- {
- TransactionStmt *n = makeNode(TransactionStmt);
- n->command = ABORT_TRANS;
- $$ = (Node *)n;
- }
- ;
- opt_trans: WORK { $$ = TRUE; }
- | TRANSACTION { $$ = TRUE; }
- | /*EMPTY*/ { $$ = TRUE; }
- ;
- /*****************************************************************************
- *
- * QUERY:
- * define view <viewname> '('target-list ')' [where <quals> ]
- *
- *****************************************************************************/
- ViewStmt: CREATE VIEW name AS SelectStmt
- {
- ViewStmt *n = makeNode(ViewStmt);
- n->viewname = $3;
- n->query = (Query *)$5;
- if (((SelectStmt *)n->query)->sortClause != NULL)
- elog(ERROR,"Order by and Distinct on views is not implemented.");
- if (((SelectStmt *)n->query)->unionClause != NULL)
- elog(ERROR,"Views on unions not implemented.");
- if (((SelectStmt *)n->query)->forUpdate != NULL)
- elog(ERROR, "SELECT FOR UPDATE is not allowed in CREATE VIEW");
- $$ = (Node *)n;
- }
- ;
- /*****************************************************************************
- *
- * QUERY:
- * load "filename"
- *
- *****************************************************************************/
- LoadStmt: LOAD file_name
- {
- LoadStmt *n = makeNode(LoadStmt);
- n->filename = $2;
- $$ = (Node *)n;
- }
- ;
- /*****************************************************************************
- *
- * QUERY:
- * createdb dbname
- *
- *****************************************************************************/
- CreatedbStmt: CREATE DATABASE database_name WITH opt_database1 opt_database2
- {
- CreatedbStmt *n = makeNode(CreatedbStmt);
- if ($5 == NULL && $6 == NULL) {
- elog(ERROR, "CREATE DATABASE WITH requires at least an option");
- }
- n->dbname = $3;
- n->dbpath = $5;
- #ifdef MULTIBYTE
- if ($6 != NULL) {
- n->encoding = pg_char_to_encoding($6);
- if (n->encoding < 0) {
- elog(ERROR, "invalid encoding name %s", $6);
- }
- } else {
- n->encoding = GetTemplateEncoding();
- }
- #else
- if ($6 != NULL)
- elog(ERROR, "WITH ENCODING is not supported");
- n->encoding = 0;
- #endif
- $$ = (Node *)n;
- }
- | CREATE DATABASE database_name
- {
- CreatedbStmt *n = makeNode(CreatedbStmt);
- n->dbname = $3;
- n->dbpath = NULL;
- #ifdef MULTIBYTE
- n->encoding = GetTemplateEncoding();
- #else
- n->encoding = 0;
- #endif
- $$ = (Node *)n;
- }
- ;
- opt_database1: LOCATION '=' location { $$ = $3; }
- | /*EMPTY*/ { $$ = NULL; }
- ;
- opt_database2: ENCODING '=' encoding { $$ = $3; }
- | /*EMPTY*/ { $$ = NULL; }
- ;
- location: Sconst { $$ = $1; }
- | DEFAULT { $$ = NULL; }
- | /*EMPTY*/ { $$ = NULL; }
- ;
- encoding: Sconst { $$ = $1; }
- | DEFAULT { $$ = NULL; }
- | /*EMPTY*/ { $$ = NULL; }
- ;
- /*****************************************************************************
- *
- * QUERY:
- * destroydb dbname
- *
- *****************************************************************************/
- DestroydbStmt: DROP DATABASE database_name
- {
- DestroydbStmt *n = makeNode(DestroydbStmt);
- n->dbname = $3;
- $$ = (Node *)n;
- }
- ;
- /*****************************************************************************
- *
- * QUERY:
- * cluster <index_name> on <relation_name>
- *
- *****************************************************************************/
- ClusterStmt: CLUSTER index_name ON relation_name
- {
- ClusterStmt *n = makeNode(ClusterStmt);
- n->relname = $4;
- n->indexname = $2;
- $$ = (Node*)n;
- }
- ;
- /*****************************************************************************
- *
- * QUERY:
- * vacuum
- *
- *****************************************************************************/
- VacuumStmt: VACUUM opt_verbose opt_analyze
- {
- VacuumStmt *n = makeNode(VacuumStmt);
- n->verbose = $2;
- n->analyze = $3;
- n->vacrel = NULL;
- n->va_spec = NIL;
- $$ = (Node *)n;
- }
- | VACUUM opt_verbose opt_analyze relation_name opt_va_list
- {
- VacuumStmt *n = makeNode(VacuumStmt);
- n->verbose = $2;
- n->analyze = $3;
- n->vacrel = $4;
- n->va_spec = $5;
- if ( $5 != NIL && !$4 )
- elog(ERROR,"parser: syntax error at or near "("");
- $$ = (Node *)n;
- }
- ;
- opt_verbose: VERBOSE { $$ = TRUE; }
- | /*EMPTY*/ { $$ = FALSE; }
- ;
- opt_analyze: ANALYZE { $$ = TRUE; }
- | /*EMPTY*/ { $$ = FALSE; }
- ;
- opt_va_list: '(' va_list ')' { $$ = $2; }
- | /*EMPTY*/ { $$ = NIL; }
- ;
- va_list: name
- { $$=lcons($1,NIL); }
- | va_list ',' name
- { $$=lappend($1,$3); }
- ;
- /*****************************************************************************
- *
- * QUERY:
- * EXPLAIN query
- *
- *****************************************************************************/
- ExplainStmt: EXPLAIN opt_verbose OptimizableStmt
- {
- ExplainStmt *n = makeNode(ExplainStmt);
- n->verbose = $2;
- n->query = (Query*)$3;
- $$ = (Node *)n;
- }
- ;
- /*****************************************************************************
- * *
- * Optimizable Stmts: *
- * *
- * one of the five queries processed by the planner *
- * *
- * [ultimately] produces query-trees as specified *
- * in the query-spec document in ~postgres/ref *
- * *
- *****************************************************************************/
- OptimizableStmt: SelectStmt
- | CursorStmt
- | UpdateStmt
- | InsertStmt
- | NotifyStmt
- | DeleteStmt /* by default all are $$=$1 */
- ;
- /*****************************************************************************
- *
- * QUERY:
- * INSERT STATEMENTS
- *
- *****************************************************************************/
- /***S*I***/
- /* This rule used 'opt_column_list' between 'relation_name' and 'insert_rest'
- * originally. When the second rule of 'insert_rest' was changed to use
- * the new 'SelectStmt' rule (for INTERSECT and EXCEPT) it produced a shift/reduce
- * conflict. So I just changed the rules 'InsertStmt' and 'insert_rest' to accept
- * the same statements without any shift/reduce conflicts */
- InsertStmt: INSERT INTO relation_name insert_rest
- {
- $4->relname = $3;
- $$ = (Node *)$4;
- }
- ;
- insert_rest: VALUES '(' res_target_list2 ')'
- {
- $$ = makeNode(InsertStmt);
- $$->cols = NULL;
- $$->unique = NULL;
- $$->targetList = $3;
- $$->fromClause = NIL;
- $$->whereClause = NULL;
- $$->groupClause = NIL;
- $$->havingClause = NULL;
- $$->unionClause = NIL;
- }
- | DEFAULT VALUES
- {
- $$ = makeNode(InsertStmt);
- $$->unique = NULL;
- $$->targetList = NIL;
- $$->fromClause = NIL;
- $$->whereClause = NULL;
- $$->groupClause = NIL;
- $$->havingClause = NULL;
- $$->unionClause = NIL;
- /***S*I***/
- $$->intersectClause = NIL;
- }
- /***S*I***/
- /* We want the full power of SelectStatements including INTERSECT and EXCEPT
- * for insertion */
- | SelectStmt
- {
- SelectStmt *n;
- n = (SelectStmt *)$1;
- $$ = makeNode(InsertStmt);
- $$->cols = NULL;
- $$->unique = n->unique;
- $$->targetList = n->targetList;
- $$->fromClause = n->fromClause;
- $$->whereClause = n->whereClause;
- $$->groupClause = n->groupClause;
- $$->havingClause = n->havingClause;
- $$->unionClause = n->unionClause;
- $$->intersectClause = n->intersectClause;
- $$->forUpdate = n->forUpdate;
- }
- | '(' columnList ')' VALUES '(' res_target_list2 ')'
- {
- $$ = makeNode(InsertStmt);
- $$->cols = $2;
- $$->unique = NULL;
- $$->targetList = $6;
- $$->fromClause = NIL;
- $$->whereClause = NULL;
- $$->groupClause = NIL;
- $$->havingClause = NULL;
- $$->unionClause = NIL;
- /***S*I***/
- $$->intersectClause = NIL;
- }
- | '(' columnList ')' SelectStmt
- {
- SelectStmt *n;
- n = (SelectStmt *)$4;
- $$ = makeNode(InsertStmt);
- $$->cols = $2;
- $$->unique = n->unique;
- $$->targetList = n->targetList;
- $$->fromClause = n->fromClause;
- $$->whereClause = n->whereClause;
- $$->groupClause = n->groupClause;
- $$->havingClause = n->havingClause;
- $$->unionClause = n->unionClause;
- $$->intersectClause = n->intersectClause;
- }
- ;
- opt_column_list: '(' columnList ')' { $$ = $2; }
- | /*EMPTY*/ { $$ = NIL; }
- ;
- columnList:
- columnList ',' columnElem
- { $$ = lappend($1, $3); }
- | columnElem
- { $$ = lcons($1, NIL); }
- ;
- columnElem: ColId opt_indirection
- {
- Ident *id = makeNode(Ident);
- id->name = $1;
- id->indirection = $2;
- $$ = (Node *)id;
- }
- ;
- /*****************************************************************************
- *
- * QUERY:
- * DELETE STATEMENTS
- *
- *****************************************************************************/
- DeleteStmt: DELETE FROM relation_name
- where_clause
- {
- DeleteStmt *n = makeNode(DeleteStmt);
- n->relname = $3;
- n->whereClause = $4;
- $$ = (Node *)n;
- }
- ;
- LockStmt: LOCK_P opt_table relation_name opt_lock
- {
- LockStmt *n = makeNode(LockStmt);
- n->relname = $3;
- n->mode = $4;
- $$ = (Node *)n;
- }
- ;
- opt_lock: IN lock_type MODE { $$ = $2; }
- | /*EMPTY*/ { $$ = AccessExclusiveLock; }
- ;
- lock_type: SHARE ROW EXCLUSIVE { $$ = ShareRowExclusiveLock; }
- | ROW opt_lmode { $$ = ($2? RowShareLock: RowExclusiveLock); }
- | ACCESS opt_lmode { $$ = ($2? AccessShareLock: AccessExclusiveLock); }
- | opt_lmode { $$ = ($1? ShareLock: ExclusiveLock); }
- ;
- opt_lmode: SHARE { $$ = TRUE; }
- | EXCLUSIVE { $$ = FALSE; }
- ;
- /*****************************************************************************
- *
- * QUERY:
- * UpdateStmt (UPDATE)
- *
- *****************************************************************************/
- UpdateStmt: UPDATE relation_name
- SET res_target_list
- from_clause
- where_clause
- {
- UpdateStmt *n = makeNode(UpdateStmt);
- n->relname = $2;
- n->targetList = $4;
- n->fromClause = $5;
- n->whereClause = $6;
- $$ = (Node *)n;
- }
- ;
- /*****************************************************************************
- *
- * QUERY:
- * CURSOR STATEMENTS
- *
- *****************************************************************************/
- /***S*I***/
- CursorStmt: DECLARE name opt_cursor CURSOR FOR SelectStmt
- {
- SelectStmt *n;
-
- n= (SelectStmt *)$6;
- /* from PORTAL name */
- /*
- * 15 august 1991 -- since 3.0 postgres does locking
- * right, we discovered that portals were violating
- * locking protocol. portal locks cannot span xacts.
- * as a short-term fix, we installed the check here.
- * -- mao
- */
- if (!IsTransactionBlock())
- elog(ERROR,"Named portals may only be used in begin/end transaction blocks");
- n->portalname = $2;
- n->binary = $3;
- if (n->forUpdate != NULL)
- elog(ERROR,"DECLARE/UPDATE not supported;"
- " Cursors must be READ ONLY.");
- $$ = (Node *)n;
- }
- ;
- opt_cursor: BINARY { $$ = TRUE; }
- | INSENSITIVE { $$ = FALSE; }
- | SCROLL { $$ = FALSE; }
- | INSENSITIVE SCROLL { $$ = FALSE; }
- | /*EMPTY*/ { $$ = FALSE; }
- ;
- /*****************************************************************************
- *
- * QUERY:
- * SELECT STATEMENTS
- *
- *****************************************************************************/
- /***S*I***/
- /* The new 'SelectStmt' rule adapted for the optional use of INTERSECT EXCEPT and UNION
- * accepts the use of '(' and ')' to select an order of set operations.
- *
- * The rule returns a SelectStmt Node having the set operations attached to
- * unionClause and intersectClause (NIL if no set operations were present)
- */
- SelectStmt: select_clause sort_clause for_update_clause opt_select_limit
- {
- /* There were no set operations, so just attach the sortClause */
- if IsA($1, SelectStmt)
- {
- SelectStmt *n = (SelectStmt *)$1;
- n->sortClause = $2;
- n->forUpdate = $3;
- n->limitOffset = nth(0, $4);
- n->limitCount = nth(1, $4);
- $$ = (Node *)n;
- }
- /* There were set operations: The root of the operator tree
- * is delivered by $1 but we cannot hand back an A_Expr Node.
- * So we search for the leftmost 'SelectStmt' in the operator
- * tree $1 (which is the first Select Statement in the query
- * typed in by the user or where ever it came from).
- *
- * Then we attach the whole operator tree to 'intersectClause',
- * and a list of all 'SelectStmt' Nodes to 'unionClause' and
- * hand back the leftmost 'SelectStmt' Node. (We do it this way
- * because the following functions (e.g. parse_analyze etc.)
- * excpect a SelectStmt node and not an operator tree! The whole
- * tree attached to 'intersectClause' won't be touched by
- * parse_analyze() etc. until the function
- * Except_Intersect_Rewrite() (in rewriteHandler.c) which performs
- * the necessary steps to be able create a plan!) */
- else
- {
- List *select_list = NIL;
- SelectStmt *first_select;
- Node *op = (Node *) $1;
- bool intersect_present = FALSE, unionall_present = FALSE;
- /* Take the operator tree as an argument and
- * create a list of all SelectStmt Nodes found in the tree.
- *
- * If one of the SelectStmt Nodes has the 'unionall' flag
- * set to true the 'unionall_present' flag is also set to
- * true */
- create_select_list((Node *)op, &select_list, &unionall_present);
- /* Replace all the A_Expr Nodes in the operator tree by
- * Expr Nodes.
- *
- * If an INTERSECT or an EXCEPT is present, the
- * 'intersect_present' flag is set to true */
- op = A_Expr_to_Expr(op, &intersect_present);
- /* If both flags are set to true we have a UNION ALL
- * statement mixed up with INTERSECT or EXCEPT
- * which can not be handled at the moment */
- if (intersect_present && unionall_present)
- {
- elog(ERROR,"UNION ALL not allowed in mixed set operations!");
- }
- /* Get the leftmost SeletStmt Node (which automatically
- * represents the first Select Statement of the query!) */
- first_select = (SelectStmt *)lfirst(select_list);
- /* Attach the list of all SeletStmt Nodes to unionClause */
- first_select->unionClause = select_list;
- /* Attach the whole operator tree to intersectClause */
- first_select->intersectClause = (List *) op;
- /* finally attach the sort clause */
- first_select->sortClause = $2;
- first_select->forUpdate = $3;
- $$ = (Node *)first_select;
- }
- if (((SelectStmt *)$$)->forUpdate != NULL && QueryIsRule)
- elog(ERROR, "SELECT FOR UPDATE is not allowed in RULES");
- }
- ;
- /***S*I***/
- /* This rule parses Select statements including UNION INTERSECT and EXCEPT.
- * '(' and ')' can be used to specify the order of the operations
- * (UNION EXCEPT INTERSECT). Without the use of '(' and ')' we want the
- * operations to be left associative.
- *
- * The sort_clause is not handled here!
- *
- * The rule builds up an operator tree using A_Expr Nodes. AND Nodes represent
- * INTERSECTs OR Nodes represent UNIONs and AND NOT nodes represent EXCEPTs.
- * The SelectStatements to be connected are the left and right arguments to
- * the A_Expr Nodes.
- * If no set operations show up in the query the tree consists only of one
- * SelectStmt Node */
- select_clause: '(' select_clause ')'
- {
- $$ = $2;
- }
- | SubSelect
- {
- $$ = $1;
- }
- | select_clause EXCEPT select_clause
- {
- $$ = (Node *)makeA_Expr(AND,NULL,$1,
- makeA_Expr(NOT,NULL,NULL,$3));
- }
- | select_clause UNION opt_union select_clause
- {
- if (IsA($4, SelectStmt))
- {
- SelectStmt *n = (SelectStmt *)$4;
- n->unionall = $3;
- }
- $$ = (Node *)makeA_Expr(OR,NULL,$1,$4);
- }
- | select_clause INTERSECT select_clause
- {
- $$ = (Node *)makeA_Expr(AND,NULL,$1,$3);
- }
- ;
- /***S*I***/
- SubSelect: SELECT opt_unique res_target_list2
- result from_clause where_clause
- group_clause having_clause
- {
- SelectStmt *n = makeNode(SelectStmt);
- n->unique = $2;
- n->unionall = FALSE;
- n->targetList = $3;
- /***S*I***/
- /* This is new: Subselects support the INTO clause
- * which allows queries that are not part of the
- * SQL92 standard and should not be formulated!
- * We need it for INTERSECT and EXCEPT and I did not
- * want to create a new rule 'SubSelect1' including the
- * feature. If it makes troubles we will have to add
- * a new rule and change this to prevent INTOs in
- * Subselects again */
- n->istemp = (bool) ((Value *) lfirst($4))->val.ival;
- n->into = (char *) lnext($4);
- n->fromClause = $5;
- n->whereClause = $6;
- n->groupClause = $7;
- n->havingClause = $8;
- $$ = (Node *)n;
- }
- ;
- /* easy way to return two values. Can someone improve this? bjm */
- result: INTO OptTemp opt_table relation_name { $$ = lcons(makeInteger($2), (List *)$4); }
- | /*EMPTY*/ { $$ = lcons(makeInteger(false), NIL); }
- ;
- opt_table: TABLE { $$ = TRUE; }
- | /*EMPTY*/ { $$ = FALSE; }
- ;
- opt_union: ALL { $$ = TRUE; }
- | /*EMPTY*/ { $$ = FALSE; }
- ;
- opt_unique: DISTINCT { $$ = "*"; }
- | DISTINCT ON ColId { $$ = $3; }
- | ALL { $$ = NULL; }
- | /*EMPTY*/ { $$ = NULL; }
- ;