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.46 1997/09/16 16:11:20 thomas 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 "nodes/print.h"
39 #include "parser/gramparse.h"
40 #include "parser/catalog_utils.h"
41 #include "parser/parse_query.h"
42 #include "storage/smgr.h"
43 #include "utils/acl.h"
44 #include "catalog/catname.h"
45 #include "utils/elog.h"
46 #include "access/xact.h"
48 static char saved_relname[NAMEDATALEN]; /* need this for complex attributes */
49 static bool QueryIsRule = FALSE;
50 static Node *saved_In_Expr;
51 extern List *parsetree;
54 * If you need access to certain yacc-generated variables and find that
55 * they're static by default, uncomment the next line. (this is not a
58 /*#define __YYSCLASS*/
60 static char *xlateSqlType(char *);
61 static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
62 static List *makeConstantList( A_Const *node);
63 static char *FlattenStringList(List *list);
65 /* old versions of flex define this as a macro */
86 ConstraintDef *constrdef;
90 SortGroupBy *sortgroupby;
107 AddAttrStmt, ClosePortalStmt,
108 CopyStmt, CreateStmt, CreateSeqStmt, DefineStmt, DestroyStmt,
109 ExtendStmt, FetchStmt, GrantStmt, CreateTrigStmt, DropTrigStmt,
110 IndexStmt, MoveStmt, ListenStmt, OptimizableStmt,
111 ProcedureStmt, PurgeStmt,
112 RecipeStmt, RemoveAggrStmt, RemoveOperStmt, RemoveFuncStmt, RemoveStmt,
113 RenameStmt, RevokeStmt, RuleStmt, TransactionStmt, ViewStmt, LoadStmt,
114 CreatedbStmt, DestroydbStmt, VacuumStmt, RetrieveStmt, CursorStmt,
115 ReplaceStmt, AppendStmt, NotifyStmt, DeleteStmt, ClusterStmt,
116 ExplainStmt, VariableSetStmt, VariableShowStmt, VariableResetStmt
118 %type <str> txname, char_type
119 %type <node> SubSelect
120 %type <str> join_expr, join_outer, join_spec
121 %type <boolean> TriggerActionTime, TriggerForSpec
123 %type <str> DateTime, TriggerEvents, TriggerFuncArg
125 %type <str> relation_name, copy_file_name, copy_delimiter, def_name,
126 database_name, access_method_clause, access_method, attr_name,
127 class, index_name, name, file_name, recipe_name,
128 var_name, aggr_argtype
130 %type <constrdef> ConstraintElem, ConstraintDef
132 %type <str> opt_id, opt_portal_name,
133 before_clause, after_clause, all_Op, MathOp, opt_name, opt_unique,
134 result, OptUseOp, opt_class, opt_range_start, opt_range_end,
137 %type <str> privileges, operation_commalist, grantee
138 %type <chr> operation, TriggerOneEvent
140 %type <list> stmtblock, stmtmulti,
141 relation_name_list, OptTableElementList, tableElementList,
142 OptInherit, OptConstraint, ConstraintList, definition,
143 opt_with, def_args, def_name_list, func_argtypes,
144 oper_argtypes, OptStmtList, OptStmtBlock, OptStmtMulti,
145 opt_column_list, columnList, opt_va_list, va_list,
146 sort_clause, sortby_list, index_params, index_list, name_list,
147 from_clause, from_list, opt_array_bounds, nest_array_bounds,
148 expr_list, attrs, res_target_list, res_target_list2,
149 def_list, opt_indirection, group_clause, groupby_list, TriggerFuncArgs
151 %type <list> union_clause, select_list
152 %type <list> join_list
153 %type <sortgroupby> join_using
155 %type <node> position_expr
156 %type <list> extract_list, position_list
157 %type <list> substr_list, substr_from, substr_for, trim_list
158 %type <list> interval_opts
160 %type <boolean> opt_inh_star, opt_binary, opt_instead, opt_with_col, opt_with_copy,
161 index_opt_unique, opt_verbose, opt_analyze, opt_null
163 %type <ival> copy_dirn, archive_type, OptArchiveType, OptArchiveLocation,
164 def_type, opt_direction, remove_type, opt_column, event
166 %type <ival> OptLocation, opt_move_where, fetch_how_many
168 %type <list> OptSeqList
169 %type <defelt> OptSeqElem
171 %type <dstmt> def_rest
172 %type <pstmt> purge_quals
173 %type <astmt> insert_rest
175 %type <typnam> Typename, typname, opt_type
176 %type <coldef> columnDef
177 %type <defelt> def_elem
178 %type <node> def_arg, columnElem, where_clause,
179 a_expr, a_expr_or_null, AexprConst,
180 in_expr_nodes, not_in_expr_nodes,
182 %type <value> NumConst
183 %type <attr> event_object, attr
184 %type <sortgroupby> groupby
185 %type <sortgroupby> sortby
186 %type <ielem> index_elem, func_index
187 %type <range> from_val
188 %type <relexp> relation_expr
189 %type <trange> time_range
190 %type <target> res_target_el, res_target_el2
191 %type <paramno> ParamNo
195 %type <str> Id, date, var_value, zone_value
198 %type <list> default_expr
199 %type <str> opt_default
200 %type <list> constraint_elem
203 * If you make any token changes, remember to:
204 * - use "yacc -d" and update parse.h
205 * - update the keyword table in parser/keywords.c
209 %token ABORT_TRANS, ACL, ADD, AFTER, AGGREGATE, ALL, ALTER, ANALYZE,
210 AND, APPEND, ARCHIVE, ARCH_STORE, AS, ASC,
211 BACKWARD, BEFORE, BEGIN_TRANS, BETWEEN, BINARY, BOTH, BY,
212 CAST, CHANGE, CHECK, CLOSE, CLUSTER, COLUMN,
213 COMMIT, CONSTRAINT, COPY, CREATE, CROSS, CURRENT, CURSOR,
214 DATABASE, DAYINTERVAL, DECLARE, DEFAULT, DELETE, DELIMITERS, DESC,
215 DISTINCT, DO, DROP, END_TRANS, EXISTS, EXTEND,
216 FETCH, FOR, FORWARD, FROM, FULL, FUNCTION, GRANT, GROUP, HAVING, HEAVY, HOURINTERVAL,
217 IN, INDEX, INHERITS, INNERJOIN, INSERT, INTERVAL, INSTEAD, INTO, IS, ISNULL,
218 JOIN, LANGUAGE, LEADING, LEFT, LIGHT, LISTEN, LOAD, LOCAL, MERGE, MINUTEINTERVAL, MONTHINTERVAL, MOVE,
219 NATURAL, NEW, NONE, NOT, NOTHING, NOTIFY, NOTNULL,
220 OIDS, ON, OPERATOR, OPTION, OR, ORDER, OUTERJOIN,
221 PNULL, 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,
224 TABLE, TIME, TO, TRAILING, TRANSACTION, TRIGGER,
225 UNION, UNIQUE, UPDATE, USING, VACUUM, VALUES,
226 VERBOSE, VERSION, VIEW, WHERE, WITH, WORK, YEARINTERVAL, ZONE
227 %token EXECUTE, RECIPE, EXPLAIN, LIKE, SEQUENCE
230 %token EXTRACT, POSITION, SUBSTRING, TRIM
231 %token DOUBLE, PRECISION
232 %token CHARACTER, VARYING
234 /* Special keywords, not in the query language - see the "lex" file */
235 %token <str> IDENT, SCONST, Op
236 %token <ival> ICONST, PARAM
239 /* these are not real. they are here so that they get generated as #define's*/
256 %left '|' /* this is the relation union op, not logical or */
257 %right ':' /* Unary Operators */
258 %left ';' /* end of statement or natural log */
271 { parsetree = lcons($1,NIL); }
274 stmtmulti: stmtmulti stmt ';'
275 { $$ = lappend($1, $2); }
277 { $$ = lappend($1, $2); }
279 { $$ = lcons($1,NIL); }
321 /*****************************************************************************
323 * Set PG internal variable
324 * SET var_name TO 'var_value'
326 *****************************************************************************/
328 VariableSetStmt: SET var_name TO var_value
330 VariableSetStmt *n = makeNode(VariableSetStmt);
335 | SET var_name '=' var_value
337 VariableSetStmt *n = makeNode(VariableSetStmt);
342 | SET TIME ZONE zone_value
344 VariableSetStmt *n = makeNode(VariableSetStmt);
345 n->name = "timezone";
351 var_value: Sconst { $$ = $1; }
354 zone_value: Sconst { $$ = $1; }
355 | LOCAL { $$ = NULL; }
358 VariableShowStmt: SHOW var_name
360 VariableShowStmt *n = makeNode(VariableShowStmt);
366 VariableResetStmt: RESET var_name
368 VariableResetStmt *n = makeNode(VariableResetStmt);
374 /*****************************************************************************
377 * addattr ( attr1 = type1 .. attrn = typen ) to <relname> [*]
379 *****************************************************************************/
381 AddAttrStmt: ALTER TABLE relation_name opt_inh_star ADD COLUMN columnDef
383 AddAttrStmt *n = makeNode(AddAttrStmt);
391 /* Column definition might include WITH TIME ZONE, but only for the data types
392 * called out in SQL92 date/time definitions. So, check explicitly for "timestamp"
393 * and "time". - thomas 1997-07-14
395 columnDef: Id Typename opt_with_col opt_default opt_null
397 $$ = makeNode(ColumnDef);
400 $$->typename->timezone = $3;
402 $$->is_not_null = $5;
403 if ($$->typename->timezone
404 && (strcasecmp($$->typename->name, "timestamp")
405 && strcasecmp($$->typename->name, "time")))
406 elog(NOTICE,"%s does not use WITH TIME ZONE",$$->typename->name);
410 opt_default: DEFAULT default_expr
412 $$ = FlattenStringList($2);
414 | /*EMPTY*/ { $$ = NULL; }
417 default_expr: AexprConst
418 { $$ = makeConstantList((A_Const *) $1); }
420 { $$ = lcons( makeString("NULL"), NIL); }
421 | '-' default_expr %prec UMINUS
422 { $$ = lcons( makeString( "-"), $2); }
423 | default_expr '+' default_expr
424 { $$ = nconc( $1, lcons( makeString( "+"), $3)); }
425 | default_expr '-' default_expr
426 { $$ = nconc( $1, lcons( makeString( "-"), $3)); }
427 | default_expr '/' default_expr
428 { $$ = nconc( $1, lcons( makeString( "/"), $3)); }
429 | default_expr '*' default_expr
430 { $$ = nconc( $1, lcons( makeString( "*"), $3)); }
431 | default_expr '=' default_expr
432 { elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
433 | default_expr '<' default_expr
434 { elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
435 | default_expr '>' default_expr
436 { elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
438 { $$ = lcons( makeString( ":"), $2); }
440 { $$ = lcons( makeString( ";"), $2); }
442 { $$ = lcons( makeString( "|"), $2); }
443 | default_expr TYPECAST Typename
445 $$ = nconc( lcons( makeString( "CAST"), $1), makeList( makeString("AS"), $3, -1));
447 | CAST default_expr AS Typename
449 $$ = nconc( lcons( makeString( "CAST"), $2), makeList( makeString("AS"), $4, -1));
451 | '(' default_expr ')'
452 { $$ = lappend( lcons( makeString( "("), $2), makeString( ")")); }
453 | name '(' default_expr ')'
455 $$ = makeList( makeString($1), makeString("("), -1);
457 $$ = lappend( $$, makeString(")"));
459 | default_expr Op default_expr
461 if (!strcmp("<=", $2) || !strcmp(">=", $2))
462 elog(WARN,"boolean expressions not supported in DEFAULT",NULL);
463 $$ = nconc( $1, lcons( makeString( $2), $3));
466 { $$ = lcons( makeString( $1), $2); }
468 { $$ = lappend( $1, makeString( $2)); }
471 opt_null: NOT PNULL { $$ = TRUE; }
472 | NOTNULL { $$ = TRUE; }
473 | /* EMPTY */ { $$ = FALSE; }
476 opt_with_col: WITH TIME ZONE { $$ = TRUE; }
477 | /* EMPTY */ { $$ = FALSE; }
480 /*****************************************************************************
485 *****************************************************************************/
487 ClosePortalStmt: CLOSE opt_id
489 ClosePortalStmt *n = makeNode(ClosePortalStmt);
496 /*****************************************************************************
499 * COPY [BINARY] <relname> FROM/TO
500 * [USING DELIMITERS <delimiter>]
502 *****************************************************************************/
504 CopyStmt: COPY opt_binary relation_name opt_with_copy copy_dirn copy_file_name copy_delimiter
506 CopyStmt *n = makeNode(CopyStmt);
524 * copy_file_name NULL indicates stdio is used. Whether stdin or stdout is
525 * used depends on the direction. (It really doesn't make sense to copy from
526 * stdout. We silently correct the "typo". - AY 9/94
528 copy_file_name: Sconst { $$ = $1; }
529 | STDIN { $$ = NULL; }
530 | STDOUT { $$ = NULL; }
533 opt_binary: BINARY { $$ = TRUE; }
534 | /*EMPTY*/ { $$ = FALSE; }
537 opt_with_copy: WITH OIDS { $$ = TRUE; }
538 | /* EMPTY */ { $$ = FALSE; }
542 * the default copy delimiter is tab but the user can configure it
544 copy_delimiter: USING DELIMITERS Sconst { $$ = $3;}
545 | /* EMPTY */ { $$ = "\t"; }
549 /*****************************************************************************
554 *****************************************************************************/
556 CreateStmt: CREATE TABLE relation_name '(' OptTableElementList ')'
557 OptInherit OptConstraint OptArchiveType OptLocation
560 CreateStmt *n = makeNode(CreateStmt);
572 OptTableElementList: tableElementList { $$ = $1; }
573 | /* EMPTY */ { $$ = NULL; }
577 tableElementList ',' columnDef
578 { $$ = lappend($1, $3); }
580 { $$ = lcons($1, NIL); }
584 OptArchiveType: ARCHIVE '=' archive_type { $$ = $3; }
585 | /*EMPTY*/ { $$ = ARCH_NONE; }
588 archive_type: HEAVY { $$ = ARCH_HEAVY; }
589 | LIGHT { $$ = ARCH_LIGHT; }
590 | NONE { $$ = ARCH_NONE; }
593 OptLocation: STORE '=' Sconst
599 OptArchiveLocation: ARCH_STORE '=' Sconst
605 OptInherit: INHERITS '(' relation_name_list ')' { $$ = $3; }
606 | /*EMPTY*/ { $$ = NIL; }
609 OptConstraint: ConstraintList { $$ = $1; }
610 | /*EMPTY*/ { $$ = NULL; }
614 ConstraintList ',' ConstraintElem
615 { $$ = lappend($1, $3); }
617 { $$ = lcons($1, NIL); }
621 CONSTRAINT name ConstraintDef
626 | ConstraintDef { $$ = $1; }
629 ConstraintDef: CHECK constraint_elem
631 ConstraintDef *constr = palloc (sizeof(ConstraintDef));
633 printf("in ConstraintDef\n");
635 constr->type = CONSTR_CHECK;
637 constr->def = FlattenStringList($2);
639 printf("ConstraintDef: string is %s\n", (char *) constr->def);
645 constraint_elem: AexprConst
646 { $$ = makeConstantList((A_Const *) $1); }
648 { $$ = lcons( makeString("NULL"), NIL); }
652 printf( "Id is %s\n", $1);
654 $$ = lcons( makeString($1), NIL);
656 | '-' constraint_elem %prec UMINUS
657 { $$ = lcons( makeString( "-"), $2); }
658 | constraint_elem '+' constraint_elem
659 { $$ = nconc( $1, lcons( makeString( "+"), $3)); }
660 | constraint_elem '-' constraint_elem
661 { $$ = nconc( $1, lcons( makeString( "-"), $3)); }
662 | constraint_elem '/' constraint_elem
663 { $$ = nconc( $1, lcons( makeString( "/"), $3)); }
664 | constraint_elem '*' constraint_elem
665 { $$ = nconc( $1, lcons( makeString( "*"), $3)); }
666 | constraint_elem '=' constraint_elem
667 { $$ = nconc( $1, lcons( makeString( "="), $3)); }
668 | constraint_elem '<' constraint_elem
669 { $$ = nconc( $1, lcons( makeString( "<"), $3)); }
670 | constraint_elem '>' constraint_elem
671 { $$ = nconc( $1, lcons( makeString( ">"), $3)); }
672 | ':' constraint_elem
673 { $$ = lcons( makeString( ":"), $2); }
674 | ';' constraint_elem
675 { $$ = lcons( makeString( ";"), $2); }
676 | '|' constraint_elem
677 { $$ = lcons( makeString( "|"), $2); }
678 | constraint_elem TYPECAST Typename
680 $$ = nconc( lcons( makeString( "CAST"), $1), makeList( makeString("AS"), $3, -1));
682 | CAST constraint_elem AS Typename
684 $$ = nconc( lcons( makeString( "CAST"), $2), makeList( makeString("AS"), $4, -1));
686 | '(' constraint_elem ')'
687 { $$ = lappend( lcons( makeString( "("), $2), makeString( ")")); }
688 | name '(' constraint_elem ')'
690 $$ = makeList( makeString($1), makeString("("), -1);
692 $$ = lappend( $$, makeString(")"));
694 | constraint_elem Op constraint_elem
695 { $$ = nconc( $1, lcons( makeString( $2), $3)); }
696 | constraint_elem AND constraint_elem
697 { $$ = nconc( $1, lcons( makeString( "AND"), $3)); }
698 | constraint_elem OR constraint_elem
699 { $$ = nconc( $1, lcons( makeString( "OR"), $3)); }
701 { $$ = lcons( makeString( $1), $2); }
703 { $$ = lappend( $1, makeString( $2)); }
707 /*****************************************************************************
710 * CREATE SEQUENCE seqname
712 *****************************************************************************/
714 CreateSeqStmt: CREATE SEQUENCE relation_name OptSeqList
716 CreateSeqStmt *n = makeNode(CreateSeqStmt);
724 OptSeqList OptSeqElem
725 { $$ = lappend($1, $2); }
729 OptSeqElem: IDENT NumConst
731 $$ = makeNode(DefElem);
733 $$->arg = (Node *)$2;
737 $$ = makeNode(DefElem);
739 $$->arg = (Node *)NULL;
744 /*****************************************************************************
750 *****************************************************************************/
752 CreateTrigStmt: CREATE TRIGGER name TriggerActionTime TriggerEvents ON
753 relation_name TriggerForSpec EXECUTE PROCEDURE
754 name '(' TriggerFuncArgs ')'
756 CreateTrigStmt *n = makeNode(CreateTrigStmt);
763 memcpy (n->actions, $5, 4);
768 TriggerActionTime: BEFORE { $$ = TRUE; }
769 | AFTER { $$ = FALSE; }
772 TriggerEvents: TriggerOneEvent
774 char *e = palloc (4);
775 e[0] = $1; e[1] = 0; $$ = e;
777 | TriggerOneEvent OR TriggerOneEvent
779 char *e = palloc (4);
780 e[0] = $1; e[1] = $3; e[2] = 0; $$ = e;
782 | TriggerOneEvent OR TriggerOneEvent OR TriggerOneEvent
784 char *e = palloc (4);
785 e[0] = $1; e[1] = $3; e[2] = $5; e[3] = 0;
790 TriggerOneEvent: INSERT { $$ = 'i'; }
791 | DELETE { $$ = 'd'; }
792 | UPDATE { $$ = 'u'; }
795 TriggerForSpec: FOR name name
797 if ( strcmp ($2, "each") != 0 )
798 elog(WARN,"parser: syntax error near %s",$2);
799 if ( strcmp ($3, "row") == 0 )
801 else if ( strcmp ($3, "statement") == 0 )
804 elog(WARN,"parser: syntax error near %s",$3);
808 TriggerFuncArgs: TriggerFuncArg
809 { $$ = lcons($1, NIL); }
810 | TriggerFuncArgs ',' TriggerFuncArg
811 { $$ = lappend($1, $3); }
812 | /* EMPTY */ { $$ = NIL; }
815 TriggerFuncArg: ICONST
817 char *s = (char *) palloc (256);
818 sprintf (s, "%d", $1);
821 | Sconst { $$ = $1; }
824 DropTrigStmt: DROP TRIGGER name ON relation_name
826 DropTrigStmt *n = makeNode(DropTrigStmt);
833 /*****************************************************************************
836 * define (type,operator,aggregate)
838 *****************************************************************************/
840 DefineStmt: CREATE def_type def_rest
847 def_rest: def_name definition
849 $$ = makeNode(DefineStmt);
852 printf("def_rest: defname is %s\n", $1);
858 def_type: OPERATOR { $$ = OPERATOR; }
862 printf("def_type: decoding P_TYPE\n");
866 | AGGREGATE { $$ = AGGREGATE; }
869 def_name: PROCEDURE { $$ = "procedure"; }
871 | MathOp { $$ = $1; }
875 definition: '(' def_list ')' { $$ = $2; }
878 def_list: def_elem { $$ = lcons($1, NIL); }
879 | def_list ',' def_elem { $$ = lappend($1, $3); }
882 def_elem: def_name '=' def_arg
885 printf("def_elem: decoding %s =\n", $1);
888 $$ = makeNode(DefElem);
890 $$->arg = (Node *)$3;
895 printf("def_elem: decoding %s\n", $1);
897 $$ = makeNode(DefElem);
899 $$->arg = (Node *)NULL;
901 | DEFAULT '=' def_arg
904 printf("def_elem: decoding DEFAULT =\n");
907 $$ = makeNode(DefElem);
908 $$->defname = "default";
909 $$->arg = (Node *)$3;
913 def_arg: Id { $$ = (Node *)makeString($1); }
914 | all_Op { $$ = (Node *)makeString($1); }
915 | NumConst { $$ = (Node *)$1; /* already a Value */ }
916 | Sconst { $$ = (Node *)makeString($1); }
919 TypeName *n = makeNode(TypeName);
922 n->arrayBounds = NULL;
925 | DOUBLE { $$ = (Node *)makeString("double"); }
929 /*****************************************************************************
932 * destroy <relname1> [, <relname2> .. <relnameN> ]
934 *****************************************************************************/
936 DestroyStmt: DROP TABLE relation_name_list
938 DestroyStmt *n = makeNode(DestroyStmt);
943 | DROP SEQUENCE relation_name_list
945 DestroyStmt *n = makeNode(DestroyStmt);
953 /*****************************************************************************
956 * fetch [forward | backward] [number | all ] [ in <portalname> ]
958 *****************************************************************************/
960 FetchStmt: FETCH opt_direction fetch_how_many opt_portal_name
962 FetchStmt *n = makeNode(FetchStmt);
970 opt_direction: FORWARD { $$ = FORWARD; }
971 | BACKWARD { $$ = BACKWARD; }
972 | /*EMPTY*/ { $$ = FORWARD; /* default */ }
975 fetch_how_many: Iconst
977 if ($1 <= 0) elog(WARN,"Please specify nonnegative count for fetch",NULL); }
978 | ALL { $$ = 0; /* 0 means fetch all tuples*/}
979 | /*EMPTY*/ { $$ = 1; /*default*/ }
982 /*****************************************************************************
985 * GRANT [privileges] ON [relation_name_list] TO [GROUP] grantee
987 *****************************************************************************/
989 GrantStmt: GRANT privileges ON relation_name_list TO grantee opt_with_grant
991 $$ = (Node*)makeAclStmt($2,$4,$6,'+');
997 privileges: ALL PRIVILEGES
999 $$ = aclmakepriv("rwaR",0);
1003 $$ = aclmakepriv("rwaR",0);
1005 | operation_commalist
1011 operation_commalist: operation
1013 $$ = aclmakepriv("",$1);
1015 | operation_commalist ',' operation
1017 $$ = aclmakepriv($1,$3);
1024 $$ = ACL_MODE_RD_CHR;
1028 $$ = ACL_MODE_AP_CHR;
1032 $$ = ACL_MODE_WR_CHR;
1036 $$ = ACL_MODE_WR_CHR;
1040 $$ = ACL_MODE_RU_CHR;
1046 $$ = aclmakeuser("A","");
1050 $$ = aclmakeuser("G",$2);
1054 $$ = aclmakeuser("U",$1);
1058 opt_with_grant : /* empty */
1061 yyerror("WITH GRANT OPTION is not supported. Only relation owners can set privileges");
1065 /*****************************************************************************
1068 * REVOKE [privileges] ON [relation_name] FROM [user]
1070 *****************************************************************************/
1072 RevokeStmt: REVOKE privileges ON relation_name_list FROM grantee
1074 $$ = (Node*)makeAclStmt($2,$4,$6,'-');
1080 /*****************************************************************************
1083 * move [<dirn>] [<whereto>] [<portalname>]
1085 *****************************************************************************/
1087 MoveStmt: MOVE opt_direction opt_move_where opt_portal_name
1089 MoveStmt *n = makeNode(MoveStmt);
1096 | MOVE opt_direction TO Iconst opt_portal_name
1098 MoveStmt *n = makeNode(MoveStmt);
1107 opt_move_where: Iconst { $$ = $1; }
1108 | /*EMPTY*/ { $$ = 1; /* default */ }
1111 opt_portal_name: IN name { $$ = $2;}
1112 | /*EMPTY*/ { $$ = NULL; }
1116 /*****************************************************************************
1119 * define [archive] index <indexname> on <relname>
1120 * using <access> "(" (<col> with <op>)+ ")" [with
1123 * [where <qual>] is not supported anymore
1124 *****************************************************************************/
1126 IndexStmt: CREATE index_opt_unique INDEX index_name ON relation_name
1127 access_method_clause '(' index_params ')' opt_with
1129 /* should check that access_method is valid,
1130 etc ... but doesn't */
1131 IndexStmt *n = makeNode(IndexStmt);
1135 n->accessMethod = $7;
1136 n->indexParams = $9;
1137 n->withClause = $11;
1138 n->whereClause = NULL;
1143 access_method_clause: USING access_method { $$ = $2; }
1144 | /* empty -- 'btree' is default access method */
1148 index_opt_unique: UNIQUE { $$ = TRUE; }
1149 | /*empty*/ { $$ = FALSE; }
1152 /*****************************************************************************
1155 * extend index <indexname> [where <qual>]
1157 *****************************************************************************/
1159 ExtendStmt: EXTEND INDEX index_name where_clause
1161 ExtendStmt *n = makeNode(ExtendStmt);
1163 n->whereClause = $4;
1168 /*****************************************************************************
1171 * execute recipe <recipeName>
1173 *****************************************************************************/
1175 RecipeStmt: EXECUTE RECIPE recipe_name
1178 if (!IsTransactionBlock())
1179 elog(WARN,"EXECUTE RECIPE may only be used in begin/end transaction blocks",NULL);
1181 n = makeNode(RecipeStmt);
1188 /*****************************************************************************
1191 * define function <fname>
1192 * (language = <lang>, returntype = <typename>
1193 * [, arch_pct = <percentage | pre-defined>]
1194 * [, disk_pct = <percentage | pre-defined>]
1195 * [, byte_pct = <percentage | pre-defined>]
1196 * [, perbyte_cpu = <int | pre-defined>]
1197 * [, percall_cpu = <int | pre-defined>]
1199 * [arg is (<type-1> { , <type-n>})]
1200 * as <filename or code in language as appropriate>
1202 *****************************************************************************/
1204 ProcedureStmt: CREATE FUNCTION def_name def_args
1205 RETURNS def_arg opt_with AS Sconst LANGUAGE Sconst
1207 ProcedureStmt *n = makeNode(ProcedureStmt);
1210 n->returnType = (Node *)$6;
1217 opt_with: WITH definition { $$ = $2; }
1218 | /* EMPTY */ { $$ = NIL; }
1221 def_args: '(' def_name_list ')' { $$ = $2; }
1222 | '(' ')' { $$ = NIL; }
1225 def_name_list: name_list;
1228 /*****************************************************************************
1231 * purge <relname> [before <date>] [after <date>]
1233 * purge <relname> [after <date>] [before <date>]
1235 *****************************************************************************/
1237 PurgeStmt: PURGE relation_name purge_quals
1244 purge_quals: before_clause
1246 $$ = makeNode(PurgeStmt);
1247 $$->beforeDate = $1;
1248 $$->afterDate = NULL;
1252 $$ = makeNode(PurgeStmt);
1253 $$->beforeDate = NULL;
1256 | before_clause after_clause
1258 $$ = makeNode(PurgeStmt);
1259 $$->beforeDate = $1;
1262 | after_clause before_clause
1264 $$ = makeNode(PurgeStmt);
1265 $$->beforeDate = $2;
1270 $$ = makeNode(PurgeStmt);
1271 $$->beforeDate = NULL;
1272 $$->afterDate = NULL;
1276 before_clause: BEFORE date { $$ = $2; }
1277 after_clause: AFTER date { $$ = $2; }
1280 /*****************************************************************************
1284 * remove function <funcname>
1285 * (REMOVE FUNCTION "funcname" (arg1, arg2, ...))
1286 * remove aggregate <aggname>
1287 * (REMOVE AGGREGATE "aggname" "aggtype")
1288 * remove operator <opname>
1289 * (REMOVE OPERATOR "opname" (leftoperand_typ rightoperand_typ))
1290 * remove type <typename>
1291 * (REMOVE TYPE "typename")
1292 * remove rule <rulename>
1293 * (REMOVE RULE "rulename")
1295 *****************************************************************************/
1297 RemoveStmt: DROP remove_type name
1299 RemoveStmt *n = makeNode(RemoveStmt);
1306 remove_type: Type { $$ = P_TYPE; }
1307 | INDEX { $$ = INDEX; }
1308 | RULE { $$ = RULE; }
1309 | VIEW { $$ = VIEW; }
1312 RemoveAggrStmt: DROP AGGREGATE name aggr_argtype
1314 RemoveAggrStmt *n = makeNode(RemoveAggrStmt);
1321 aggr_argtype: name { $$ = $1; }
1322 | '*' { $$ = NULL; }
1325 RemoveFuncStmt: DROP FUNCTION name '(' func_argtypes ')'
1327 RemoveFuncStmt *n = makeNode(RemoveFuncStmt);
1334 func_argtypes: name_list { $$ = $1; }
1335 | /*EMPTY*/ { $$ = NIL; }
1338 RemoveOperStmt: DROP OPERATOR all_Op '(' oper_argtypes ')'
1340 RemoveOperStmt *n = makeNode(RemoveOperStmt);
1347 all_Op: Op | MathOp;
1349 MathOp: '+' { $$ = "+"; }
1360 elog(WARN,"parser: argument type missing (use NONE for unary operators)",NULL);
1363 { $$ = makeList(makeString($1), makeString($3), -1); }
1364 | NONE ',' name /* left unary */
1365 { $$ = makeList(NULL, makeString($3), -1); }
1366 | name ',' NONE /* right unary */
1367 { $$ = makeList(makeString($1), NULL, -1); }
1370 /*****************************************************************************
1373 * rename <attrname1> in <relname> [*] to <attrname2>
1374 * rename <relname1> to <relname2>
1376 *****************************************************************************/
1378 RenameStmt: ALTER TABLE relation_name opt_inh_star
1379 RENAME opt_column opt_name TO name
1381 RenameStmt *n = makeNode(RenameStmt);
1390 opt_name: name { $$ = $1; }
1391 | /*EMPTY*/ { $$ = NULL; }
1394 opt_column: COLUMN { $$ = COLUMN; }
1395 | /*EMPTY*/ { $$ = 0; }
1399 /*****************************************************************************
1401 * QUERY: Define Rewrite Rule , Define Tuple Rule
1402 * Define Rule <old rules >
1404 * only rewrite rule is supported -- ay 9/94
1406 *****************************************************************************/
1408 RuleStmt: CREATE RULE name AS
1409 { QueryIsRule=TRUE; }
1410 ON event TO event_object where_clause
1411 DO opt_instead OptStmtList
1413 RuleStmt *n = makeNode(RuleStmt);
1417 n->whereClause = $10;
1424 OptStmtList: NOTHING { $$ = NIL; }
1425 | OptimizableStmt { $$ = lcons($1, NIL); }
1426 | '[' OptStmtBlock ']' { $$ = $2; }
1429 OptStmtBlock: OptStmtMulti
1432 { $$ = lcons($1, NIL); }
1435 OptStmtMulti: OptStmtMulti OptimizableStmt ';'
1436 { $$ = lappend($1, $2); }
1437 | OptStmtMulti OptimizableStmt
1438 { $$ = lappend($1, $2); }
1439 | OptimizableStmt ';'
1440 { $$ = lcons($1, NIL); }
1443 event_object: relation_name '.' attr_name
1445 $$ = makeNode(Attr);
1448 $$->attrs = lcons(makeString($3), NIL);
1449 $$->indirection = NIL;
1453 $$ = makeNode(Attr);
1457 $$->indirection = NIL;
1461 /* change me to select, update, etc. some day */
1462 event: SELECT { $$ = CMD_SELECT; }
1463 | UPDATE { $$ = CMD_UPDATE; }
1464 | DELETE { $$ = CMD_DELETE; }
1465 | INSERT { $$ = CMD_INSERT; }
1468 opt_instead: INSTEAD { $$ = TRUE; }
1469 | /* EMPTY */ { $$ = FALSE; }
1473 /*****************************************************************************
1476 * NOTIFY <relation_name> can appear both in rule bodies and
1477 * as a query-level command
1479 *****************************************************************************/
1481 NotifyStmt: NOTIFY relation_name
1483 NotifyStmt *n = makeNode(NotifyStmt);
1489 ListenStmt: LISTEN relation_name
1491 ListenStmt *n = makeNode(ListenStmt);
1498 /*****************************************************************************
1509 *****************************************************************************/
1511 TransactionStmt: ABORT_TRANS TRANSACTION
1513 TransactionStmt *n = makeNode(TransactionStmt);
1514 n->command = ABORT_TRANS;
1517 | BEGIN_TRANS TRANSACTION
1519 TransactionStmt *n = makeNode(TransactionStmt);
1520 n->command = BEGIN_TRANS;
1525 TransactionStmt *n = makeNode(TransactionStmt);
1526 n->command = BEGIN_TRANS;
1531 TransactionStmt *n = makeNode(TransactionStmt);
1532 n->command = END_TRANS;
1535 | END_TRANS TRANSACTION
1537 TransactionStmt *n = makeNode(TransactionStmt);
1538 n->command = END_TRANS;
1543 TransactionStmt *n = makeNode(TransactionStmt);
1544 n->command = ABORT_TRANS;
1550 TransactionStmt *n = makeNode(TransactionStmt);
1551 n->command = ABORT_TRANS;
1556 TransactionStmt *n = makeNode(TransactionStmt);
1557 n->command = BEGIN_TRANS;
1562 TransactionStmt *n = makeNode(TransactionStmt);
1563 n->command = END_TRANS;
1569 TransactionStmt *n = makeNode(TransactionStmt);
1570 n->command = END_TRANS;
1575 TransactionStmt *n = makeNode(TransactionStmt);
1576 n->command = ABORT_TRANS;
1582 /*****************************************************************************
1585 * define view <viewname> '('target-list ')' [where <quals> ]
1587 *****************************************************************************/
1589 ViewStmt: CREATE VIEW name AS RetrieveStmt
1591 ViewStmt *n = makeNode(ViewStmt);
1593 n->query = (Query *)$5;
1599 /*****************************************************************************
1604 *****************************************************************************/
1606 LoadStmt: LOAD file_name
1608 LoadStmt *n = makeNode(LoadStmt);
1615 /*****************************************************************************
1620 *****************************************************************************/
1622 CreatedbStmt: CREATE DATABASE database_name
1624 CreatedbStmt *n = makeNode(CreatedbStmt);
1631 /*****************************************************************************
1636 *****************************************************************************/
1638 DestroydbStmt: DROP DATABASE database_name
1640 DestroydbStmt *n = makeNode(DestroydbStmt);
1647 /*****************************************************************************
1650 * cluster <index_name> on <relation_name>
1652 *****************************************************************************/
1654 ClusterStmt: CLUSTER index_name ON relation_name
1656 ClusterStmt *n = makeNode(ClusterStmt);
1663 /*****************************************************************************
1668 *****************************************************************************/
1670 VacuumStmt: VACUUM opt_verbose opt_analyze
1672 VacuumStmt *n = makeNode(VacuumStmt);
1679 | VACUUM opt_verbose relation_name opt_analyze opt_va_list
1681 VacuumStmt *n = makeNode(VacuumStmt);
1686 if ( $5 != NIL && !$4 )
1687 elog(WARN,"parser: syntax error at or near \"(\"",NULL);
1692 opt_verbose: VERBOSE { $$ = TRUE; }
1693 | /* EMPTY */ { $$ = FALSE; }
1696 opt_analyze: ANALYZE { $$ = TRUE; }
1697 | /* EMPTY */ { $$ = FALSE; }
1700 opt_va_list: '(' va_list ')'
1707 { $$=lcons($1,NIL); }
1709 { $$=lappend($1,$3); }
1712 /*****************************************************************************
1717 *****************************************************************************/
1719 ExplainStmt: EXPLAIN opt_verbose OptimizableStmt
1721 ExplainStmt *n = makeNode(ExplainStmt);
1723 n->query = (Query*)$3;
1728 /*****************************************************************************
1730 * Optimizable Stmts: *
1732 * one of the five queries processed by the planner *
1734 * [ultimately] produces query-trees as specified *
1735 * in the query-spec document in ~postgres/ref *
1737 *****************************************************************************/
1739 OptimizableStmt: RetrieveStmt
1744 | DeleteStmt /* by default all are $$=$1 */
1748 /*****************************************************************************
1753 *****************************************************************************/
1755 AppendStmt: INSERT INTO relation_name opt_column_list insert_rest
1763 insert_rest: VALUES '(' res_target_list2 ')'
1765 $$ = makeNode(AppendStmt);
1766 $$->targetList = $3;
1767 $$->fromClause = NIL;
1768 $$->whereClause = NULL;
1770 | SELECT res_target_list2 from_clause where_clause
1772 $$ = makeNode(AppendStmt);
1773 $$->targetList = $2;
1774 $$->fromClause = $3;
1775 $$->whereClause = $4;
1779 opt_column_list: '(' columnList ')' { $$ = $2; }
1780 | /*EMPTY*/ { $$ = NIL; }
1784 columnList ',' columnElem
1785 { $$ = lappend($1, $3); }
1787 { $$ = lcons($1, NIL); }
1790 columnElem: Id opt_indirection
1792 Ident *id = makeNode(Ident);
1794 id->indirection = $2;
1799 /*****************************************************************************
1804 *****************************************************************************/
1806 DeleteStmt: DELETE FROM relation_name
1809 DeleteStmt *n = makeNode(DeleteStmt);
1811 n->whereClause = $4;
1817 /*****************************************************************************
1820 * ReplaceStmt (UPDATE)
1822 *****************************************************************************/
1824 ReplaceStmt: UPDATE relation_name
1829 ReplaceStmt *n = makeNode(ReplaceStmt);
1833 n->whereClause = $6;
1839 /*****************************************************************************
1844 *****************************************************************************/
1846 CursorStmt: DECLARE name opt_binary CURSOR FOR
1847 SELECT opt_unique res_target_list2
1848 from_clause where_clause group_clause sort_clause
1850 CursorStmt *n = makeNode(CursorStmt);
1852 /* from PORTAL name */
1854 * 15 august 1991 -- since 3.0 postgres does locking
1855 * right, we discovered that portals were violating
1856 * locking protocol. portal locks cannot span xacts.
1857 * as a short-term fix, we installed the check here.
1860 if (!IsTransactionBlock())
1861 elog(WARN,"Named portals may only be used in begin/end transaction blocks",NULL);
1868 n->whereClause = $10;
1869 n->groupClause = $11;
1870 n->sortClause = $12;
1876 /*****************************************************************************
1881 *****************************************************************************/
1883 /******************************************************************************
1884 RetrieveStmt: SELECT opt_unique res_target_list2
1885 result from_clause where_clause
1886 group_clause having_clause
1889 RetrieveStmt *n = makeNode(RetrieveStmt);
1894 n->whereClause = $6;
1895 n->groupClause = $7;
1896 n->havingClause = $8;
1902 RetrieveStmt: Select UNION select_list sort_clause
1903 | Select sort_clause
1904 Select: SELECT opt_unique res_target_list2
1905 result from_clause where_clause
1906 group_clause having_clause
1908 Select *n = makeNode(Select);
1913 n->whereClause = $6;
1914 n->groupClause = $7;
1915 n->havingClause = $8;
1919 ******************************************************************************/
1921 RetrieveStmt: SELECT opt_unique res_target_list2
1922 result from_clause where_clause
1923 group_clause having_clause
1924 union_clause sort_clause
1926 RetrieveStmt *n = makeNode(RetrieveStmt);
1931 n->whereClause = $6;
1932 n->groupClause = $7;
1933 n->havingClause = $8;
1934 n->selectClause = $9;
1935 n->sortClause = $10;
1940 union_clause: UNION select_list { $$ = $2; }
1941 | /*EMPTY*/ { $$ = NIL; }
1944 select_list: select_list UNION SubSelect
1945 { $$ = lappend($1, $3); }
1947 { $$ = lcons($1, NIL); }
1950 SubSelect: SELECT opt_unique res_target_list2
1951 result from_clause where_clause
1952 group_clause having_clause
1954 SubSelect *n = makeNode(SubSelect);
1958 n->whereClause = $6;
1959 n->groupClause = $7;
1960 n->havingClause = $8;
1965 result: INTO TABLE relation_name
1966 { $$= $3; /* should check for archive level */ }
1971 opt_unique: DISTINCT { $$ = "*"; }
1972 | DISTINCT ON Id { $$ = $3; }
1973 | /*EMPTY*/ { $$ = NULL;}
1976 sort_clause: ORDER BY sortby_list { $$ = $3; }
1977 | /*EMPTY*/ { $$ = NIL; }
1981 { $$ = lcons($1, NIL); }
1982 | sortby_list ',' sortby
1983 { $$ = lappend($1, $3); }
1988 $$ = makeNode(SortGroupBy);
1994 | Id '.' Id OptUseOp
1996 $$ = makeNode(SortGroupBy);
2004 $$ = makeNode(SortGroupBy);
2012 OptUseOp: USING Op { $$ = $2; }
2013 | USING '<' { $$ = "<"; }
2014 | USING '>' { $$ = ">"; }
2016 | DESC { $$ = ">"; }
2017 | /*EMPTY*/ { $$ = "<"; /*default*/ }
2020 index_params: index_list { $$ = $1; }
2021 | func_index { $$ = lcons($1,NIL); }
2025 index_list ',' index_elem
2026 { $$ = lappend($1, $3); }
2028 { $$ = lcons($1, NIL); }
2031 func_index: name '(' name_list ')' opt_type opt_class
2033 $$ = makeNode(IndexElem);
2041 index_elem: attr_name opt_type opt_class
2043 $$ = makeNode(IndexElem);
2051 opt_type: ':' Typename { $$ = $2;}
2052 | /*EMPTY*/ { $$ = NULL;}
2056 | WITH class { $$ = $2; }
2057 | /*EMPTY*/ { $$ = NULL; }
2061 * jimmy bell-style recursive queries aren't supported in the
2064 * ...however, recursive addattr and rename supported. make special
2067 * XXX i believe '*' should be the default behavior, but...
2069 opt_inh_star: '*' { $$ = TRUE; }
2070 | /*EMPTY*/ { $$ = FALSE; }
2073 relation_name_list: name_list ;
2076 { $$=lcons(makeString($1),NIL); }
2077 | name_list ',' name
2078 { $$=lappend($1,makeString($3)); }
2081 group_clause: GROUP BY groupby_list { $$ = $3; }
2082 | /*EMPTY*/ { $$ = NIL; }
2085 groupby_list: groupby { $$ = lcons($1, NIL); }
2086 | groupby_list ',' groupby { $$ = lappend($1, $3); }
2091 $$ = makeNode(SortGroupBy);
2099 $$ = makeNode(SortGroupBy);
2107 $$ = makeNode(SortGroupBy);
2115 having_clause: HAVING a_expr { $$ = $2; }
2116 | /*EMPTY*/ { $$ = NULL; }
2119 /*****************************************************************************
2121 * clauses common to all Optimizable Stmts:
2125 *****************************************************************************/
2127 from_clause: FROM '(' relation_expr join_expr JOIN relation_expr join_spec ')'
2130 elog(WARN,"JOIN not yet implemented",NULL);
2132 | FROM from_list { $$ = $2; }
2133 | /*EMPTY*/ { $$ = NIL; }
2136 from_list: from_list ',' from_val
2137 { $$ = lappend($1, $3); }
2138 | from_val CROSS JOIN from_val
2139 { elog(WARN,"CROSS JOIN not yet implemented",NULL); }
2141 { $$ = lcons($1, NIL); }
2144 from_val: relation_expr AS var_name
2146 $$ = makeNode(RangeVar);
2150 | relation_expr var_name
2152 $$ = makeNode(RangeVar);
2158 $$ = makeNode(RangeVar);
2164 join_expr: NATURAL join_expr { $$ = NULL; }
2166 { elog(WARN,"FULL OUTER JOIN not yet implemented",NULL); }
2168 { elog(WARN,"LEFT OUTER JOIN not yet implemented",NULL); }
2170 { elog(WARN,"RIGHT OUTER JOIN not yet implemented",NULL); }
2172 { elog(WARN,"OUTER JOIN not yet implemented",NULL); }
2174 { elog(WARN,"INNER JOIN not yet implemented",NULL); }
2176 { elog(WARN,"UNION JOIN not yet implemented",NULL); }
2178 { elog(WARN,"INNER JOIN not yet implemented",NULL); }
2181 join_outer: OUTERJOIN { $$ = NULL; }
2182 | /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
2185 join_spec: ON '(' a_expr ')' { $$ = NULL; }
2186 | USING '(' join_list ')' { $$ = NULL; }
2187 | /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
2190 join_list: join_using { $$ = lcons($1, NIL); }
2191 | join_list ',' join_using { $$ = lappend($1, $3); }
2196 $$ = makeNode(SortGroupBy);
2204 $$ = makeNode(SortGroupBy);
2212 $$ = makeNode(SortGroupBy);
2220 where_clause: WHERE a_expr { $$ = $2; }
2221 | /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
2224 relation_expr: relation_name
2226 /* normal relations */
2227 $$ = makeNode(RelExpr);
2230 $$->timeRange = NULL;
2232 | relation_name '*' %prec '='
2234 /* inheiritance query */
2235 $$ = makeNode(RelExpr);
2238 $$->timeRange = NULL;
2240 | relation_name time_range
2242 /* time-qualified query */
2243 $$ = makeNode(RelExpr);
2251 time_range: '[' opt_range_start ',' opt_range_end ']'
2253 $$ = makeNode(TimeRange);
2259 $$ = makeNode(TimeRange);
2265 opt_range_start: date
2266 | /*EMPTY*/ { $$ = "epoch"; }
2270 | /*EMPTY*/ { $$ = "now"; }
2273 opt_array_bounds: '[' ']' nest_array_bounds
2274 { $$ = lcons(makeInteger(-1), $3); }
2275 | '[' Iconst ']' nest_array_bounds
2276 { $$ = lcons(makeInteger($2), $4); }
2281 nest_array_bounds: '[' ']' nest_array_bounds
2282 { $$ = lcons(makeInteger(-1), $3); }
2283 | '[' Iconst ']' nest_array_bounds
2284 { $$ = lcons(makeInteger($2), $4); }
2291 char *tname = xlateSqlType($1);
2292 $$ = makeNode(TypeName);
2295 /* Is this the name of a complex type? If so, implement
2298 if (!strcmp(saved_relname, tname))
2299 /* This attr is the same type as the relation
2300 * being defined. The classic example: create
2301 * emp(name=text,mgr=emp)
2304 else if (get_typrelid((Type)type(tname)) != InvalidOid)
2305 /* (Eventually add in here that the set can only
2306 * contain one element.)
2314 char *tname = xlateSqlType($2);
2315 $$ = makeNode(TypeName);
2321 txname: Id { $$ = $1; }
2322 | TIME { $$ = xlateSqlType("time"); }
2323 | INTERVAL interval_opts { $$ = xlateSqlType("interval"); }
2324 | CHARACTER char_type { $$ = $2; }
2325 | DOUBLE PRECISION { $$ = xlateSqlType("float8"); }
2328 char_type: VARYING { $$ = xlateSqlType("varchar"); }
2329 | /*EMPTY*/ { $$ = xlateSqlType("char"); }
2332 interval_opts: YEARINTERVAL { $$ = lcons("year", NIL); }
2333 | MONTHINTERVAL { $$ = NIL; }
2334 | DAYINTERVAL { $$ = NIL; }
2335 | HOURINTERVAL { $$ = NIL; }
2336 | MINUTEINTERVAL { $$ = NIL; }
2337 | SECONDINTERVAL { $$ = NIL; }
2338 | YEARINTERVAL TO MONTHINTERVAL { $$ = NIL; }
2339 | DAYINTERVAL TO HOURINTERVAL { $$ = NIL; }
2340 | DAYINTERVAL TO MINUTEINTERVAL { $$ = NIL; }
2341 | DAYINTERVAL TO SECONDINTERVAL { $$ = NIL; }
2342 | HOURINTERVAL TO MINUTEINTERVAL { $$ = NIL; }
2343 | HOURINTERVAL TO SECONDINTERVAL { $$ = NIL; }
2344 | /* EMPTY */ { $$ = NIL; }
2347 Typename: typname opt_array_bounds
2350 $$->arrayBounds = $2;
2351 if (!strcasecmp($1->name, "varchar"))
2356 | txname '(' Iconst ')'
2359 * This block gets hit when the parser is passed a query
2360 * which contains only spaces (e.g. from psql type " \g").
2361 * Let's check explicitly for a zero-length argument
2362 * here, and do nothing if so. This seems to fix the problem.
2363 * - thomas 1997-07-13
2369 * The following implements char() and varchar().
2370 * We do it here instead of the 'typname:' production
2371 * because we don't want to allow arrays of varchar().
2372 * I haven't thought about whether that will work or not.
2375 $$ = makeNode(TypeName);
2376 if (!strcasecmp($1, "char"))
2377 $$->name = "bpchar"; /* strdup("bpchar"); */
2378 else if (!strcasecmp($1, "varchar"))
2379 $$->name = "varchar"; /* strdup("varchar"); */
2381 yyerror("parse error");
2383 elog(WARN,"length for '%s' type must be at least 1",$1);
2385 /* we can store a char() of length up to the size
2386 * of a page (8KB) - page headers and friends but
2387 * just to be safe here... - ay 6/95
2388 * XXX note this hardcoded limit - thomas 1997-07-13
2390 elog(WARN,"length for '%s' type cannot exceed 4096",$1);
2392 /* we actually implement this sort of like a varlen, so
2393 * the first 4 bytes is the length. (the difference
2394 * between this and "text" is that we blank-pad and
2395 * truncate where necessary
2397 $$->typlen = 4 + $3;
2404 /*****************************************************************************
2406 * expression grammar, still needs some cleanup
2408 *****************************************************************************/
2410 a_expr_or_null: a_expr
2414 A_Const *n = makeNode(A_Const);
2415 n->val.type = T_Null;
2419 a_expr: attr opt_indirection
2421 $1->indirection = $2;
2426 | '-' a_expr %prec UMINUS
2427 { $$ = makeA_Expr(OP, "-", NULL, $2); }
2429 { $$ = makeA_Expr(OP, "+", $1, $3); }
2431 { $$ = makeA_Expr(OP, "-", $1, $3); }
2433 { $$ = makeA_Expr(OP, "/", $1, $3); }
2435 { $$ = makeA_Expr(OP, "*", $1, $3); }
2437 { $$ = makeA_Expr(OP, "<", $1, $3); }
2439 { $$ = makeA_Expr(OP, ">", $1, $3); }
2441 { $$ = makeA_Expr(OP, "=", $1, $3); }
2443 { $$ = makeA_Expr(OP, ":", NULL, $2); }
2445 { $$ = makeA_Expr(OP, ";", NULL, $2); }
2447 { $$ = makeA_Expr(OP, "|", NULL, $2); }
2448 | AexprConst TYPECAST Typename
2450 /* AexprConst can be either A_Const or ParamNo */
2451 if (nodeTag($1) == T_A_Const)
2452 ((A_Const *)$1)->typename = $3;
2454 ((ParamNo *)$1)->typename = $3;
2457 | CAST AexprConst AS Typename
2459 /* AexprConst can be either A_Const or ParamNo */
2460 if (nodeTag($2) == T_A_Const)
2461 ((A_Const *)$2)->typename = $4;
2463 ((ParamNo *)$2)->typename = $4;
2466 | '(' a_expr_or_null ')'
2469 { $$ = makeA_Expr(OP, $2, $1, $3); }
2470 | a_expr LIKE a_expr
2471 { $$ = makeA_Expr(OP, "~~", $1, $3); }
2472 | a_expr NOT LIKE a_expr
2473 { $$ = makeA_Expr(OP, "!~~", $1, $4); }
2475 { $$ = makeA_Expr(OP, $1, NULL, $2); }
2477 { $$ = makeA_Expr(OP, $2, $1, NULL); }
2480 /* could be a column name or a relation_name */
2481 Ident *n = makeNode(Ident);
2483 n->indirection = NULL;
2488 FuncCall *n = makeNode(FuncCall);
2489 Ident *star = makeNode(Ident);
2491 /* cheap hack for aggregate (eg. count) */
2494 n->args = lcons(star, NIL);
2499 FuncCall *n = makeNode(FuncCall);
2504 /* We probably need to define an "exists" node,
2505 * since the optimizer could choose to find only one match.
2506 * Perhaps the first implementation could just check for
2507 * count(*) > 0? - thomas 1997-07-19
2509 | EXISTS '(' SubSelect ')'
2511 elog(WARN,"EXISTS not yet supported",NULL);
2514 | EXTRACT '(' extract_list ')'
2516 FuncCall *n = makeNode(FuncCall);
2517 n->funcname = "date_part";
2521 | POSITION '(' position_list ')'
2523 FuncCall *n = makeNode(FuncCall);
2524 n->funcname = "strpos";
2528 | SUBSTRING '(' substr_list ')'
2530 FuncCall *n = makeNode(FuncCall);
2531 n->funcname = "substr";
2535 /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
2536 | TRIM '(' BOTH trim_list ')'
2538 FuncCall *n = makeNode(FuncCall);
2539 n->funcname = "btrim";
2543 | TRIM '(' LEADING trim_list ')'
2545 FuncCall *n = makeNode(FuncCall);
2546 n->funcname = "ltrim";
2550 | TRIM '(' TRAILING trim_list ')'
2552 FuncCall *n = makeNode(FuncCall);
2553 n->funcname = "rtrim";
2557 | TRIM '(' trim_list ')'
2559 FuncCall *n = makeNode(FuncCall);
2560 n->funcname = "btrim";
2564 | name '(' expr_list ')'
2566 FuncCall *n = makeNode(FuncCall);
2572 { $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
2574 { $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
2576 { $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); }
2577 | a_expr IS NOT PNULL
2578 { $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); }
2579 | a_expr BETWEEN AexprConst AND AexprConst
2581 $$ = makeA_Expr(AND, NULL,
2582 makeA_Expr(OP, ">=", $1, $3),
2583 makeA_Expr(OP, "<=", $1, $5));
2585 | a_expr NOT BETWEEN AexprConst AND AexprConst
2587 $$ = makeA_Expr(OR, NULL,
2588 makeA_Expr(OP, "<", $1, $4),
2589 makeA_Expr(OP, ">", $1, $6));
2591 | a_expr IN { saved_In_Expr = $1; } '(' in_expr_nodes ')'
2593 | a_expr NOT IN { saved_In_Expr = $1; } '(' not_in_expr_nodes ')'
2596 { $$ = makeA_Expr(AND, NULL, $1, $3); }
2598 { $$ = makeA_Expr(OR, NULL, $1, $3); }
2600 { $$ = makeA_Expr(NOT, NULL, NULL, $2); }
2603 opt_indirection: '[' a_expr ']' opt_indirection
2605 A_Indices *ai = makeNode(A_Indices);
2610 | '[' a_expr ':' a_expr ']' opt_indirection
2612 A_Indices *ai = makeNode(A_Indices);
2621 expr_list: a_expr_or_null
2622 { $$ = lcons($1, NIL); }
2623 | expr_list ',' a_expr_or_null
2624 { $$ = lappend($1, $3); }
2625 | expr_list USING a_expr
2626 { $$ = lappend($1, $3); }
2629 extract_list: DateTime FROM a_expr
2631 A_Const *n = makeNode(A_Const);
2632 n->val.type = T_String;
2633 n->val.val.str = $1;
2635 printf( "string is %s\n", $1);
2637 $$ = lappend(lcons((Node *)n,NIL), $3);
2643 position_list: position_expr IN position_expr
2644 { $$ = makeList($3, $1, -1); }
2649 position_expr: attr opt_indirection
2651 $1->indirection = $2;
2656 | '-' position_expr %prec UMINUS
2657 { $$ = makeA_Expr(OP, "-", NULL, $2); }
2658 | position_expr '+' position_expr
2659 { $$ = makeA_Expr(OP, "+", $1, $3); }
2660 | position_expr '-' position_expr
2661 { $$ = makeA_Expr(OP, "-", $1, $3); }
2662 | position_expr '/' position_expr
2663 { $$ = makeA_Expr(OP, "/", $1, $3); }
2664 | position_expr '*' position_expr
2665 { $$ = makeA_Expr(OP, "*", $1, $3); }
2667 { $$ = makeA_Expr(OP, "|", NULL, $2); }
2668 | AexprConst TYPECAST Typename
2670 /* AexprConst can be either A_Const or ParamNo */
2671 if (nodeTag($1) == T_A_Const)
2672 ((A_Const *)$1)->typename = $3;
2674 ((ParamNo *)$1)->typename = $3;
2677 | CAST AexprConst AS Typename
2679 /* AexprConst can be either A_Const or ParamNo */
2680 if (nodeTag($2) == T_A_Const)
2681 ((A_Const *)$2)->typename = $4;
2683 ((ParamNo *)$2)->typename = $4;
2686 | '(' position_expr ')'
2688 | position_expr Op position_expr
2689 { $$ = makeA_Expr(OP, $2, $1, $3); }
2691 { $$ = makeA_Expr(OP, $1, NULL, $2); }
2693 { $$ = makeA_Expr(OP, $2, $1, NULL); }
2696 /* could be a column name or a relation_name */
2697 Ident *n = makeNode(Ident);
2699 n->indirection = NULL;
2704 FuncCall *n = makeNode(FuncCall);
2709 | POSITION '(' position_list ')'
2711 FuncCall *n = makeNode(FuncCall);
2712 n->funcname = "strpos";
2716 | SUBSTRING '(' substr_list ')'
2718 FuncCall *n = makeNode(FuncCall);
2719 n->funcname = "substr";
2723 /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
2724 | TRIM '(' BOTH trim_list ')'
2726 FuncCall *n = makeNode(FuncCall);
2727 n->funcname = "btrim";
2731 | TRIM '(' LEADING trim_list ')'
2733 FuncCall *n = makeNode(FuncCall);
2734 n->funcname = "ltrim";
2738 | TRIM '(' TRAILING trim_list ')'
2740 FuncCall *n = makeNode(FuncCall);
2741 n->funcname = "rtrim";
2745 | TRIM '(' trim_list ')'
2747 FuncCall *n = makeNode(FuncCall);
2748 n->funcname = "btrim";
2752 | name '(' expr_list ')'
2754 FuncCall *n = makeNode(FuncCall);
2761 substr_list: expr_list substr_from substr_for
2764 if ($2 != NULL) $$ = lappend($$, $2);
2765 if ($3 != NULL) $$ = lappend($$, $3);
2771 substr_from: FROM expr_list
2777 substr_for: FOR expr_list
2783 trim_list: a_expr FROM expr_list
2784 { $$ = lappend($3, $1); }
2791 in_expr_nodes: AexprConst
2792 { $$ = makeA_Expr(OP, "=", saved_In_Expr, $1); }
2793 | in_expr_nodes ',' AexprConst
2794 { $$ = makeA_Expr(OR, NULL, $1,
2795 makeA_Expr(OP, "=", saved_In_Expr, $3));
2799 not_in_expr_nodes: AexprConst
2800 { $$ = makeA_Expr(OP, "<>", saved_In_Expr, $1); }
2801 | not_in_expr_nodes ',' AexprConst
2802 { $$ = makeA_Expr(AND, NULL, $1,
2803 makeA_Expr(OP, "<>", saved_In_Expr, $3));
2807 attr: relation_name '.' attrs
2809 $$ = makeNode(Attr);
2813 $$->indirection = NULL;
2817 $$ = makeNode(Attr);
2821 $$->indirection = NULL;
2826 { $$ = lcons(makeString($1), NIL); }
2827 | attrs '.' attr_name
2828 { $$ = lappend($1, makeString($3)); }
2830 { $$ = lappend($1, makeString("*")); }
2833 DateTime: YEARINTERVAL { $$ = "year"; }
2834 | MONTHINTERVAL { $$ = "month"; }
2835 | DAYINTERVAL { $$ = "day"; }
2836 | HOURINTERVAL { $$ = "hour"; }
2837 | MINUTEINTERVAL { $$ = "minute"; }
2838 | SECONDINTERVAL { $$ = "second"; }
2841 /*****************************************************************************
2845 *****************************************************************************/
2847 res_target_list: res_target_list ',' res_target_el
2848 { $$ = lappend($1,$3); }
2850 { $$ = lcons($1, NIL); }
2853 ResTarget *rt = makeNode(ResTarget);
2854 Attr *att = makeNode(Attr);
2856 att->paramNo = NULL;
2858 att->indirection = NIL;
2860 rt->indirection = NULL;
2861 rt->val = (Node *)att;
2862 $$ = lcons(rt, NIL);
2866 res_target_el: Id opt_indirection '=' a_expr_or_null
2868 $$ = makeNode(ResTarget);
2870 $$->indirection = $2;
2871 $$->val = (Node *)$4;
2873 | attr opt_indirection
2875 $$ = makeNode(ResTarget);
2877 $$->indirection = $2;
2878 $$->val = (Node *)$1;
2880 | relation_name '.' '*'
2882 Attr *att = makeNode(Attr);
2884 att->paramNo = NULL;
2885 att->attrs = lcons(makeString("*"), NIL);
2886 att->indirection = NIL;
2887 $$ = makeNode(ResTarget);
2889 $$->indirection = NULL;
2890 $$->val = (Node *)att;
2895 ** target list for select.
2896 ** should get rid of the other but is still needed by the defunct retrieve into
2897 ** and update (uses a subset)
2899 res_target_list2: res_target_list2 ',' res_target_el2
2900 { $$ = lappend($1, $3); }
2902 { $$ = lcons($1, NIL); }
2905 /* AS is not optional because shift/red conflict with unary ops */
2906 res_target_el2: a_expr_or_null AS ColId
2908 $$ = makeNode(ResTarget);
2910 $$->indirection = NULL;
2911 $$->val = (Node *)$1;
2915 $$ = makeNode(ResTarget);
2917 $$->indirection = NULL;
2918 $$->val = (Node *)$1;
2920 | relation_name '.' '*'
2922 Attr *att = makeNode(Attr);
2924 att->paramNo = NULL;
2925 att->attrs = lcons(makeString("*"), NIL);
2926 att->indirection = NIL;
2927 $$ = makeNode(ResTarget);
2929 $$->indirection = NULL;
2930 $$->val = (Node *)att;
2934 Attr *att = makeNode(Attr);
2936 att->paramNo = NULL;
2938 att->indirection = NIL;
2939 $$ = makeNode(ResTarget);
2941 $$->indirection = NULL;
2942 $$->val = (Node *)att;
2946 opt_id: Id { $$ = $1; }
2947 | /* EMPTY */ { $$ = NULL; }
2950 relation_name: SpecialRuleRelation
2953 strNcpy(saved_relname, $1, NAMEDATALEN-1);
2957 /* disallow refs to magic system tables */
2958 if (strcmp(LogRelationName, $1) == 0
2959 || strcmp(VariableRelationName, $1) == 0
2960 || strcmp(TimeRelationName, $1) == 0
2961 || strcmp(MagicRelationName, $1) == 0)
2962 elog(WARN,"%s cannot be accessed by users",$1);
2965 strNcpy(saved_relname, $1, NAMEDATALEN-1);
2969 database_name: Id { $$ = $1; };
2970 access_method: Id { $$ = $1; };
2971 attr_name: ColId { $$ = $1; };
2972 class: Id { $$ = $1; };
2973 index_name: Id { $$ = $1; };
2974 var_name: Id { $$ = $1; };
2975 name: Id { $$ = $1; };
2977 date: Sconst { $$ = $1; };
2978 file_name: Sconst { $$ = $1; };
2979 recipe_name: Id { $$ = $1; };
2983 A_Const *n = makeNode(A_Const);
2984 n->val.type = T_Integer;
2985 n->val.val.ival = $1;
2990 A_Const *n = makeNode(A_Const);
2991 n->val.type = T_Float;
2992 n->val.val.dval = $1;
2997 A_Const *n = makeNode(A_Const);
2998 n->val.type = T_String;
2999 n->val.val.str = $1;
3003 { $$ = (Node *)$1; }
3008 $$ = makeNode(ParamNo);
3013 NumConst: Iconst { $$ = makeInteger($1); }
3014 | FCONST { $$ = makeFloat($1); }
3017 Iconst: ICONST { $$ = $1; };
3018 Sconst: SCONST { $$ = $1; };
3020 Id: IDENT { $$ = $1; };
3022 ColId: Id { $$ = $1; }
3023 | DateTime { $$ = $1; }
3026 SpecialRuleRelation: CURRENT
3031 elog(WARN,"CURRENT used in non-rule query",NULL);
3038 elog(WARN,"NEW used in non-rule query",NULL);
3048 static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr)
3050 A_Expr *a = makeNode(A_Expr);
3059 * Convert alternate type names to internal Postgres types.
3062 xlateSqlType(char *name)
3064 if (!strcasecmp(name,"int") ||
3065 !strcasecmp(name,"integer"))
3066 return "int4"; /* strdup("int4") -- strdup leaks memory here */
3067 else if (!strcasecmp(name, "smallint"))
3069 else if (!strcasecmp(name, "float") ||
3070 !strcasecmp(name, "real"))
3072 else if (!strcasecmp(name, "interval"))
3078 void parser_init(Oid *typev, int nargs)
3080 QueryIsRule = FALSE;
3081 saved_relname[0]= '\0';
3082 saved_In_Expr = NULL;
3084 param_type_init(typev, nargs);
3087 /* FlattenStringList()
3088 * Traverse list of string nodes and convert to a single string.
3089 * Used for reconstructing string form of complex expressions.
3092 FlattenStringList(List *list)
3099 nlist = length(list);
3101 printf( "list has %d elements\n", nlist);
3106 sp = (char *)(lp->elem.ptr_value);
3109 printf( "length of %s is %d\n", sp, strlen(sp));
3111 len += strlen(sp)+1;
3114 s = (char*) palloc(len);
3120 sp = (char *)(lp->elem.ptr_value);
3123 printf( "length of %s is %d\n", sp, strlen(sp));
3131 printf( "flattened string is \"%s\"\n", s);
3135 } /* FlattenStringList() */
3137 /* makeConstantList()
3138 * Convert constant value node into string node.
3141 makeConstantList( A_Const *n)
3143 char *defval = NULL;
3145 printf( "in AexprConst\n");
3147 if (nodeTag(n) != T_A_Const) {
3148 elog(WARN,"Cannot handle non-constant parameter",NULL);
3150 } else if (n->val.type == T_Float) {
3152 printf( "AexprConst float is %f\n", n->val.val.dval);
3154 defval = (char*) palloc(20+1);
3155 sprintf( defval, "%g", n->val.val.dval);
3157 } else if (n->val.type == T_Integer) {
3159 printf( "AexprConst integer is %ld\n", n->val.val.ival);
3161 defval = (char*) palloc(20+1);
3162 sprintf( defval, "%ld", n->val.val.ival);
3164 } else if (n->val.type == T_String) {
3167 printf( "AexprConst string is \"%s\"\n", n->val.val.str);
3170 defval = (char*) palloc(strlen( ((A_Const *) n)->val.val.str) + 3);
3171 strcpy( defval, "'");
3172 strcat( defval, ((A_Const *) n)->val.val.str);
3173 strcat( defval, "'");
3176 elog(WARN,"Internal error: cannot encode node",NULL);
3180 printf( "AexprConst argument is \"%s\"\n", defval);
3183 return( lcons( makeString(defval), NIL));
3184 } /* makeConstantList() */