4 /*-------------------------------------------------------------------------
7 * POSTGRES SQL YACC rules/actions
9 * Copyright (c) 1994, Regents of the University of California
13 * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.43 1997/09/08 03:19:57 momjian Exp $
16 * AUTHOR DATE MAJOR EVENT
17 * Andrew Yu Sept, 1994 POSTQUEL to SQL conversion
18 * Andrew Yu Oct, 1994 lispy code conversion
21 * CAPITALS are used to represent terminal symbols.
22 * non-capitals are used to represent non-terminals.
24 * if you use list, make sure the datum is a node so that the printing
28 * sometimes we assign constants to makeStrings. Make sure we don't free
31 *-------------------------------------------------------------------------
37 #include "nodes/parsenodes.h"
38 #include "parser/gramparse.h"
39 #include "parser/catalog_utils.h"
40 #include "parser/parse_query.h"
41 #include "storage/smgr.h"
42 #include "utils/acl.h"
43 #include "catalog/catname.h"
44 #include "utils/elog.h"
45 #include "access/xact.h"
47 static char saved_relname[NAMEDATALEN]; /* need this for complex attributes */
48 static bool QueryIsRule = FALSE;
49 static Node *saved_In_Expr;
50 extern List *parsetree;
52 extern int CurScanPosition(void);
53 extern int DefaultStartPosition;
54 extern int CheckStartPosition;
55 extern char *parseString;
58 * If you need access to certain yacc-generated variables and find that
59 * they're static by default, uncomment the next line. (this is not a
62 /*#define __YYSCLASS*/
64 static char *xlateSqlType(char *);
65 static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
67 /* old versions of flex define this as a macro */
88 ConstraintDef *constrdef;
92 SortGroupBy *sortgroupby;
109 AddAttrStmt, ClosePortalStmt,
110 CopyStmt, CreateStmt, CreateSeqStmt, DefineStmt, DestroyStmt,
111 ExtendStmt, FetchStmt, GrantStmt, CreateTrigStmt, DropTrigStmt,
112 IndexStmt, MoveStmt, ListenStmt, OptimizableStmt,
113 ProcedureStmt, PurgeStmt,
114 RecipeStmt, RemoveAggrStmt, RemoveOperStmt, RemoveFuncStmt, RemoveStmt,
115 RenameStmt, RevokeStmt, RuleStmt, TransactionStmt, ViewStmt, LoadStmt,
116 CreatedbStmt, DestroydbStmt, VacuumStmt, RetrieveStmt, CursorStmt,
117 ReplaceStmt, AppendStmt, NotifyStmt, DeleteStmt, ClusterStmt,
118 ExplainStmt, VariableSetStmt, VariableShowStmt, VariableResetStmt
121 %type <node> SubSelect
122 %type <str> join_clause, join_type, join_outer, join_spec
123 %type <boolean> join_qual, TriggerActionTime, TriggerForSpec
125 %type <str> datetime, TriggerEvents, TriggerFuncArg
127 %type <str> relation_name, copy_file_name, copy_delimiter, def_name,
128 database_name, access_method_clause, access_method, attr_name,
129 class, index_name, name, file_name, recipe_name,
130 var_name, aggr_argtype, OptDefault
132 %type <constrdef> ConstraintElem, ConstraintDef
134 %type <str> opt_id, opt_portal_name,
135 before_clause, after_clause, all_Op, MathOp, opt_name, opt_unique,
136 result, OptUseOp, opt_class, opt_range_start, opt_range_end,
139 %type <str> privileges, operation_commalist, grantee
140 %type <chr> operation, TriggerOneEvent
142 %type <list> stmtblock, stmtmulti,
143 relation_name_list, OptTableElementList, tableElementList,
144 OptInherit, OptConstraint, ConstraintList, definition,
145 opt_with, def_args, def_name_list, func_argtypes,
146 oper_argtypes, OptStmtList, OptStmtBlock, OptStmtMulti,
147 opt_column_list, columnList, opt_va_list, va_list,
148 sort_clause, sortby_list, index_params, index_list, name_list,
149 from_clause, from_list, opt_array_bounds, nest_array_bounds,
150 expr_list, default_expr_list, attrs, res_target_list, res_target_list2,
151 def_list, opt_indirection, group_clause, groupby_list, TriggerFuncArgs
153 %type <list> union_clause, select_list
154 %type <list> join_list
155 %type <sortgroupby> join_using
157 %type <list> extract_list, position_list
158 %type <list> substr_list, substr_from, substr_for, trim_list
159 %type <list> interval_opts
161 %type <boolean> opt_inh_star, opt_binary, opt_instead, opt_with_col, opt_with_copy,
162 index_opt_unique, opt_verbose, opt_analyze, opt_null
164 %type <ival> copy_dirn, archive_type, OptArchiveType, OptArchiveLocation,
165 def_type, opt_direction, remove_type, opt_column, event
167 %type <ival> OptLocation, opt_move_where, fetch_how_many
169 %type <list> OptSeqList
170 %type <defelt> OptSeqElem
172 %type <dstmt> def_rest
173 %type <pstmt> purge_quals
174 %type <astmt> insert_rest
176 %type <typnam> Typename, typname, opt_type
177 %type <coldef> columnDef
178 %type <defelt> def_elem
179 %type <node> def_arg, columnElem, where_clause,
180 a_expr, a_expr_or_null, AexprConst,
181 default_expr, default_expr_or_null,
182 in_expr_nodes, not_in_expr_nodes,
184 %type <value> NumConst
185 %type <attr> event_object, attr
186 %type <sortgroupby> groupby
187 %type <sortgroupby> sortby
188 %type <ielem> index_elem, func_index
189 %type <range> from_val
190 %type <relexp> relation_expr
191 %type <trange> time_range
192 %type <target> res_target_el, res_target_el2
193 %type <paramno> ParamNo
197 %type <str> Id, date, var_value, zone_value
202 * If you make any token changes, remember to:
203 * - use "yacc -d" and update parse.h
204 * - update the keyword table in parser/keywords.c
208 %token ABORT_TRANS, ACL, ADD, AFTER, AGGREGATE, ALL, ALTER, ANALYZE,
209 AND, APPEND, ARCHIVE, ARCH_STORE, AS, ASC,
210 BACKWARD, BEFORE, BEGIN_TRANS, BETWEEN, BINARY, BOTH, BY,
211 CAST, CHANGE, CHECK, CLOSE, CLUSTER, COLUMN, COMMIT, CONSTRAINT, COPY, CREATE, CROSS,
212 CURRENT, CURSOR, DATABASE, DAYINTERVAL, DECLARE, DEFAULT, DELETE, DELIMITERS, DESC,
213 DISTINCT, DO, DROP, END_TRANS, EXISTS, EXTEND, EXTRACT,
214 FETCH, FOR, FORWARD, FROM, FULL, FUNCTION, GRANT, GROUP,
215 HAVING, HEAVY, HOURINTERVAL,
216 IN, INDEX, INHERITS, INNERJOIN, INSERT, INSTEAD, INTERVAL, INTO, IS, ISNULL,
217 JOIN, LANGUAGE, LEADING, LEFT, LIGHT, LISTEN, LOAD, LOCAL,
218 MERGE, MINUTEINTERVAL, MONTHINTERVAL, MOVE,
219 NATURAL, NEW, NONE, NOT, NOTHING, NOTIFY, NOTNULL,
220 OIDS, ON, OPERATOR, OPTION, OR, ORDER, OUTERJOIN,
221 PNULL, POSITION, PRIVILEGES, PROCEDURE, PUBLIC, PURGE, P_TYPE,
222 RENAME, REPLACE, RESET, RETRIEVE, RETURNS, REVOKE, RIGHT, ROLLBACK, RULE,
223 SECONDINTERVAL, SELECT, SET, SETOF, SHOW, STDIN, STDOUT, STORE, SUBSTRING,
224 TABLE, TIME, TO, TRAILING, TRANSACTION, TRIGGER, TRIM,
225 UNION, UNIQUE, UPDATE, USING, VACUUM, VALUES,
226 VERBOSE, VERSION, VIEW, WHERE, WITH, WORK, YEARINTERVAL, ZONE
227 %token EXECUTE, RECIPE, EXPLAIN, LIKE, SEQUENCE
229 /* Special keywords, not in the query language - see the "lex" file */
230 %token <str> IDENT, SCONST, Op
231 %token <ival> ICONST, PARAM
234 /* these are not real. they are here so that they gets generated as #define's*/
251 %left '|' /* this is the relation union op, not logical or */
252 %right ':' /* Unary Operators */
253 %left ';' /* end of statement or natural log */
266 { parsetree = lcons($1,NIL); }
269 stmtmulti: stmtmulti stmt ';'
270 { $$ = lappend($1, $2); }
272 { $$ = lappend($1, $2); }
274 { $$ = lcons($1,NIL); }
316 /*****************************************************************************
318 * Set PG internal variable
319 * SET var_name TO 'var_value'
321 *****************************************************************************/
323 VariableSetStmt: SET var_name TO var_value
325 VariableSetStmt *n = makeNode(VariableSetStmt);
330 | SET var_name '=' var_value
332 VariableSetStmt *n = makeNode(VariableSetStmt);
337 | SET TIME ZONE zone_value
339 VariableSetStmt *n = makeNode(VariableSetStmt);
340 n->name = "timezone";
346 var_value: Sconst { $$ = $1; }
349 zone_value: Sconst { $$ = $1; }
350 | LOCAL { $$ = NULL; }
353 VariableShowStmt: SHOW var_name
355 VariableShowStmt *n = makeNode(VariableShowStmt);
361 VariableResetStmt: RESET var_name
363 VariableResetStmt *n = makeNode(VariableResetStmt);
369 /*****************************************************************************
372 * addattr ( attr1 = type1 .. attrn = typen ) to <relname> [*]
374 *****************************************************************************/
376 AddAttrStmt: ALTER TABLE relation_name opt_inh_star ADD COLUMN columnDef
378 AddAttrStmt *n = makeNode(AddAttrStmt);
386 /* Column definition might include WITH TIME ZONE, but only for the data types
387 * called out in SQL92 date/time definitions. So, check explicitly for "timestamp"
388 * and "time". - thomas 1997-07-14
390 columnDef: Id Typename opt_with_col OptDefault opt_null
392 $$ = makeNode(ColumnDef);
395 $$->typename->timezone = $3;
397 $$->is_not_null = $5;
398 if ($$->typename->timezone
399 && (strcasecmp($$->typename->name, "timestamp")
400 && strcasecmp($$->typename->name, "time")))
401 elog(NOTICE,"%s does not use WITH TIME ZONE",$$->typename->name);
405 OptDefault: DEFAULT default_expr
407 int deflen = CurScanPosition() - DefaultStartPosition;
410 defval = (char*) palloc (deflen + 1);
411 memcpy (defval, parseString + DefaultStartPosition,
416 | /*EMPTY*/ { $$ = NULL; }
419 default_expr_or_null: default_expr
423 A_Const *n = makeNode(A_Const);
424 n->val.type = T_Null;
428 default_expr: AexprConst
430 if (nodeTag($1) != T_A_Const)
431 elog (WARN, "Cannot handle parameter in DEFAULT");
434 | '-' default_expr %prec UMINUS
435 { $$ = makeA_Expr(OP, "-", NULL, $2); }
436 | default_expr '+' default_expr
437 { $$ = makeA_Expr(OP, "+", $1, $3); }
438 | default_expr '-' default_expr
439 { $$ = makeA_Expr(OP, "-", $1, $3); }
440 | default_expr '/' default_expr
441 { $$ = makeA_Expr(OP, "/", $1, $3); }
442 | default_expr '*' default_expr
443 { $$ = makeA_Expr(OP, "*", $1, $3); }
444 | default_expr '<' default_expr
445 { $$ = makeA_Expr(OP, "<", $1, $3); }
446 | default_expr '>' default_expr
447 { $$ = makeA_Expr(OP, ">", $1, $3); }
448 | default_expr '=' default_expr
449 { $$ = makeA_Expr(OP, "=", $1, $3); }
451 { $$ = makeA_Expr(OP, ":", NULL, $2); }
453 { $$ = makeA_Expr(OP, ";", NULL, $2); }
455 { $$ = makeA_Expr(OP, "|", NULL, $2); }
456 | AexprConst TYPECAST Typename
458 /* AexprConst can be either A_Const or ParamNo */
459 if (nodeTag($1) == T_A_Const)
460 ((A_Const *)$1)->typename = $3;
462 elog (WARN, "Cannot handle parameter in DEFAULT");
465 | CAST AexprConst AS Typename
467 /* AexprConst can be either A_Const or ParamNo */
468 if (nodeTag($2) == T_A_Const)
469 ((A_Const *)$2)->typename = $4;
471 elog (WARN, "Cannot handle parameter in DEFAULT");
474 | '(' default_expr ')'
476 | default_expr Op default_expr
477 { $$ = makeA_Expr(OP, $2, $1, $3); }
479 { $$ = makeA_Expr(OP, $1, NULL, $2); }
481 { $$ = makeA_Expr(OP, $2, $1, NULL); }
484 FuncCall *n = makeNode(FuncCall);
489 | name '(' default_expr_list ')'
491 FuncCall *n = makeNode(FuncCall);
498 default_expr_list: default_expr_or_null
499 { $$ = lcons($1, NIL); }
500 | default_expr_list ',' default_expr_or_null
501 { $$ = lappend($1, $3); }
504 opt_null: NOT PNULL { $$ = true; }
505 | NOTNULL { $$ = true; }
506 | /* EMPTY */ { $$ = false; }
509 opt_with_col: WITH TIME ZONE { $$ = TRUE; }
510 | /* EMPTY */ { $$ = FALSE; }
513 /*****************************************************************************
518 *****************************************************************************/
520 ClosePortalStmt: CLOSE opt_id
522 ClosePortalStmt *n = makeNode(ClosePortalStmt);
529 /*****************************************************************************
532 * COPY [BINARY] <relname> FROM/TO
533 * [USING DELIMITERS <delimiter>]
535 *****************************************************************************/
537 CopyStmt: COPY opt_binary relation_name opt_with_copy copy_dirn copy_file_name copy_delimiter
539 CopyStmt *n = makeNode(CopyStmt);
557 * copy_file_name NULL indicates stdio is used. Whether stdin or stdout is
558 * used depends on the direction. (It really doesn't make sense to copy from
559 * stdout. We silently correct the "typo". - AY 9/94
561 copy_file_name: Sconst { $$ = $1; }
562 | STDIN { $$ = NULL; }
563 | STDOUT { $$ = NULL; }
566 opt_binary: BINARY { $$ = TRUE; }
567 | /*EMPTY*/ { $$ = FALSE; }
570 opt_with_copy: WITH OIDS { $$ = TRUE; }
571 | /* EMPTY */ { $$ = FALSE; }
575 * the default copy delimiter is tab but the user can configure it
577 copy_delimiter: USING DELIMITERS Sconst { $$ = $3;}
578 | /* EMPTY */ { $$ = "\t"; }
582 /*****************************************************************************
587 *****************************************************************************/
589 CreateStmt: CREATE TABLE relation_name '(' OptTableElementList ')'
590 OptInherit OptConstraint OptArchiveType OptLocation
593 CreateStmt *n = makeNode(CreateStmt);
605 OptTableElementList: tableElementList { $$ = $1; }
606 | /* EMPTY */ { $$ = NULL; }
610 tableElementList ',' columnDef
611 { $$ = lappend($1, $3); }
613 { $$ = lcons($1, NIL); }
617 OptArchiveType: ARCHIVE '=' archive_type { $$ = $3; }
618 | /*EMPTY*/ { $$ = ARCH_NONE; }
621 archive_type: HEAVY { $$ = ARCH_HEAVY; }
622 | LIGHT { $$ = ARCH_LIGHT; }
623 | NONE { $$ = ARCH_NONE; }
626 OptLocation: STORE '=' Sconst
632 OptArchiveLocation: ARCH_STORE '=' Sconst
638 OptInherit: INHERITS '(' relation_name_list ')' { $$ = $3; }
639 | /*EMPTY*/ { $$ = NIL; }
642 OptConstraint: ConstraintList { $$ = $1; }
647 ConstraintList ',' ConstraintElem
648 { $$ = lappend($1, $3); }
650 { $$ = lcons($1, NIL); }
654 CONSTRAINT name ConstraintDef
659 | ConstraintDef { $$ = $1; }
662 ConstraintDef: CHECK a_expr
664 ConstraintDef *constr = palloc (sizeof(ConstraintDef));
665 int chklen = CurScanPosition() - CheckStartPosition;
668 check = (char*) palloc (chklen + 1);
670 parseString + CheckStartPosition,
673 constr->type = CONSTR_CHECK;
675 constr->def = (void*) check;
680 /*****************************************************************************
683 * CREATE SEQUENCE seqname
685 *****************************************************************************/
687 CreateSeqStmt: CREATE SEQUENCE relation_name OptSeqList
689 CreateSeqStmt *n = makeNode(CreateSeqStmt);
697 OptSeqList OptSeqElem
698 { $$ = lappend($1, $2); }
702 OptSeqElem: IDENT NumConst
704 $$ = makeNode(DefElem);
706 $$->arg = (Node *)$2;
710 $$ = makeNode(DefElem);
712 $$->arg = (Node *)NULL;
717 /*****************************************************************************
723 *****************************************************************************/
725 CreateTrigStmt: CREATE TRIGGER name TriggerActionTime TriggerEvents ON
726 relation_name TriggerForSpec EXECUTE PROCEDURE
727 name '(' TriggerFuncArgs ')'
729 CreateTrigStmt *n = makeNode(CreateTrigStmt);
736 memcpy (n->actions, $5, 4);
741 TriggerActionTime: BEFORE { $$ = true; }
742 | AFTER { $$ = false; }
745 TriggerEvents: TriggerOneEvent
747 char *e = palloc (4);
748 e[0] = $1; e[1] = 0; $$ = e;
750 | TriggerOneEvent OR TriggerOneEvent
752 char *e = palloc (4);
753 e[0] = $1; e[1] = $3; e[2] = 0; $$ = e;
755 | TriggerOneEvent OR TriggerOneEvent OR TriggerOneEvent
757 char *e = palloc (4);
758 e[0] = $1; e[1] = $3; e[2] = $5; e[3] = 0;
763 TriggerOneEvent: INSERT { $$ = 'i'; }
764 | DELETE { $$ = 'd'; }
765 | UPDATE { $$ = 'u'; }
768 TriggerForSpec: FOR name name
770 if ( strcmp ($2, "each") != 0 )
771 elog (WARN, "parser: syntax error near %s", $2);
772 if ( strcmp ($3, "row") == 0 )
774 else if ( strcmp ($3, "statement") == 0 )
777 elog (WARN, "parser: syntax error near %s", $3);
781 TriggerFuncArgs: TriggerFuncArg
782 { $$ = lcons($1, NIL); }
783 | TriggerFuncArgs ',' TriggerFuncArg
784 { $$ = lappend($1, $3); }
785 | /* EMPTY */ { $$ = NIL; }
788 TriggerFuncArg: ICONST
790 char *s = (char *) palloc (256);
791 sprintf (s, "%d", $1);
794 | Sconst { $$ = $1; }
797 DropTrigStmt: DROP TRIGGER name ON relation_name
799 DropTrigStmt *n = makeNode(DropTrigStmt);
806 /*****************************************************************************
809 * define (type,operator,aggregate)
811 *****************************************************************************/
813 DefineStmt: CREATE def_type def_rest
820 def_rest: def_name definition
822 $$ = makeNode(DefineStmt);
828 def_type: OPERATOR { $$ = OPERATOR; }
829 | Type { $$ = P_TYPE; }
830 | AGGREGATE { $$ = AGGREGATE; }
833 def_name: Id | MathOp | Op
837 definition: '(' def_list ')' { $$ = $2; }
842 { $$ = lcons($1, NIL); }
843 | def_list ',' def_elem
844 { $$ = lappend($1, $3); }
847 def_elem: def_name '=' def_arg
849 $$ = makeNode(DefElem);
851 $$->arg = (Node *)$3;
855 $$ = makeNode(DefElem);
857 $$->arg = (Node *)NULL;
859 | DEFAULT '=' def_arg
861 $$ = makeNode(DefElem);
862 $$->defname = (char*) palloc (8);
863 strcpy ($$->defname, "default");
864 $$->arg = (Node *)$3;
868 def_arg: Id { $$ = (Node *)makeString($1); }
869 | all_Op { $$ = (Node *)makeString($1); }
870 | NumConst { $$ = (Node *)$1; /* already a Value */ }
871 | Sconst { $$ = (Node *)makeString($1); }
873 TypeName *n = makeNode(TypeName);
876 n->arrayBounds = NULL;
882 /*****************************************************************************
885 * destroy <relname1> [, <relname2> .. <relnameN> ]
887 *****************************************************************************/
889 DestroyStmt: DROP TABLE relation_name_list
891 DestroyStmt *n = makeNode(DestroyStmt);
896 | DROP SEQUENCE relation_name_list
898 DestroyStmt *n = makeNode(DestroyStmt);
906 /*****************************************************************************
909 * fetch [forward | backward] [number | all ] [ in <portalname> ]
911 *****************************************************************************/
913 FetchStmt: FETCH opt_direction fetch_how_many opt_portal_name
915 FetchStmt *n = makeNode(FetchStmt);
923 opt_direction: FORWARD { $$ = FORWARD; }
924 | BACKWARD { $$ = BACKWARD; }
925 | /*EMPTY*/ { $$ = FORWARD; /* default */ }
928 fetch_how_many: Iconst
930 if ($1 <= 0) elog(WARN,"Please specify nonnegative count for fetch"); }
931 | ALL { $$ = 0; /* 0 means fetch all tuples*/}
932 | /*EMPTY*/ { $$ = 1; /*default*/ }
935 /*****************************************************************************
938 * GRANT [privileges] ON [relation_name_list] TO [GROUP] grantee
940 *****************************************************************************/
942 GrantStmt: GRANT privileges ON relation_name_list TO grantee opt_with_grant
944 $$ = (Node*)makeAclStmt($2,$4,$6,'+');
950 privileges: ALL PRIVILEGES
952 $$ = aclmakepriv("rwaR",0);
956 $$ = aclmakepriv("rwaR",0);
958 | operation_commalist
964 operation_commalist: operation
966 $$ = aclmakepriv("",$1);
968 | operation_commalist ',' operation
970 $$ = aclmakepriv($1,$3);
977 $$ = ACL_MODE_RD_CHR;
981 $$ = ACL_MODE_AP_CHR;
985 $$ = ACL_MODE_WR_CHR;
989 $$ = ACL_MODE_WR_CHR;
993 $$ = ACL_MODE_RU_CHR;
999 $$ = aclmakeuser("A","");
1003 $$ = aclmakeuser("G",$2);
1007 $$ = aclmakeuser("U",$1);
1011 opt_with_grant : /* empty */
1014 yyerror("WITH GRANT OPTION is not supported. Only relation owners can set privileges");
1018 /*****************************************************************************
1021 * REVOKE [privileges] ON [relation_name] FROM [user]
1023 *****************************************************************************/
1025 RevokeStmt: REVOKE privileges ON relation_name_list FROM grantee
1027 $$ = (Node*)makeAclStmt($2,$4,$6,'-');
1033 /*****************************************************************************
1036 * move [<dirn>] [<whereto>] [<portalname>]
1038 *****************************************************************************/
1040 MoveStmt: MOVE opt_direction opt_move_where opt_portal_name
1042 MoveStmt *n = makeNode(MoveStmt);
1049 | MOVE opt_direction TO Iconst opt_portal_name
1051 MoveStmt *n = makeNode(MoveStmt);
1060 opt_move_where: Iconst { $$ = $1; }
1061 | /*EMPTY*/ { $$ = 1; /* default */ }
1064 opt_portal_name: IN name { $$ = $2;}
1065 | /*EMPTY*/ { $$ = NULL; }
1069 /*****************************************************************************
1072 * define [archive] index <indexname> on <relname>
1073 * using <access> "(" (<col> with <op>)+ ")" [with
1076 * [where <qual>] is not supported anymore
1077 *****************************************************************************/
1079 IndexStmt: CREATE index_opt_unique INDEX index_name ON relation_name
1080 access_method_clause '(' index_params ')' opt_with
1082 /* should check that access_method is valid,
1083 etc ... but doesn't */
1084 IndexStmt *n = makeNode(IndexStmt);
1088 n->accessMethod = $7;
1089 n->indexParams = $9;
1090 n->withClause = $11;
1091 n->whereClause = NULL;
1096 access_method_clause: USING access_method { $$ = $2; }
1097 | /* empty -- 'btree' is default access method */
1101 index_opt_unique: UNIQUE { $$ = TRUE; }
1102 | /*empty*/ { $$ = FALSE; }
1105 /*****************************************************************************
1108 * extend index <indexname> [where <qual>]
1110 *****************************************************************************/
1112 ExtendStmt: EXTEND INDEX index_name where_clause
1114 ExtendStmt *n = makeNode(ExtendStmt);
1116 n->whereClause = $4;
1121 /*****************************************************************************
1124 * execute recipe <recipeName>
1126 *****************************************************************************/
1128 RecipeStmt: EXECUTE RECIPE recipe_name
1131 if (!IsTransactionBlock())
1132 elog(WARN, "EXECUTE RECIPE may only be used in begin/end transaction blocks.");
1134 n = makeNode(RecipeStmt);
1141 /*****************************************************************************
1144 * define function <fname>
1145 * (language = <lang>, returntype = <typename>
1146 * [, arch_pct = <percentage | pre-defined>]
1147 * [, disk_pct = <percentage | pre-defined>]
1148 * [, byte_pct = <percentage | pre-defined>]
1149 * [, perbyte_cpu = <int | pre-defined>]
1150 * [, percall_cpu = <int | pre-defined>]
1152 * [arg is (<type-1> { , <type-n>})]
1153 * as <filename or code in language as appropriate>
1155 *****************************************************************************/
1157 ProcedureStmt: CREATE FUNCTION def_name def_args
1158 RETURNS def_arg opt_with AS Sconst LANGUAGE Sconst
1160 ProcedureStmt *n = makeNode(ProcedureStmt);
1163 n->returnType = (Node *)$6;
1170 opt_with: WITH definition { $$ = $2; }
1171 | /* EMPTY */ { $$ = NIL; }
1174 def_args: '(' def_name_list ')' { $$ = $2; }
1175 | '(' ')' { $$ = NIL; }
1178 def_name_list: name_list;
1181 /*****************************************************************************
1184 * purge <relname> [before <date>] [after <date>]
1186 * purge <relname> [after <date>] [before <date>]
1188 *****************************************************************************/
1190 PurgeStmt: PURGE relation_name purge_quals
1197 purge_quals: before_clause
1199 $$ = makeNode(PurgeStmt);
1200 $$->beforeDate = $1;
1201 $$->afterDate = NULL;
1205 $$ = makeNode(PurgeStmt);
1206 $$->beforeDate = NULL;
1209 | before_clause after_clause
1211 $$ = makeNode(PurgeStmt);
1212 $$->beforeDate = $1;
1215 | after_clause before_clause
1217 $$ = makeNode(PurgeStmt);
1218 $$->beforeDate = $2;
1223 $$ = makeNode(PurgeStmt);
1224 $$->beforeDate = NULL;
1225 $$->afterDate = NULL;
1229 before_clause: BEFORE date { $$ = $2; }
1230 after_clause: AFTER date { $$ = $2; }
1233 /*****************************************************************************
1237 * remove function <funcname>
1238 * (REMOVE FUNCTION "funcname" (arg1, arg2, ...))
1239 * remove aggregate <aggname>
1240 * (REMOVE AGGREGATE "aggname" "aggtype")
1241 * remove operator <opname>
1242 * (REMOVE OPERATOR "opname" (leftoperand_typ rightoperand_typ))
1243 * remove type <typename>
1244 * (REMOVE TYPE "typename")
1245 * remove rule <rulename>
1246 * (REMOVE RULE "rulename")
1248 *****************************************************************************/
1250 RemoveStmt: DROP remove_type name
1252 RemoveStmt *n = makeNode(RemoveStmt);
1259 remove_type: Type { $$ = P_TYPE; }
1260 | INDEX { $$ = INDEX; }
1261 | RULE { $$ = RULE; }
1262 | VIEW { $$ = VIEW; }
1265 RemoveAggrStmt: DROP AGGREGATE name aggr_argtype
1267 RemoveAggrStmt *n = makeNode(RemoveAggrStmt);
1274 aggr_argtype: name { $$ = $1; }
1275 | '*' { $$ = NULL; }
1278 RemoveFuncStmt: DROP FUNCTION name '(' func_argtypes ')'
1280 RemoveFuncStmt *n = makeNode(RemoveFuncStmt);
1287 func_argtypes: name_list { $$ = $1; }
1288 | /*EMPTY*/ { $$ = NIL; }
1291 RemoveOperStmt: DROP OPERATOR all_Op '(' oper_argtypes ')'
1293 RemoveOperStmt *n = makeNode(RemoveOperStmt);
1300 all_Op: Op | MathOp;
1302 MathOp: '+' { $$ = "+"; }
1313 elog(WARN, "parser: argument type missing (use NONE for unary operators)");
1316 { $$ = makeList(makeString($1), makeString($3), -1); }
1317 | NONE ',' name /* left unary */
1318 { $$ = makeList(NULL, makeString($3), -1); }
1319 | name ',' NONE /* right unary */
1320 { $$ = makeList(makeString($1), NULL, -1); }
1323 /*****************************************************************************
1326 * rename <attrname1> in <relname> [*] to <attrname2>
1327 * rename <relname1> to <relname2>
1329 *****************************************************************************/
1331 RenameStmt: ALTER TABLE relation_name opt_inh_star
1332 RENAME opt_column opt_name TO name
1334 RenameStmt *n = makeNode(RenameStmt);
1343 opt_name: name { $$ = $1; }
1344 | /*EMPTY*/ { $$ = NULL; }
1347 opt_column: COLUMN { $$ = COLUMN; }
1348 | /*EMPTY*/ { $$ = 0; }
1352 /*****************************************************************************
1354 * QUERY: Define Rewrite Rule , Define Tuple Rule
1355 * Define Rule <old rules >
1357 * only rewrite rule is supported -- ay 9/94
1359 *****************************************************************************/
1361 RuleStmt: CREATE RULE name AS
1362 { QueryIsRule=TRUE; }
1363 ON event TO event_object where_clause
1364 DO opt_instead OptStmtList
1366 RuleStmt *n = makeNode(RuleStmt);
1370 n->whereClause = $10;
1377 OptStmtList: NOTHING { $$ = NIL; }
1378 | OptimizableStmt { $$ = lcons($1, NIL); }
1379 | '[' OptStmtBlock ']' { $$ = $2; }
1382 OptStmtBlock: OptStmtMulti
1385 { $$ = lcons($1, NIL); }
1388 OptStmtMulti: OptStmtMulti OptimizableStmt ';'
1389 { $$ = lappend($1, $2); }
1390 | OptStmtMulti OptimizableStmt
1391 { $$ = lappend($1, $2); }
1392 | OptimizableStmt ';'
1393 { $$ = lcons($1, NIL); }
1396 event_object: relation_name '.' attr_name
1398 $$ = makeNode(Attr);
1401 $$->attrs = lcons(makeString($3), NIL);
1402 $$->indirection = NIL;
1406 $$ = makeNode(Attr);
1410 $$->indirection = NIL;
1414 /* change me to select, update, etc. some day */
1415 event: SELECT { $$ = CMD_SELECT; }
1416 | UPDATE { $$ = CMD_UPDATE; }
1417 | DELETE { $$ = CMD_DELETE; }
1418 | INSERT { $$ = CMD_INSERT; }
1421 opt_instead: INSTEAD { $$ = TRUE; }
1422 | /* EMPTY */ { $$ = FALSE; }
1426 /*****************************************************************************
1429 * NOTIFY <relation_name> can appear both in rule bodies and
1430 * as a query-level command
1432 *****************************************************************************/
1434 NotifyStmt: NOTIFY relation_name
1436 NotifyStmt *n = makeNode(NotifyStmt);
1442 ListenStmt: LISTEN relation_name
1444 ListenStmt *n = makeNode(ListenStmt);
1451 /*****************************************************************************
1462 *****************************************************************************/
1464 TransactionStmt: ABORT_TRANS TRANSACTION
1466 TransactionStmt *n = makeNode(TransactionStmt);
1467 n->command = ABORT_TRANS;
1470 | BEGIN_TRANS TRANSACTION
1472 TransactionStmt *n = makeNode(TransactionStmt);
1473 n->command = BEGIN_TRANS;
1478 TransactionStmt *n = makeNode(TransactionStmt);
1479 n->command = BEGIN_TRANS;
1484 TransactionStmt *n = makeNode(TransactionStmt);
1485 n->command = END_TRANS;
1488 | END_TRANS TRANSACTION
1490 TransactionStmt *n = makeNode(TransactionStmt);
1491 n->command = END_TRANS;
1496 TransactionStmt *n = makeNode(TransactionStmt);
1497 n->command = ABORT_TRANS;
1503 TransactionStmt *n = makeNode(TransactionStmt);
1504 n->command = ABORT_TRANS;
1509 TransactionStmt *n = makeNode(TransactionStmt);
1510 n->command = BEGIN_TRANS;
1515 TransactionStmt *n = makeNode(TransactionStmt);
1516 n->command = END_TRANS;
1522 TransactionStmt *n = makeNode(TransactionStmt);
1523 n->command = END_TRANS;
1528 TransactionStmt *n = makeNode(TransactionStmt);
1529 n->command = ABORT_TRANS;
1535 /*****************************************************************************
1538 * define view <viewname> '('target-list ')' [where <quals> ]
1540 *****************************************************************************/
1542 ViewStmt: CREATE VIEW name AS RetrieveStmt
1544 ViewStmt *n = makeNode(ViewStmt);
1546 n->query = (Query *)$5;
1552 /*****************************************************************************
1557 *****************************************************************************/
1559 LoadStmt: LOAD file_name
1561 LoadStmt *n = makeNode(LoadStmt);
1568 /*****************************************************************************
1573 *****************************************************************************/
1575 CreatedbStmt: CREATE DATABASE database_name
1577 CreatedbStmt *n = makeNode(CreatedbStmt);
1584 /*****************************************************************************
1589 *****************************************************************************/
1591 DestroydbStmt: DROP DATABASE database_name
1593 DestroydbStmt *n = makeNode(DestroydbStmt);
1600 /*****************************************************************************
1603 * cluster <index_name> on <relation_name>
1605 *****************************************************************************/
1607 ClusterStmt: CLUSTER index_name ON relation_name
1609 ClusterStmt *n = makeNode(ClusterStmt);
1616 /*****************************************************************************
1621 *****************************************************************************/
1623 VacuumStmt: VACUUM opt_verbose opt_analyze
1625 VacuumStmt *n = makeNode(VacuumStmt);
1632 | VACUUM opt_verbose relation_name opt_analyze opt_va_list
1634 VacuumStmt *n = makeNode(VacuumStmt);
1639 if ( $5 != NIL && !$4 )
1640 elog (WARN, "parser: syntax error at or near \"(\"");
1645 opt_verbose: VERBOSE { $$ = TRUE; }
1646 | /* EMPTY */ { $$ = FALSE; }
1649 opt_analyze: ANALYZE { $$ = TRUE; }
1650 | /* EMPTY */ { $$ = FALSE; }
1653 opt_va_list: '(' va_list ')'
1660 { $$=lcons($1,NIL); }
1662 { $$=lappend($1,$3); }
1665 /*****************************************************************************
1670 *****************************************************************************/
1672 ExplainStmt: EXPLAIN opt_verbose OptimizableStmt
1674 ExplainStmt *n = makeNode(ExplainStmt);
1676 n->query = (Query*)$3;
1681 /*****************************************************************************
1683 * Optimizable Stmts: *
1685 * one of the five queries processed by the planner *
1687 * [ultimately] produces query-trees as specified *
1688 * in the query-spec document in ~postgres/ref *
1690 *****************************************************************************/
1692 OptimizableStmt: RetrieveStmt
1697 | DeleteStmt /* by default all are $$=$1 */
1701 /*****************************************************************************
1706 *****************************************************************************/
1708 AppendStmt: INSERT INTO relation_name opt_column_list insert_rest
1716 insert_rest: VALUES '(' res_target_list2 ')'
1718 $$ = makeNode(AppendStmt);
1719 $$->targetList = $3;
1720 $$->fromClause = NIL;
1721 $$->whereClause = NULL;
1723 | SELECT res_target_list2 from_clause where_clause
1725 $$ = makeNode(AppendStmt);
1726 $$->targetList = $2;
1727 $$->fromClause = $3;
1728 $$->whereClause = $4;
1732 opt_column_list: '(' columnList ')' { $$ = $2; }
1733 | /*EMPTY*/ { $$ = NIL; }
1737 columnList ',' columnElem
1738 { $$ = lappend($1, $3); }
1740 { $$ = lcons($1, NIL); }
1743 columnElem: Id opt_indirection
1745 Ident *id = makeNode(Ident);
1747 id->indirection = $2;
1752 /*****************************************************************************
1757 *****************************************************************************/
1759 DeleteStmt: DELETE FROM relation_name
1762 DeleteStmt *n = makeNode(DeleteStmt);
1764 n->whereClause = $4;
1770 /*****************************************************************************
1773 * ReplaceStmt (UPDATE)
1775 *****************************************************************************/
1777 ReplaceStmt: UPDATE relation_name
1782 ReplaceStmt *n = makeNode(ReplaceStmt);
1786 n->whereClause = $6;
1792 /*****************************************************************************
1797 *****************************************************************************/
1799 CursorStmt: DECLARE name opt_binary CURSOR FOR
1800 SELECT opt_unique res_target_list2
1801 from_clause where_clause group_clause sort_clause
1803 CursorStmt *n = makeNode(CursorStmt);
1805 /* from PORTAL name */
1807 * 15 august 1991 -- since 3.0 postgres does locking
1808 * right, we discovered that portals were violating
1809 * locking protocol. portal locks cannot span xacts.
1810 * as a short-term fix, we installed the check here.
1813 if (!IsTransactionBlock())
1814 elog(WARN, "Named portals may only be used in begin/end transaction blocks.");
1821 n->whereClause = $10;
1822 n->groupClause = $11;
1823 n->sortClause = $12;
1829 /*****************************************************************************
1834 *****************************************************************************/
1836 /******************************************************************************
1837 RetrieveStmt: SELECT opt_unique res_target_list2
1838 result from_clause where_clause
1839 group_clause having_clause
1842 RetrieveStmt *n = makeNode(RetrieveStmt);
1847 n->whereClause = $6;
1848 n->groupClause = $7;
1849 n->havingClause = $8;
1855 RetrieveStmt: Select UNION select_list sort_clause
1856 | Select sort_clause
1857 Select: SELECT opt_unique res_target_list2
1858 result from_clause where_clause
1859 group_clause having_clause
1861 Select *n = makeNode(Select);
1866 n->whereClause = $6;
1867 n->groupClause = $7;
1868 n->havingClause = $8;
1872 ******************************************************************************/
1874 RetrieveStmt: SELECT opt_unique res_target_list2
1875 result from_clause where_clause
1876 group_clause having_clause
1877 union_clause sort_clause
1879 RetrieveStmt *n = makeNode(RetrieveStmt);
1884 n->whereClause = $6;
1885 n->groupClause = $7;
1886 n->havingClause = $8;
1887 n->selectClause = $9;
1888 n->sortClause = $10;
1893 union_clause: UNION select_list { $$ = $2; }
1894 | /*EMPTY*/ { $$ = NIL; }
1897 select_list: select_list UNION SubSelect
1898 { $$ = lappend($1, $3); }
1900 { $$ = lcons($1, NIL); }
1903 SubSelect: SELECT opt_unique res_target_list2
1904 result from_clause where_clause
1905 group_clause having_clause
1907 SubSelect *n = makeNode(SubSelect);
1911 n->whereClause = $6;
1912 n->groupClause = $7;
1913 n->havingClause = $8;
1918 result: INTO TABLE relation_name
1919 { $$= $3; /* should check for archive level */ }
1924 opt_unique: DISTINCT { $$ = "*"; }
1925 | DISTINCT ON Id { $$ = $3; }
1926 | /*EMPTY*/ { $$ = NULL;}
1929 sort_clause: ORDER BY sortby_list { $$ = $3; }
1930 | /*EMPTY*/ { $$ = NIL; }
1934 { $$ = lcons($1, NIL); }
1935 | sortby_list ',' sortby
1936 { $$ = lappend($1, $3); }
1941 $$ = makeNode(SortGroupBy);
1947 | Id '.' Id OptUseOp
1949 $$ = makeNode(SortGroupBy);
1957 $$ = makeNode(SortGroupBy);
1965 OptUseOp: USING Op { $$ = $2; }
1966 | USING '<' { $$ = "<"; }
1967 | USING '>' { $$ = ">"; }
1969 | DESC { $$ = ">"; }
1970 | /*EMPTY*/ { $$ = "<"; /*default*/ }
1973 index_params: index_list { $$ = $1; }
1974 | func_index { $$ = lcons($1,NIL); }
1978 index_list ',' index_elem
1979 { $$ = lappend($1, $3); }
1981 { $$ = lcons($1, NIL); }
1984 func_index: name '(' name_list ')' opt_type opt_class
1986 $$ = makeNode(IndexElem);
1994 index_elem: attr_name opt_type opt_class
1996 $$ = makeNode(IndexElem);
2004 opt_type: ':' Typename { $$ = $2;}
2005 | /*EMPTY*/ { $$ = NULL;}
2009 | WITH class { $$ = $2; }
2010 | /*EMPTY*/ { $$ = NULL; }
2014 * jimmy bell-style recursive queries aren't supported in the
2017 * ...however, recursive addattr and rename supported. make special
2020 * XXX i believe '*' should be the default behavior, but...
2022 opt_inh_star: '*' { $$ = TRUE; }
2023 | /*EMPTY*/ { $$ = FALSE; }
2026 relation_name_list: name_list ;
2029 { $$=lcons(makeString($1),NIL); }
2030 | name_list ',' name
2031 { $$=lappend($1,makeString($3)); }
2034 group_clause: GROUP BY groupby_list { $$ = $3; }
2035 | /*EMPTY*/ { $$ = NIL; }
2038 groupby_list: groupby { $$ = lcons($1, NIL); }
2039 | groupby_list ',' groupby { $$ = lappend($1, $3); }
2044 $$ = makeNode(SortGroupBy);
2052 $$ = makeNode(SortGroupBy);
2060 $$ = makeNode(SortGroupBy);
2068 having_clause: HAVING a_expr { $$ = $2; }
2069 | /*EMPTY*/ { $$ = NULL; }
2072 /*****************************************************************************
2074 * clauses common to all Optimizable Stmts:
2078 *****************************************************************************/
2080 from_clause: FROM '(' relation_expr join_clause relation_expr join_spec ')'
2083 elog(WARN,"JOIN not yet implemented",NULL);
2085 | FROM from_list { $$ = $2; }
2086 | /*EMPTY*/ { $$ = NIL; }
2089 from_list: from_list ',' from_val
2090 { $$ = lappend($1, $3); }
2091 | from_val CROSS JOIN from_val
2092 { elog(WARN,"CROSS JOIN not yet implemented",NULL); }
2094 { $$ = lcons($1, NIL); }
2097 from_val: relation_expr AS var_name
2099 $$ = makeNode(RangeVar);
2103 | relation_expr var_name
2105 $$ = makeNode(RangeVar);
2111 $$ = makeNode(RangeVar);
2117 join_clause: join_qual join_type JOIN
2123 join_qual: NATURAL { $$ = TRUE; }
2124 | /*EMPTY*/ { $$ = FALSE; }
2127 join_type: FULL join_outer
2128 { elog(WARN,"FULL OUTER JOIN not yet implemented",NULL); }
2130 { elog(WARN,"LEFT OUTER JOIN not yet implemented",NULL); }
2132 { elog(WARN,"RIGHT OUTER JOIN not yet implemented",NULL); }
2134 { elog(WARN,"OUTER JOIN not yet implemented",NULL); }
2136 { elog(WARN,"INNER JOIN not yet implemented",NULL); }
2138 { elog(WARN,"UNION JOIN not yet implemented",NULL); }
2139 | /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
2142 join_outer: OUTERJOIN { $$ = NULL; }
2143 | /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
2146 join_spec: ON '(' a_expr ')' { $$ = NULL; }
2147 | USING '(' join_list ')' { $$ = NULL; }
2148 | /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
2151 join_list: join_using { $$ = lcons($1, NIL); }
2152 | join_list ',' join_using { $$ = lappend($1, $3); }
2157 $$ = makeNode(SortGroupBy);
2165 $$ = makeNode(SortGroupBy);
2173 $$ = makeNode(SortGroupBy);
2181 where_clause: WHERE a_expr { $$ = $2; }
2182 | /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
2185 relation_expr: relation_name
2187 /* normal relations */
2188 $$ = makeNode(RelExpr);
2191 $$->timeRange = NULL;
2193 | relation_name '*' %prec '='
2195 /* inheiritance query */
2196 $$ = makeNode(RelExpr);
2199 $$->timeRange = NULL;
2201 | relation_name time_range
2203 /* time-qualified query */
2204 $$ = makeNode(RelExpr);
2212 time_range: '[' opt_range_start ',' opt_range_end ']'
2214 $$ = makeNode(TimeRange);
2220 $$ = makeNode(TimeRange);
2226 opt_range_start: date
2227 | /*EMPTY*/ { $$ = "epoch"; }
2231 | /*EMPTY*/ { $$ = "now"; }
2234 opt_array_bounds: '[' ']' nest_array_bounds
2235 { $$ = lcons(makeInteger(-1), $3); }
2236 | '[' Iconst ']' nest_array_bounds
2237 { $$ = lcons(makeInteger($2), $4); }
2242 nest_array_bounds: '[' ']' nest_array_bounds
2243 { $$ = lcons(makeInteger(-1), $3); }
2244 | '[' Iconst ']' nest_array_bounds
2245 { $$ = lcons(makeInteger($2), $4); }
2252 char *tname = xlateSqlType($1);
2253 $$ = makeNode(TypeName);
2256 /* Is this the name of a complex type? If so, implement
2259 if (!strcmp(saved_relname, tname))
2260 /* This attr is the same type as the relation
2261 * being defined. The classic example: create
2262 * emp(name=text,mgr=emp)
2265 else if (get_typrelid((Type)type(tname)) != InvalidOid)
2266 /* (Eventually add in here that the set can only
2267 * contain one element.)
2275 char *tname = xlateSqlType($2);
2276 $$ = makeNode(TypeName);
2282 txname: Id { $$ = $1; }
2283 | TIME { $$ = "time"; }
2284 | INTERVAL interval_opts { $$ = "interval"; }
2287 interval_opts: YEARINTERVAL { $$ = lcons("year", NIL); }
2288 | MONTHINTERVAL { $$ = NIL; }
2289 | DAYINTERVAL { $$ = NIL; }
2290 | HOURINTERVAL { $$ = NIL; }
2291 | MINUTEINTERVAL { $$ = NIL; }
2292 | SECONDINTERVAL { $$ = NIL; }
2293 | YEARINTERVAL TO MONTHINTERVAL { $$ = NIL; }
2294 | DAYINTERVAL TO HOURINTERVAL { $$ = NIL; }
2295 | DAYINTERVAL TO MINUTEINTERVAL { $$ = NIL; }
2296 | DAYINTERVAL TO SECONDINTERVAL { $$ = NIL; }
2297 | HOURINTERVAL TO MINUTEINTERVAL { $$ = NIL; }
2298 | HOURINTERVAL TO SECONDINTERVAL { $$ = NIL; }
2299 | /* EMPTY */ { $$ = NIL; }
2302 Typename: typname opt_array_bounds
2305 $$->arrayBounds = $2;
2307 | txname '(' Iconst ')'
2310 * This block gets hit when the parser is passed a query
2311 * which contains only spaces (e.g. from psql type " \g").
2312 * Let's check explicitly for a zero-length argument
2313 * here, and do nothing if so. This seems to fix the problem.
2314 * - thomas 1997-07-13
2320 * The following implements char() and varchar().
2321 * We do it here instead of the 'typname:' production
2322 * because we don't want to allow arrays of varchar().
2323 * I haven't thought about whether that will work or not.
2326 $$ = makeNode(TypeName);
2327 if (!strcasecmp($1, "char"))
2328 $$->name = "bpchar"; /* strdup("bpchar"); */
2329 else if (!strcasecmp($1, "varchar"))
2330 $$->name = "varchar"; /* strdup("varchar"); */
2332 yyerror("parse error");
2334 elog(WARN, "length for '%s' type must be at least 1",$1);
2336 /* we can store a char() of length up to the size
2337 * of a page (8KB) - page headers and friends but
2338 * just to be safe here... - ay 6/95
2339 * XXX note this hardcoded limit - thomas 1997-07-13
2341 elog(WARN, "length for '%s' type cannot exceed 4096",$1);
2343 /* we actually implement this sort of like a varlen, so
2344 * the first 4 bytes is the length. (the difference
2345 * between this and "text" is that we blank-pad and
2346 * truncate where necessary
2348 $$->typlen = 4 + $3;
2355 /*****************************************************************************
2357 * expression grammar, still needs some cleanup
2359 *****************************************************************************/
2361 a_expr_or_null: a_expr
2365 A_Const *n = makeNode(A_Const);
2366 n->val.type = T_Null;
2370 a_expr: attr opt_indirection
2372 $1->indirection = $2;
2377 | '-' a_expr %prec UMINUS
2378 { $$ = makeA_Expr(OP, "-", NULL, $2); }
2380 { $$ = makeA_Expr(OP, "+", $1, $3); }
2382 { $$ = makeA_Expr(OP, "-", $1, $3); }
2384 { $$ = makeA_Expr(OP, "/", $1, $3); }
2386 { $$ = makeA_Expr(OP, "*", $1, $3); }
2388 { $$ = makeA_Expr(OP, "<", $1, $3); }
2390 { $$ = makeA_Expr(OP, ">", $1, $3); }
2392 { $$ = makeA_Expr(OP, "=", $1, $3); }
2394 { $$ = makeA_Expr(OP, ":", NULL, $2); }
2396 { $$ = makeA_Expr(OP, ";", NULL, $2); }
2398 { $$ = makeA_Expr(OP, "|", NULL, $2); }
2399 | AexprConst TYPECAST Typename
2401 /* AexprConst can be either A_Const or ParamNo */
2402 if (nodeTag($1) == T_A_Const)
2403 ((A_Const *)$1)->typename = $3;
2405 ((ParamNo *)$1)->typename = $3;
2408 | CAST AexprConst AS Typename
2410 /* AexprConst can be either A_Const or ParamNo */
2411 if (nodeTag($2) == T_A_Const)
2412 ((A_Const *)$2)->typename = $4;
2414 ((ParamNo *)$2)->typename = $4;
2417 | '(' a_expr_or_null ')'
2420 { $$ = makeA_Expr(OP, $2, $1, $3); }
2421 | a_expr LIKE a_expr
2422 { $$ = makeA_Expr(OP, "~~", $1, $3); }
2423 | a_expr NOT LIKE a_expr
2424 { $$ = makeA_Expr(OP, "!~~", $1, $4); }
2426 { $$ = makeA_Expr(OP, $1, NULL, $2); }
2428 { $$ = makeA_Expr(OP, $2, $1, NULL); }
2431 /* could be a column name or a relation_name */
2432 Ident *n = makeNode(Ident);
2434 n->indirection = NULL;
2439 FuncCall *n = makeNode(FuncCall);
2440 Ident *star = makeNode(Ident);
2442 /* cheap hack for aggregate (eg. count) */
2445 n->args = lcons(star, NIL);
2450 FuncCall *n = makeNode(FuncCall);
2455 /* We probably need to define an "exists" node,
2456 * since the optimizer could choose to find only one match.
2457 * Perhaps the first implementation could just check for
2458 * count(*) > 0? - thomas 1997-07-19
2460 | EXISTS '(' SubSelect ')'
2462 elog(WARN,"EXISTS not yet supported",NULL);
2465 | EXTRACT '(' extract_list ')'
2467 FuncCall *n = makeNode(FuncCall);
2468 n->funcname = "date_part";
2472 | POSITION '(' position_list ')'
2474 FuncCall *n = makeNode(FuncCall);
2475 n->funcname = "strpos";
2479 | SUBSTRING '(' substr_list ')'
2481 FuncCall *n = makeNode(FuncCall);
2482 n->funcname = "substr";
2486 /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
2487 | TRIM '(' BOTH trim_list ')'
2489 FuncCall *n = makeNode(FuncCall);
2490 n->funcname = "btrim";
2494 | TRIM '(' LEADING trim_list ')'
2496 FuncCall *n = makeNode(FuncCall);
2497 n->funcname = "ltrim";
2501 | TRIM '(' TRAILING trim_list ')'
2503 FuncCall *n = makeNode(FuncCall);
2504 n->funcname = "rtrim";
2508 | TRIM '(' trim_list ')'
2510 FuncCall *n = makeNode(FuncCall);
2511 n->funcname = "btrim";
2515 | name '(' expr_list ')'
2517 FuncCall *n = makeNode(FuncCall);
2523 { $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
2525 { $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
2527 { $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); }
2528 | a_expr IS NOT PNULL
2529 { $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); }
2530 | a_expr BETWEEN AexprConst AND AexprConst
2532 $$ = makeA_Expr(AND, NULL,
2533 makeA_Expr(OP, ">=", $1, $3),
2534 makeA_Expr(OP, "<=", $1, $5));
2536 | a_expr NOT BETWEEN AexprConst AND AexprConst
2538 $$ = makeA_Expr(OR, NULL,
2539 makeA_Expr(OP, "<", $1, $4),
2540 makeA_Expr(OP, ">", $1, $6));
2542 | a_expr IN { saved_In_Expr = $1; } '(' in_expr_nodes ')'
2544 | a_expr NOT IN { saved_In_Expr = $1; } '(' not_in_expr_nodes ')'
2547 { $$ = makeA_Expr(AND, NULL, $1, $3); }
2549 { $$ = makeA_Expr(OR, NULL, $1, $3); }
2551 { $$ = makeA_Expr(NOT, NULL, NULL, $2); }
2554 opt_indirection: '[' a_expr ']' opt_indirection
2556 A_Indices *ai = makeNode(A_Indices);
2561 | '[' a_expr ':' a_expr ']' opt_indirection
2563 A_Indices *ai = makeNode(A_Indices);
2572 expr_list: a_expr_or_null
2573 { $$ = lcons($1, NIL); }
2574 | expr_list ',' a_expr_or_null
2575 { $$ = lappend($1, $3); }
2576 | expr_list USING a_expr
2577 { $$ = lappend($1, $3); }
2580 extract_list: datetime FROM a_expr
2582 A_Const *n = makeNode(A_Const);
2583 n->val.type = T_String;
2584 n->val.val.str = $1;
2585 printf( "string is %s\n", $1);
2586 $$ = lappend(lcons((Node *)n,NIL), $3);
2592 position_list: a_expr IN expr_list
2593 { $$ = lappend($3, $1); }
2598 substr_list: expr_list substr_from substr_for
2601 if ($2 != NULL) $$ = lappend($$, $2);
2602 if ($3 != NULL) $$ = lappend($$, $3);
2608 substr_from: FROM expr_list
2614 substr_for: FOR expr_list
2620 trim_list: a_expr FROM expr_list
2621 { $$ = lappend($3, $1); }
2628 in_expr_nodes: AexprConst
2629 { $$ = makeA_Expr(OP, "=", saved_In_Expr, $1); }
2630 | in_expr_nodes ',' AexprConst
2631 { $$ = makeA_Expr(OR, NULL, $1,
2632 makeA_Expr(OP, "=", saved_In_Expr, $3));
2636 not_in_expr_nodes: AexprConst
2637 { $$ = makeA_Expr(OP, "<>", saved_In_Expr, $1); }
2638 | not_in_expr_nodes ',' AexprConst
2639 { $$ = makeA_Expr(AND, NULL, $1,
2640 makeA_Expr(OP, "<>", saved_In_Expr, $3));
2644 attr: relation_name '.' attrs
2646 $$ = makeNode(Attr);
2650 $$->indirection = NULL;
2654 $$ = makeNode(Attr);
2658 $$->indirection = NULL;
2663 { $$ = lcons(makeString($1), NIL); }
2664 | attrs '.' attr_name
2665 { $$ = lappend($1, makeString($3)); }
2667 { $$ = lappend($1, makeString("*")); }
2670 datetime: YEARINTERVAL { $$ = "year"; }
2671 | MONTHINTERVAL { $$ = "month"; }
2672 | DAYINTERVAL { $$ = "day"; }
2673 | HOURINTERVAL { $$ = "hour"; }
2674 | MINUTEINTERVAL { $$ = "minute"; }
2675 | SECONDINTERVAL { $$ = "second"; }
2678 /*****************************************************************************
2682 *****************************************************************************/
2684 res_target_list: res_target_list ',' res_target_el
2685 { $$ = lappend($1,$3); }
2687 { $$ = lcons($1, NIL); }
2690 ResTarget *rt = makeNode(ResTarget);
2691 Attr *att = makeNode(Attr);
2693 att->paramNo = NULL;
2695 att->indirection = NIL;
2697 rt->indirection = NULL;
2698 rt->val = (Node *)att;
2699 $$ = lcons(rt, NIL);
2703 res_target_el: Id opt_indirection '=' a_expr_or_null
2705 $$ = makeNode(ResTarget);
2707 $$->indirection = $2;
2708 $$->val = (Node *)$4;
2710 | attr opt_indirection
2712 $$ = makeNode(ResTarget);
2714 $$->indirection = $2;
2715 $$->val = (Node *)$1;
2717 | relation_name '.' '*'
2719 Attr *att = makeNode(Attr);
2721 att->paramNo = NULL;
2722 att->attrs = lcons(makeString("*"), NIL);
2723 att->indirection = NIL;
2724 $$ = makeNode(ResTarget);
2726 $$->indirection = NULL;
2727 $$->val = (Node *)att;
2732 ** target list for select.
2733 ** should get rid of the other but is still needed by the defunct retrieve into
2734 ** and update (uses a subset)
2736 res_target_list2: res_target_list2 ',' res_target_el2
2737 { $$ = lappend($1, $3); }
2739 { $$ = lcons($1, NIL); }
2742 /* AS is not optional because shift/red conflict with unary ops */
2743 res_target_el2: a_expr AS ColId
2745 $$ = makeNode(ResTarget);
2747 $$->indirection = NULL;
2748 $$->val = (Node *)$1;
2752 $$ = makeNode(ResTarget);
2754 $$->indirection = NULL;
2755 $$->val = (Node *)$1;
2757 | relation_name '.' '*'
2759 Attr *att = makeNode(Attr);
2761 att->paramNo = NULL;
2762 att->attrs = lcons(makeString("*"), NIL);
2763 att->indirection = NIL;
2764 $$ = makeNode(ResTarget);
2766 $$->indirection = NULL;
2767 $$->val = (Node *)att;
2771 Attr *att = makeNode(Attr);
2773 att->paramNo = NULL;
2775 att->indirection = NIL;
2776 $$ = makeNode(ResTarget);
2778 $$->indirection = NULL;
2779 $$->val = (Node *)att;
2783 opt_id: Id { $$ = $1; }
2784 | /* EMPTY */ { $$ = NULL; }
2787 relation_name: SpecialRuleRelation
2790 strNcpy(saved_relname, $1, NAMEDATALEN-1);
2794 /* disallow refs to magic system tables */
2795 if (strcmp(LogRelationName, $1) == 0
2796 || strcmp(VariableRelationName, $1) == 0
2797 || strcmp(TimeRelationName, $1) == 0
2798 || strcmp(MagicRelationName, $1) == 0)
2799 elog(WARN, "%s cannot be accessed by users", $1);
2802 strNcpy(saved_relname, $1, NAMEDATALEN-1);
2806 database_name: Id { $$ = $1; };
2807 access_method: Id { $$ = $1; };
2808 attr_name: ColId { $$ = $1; };
2809 class: Id { $$ = $1; };
2810 index_name: Id { $$ = $1; };
2811 var_name: Id { $$ = $1; };
2812 name: Id { $$ = $1; };
2814 date: Sconst { $$ = $1; };
2815 file_name: Sconst { $$ = $1; };
2816 recipe_name: Id { $$ = $1; };
2820 A_Const *n = makeNode(A_Const);
2821 n->val.type = T_Integer;
2822 n->val.val.ival = $1;
2827 A_Const *n = makeNode(A_Const);
2828 n->val.type = T_Float;
2829 n->val.val.dval = $1;
2834 A_Const *n = makeNode(A_Const);
2835 n->val.type = T_String;
2836 n->val.val.str = $1;
2840 { $$ = (Node *)$1; }
2845 $$ = makeNode(ParamNo);
2850 NumConst: Iconst { $$ = makeInteger($1); }
2851 | FCONST { $$ = makeFloat($1); }
2854 Iconst: ICONST { $$ = $1; };
2855 Sconst: SCONST { $$ = $1; };
2857 Id: IDENT { $$ = $1; };
2859 ColId: Id { $$ = $1; }
2860 | datetime { $$ = $1; }
2863 SpecialRuleRelation: CURRENT
2868 elog(WARN,"CURRENT used in non-rule query");
2875 elog(WARN,"NEW used in non-rule query");
2885 static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr)
2887 A_Expr *a = makeNode(A_Expr);
2896 xlateSqlType(char *name)
2898 if (!strcasecmp(name,"int") ||
2899 !strcasecmp(name,"integer"))
2900 return "int4"; /* strdup("int4") -- strdup leaks memory here */
2901 else if (!strcasecmp(name, "smallint"))
2903 else if (!strcasecmp(name, "float") ||
2904 !strcasecmp(name, "real"))
2906 else if (!strcasecmp(name, "interval"))
2912 void parser_init(Oid *typev, int nargs)
2914 QueryIsRule = false;
2915 saved_relname[0]= '\0';
2916 saved_In_Expr = NULL;
2918 param_type_init(typev, nargs);