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.58 1997/10/25 05:56:41 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.
23 * SQL92-specific syntax is separated from plain SQL/Postgres syntax
24 * to help isolate the non-extensible portions of the parser.
26 * if you use list, make sure the datum is a node so that the printing
30 * sometimes we assign constants to makeStrings. Make sure we don't free
33 *-------------------------------------------------------------------------
39 #include "nodes/parsenodes.h"
40 #include "nodes/print.h"
41 #include "parser/gramparse.h"
42 #include "parser/catalog_utils.h"
43 #include "parser/parse_query.h"
44 #include "storage/smgr.h"
45 #include "utils/acl.h"
46 #include "catalog/catname.h"
47 #include "utils/elog.h"
48 #include "access/xact.h"
50 static char saved_relname[NAMEDATALEN]; /* need this for complex attributes */
51 static bool QueryIsRule = FALSE;
52 static Node *saved_In_Expr;
53 extern List *parsetree;
56 * If you need access to certain yacc-generated variables and find that
57 * they're static by default, uncomment the next line. (this is not a
60 /*#define __YYSCLASS*/
62 static char *xlateSqlType(char *);
63 static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
64 static List *makeConstantList( A_Const *node);
65 static char *FlattenStringList(List *list);
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, 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
120 %type <node> SubSelect
121 %type <str> join_expr, join_outer, join_spec
122 %type <boolean> TriggerActionTime, TriggerForSpec
124 %type <str> TriggerEvents, TriggerFuncArg
126 %type <str> relation_name, copy_file_name, copy_delimiter, def_name,
127 database_name, access_method_clause, access_method, attr_name,
128 class, index_name, name, file_name, recipe_name, aggr_argtype
130 %type <str> opt_id, opt_portal_name,
131 before_clause, after_clause, all_Op, MathOp, opt_name, opt_unique,
132 result, OptUseOp, opt_class, opt_range_start, opt_range_end,
135 %type <str> privileges, operation_commalist, grantee
136 %type <chr> operation, TriggerOneEvent
138 %type <list> stmtblock, stmtmulti,
139 relation_name_list, OptTableElementList, tableElementList,
140 OptInherit, OptConstraint, ConstraintList, definition,
141 opt_with, def_args, def_name_list, func_argtypes,
142 oper_argtypes, OptStmtList, OptStmtBlock, OptStmtMulti,
143 opt_column_list, columnList, opt_va_list, va_list,
144 sort_clause, sortby_list, index_params, index_list, name_list,
145 from_clause, from_list, opt_array_bounds, nest_array_bounds,
146 expr_list, attrs, res_target_list, res_target_list2,
147 def_list, opt_indirection, group_clause, groupby_list, TriggerFuncArgs
149 %type <list> union_clause, select_list
150 %type <list> join_list
151 %type <sortgroupby> join_using
153 %type <node> position_expr
154 %type <list> extract_list, position_list
155 %type <list> substr_list, substr_from, substr_for, trim_list
156 %type <list> opt_interval
158 %type <boolean> opt_inh_star, opt_binary, opt_instead, opt_with_copy,
159 index_opt_unique, opt_verbose, opt_analyze
161 %type <ival> copy_dirn, archive_type, OptArchiveType, OptArchiveLocation,
162 def_type, opt_direction, remove_type, opt_column, event
164 %type <ival> OptLocation, fetch_how_many
166 %type <list> OptSeqList
167 %type <defelt> OptSeqElem
169 %type <dstmt> def_rest
170 %type <pstmt> purge_quals
171 %type <astmt> insert_rest
173 %type <coldef> columnDef, alter_clause
174 %type <defelt> def_elem
175 %type <node> def_arg, columnElem, where_clause,
176 a_expr, a_expr_or_null, AexprConst,
177 in_expr, in_expr_nodes, not_in_expr, not_in_expr_nodes,
179 %type <value> NumConst
180 %type <attr> event_object, attr
181 %type <sortgroupby> groupby
182 %type <sortgroupby> sortby
183 %type <ielem> index_elem, func_index
184 %type <range> from_val
185 %type <relexp> relation_expr
186 %type <trange> time_range
187 %type <target> res_target_el, res_target_el2
188 %type <paramno> ParamNo
190 %type <typnam> Typename, opt_type, Array, Generic, Character, Datetime, Numeric
191 %type <str> generic, character, datetime
192 %type <str> opt_charset, opt_collate
193 %type <str> opt_float, opt_numeric, opt_decimal
194 %type <boolean> opt_varying, opt_timezone
198 %type <str> Id, date, var_value, zone_value
199 %type <str> ColId, ColLabel
201 %type <constrdef> ConstraintElem, ConstraintDef
203 %type <list> constraint_elem
204 %type <list> default_expr
205 %type <str> opt_default
206 %type <boolean> opt_constraint
207 %type <list> key_actions, key_action
208 %type <str> key_match, key_reference
211 * If you make any token changes, remember to:
212 * - use "yacc -d" and update parse.h
213 * - update the keyword table in parser/keywords.c
216 /* Reserved word tokens
217 * SQL92 syntax has many type-specific constructs.
218 * So, go ahead and make these types reserved words,
219 * and call-out the syntax explicitly.
220 * This gets annoying when trying to also retain Postgres' nice
221 * type-extensible features, but we don't really have a choice.
222 * - thomas 1997-10-11
225 /* Keywords (in SQL92 reserved words) */
226 %token ACTION, ADD, ALL, ALTER, AND, AS, ASC,
227 BEGIN_TRANS, BETWEEN, BOTH, BY,
228 CASCADE, CAST, CHAR, CHARACTER, CHECK, CLOSE,
229 COLLATE, COLUMN, COMMIT, CONSTRAINT, CREATE, CROSS,
230 CURRENT, CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP, CURRENT_USER, CURSOR,
231 DAY_P, DECIMAL, DECLARE, DEFAULT, DELETE, DESC, DISTINCT, DOUBLE, DROP,
232 END_TRANS, EXECUTE, EXISTS, EXTRACT,
233 FETCH, FLOAT, FOR, FOREIGN, FROM, FULL,
234 GRANT, GROUP, HAVING, HOUR_P,
235 IN, INNER_P, INSERT, INTERVAL, INTO, IS,
236 JOIN, KEY, LANGUAGE, LEADING, LEFT, LIKE, LOCAL,
237 MATCH, MINUTE_P, MONTH_P,
238 NATIONAL, NATURAL, NCHAR, NO, NOT, NOTIFY, NOTNULL, NULL_P, NUMERIC,
239 ON, OPTION, OR, ORDER, OUTER_P,
240 PARTIAL, PRECISION, POSITION, PRIMARY, PRIVILEGES, PROCEDURE, PUBLIC,
241 REFERENCES, REVOKE, RIGHT, ROLLBACK,
242 SECOND_P, SELECT, SET, SUBSTRING,
243 TABLE, TIME, TIMESTAMP, TO, TRAILING, TRANSACTION, TRIM,
244 UNION, UNIQUE, UPDATE, USING,
245 VALUES, VARCHAR, VARYING, VERBOSE, VERSION, VIEW,
246 WHERE, WITH, WORK, YEAR_P, ZONE
248 /* Keywords (in SQL3 reserved words) */
249 %token FALSE_P, TRIGGER, TRUE_P
251 /* Keywords (in SQL92 non-reserved words) */
254 /* Keywords for Postgres support (not in SQL92 reserved words) */
255 %token ABORT_TRANS, ACL, AFTER, AGGREGATE, ANALYZE,
256 APPEND, ARCHIVE, ARCH_STORE,
257 BACKWARD, BEFORE, BINARY, CHANGE, CLUSTER, COPY,
258 DATABASE, DELIMITERS, DO, EXPLAIN, EXTEND,
259 FORWARD, FUNCTION, HEAVY,
260 INDEX, INHERITS, INSTEAD, ISNULL,
261 LIGHT, LISTEN, LOAD, MERGE, MOVE,
262 NEW, NONE, NOTHING, OIDS, OPERATOR, PURGE,
263 RECIPE, RENAME, REPLACE, RESET, RETRIEVE, RETURNS, RULE,
264 SEQUENCE, SETOF, SHOW, STDIN, STDOUT, STORE,
265 VACUUM, VERBOSE, VERSION
267 /* Special keywords, not in the query language - see the "lex" file */
268 %token <str> IDENT, SCONST, Op
269 %token <ival> ICONST, PARAM
272 /* these are not real. they are here so that they get generated as #define's*/
289 %left '|' /* this is the relation union op, not logical or */
290 /* Unary Operators */
292 %left ';' /* end of statement or natural log */
305 { parsetree = lcons($1,NIL); }
308 stmtmulti: stmtmulti stmt ';'
309 { $$ = lappend($1, $2); }
311 { $$ = lappend($1, $2); }
313 { $$ = lcons($1,NIL); }
355 /*****************************************************************************
357 * Set PG internal variable
358 * SET name TO 'var_value'
359 * Include SQL92 syntax (thomas 1997-10-22):
360 * SET TIME ZONE 'var_value'
362 *****************************************************************************/
364 VariableSetStmt: SET ColId TO var_value
366 VariableSetStmt *n = makeNode(VariableSetStmt);
371 | SET ColId '=' var_value
373 VariableSetStmt *n = makeNode(VariableSetStmt);
378 | SET TIME ZONE zone_value
380 VariableSetStmt *n = makeNode(VariableSetStmt);
381 n->name = "timezone";
387 var_value: Sconst { $$ = $1; }
390 zone_value: Sconst { $$ = $1; }
391 | LOCAL { $$ = "default"; }
394 VariableShowStmt: SHOW ColId
396 VariableShowStmt *n = makeNode(VariableShowStmt);
402 VariableResetStmt: RESET ColId
404 VariableResetStmt *n = makeNode(VariableResetStmt);
411 /*****************************************************************************
414 * addattr ( attr1 = type1 .. attrn = typen ) to <relname> [*]
416 *****************************************************************************/
418 AddAttrStmt: ALTER TABLE relation_name opt_inh_star alter_clause
420 AddAttrStmt *n = makeNode(AddAttrStmt);
428 alter_clause: ADD opt_column columnDef
432 | ADD '(' tableElementList ')'
434 ColumnDef *lp = lfirst($3);
437 elog(WARN,"ALTER TABLE/ADD() allows one column only",NULL);
439 printf( "list has %d elements\n", length($3));
443 | DROP opt_column ColId
444 { elog(WARN,"ALTER TABLE/DROP COLUMN not yet implemented",NULL); }
445 | ALTER opt_column ColId SET opt_default
446 { elog(WARN,"ALTER TABLE/ALTER COLUMN/SET DEFAULT not yet implemented",NULL); }
447 | ALTER opt_column ColId DROP DEFAULT
448 { elog(WARN,"ALTER TABLE/ALTER COLUMN/DROP DEFAULT not yet implemented",NULL); }
450 { elog(WARN,"ALTER TABLE/ADD CONSTRAINT not yet implemented",NULL); }
453 columnDef: ColId Typename opt_default opt_constraint
455 $$ = makeNode(ColumnDef);
459 $$->is_not_null = $4;
463 opt_default: DEFAULT default_expr
465 $$ = FlattenStringList($2);
467 | /*EMPTY*/ { $$ = NULL; }
470 default_expr: AexprConst
471 { $$ = makeConstantList((A_Const *) $1); }
473 { $$ = lcons( makeString("NULL"), NIL); }
474 | '-' default_expr %prec UMINUS
475 { $$ = lcons( makeString( "-"), $2); }
476 | default_expr '+' default_expr
477 { $$ = nconc( $1, lcons( makeString( "+"), $3)); }
478 | default_expr '-' default_expr
479 { $$ = nconc( $1, lcons( makeString( "-"), $3)); }
480 | default_expr '/' default_expr
481 { $$ = nconc( $1, lcons( makeString( "/"), $3)); }
482 | default_expr '*' default_expr
483 { $$ = nconc( $1, lcons( makeString( "*"), $3)); }
484 | default_expr '=' default_expr
485 { elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
486 | default_expr '<' default_expr
487 { elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
488 | default_expr '>' default_expr
489 { elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
491 { $$ = lcons( makeString( ":"), $2); }
493 { $$ = lcons( makeString( ";"), $2); }
495 { $$ = lcons( makeString( "|"), $2); }
496 | default_expr TYPECAST Typename
498 $$ = nconc( lcons( makeString( "CAST"), $1), makeList( makeString("AS"), $3, -1));
500 | CAST default_expr AS Typename
502 $$ = nconc( lcons( makeString( "CAST"), $2), makeList( makeString("AS"), $4, -1));
504 | '(' default_expr ')'
505 { $$ = lappend( lcons( makeString( "("), $2), makeString( ")")); }
506 | name '(' default_expr ')'
508 $$ = makeList( makeString($1), makeString("("), -1);
510 $$ = lappend( $$, makeString(")"));
514 $$ = makeList( makeString($1), makeString("("), -1);
515 $$ = lappend( $$, makeString(")"));
517 | default_expr Op default_expr
519 if (!strcmp("<=", $2) || !strcmp(">=", $2))
520 elog(WARN,"boolean expressions not supported in DEFAULT",NULL);
521 $$ = nconc( $1, lcons( makeString( $2), $3));
524 { $$ = lcons( makeString( $1), $2); }
526 { $$ = lappend( $1, makeString( $2)); }
527 /* XXX - thomas 1997-10-07 v6.2 function-specific code to be changed */
529 { $$ = lcons( makeString( "date( 'current'::datetime + '0 sec')"), NIL); }
531 { $$ = lcons( makeString( "'now'::time"), NIL); }
532 | CURRENT_TIME '(' Iconst ')'
535 elog(NOTICE,"CURRENT_TIME(p) precision must be zero",NULL);
536 $$ = lcons( makeString( "'now'::time"), NIL);
539 { $$ = lcons( makeString( "now()"), NIL); }
540 | CURRENT_TIMESTAMP '(' Iconst ')'
543 elog(NOTICE,"CURRENT_TIMESTAMP(p) precision must be zero",NULL);
544 $$ = lcons( makeString( "now()"), NIL);
547 { $$ = lcons( makeString( "CURRENT_USER"), NIL); }
550 opt_constraint: NOT NULL_P { $$ = TRUE; }
551 | NOTNULL { $$ = TRUE; }
554 elog(WARN,"CREATE TABLE/UNIQUE not yet implemented",NULL);
559 elog(WARN,"CREATE TABLE/PRIMARY KEY not yet implemented",NULL);
562 | REFERENCES ColId opt_column_list key_match key_actions
564 elog(WARN,"CREATE TABLE/FOREIGN KEY not yet implemented",NULL);
567 | /* EMPTY */ { $$ = FALSE; }
571 /*****************************************************************************
576 *****************************************************************************/
578 ClosePortalStmt: CLOSE opt_id
580 ClosePortalStmt *n = makeNode(ClosePortalStmt);
587 /*****************************************************************************
590 * COPY [BINARY] <relname> FROM/TO
591 * [USING DELIMITERS <delimiter>]
593 *****************************************************************************/
595 CopyStmt: COPY opt_binary relation_name opt_with_copy copy_dirn copy_file_name copy_delimiter
597 CopyStmt *n = makeNode(CopyStmt);
615 * copy_file_name NULL indicates stdio is used. Whether stdin or stdout is
616 * used depends on the direction. (It really doesn't make sense to copy from
617 * stdout. We silently correct the "typo". - AY 9/94
619 copy_file_name: Sconst { $$ = $1; }
620 | STDIN { $$ = NULL; }
621 | STDOUT { $$ = NULL; }
624 opt_binary: BINARY { $$ = TRUE; }
625 | /*EMPTY*/ { $$ = FALSE; }
628 opt_with_copy: WITH OIDS { $$ = TRUE; }
629 | /* EMPTY */ { $$ = FALSE; }
633 * the default copy delimiter is tab but the user can configure it
635 copy_delimiter: USING DELIMITERS Sconst { $$ = $3;}
636 | /* EMPTY */ { $$ = "\t"; }
640 /*****************************************************************************
645 *****************************************************************************/
647 CreateStmt: CREATE TABLE relation_name '(' OptTableElementList ')'
648 OptInherit OptConstraint OptArchiveType OptLocation
651 CreateStmt *n = makeNode(CreateStmt);
663 OptTableElementList: tableElementList { $$ = $1; }
664 | /* EMPTY */ { $$ = NULL; }
668 tableElementList ',' columnDef
669 { $$ = lappend($1, $3); }
671 { $$ = lcons($1, NIL); }
675 OptArchiveType: ARCHIVE '=' archive_type { $$ = $3; }
676 | /*EMPTY*/ { $$ = ARCH_NONE; }
679 archive_type: HEAVY { $$ = ARCH_HEAVY; }
680 | LIGHT { $$ = ARCH_LIGHT; }
681 | NONE { $$ = ARCH_NONE; }
684 OptLocation: STORE '=' Sconst
690 OptArchiveLocation: ARCH_STORE '=' Sconst
696 OptInherit: INHERITS '(' relation_name_list ')' { $$ = $3; }
697 | /*EMPTY*/ { $$ = NIL; }
700 OptConstraint: ConstraintList { $$ = $1; }
701 | /*EMPTY*/ { $$ = NULL; }
705 ConstraintList ',' ConstraintElem
706 { $$ = lappend($1, $3); }
708 { $$ = lcons($1, NIL); }
712 CONSTRAINT name ConstraintDef
717 | ConstraintDef { $$ = $1; }
720 ConstraintDef: CHECK constraint_elem
722 ConstraintDef *constr = palloc (sizeof(ConstraintDef));
724 printf("in ConstraintDef\n");
726 constr->type = CONSTR_CHECK;
728 constr->def = FlattenStringList($2);
730 printf("ConstraintDef: string is %s\n", (char *) constr->def);
734 | UNIQUE '(' columnList ')'
735 { elog(WARN,"CREATE TABLE/UNIQUE not yet implemented",NULL); }
736 | PRIMARY KEY '(' columnList ')'
737 { elog(WARN,"CREATE TABLE/PRIMARY KEY not yet implemented",NULL); }
738 | FOREIGN KEY '(' columnList ')' REFERENCES ColId opt_column_list key_match key_actions
739 { elog(WARN,"CREATE TABLE/FOREIGN KEY not yet implemented",NULL); }
742 constraint_elem: AexprConst
743 { $$ = makeConstantList((A_Const *) $1); }
745 { $$ = lcons( makeString("NULL"), NIL); }
749 printf( "ColId is %s\n", $1);
751 $$ = lcons( makeString($1), NIL);
753 | '-' constraint_elem %prec UMINUS
754 { $$ = lcons( makeString( "-"), $2); }
755 | constraint_elem '+' constraint_elem
756 { $$ = nconc( $1, lcons( makeString( "+"), $3)); }
757 | constraint_elem '-' constraint_elem
758 { $$ = nconc( $1, lcons( makeString( "-"), $3)); }
759 | constraint_elem '/' constraint_elem
760 { $$ = nconc( $1, lcons( makeString( "/"), $3)); }
761 | constraint_elem '*' constraint_elem
762 { $$ = nconc( $1, lcons( makeString( "*"), $3)); }
763 | constraint_elem '=' constraint_elem
764 { $$ = nconc( $1, lcons( makeString( "="), $3)); }
765 | constraint_elem '<' constraint_elem
766 { $$ = nconc( $1, lcons( makeString( "<"), $3)); }
767 | constraint_elem '>' constraint_elem
768 { $$ = nconc( $1, lcons( makeString( ">"), $3)); }
769 | ':' constraint_elem
770 { $$ = lcons( makeString( ":"), $2); }
771 | ';' constraint_elem
772 { $$ = lcons( makeString( ";"), $2); }
773 | '|' constraint_elem
774 { $$ = lcons( makeString( "|"), $2); }
775 | constraint_elem TYPECAST Typename
777 $$ = nconc( lcons( makeString( "CAST"), $1), makeList( makeString("AS"), $3, -1));
779 | CAST constraint_elem AS Typename
781 $$ = nconc( lcons( makeString( "CAST"), $2), makeList( makeString("AS"), $4, -1));
783 | '(' constraint_elem ')'
784 { $$ = lappend( lcons( makeString( "("), $2), makeString( ")")); }
785 | name '(' constraint_elem ')'
787 $$ = makeList( makeString($1), makeString("("), -1);
789 $$ = lappend( $$, makeString(")"));
791 | constraint_elem Op constraint_elem
792 { $$ = nconc( $1, lcons( makeString( $2), $3)); }
793 | constraint_elem AND constraint_elem
794 { $$ = nconc( $1, lcons( makeString( "AND"), $3)); }
795 | constraint_elem OR constraint_elem
796 { $$ = nconc( $1, lcons( makeString( "OR"), $3)); }
798 { $$ = lcons( makeString( $1), $2); }
800 { $$ = lappend( $1, makeString( $2)); }
803 key_match: MATCH FULL { $$ = NULL; }
804 | MATCH PARTIAL { $$ = NULL; }
805 | /*EMPTY*/ { $$ = NULL; }
808 key_actions: key_action key_action { $$ = NIL; }
809 | key_action { $$ = NIL; }
810 | /*EMPTY*/ { $$ = NIL; }
813 key_action: ON DELETE key_reference { $$ = NIL; }
814 | ON UPDATE key_reference { $$ = NIL; }
817 key_reference: NO ACTION { $$ = NULL; }
818 | CASCADE { $$ = NULL; }
819 | SET DEFAULT { $$ = NULL; }
820 | SET NULL_P { $$ = NULL; }
824 /*****************************************************************************
827 * CREATE SEQUENCE seqname
829 *****************************************************************************/
831 CreateSeqStmt: CREATE SEQUENCE relation_name OptSeqList
833 CreateSeqStmt *n = makeNode(CreateSeqStmt);
841 OptSeqList OptSeqElem
842 { $$ = lappend($1, $2); }
846 OptSeqElem: IDENT NumConst
848 $$ = makeNode(DefElem);
850 $$->arg = (Node *)$2;
854 $$ = makeNode(DefElem);
856 $$->arg = (Node *)NULL;
861 /*****************************************************************************
867 *****************************************************************************/
869 CreateTrigStmt: CREATE TRIGGER name TriggerActionTime TriggerEvents ON
870 relation_name TriggerForSpec EXECUTE PROCEDURE
871 name '(' TriggerFuncArgs ')'
873 CreateTrigStmt *n = makeNode(CreateTrigStmt);
880 memcpy (n->actions, $5, 4);
885 TriggerActionTime: BEFORE { $$ = TRUE; }
886 | AFTER { $$ = FALSE; }
889 TriggerEvents: TriggerOneEvent
891 char *e = palloc (4);
892 e[0] = $1; e[1] = 0; $$ = e;
894 | TriggerOneEvent OR TriggerOneEvent
896 char *e = palloc (4);
897 e[0] = $1; e[1] = $3; e[2] = 0; $$ = e;
899 | TriggerOneEvent OR TriggerOneEvent OR TriggerOneEvent
901 char *e = palloc (4);
902 e[0] = $1; e[1] = $3; e[2] = $5; e[3] = 0;
907 TriggerOneEvent: INSERT { $$ = 'i'; }
908 | DELETE { $$ = 'd'; }
909 | UPDATE { $$ = 'u'; }
912 TriggerForSpec: FOR name name
914 if ( strcmp ($2, "each") != 0 )
915 elog(WARN,"parser: syntax error near %s",$2);
916 if ( strcmp ($3, "row") == 0 )
918 else if ( strcmp ($3, "statement") == 0 )
921 elog(WARN,"parser: syntax error near %s",$3);
925 TriggerFuncArgs: TriggerFuncArg
926 { $$ = lcons($1, NIL); }
927 | TriggerFuncArgs ',' TriggerFuncArg
928 { $$ = lappend($1, $3); }
929 | /* EMPTY */ { $$ = NIL; }
932 TriggerFuncArg: ICONST
934 char *s = (char *) palloc (256);
935 sprintf (s, "%d", $1);
940 char *s = (char *) palloc (256);
941 sprintf (s, "%g", $1);
944 | Sconst { $$ = $1; }
948 DropTrigStmt: DROP TRIGGER name ON relation_name
950 DropTrigStmt *n = makeNode(DropTrigStmt);
958 /*****************************************************************************
961 * define (type,operator,aggregate)
963 *****************************************************************************/
965 DefineStmt: CREATE def_type def_rest
972 def_rest: def_name definition
974 $$ = makeNode(DefineStmt);
977 printf("def_rest: defname is %s\n", $1);
983 def_type: OPERATOR { $$ = OPERATOR; }
987 printf("def_type: decoding TYPE_P\n");
991 | AGGREGATE { $$ = AGGREGATE; }
994 def_name: PROCEDURE { $$ = "procedure"; }
996 | MathOp { $$ = $1; }
1000 definition: '(' def_list ')' { $$ = $2; }
1003 def_list: def_elem { $$ = lcons($1, NIL); }
1004 | def_list ',' def_elem { $$ = lappend($1, $3); }
1007 def_elem: def_name '=' def_arg
1010 printf("def_elem: decoding %s =\n", $1);
1013 $$ = makeNode(DefElem);
1015 $$->arg = (Node *)$3;
1020 printf("def_elem: decoding %s\n", $1);
1022 $$ = makeNode(DefElem);
1024 $$->arg = (Node *)NULL;
1026 | DEFAULT '=' def_arg
1029 printf("def_elem: decoding DEFAULT =\n");
1032 $$ = makeNode(DefElem);
1033 $$->defname = "default";
1034 $$->arg = (Node *)$3;
1038 def_arg: ColId { $$ = (Node *)makeString($1); }
1039 | all_Op { $$ = (Node *)makeString($1); }
1040 | NumConst { $$ = (Node *)$1; /* already a Value */ }
1041 | Sconst { $$ = (Node *)makeString($1); }
1044 TypeName *n = makeNode(TypeName);
1047 n->arrayBounds = NULL;
1050 | DOUBLE { $$ = (Node *)makeString("double"); }
1054 /*****************************************************************************
1057 * destroy <relname1> [, <relname2> .. <relnameN> ]
1059 *****************************************************************************/
1061 DestroyStmt: DROP TABLE relation_name_list
1063 DestroyStmt *n = makeNode(DestroyStmt);
1065 n->sequence = FALSE;
1068 | DROP SEQUENCE relation_name_list
1070 DestroyStmt *n = makeNode(DestroyStmt);
1078 /*****************************************************************************
1081 * fetch/move [forward | backward] [number | all ] [ in <portalname> ]
1083 *****************************************************************************/
1085 FetchStmt: FETCH opt_direction fetch_how_many opt_portal_name
1087 FetchStmt *n = makeNode(FetchStmt);
1094 | MOVE opt_direction fetch_how_many opt_portal_name
1096 FetchStmt *n = makeNode(FetchStmt);
1105 opt_direction: FORWARD { $$ = FORWARD; }
1106 | BACKWARD { $$ = BACKWARD; }
1107 | /*EMPTY*/ { $$ = FORWARD; /* default */ }
1110 fetch_how_many: Iconst
1112 if ($1 <= 0) elog(WARN,"Please specify nonnegative count for fetch",NULL); }
1113 | ALL { $$ = 0; /* 0 means fetch all tuples*/}
1114 | /*EMPTY*/ { $$ = 1; /*default*/ }
1117 opt_portal_name: IN name { $$ = $2;}
1118 | /*EMPTY*/ { $$ = NULL; }
1122 /*****************************************************************************
1125 * GRANT [privileges] ON [relation_name_list] TO [GROUP] grantee
1127 *****************************************************************************/
1129 GrantStmt: GRANT privileges ON relation_name_list TO grantee opt_with_grant
1131 $$ = (Node*)makeAclStmt($2,$4,$6,'+');
1137 privileges: ALL PRIVILEGES
1139 $$ = aclmakepriv("rwaR",0);
1143 $$ = aclmakepriv("rwaR",0);
1145 | operation_commalist
1151 operation_commalist: operation
1153 $$ = aclmakepriv("",$1);
1155 | operation_commalist ',' operation
1157 $$ = aclmakepriv($1,$3);
1164 $$ = ACL_MODE_RD_CHR;
1168 $$ = ACL_MODE_AP_CHR;
1172 $$ = ACL_MODE_WR_CHR;
1176 $$ = ACL_MODE_WR_CHR;
1180 $$ = ACL_MODE_RU_CHR;
1186 $$ = aclmakeuser("A","");
1190 $$ = aclmakeuser("G",$2);
1194 $$ = aclmakeuser("U",$1);
1198 opt_with_grant: WITH GRANT OPTION
1200 yyerror("WITH GRANT OPTION is not supported. Only relation owners can set privileges");
1206 /*****************************************************************************
1209 * REVOKE [privileges] ON [relation_name] FROM [user]
1211 *****************************************************************************/
1213 RevokeStmt: REVOKE privileges ON relation_name_list FROM grantee
1215 $$ = (Node*)makeAclStmt($2,$4,$6,'-');
1222 /*****************************************************************************
1225 * define [archive] index <indexname> on <relname>
1226 * using <access> "(" (<col> with <op>)+ ")" [with
1229 * [where <qual>] is not supported anymore
1230 *****************************************************************************/
1232 IndexStmt: CREATE index_opt_unique INDEX index_name ON relation_name
1233 access_method_clause '(' index_params ')' opt_with
1235 /* should check that access_method is valid,
1236 etc ... but doesn't */
1237 IndexStmt *n = makeNode(IndexStmt);
1241 n->accessMethod = $7;
1242 n->indexParams = $9;
1243 n->withClause = $11;
1244 n->whereClause = NULL;
1249 index_opt_unique: UNIQUE { $$ = TRUE; }
1250 | /*EMPTY*/ { $$ = FALSE; }
1253 access_method_clause: USING access_method { $$ = $2; }
1254 | /*EMPTY*/ { $$ = "btree"; }
1257 index_params: index_list { $$ = $1; }
1258 | func_index { $$ = lcons($1,NIL); }
1261 index_list: index_list ',' index_elem { $$ = lappend($1, $3); }
1262 | index_elem { $$ = lcons($1, NIL); }
1265 func_index: name '(' name_list ')' opt_type opt_class
1267 $$ = makeNode(IndexElem);
1275 index_elem: attr_name opt_type opt_class
1277 $$ = makeNode(IndexElem);
1285 opt_type: ':' Typename { $$ = $2;}
1286 | FOR Typename { $$ = $2;}
1287 | /*EMPTY*/ { $$ = NULL;}
1290 /* opt_class "WITH class" conflicts with preceeding opt_type
1291 * for Typename of "TIMESTAMP WITH TIME ZONE"
1292 * So, remove "WITH class" from the syntax. OK??
1293 * - thomas 1997-10-12
1294 * | WITH class { $$ = $2; }
1296 opt_class: class { $$ = $1; }
1297 | USING class { $$ = $2; }
1298 | /*EMPTY*/ { $$ = NULL; }
1302 /*****************************************************************************
1305 * extend index <indexname> [where <qual>]
1307 *****************************************************************************/
1309 ExtendStmt: EXTEND INDEX index_name where_clause
1311 ExtendStmt *n = makeNode(ExtendStmt);
1313 n->whereClause = $4;
1319 /*****************************************************************************
1322 * execute recipe <recipeName>
1324 *****************************************************************************/
1326 RecipeStmt: EXECUTE RECIPE recipe_name
1329 if (!IsTransactionBlock())
1330 elog(WARN,"EXECUTE RECIPE may only be used in begin/end transaction blocks",NULL);
1332 n = makeNode(RecipeStmt);
1339 /*****************************************************************************
1342 * define function <fname>
1343 * (language = <lang>, returntype = <typename>
1344 * [, arch_pct = <percentage | pre-defined>]
1345 * [, disk_pct = <percentage | pre-defined>]
1346 * [, byte_pct = <percentage | pre-defined>]
1347 * [, perbyte_cpu = <int | pre-defined>]
1348 * [, percall_cpu = <int | pre-defined>]
1350 * [arg is (<type-1> { , <type-n>})]
1351 * as <filename or code in language as appropriate>
1353 *****************************************************************************/
1355 ProcedureStmt: CREATE FUNCTION def_name def_args
1356 RETURNS def_arg opt_with AS Sconst LANGUAGE Sconst
1358 ProcedureStmt *n = makeNode(ProcedureStmt);
1361 n->returnType = (Node *)$6;
1368 opt_with: WITH definition { $$ = $2; }
1369 | /* EMPTY */ { $$ = NIL; }
1372 def_args: '(' def_name_list ')' { $$ = $2; }
1373 | '(' ')' { $$ = NIL; }
1376 def_name_list: name_list;
1379 /*****************************************************************************
1382 * purge <relname> [before <date>] [after <date>]
1384 * purge <relname> [after <date>] [before <date>]
1386 *****************************************************************************/
1388 PurgeStmt: PURGE relation_name purge_quals
1395 purge_quals: before_clause
1397 $$ = makeNode(PurgeStmt);
1398 $$->beforeDate = $1;
1399 $$->afterDate = NULL;
1403 $$ = makeNode(PurgeStmt);
1404 $$->beforeDate = NULL;
1407 | before_clause after_clause
1409 $$ = makeNode(PurgeStmt);
1410 $$->beforeDate = $1;
1413 | after_clause before_clause
1415 $$ = makeNode(PurgeStmt);
1416 $$->beforeDate = $2;
1421 $$ = makeNode(PurgeStmt);
1422 $$->beforeDate = NULL;
1423 $$->afterDate = NULL;
1427 before_clause: BEFORE date { $$ = $2; }
1428 after_clause: AFTER date { $$ = $2; }
1431 /*****************************************************************************
1435 * remove function <funcname>
1436 * (REMOVE FUNCTION "funcname" (arg1, arg2, ...))
1437 * remove aggregate <aggname>
1438 * (REMOVE AGGREGATE "aggname" "aggtype")
1439 * remove operator <opname>
1440 * (REMOVE OPERATOR "opname" (leftoperand_typ rightoperand_typ))
1441 * remove type <typename>
1442 * (REMOVE TYPE "typename")
1443 * remove rule <rulename>
1444 * (REMOVE RULE "rulename")
1446 *****************************************************************************/
1448 RemoveStmt: DROP remove_type name
1450 RemoveStmt *n = makeNode(RemoveStmt);
1457 remove_type: Type { $$ = TYPE_P; }
1458 | INDEX { $$ = INDEX; }
1459 | RULE { $$ = RULE; }
1460 | VIEW { $$ = VIEW; }
1463 RemoveAggrStmt: DROP AGGREGATE name aggr_argtype
1465 RemoveAggrStmt *n = makeNode(RemoveAggrStmt);
1472 aggr_argtype: name { $$ = $1; }
1473 | '*' { $$ = NULL; }
1476 RemoveFuncStmt: DROP FUNCTION name '(' func_argtypes ')'
1478 RemoveFuncStmt *n = makeNode(RemoveFuncStmt);
1485 func_argtypes: name_list { $$ = $1; }
1486 | /*EMPTY*/ { $$ = NIL; }
1489 RemoveOperStmt: DROP OPERATOR all_Op '(' oper_argtypes ')'
1491 RemoveOperStmt *n = makeNode(RemoveOperStmt);
1498 all_Op: Op | MathOp;
1500 MathOp: '+' { $$ = "+"; }
1511 elog(WARN,"parser: argument type missing (use NONE for unary operators)",NULL);
1514 { $$ = makeList(makeString($1), makeString($3), -1); }
1515 | NONE ',' name /* left unary */
1516 { $$ = makeList(NULL, makeString($3), -1); }
1517 | name ',' NONE /* right unary */
1518 { $$ = makeList(makeString($1), NULL, -1); }
1522 /*****************************************************************************
1525 * rename <attrname1> in <relname> [*] to <attrname2>
1526 * rename <relname1> to <relname2>
1528 *****************************************************************************/
1530 RenameStmt: ALTER TABLE relation_name opt_inh_star
1531 RENAME opt_column opt_name TO name
1533 RenameStmt *n = makeNode(RenameStmt);
1542 opt_name: name { $$ = $1; }
1543 | /*EMPTY*/ { $$ = NULL; }
1546 opt_column: COLUMN { $$ = COLUMN; }
1547 | /*EMPTY*/ { $$ = 0; }
1551 /*****************************************************************************
1553 * QUERY: Define Rewrite Rule , Define Tuple Rule
1554 * Define Rule <old rules >
1556 * only rewrite rule is supported -- ay 9/94
1558 *****************************************************************************/
1560 RuleStmt: CREATE RULE name AS
1561 { QueryIsRule=TRUE; }
1562 ON event TO event_object where_clause
1563 DO opt_instead OptStmtList
1565 RuleStmt *n = makeNode(RuleStmt);
1569 n->whereClause = $10;
1576 OptStmtList: NOTHING { $$ = NIL; }
1577 | OptimizableStmt { $$ = lcons($1, NIL); }
1578 | '[' OptStmtBlock ']' { $$ = $2; }
1581 OptStmtBlock: OptStmtMulti
1584 { $$ = lcons($1, NIL); }
1587 OptStmtMulti: OptStmtMulti OptimizableStmt ';'
1588 { $$ = lappend($1, $2); }
1589 | OptStmtMulti OptimizableStmt
1590 { $$ = lappend($1, $2); }
1591 | OptimizableStmt ';'
1592 { $$ = lcons($1, NIL); }
1595 event_object: relation_name '.' attr_name
1597 $$ = makeNode(Attr);
1600 $$->attrs = lcons(makeString($3), NIL);
1601 $$->indirection = NIL;
1605 $$ = makeNode(Attr);
1609 $$->indirection = NIL;
1613 /* change me to select, update, etc. some day */
1614 event: SELECT { $$ = CMD_SELECT; }
1615 | UPDATE { $$ = CMD_UPDATE; }
1616 | DELETE { $$ = CMD_DELETE; }
1617 | INSERT { $$ = CMD_INSERT; }
1620 opt_instead: INSTEAD { $$ = TRUE; }
1621 | /* EMPTY */ { $$ = FALSE; }
1625 /*****************************************************************************
1628 * NOTIFY <relation_name> can appear both in rule bodies and
1629 * as a query-level command
1631 *****************************************************************************/
1633 NotifyStmt: NOTIFY relation_name
1635 NotifyStmt *n = makeNode(NotifyStmt);
1641 ListenStmt: LISTEN relation_name
1643 ListenStmt *n = makeNode(ListenStmt);
1650 /*****************************************************************************
1661 *****************************************************************************/
1663 TransactionStmt: ABORT_TRANS TRANSACTION
1665 TransactionStmt *n = makeNode(TransactionStmt);
1666 n->command = ABORT_TRANS;
1669 | BEGIN_TRANS TRANSACTION
1671 TransactionStmt *n = makeNode(TransactionStmt);
1672 n->command = BEGIN_TRANS;
1677 TransactionStmt *n = makeNode(TransactionStmt);
1678 n->command = BEGIN_TRANS;
1683 TransactionStmt *n = makeNode(TransactionStmt);
1684 n->command = END_TRANS;
1687 | END_TRANS TRANSACTION
1689 TransactionStmt *n = makeNode(TransactionStmt);
1690 n->command = END_TRANS;
1695 TransactionStmt *n = makeNode(TransactionStmt);
1696 n->command = ABORT_TRANS;
1702 TransactionStmt *n = makeNode(TransactionStmt);
1703 n->command = ABORT_TRANS;
1708 TransactionStmt *n = makeNode(TransactionStmt);
1709 n->command = BEGIN_TRANS;
1714 TransactionStmt *n = makeNode(TransactionStmt);
1715 n->command = END_TRANS;
1721 TransactionStmt *n = makeNode(TransactionStmt);
1722 n->command = END_TRANS;
1727 TransactionStmt *n = makeNode(TransactionStmt);
1728 n->command = ABORT_TRANS;
1734 /*****************************************************************************
1737 * define view <viewname> '('target-list ')' [where <quals> ]
1739 *****************************************************************************/
1741 ViewStmt: CREATE VIEW name AS RetrieveStmt
1743 ViewStmt *n = makeNode(ViewStmt);
1745 n->query = (Query *)$5;
1751 /*****************************************************************************
1756 *****************************************************************************/
1758 LoadStmt: LOAD file_name
1760 LoadStmt *n = makeNode(LoadStmt);
1767 /*****************************************************************************
1772 *****************************************************************************/
1774 CreatedbStmt: CREATE DATABASE database_name
1776 CreatedbStmt *n = makeNode(CreatedbStmt);
1783 /*****************************************************************************
1788 *****************************************************************************/
1790 DestroydbStmt: DROP DATABASE database_name
1792 DestroydbStmt *n = makeNode(DestroydbStmt);
1799 /*****************************************************************************
1802 * cluster <index_name> on <relation_name>
1804 *****************************************************************************/
1806 ClusterStmt: CLUSTER index_name ON relation_name
1808 ClusterStmt *n = makeNode(ClusterStmt);
1816 /*****************************************************************************
1821 *****************************************************************************/
1823 VacuumStmt: VACUUM opt_verbose opt_analyze
1825 VacuumStmt *n = makeNode(VacuumStmt);
1832 | VACUUM opt_verbose relation_name opt_analyze opt_va_list
1834 VacuumStmt *n = makeNode(VacuumStmt);
1839 if ( $5 != NIL && !$4 )
1840 elog(WARN,"parser: syntax error at or near \"(\"",NULL);
1845 opt_verbose: VERBOSE { $$ = TRUE; }
1846 | /* EMPTY */ { $$ = FALSE; }
1849 opt_analyze: ANALYZE { $$ = TRUE; }
1850 | /* EMPTY */ { $$ = FALSE; }
1853 opt_va_list: '(' va_list ')'
1860 { $$=lcons($1,NIL); }
1862 { $$=lappend($1,$3); }
1866 /*****************************************************************************
1871 *****************************************************************************/
1873 ExplainStmt: EXPLAIN opt_verbose OptimizableStmt
1875 ExplainStmt *n = makeNode(ExplainStmt);
1877 n->query = (Query*)$3;
1883 /*****************************************************************************
1885 * Optimizable Stmts: *
1887 * one of the five queries processed by the planner *
1889 * [ultimately] produces query-trees as specified *
1890 * in the query-spec document in ~postgres/ref *
1892 *****************************************************************************/
1894 OptimizableStmt: RetrieveStmt
1899 | DeleteStmt /* by default all are $$=$1 */
1903 /*****************************************************************************
1908 *****************************************************************************/
1910 AppendStmt: INSERT INTO relation_name opt_column_list insert_rest
1918 insert_rest: VALUES '(' res_target_list2 ')'
1920 $$ = makeNode(AppendStmt);
1921 $$->targetList = $3;
1922 $$->fromClause = NIL;
1923 $$->whereClause = NULL;
1925 | SELECT res_target_list2 from_clause where_clause
1927 $$ = makeNode(AppendStmt);
1928 $$->targetList = $2;
1929 $$->fromClause = $3;
1930 $$->whereClause = $4;
1934 opt_column_list: '(' columnList ')' { $$ = $2; }
1935 | /*EMPTY*/ { $$ = NIL; }
1939 columnList ',' columnElem
1940 { $$ = lappend($1, $3); }
1942 { $$ = lcons($1, NIL); }
1945 columnElem: ColId opt_indirection
1947 Ident *id = makeNode(Ident);
1949 id->indirection = $2;
1955 /*****************************************************************************
1960 *****************************************************************************/
1962 DeleteStmt: DELETE FROM relation_name
1965 DeleteStmt *n = makeNode(DeleteStmt);
1967 n->whereClause = $4;
1973 /*****************************************************************************
1976 * ReplaceStmt (UPDATE)
1978 *****************************************************************************/
1980 ReplaceStmt: UPDATE relation_name
1985 ReplaceStmt *n = makeNode(ReplaceStmt);
1989 n->whereClause = $6;
1995 /*****************************************************************************
2000 *****************************************************************************/
2002 CursorStmt: DECLARE name opt_binary CURSOR FOR
2003 SELECT opt_unique res_target_list2
2004 from_clause where_clause group_clause sort_clause
2006 CursorStmt *n = makeNode(CursorStmt);
2008 /* from PORTAL name */
2010 * 15 august 1991 -- since 3.0 postgres does locking
2011 * right, we discovered that portals were violating
2012 * locking protocol. portal locks cannot span xacts.
2013 * as a short-term fix, we installed the check here.
2016 if (!IsTransactionBlock())
2017 elog(WARN,"Named portals may only be used in begin/end transaction blocks",NULL);
2024 n->whereClause = $10;
2025 n->groupClause = $11;
2026 n->sortClause = $12;
2032 /*****************************************************************************
2037 *****************************************************************************/
2039 RetrieveStmt: SELECT opt_unique res_target_list2
2040 result from_clause where_clause
2041 group_clause having_clause
2042 union_clause sort_clause
2044 RetrieveStmt *n = makeNode(RetrieveStmt);
2049 n->whereClause = $6;
2050 n->groupClause = $7;
2051 n->havingClause = $8;
2052 n->selectClause = $9;
2053 n->sortClause = $10;
2058 union_clause: UNION select_list { $$ = $2; }
2059 | /*EMPTY*/ { $$ = NIL; }
2062 select_list: select_list UNION SubSelect
2063 { $$ = lappend($1, $3); }
2065 { $$ = lcons($1, NIL); }
2068 SubSelect: SELECT opt_unique res_target_list2
2069 result from_clause where_clause
2070 group_clause having_clause
2072 SubSelect *n = makeNode(SubSelect);
2076 n->whereClause = $6;
2077 n->groupClause = $7;
2078 n->havingClause = $8;
2083 result: INTO TABLE relation_name
2084 { $$= $3; /* should check for archive level */ }
2089 opt_unique: DISTINCT { $$ = "*"; }
2090 | DISTINCT ON ColId { $$ = $3; }
2091 | /*EMPTY*/ { $$ = NULL;}
2094 sort_clause: ORDER BY sortby_list { $$ = $3; }
2095 | /*EMPTY*/ { $$ = NIL; }
2098 sortby_list: sortby { $$ = lcons($1, NIL); }
2099 | sortby_list ',' sortby { $$ = lappend($1, $3); }
2102 sortby: ColId OptUseOp
2104 $$ = makeNode(SortGroupBy);
2110 | ColId '.' ColId OptUseOp
2112 $$ = makeNode(SortGroupBy);
2120 $$ = makeNode(SortGroupBy);
2128 OptUseOp: USING Op { $$ = $2; }
2129 | USING '<' { $$ = "<"; }
2130 | USING '>' { $$ = ">"; }
2132 | DESC { $$ = ">"; }
2133 | /*EMPTY*/ { $$ = "<"; /*default*/ }
2137 * jimmy bell-style recursive queries aren't supported in the
2140 * ...however, recursive addattr and rename supported. make special
2143 * XXX i believe '*' should be the default behavior, but...
2145 opt_inh_star: '*' { $$ = TRUE; }
2146 | /*EMPTY*/ { $$ = FALSE; }
2149 relation_name_list: name_list;
2152 { $$ = lcons(makeString($1),NIL); }
2153 | name_list ',' name
2154 { $$ = lappend($1,makeString($3)); }
2157 group_clause: GROUP BY groupby_list { $$ = $3; }
2158 | /*EMPTY*/ { $$ = NIL; }
2161 groupby_list: groupby { $$ = lcons($1, NIL); }
2162 | groupby_list ',' groupby { $$ = lappend($1, $3); }
2167 $$ = makeNode(SortGroupBy);
2175 $$ = makeNode(SortGroupBy);
2183 $$ = makeNode(SortGroupBy);
2191 having_clause: HAVING a_expr { $$ = $2; }
2192 | /*EMPTY*/ { $$ = NULL; }
2196 /*****************************************************************************
2198 * clauses common to all Optimizable Stmts:
2202 *****************************************************************************/
2204 from_clause: FROM '(' relation_expr join_expr JOIN relation_expr join_spec ')'
2207 elog(WARN,"JOIN not yet implemented",NULL);
2209 | FROM from_list { $$ = $2; }
2210 | /*EMPTY*/ { $$ = NIL; }
2213 from_list: from_list ',' from_val
2214 { $$ = lappend($1, $3); }
2215 | from_val CROSS JOIN from_val
2216 { elog(WARN,"CROSS JOIN not yet implemented",NULL); }
2218 { $$ = lcons($1, NIL); }
2221 from_val: relation_expr AS ColLabel
2223 $$ = makeNode(RangeVar);
2227 | relation_expr ColId
2229 $$ = makeNode(RangeVar);
2235 $$ = makeNode(RangeVar);
2241 join_expr: NATURAL join_expr { $$ = NULL; }
2243 { elog(WARN,"FULL OUTER JOIN not yet implemented",NULL); }
2245 { elog(WARN,"LEFT OUTER JOIN not yet implemented",NULL); }
2247 { elog(WARN,"RIGHT OUTER JOIN not yet implemented",NULL); }
2249 { elog(WARN,"OUTER JOIN not yet implemented",NULL); }
2251 { elog(WARN,"INNER JOIN not yet implemented",NULL); }
2253 { elog(WARN,"UNION JOIN not yet implemented",NULL); }
2255 { elog(WARN,"INNER JOIN not yet implemented",NULL); }
2258 join_outer: OUTER_P { $$ = NULL; }
2259 | /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
2262 join_spec: ON '(' a_expr ')' { $$ = NULL; }
2263 | USING '(' join_list ')' { $$ = NULL; }
2264 | /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
2267 join_list: join_using { $$ = lcons($1, NIL); }
2268 | join_list ',' join_using { $$ = lappend($1, $3); }
2273 $$ = makeNode(SortGroupBy);
2281 $$ = makeNode(SortGroupBy);
2289 $$ = makeNode(SortGroupBy);
2297 where_clause: WHERE a_expr { $$ = $2; }
2298 | /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
2301 relation_expr: relation_name
2303 /* normal relations */
2304 $$ = makeNode(RelExpr);
2307 $$->timeRange = NULL;
2309 | relation_name '*' %prec '='
2311 /* inheiritance query */
2312 $$ = makeNode(RelExpr);
2315 $$->timeRange = NULL;
2317 | relation_name time_range
2319 /* time-qualified query */
2320 $$ = makeNode(RelExpr);
2328 * Range specification clause.
2330 time_range: '[' opt_range_start ',' opt_range_end ']'
2332 $$ = makeNode(TimeRange);
2338 $$ = makeNode(TimeRange);
2344 opt_range_start: date
2345 | /*EMPTY*/ { $$ = "epoch"; }
2349 | /*EMPTY*/ { $$ = "now"; }
2352 opt_array_bounds: '[' ']' nest_array_bounds
2353 { $$ = lcons(makeInteger(-1), $3); }
2354 | '[' Iconst ']' nest_array_bounds
2355 { $$ = lcons(makeInteger($2), $4); }
2360 nest_array_bounds: '[' ']' nest_array_bounds
2361 { $$ = lcons(makeInteger(-1), $3); }
2362 | '[' Iconst ']' nest_array_bounds
2363 { $$ = lcons(makeInteger($2), $4); }
2369 /*****************************************************************************
2372 * SQL92 introduces a large amount of type-specific syntax.
2373 * Define individual clauses to handle these cases, and use
2374 * the generic case to handle regular type-extensible Postgres syntax.
2375 * - thomas 1997-10-10
2377 *****************************************************************************/
2379 Typename: Array opt_array_bounds
2382 $$->arrayBounds = $2;
2384 /* Is this the name of a complex type? If so, implement
2387 if (!strcmp(saved_relname, $$->name))
2388 /* This attr is the same type as the relation
2389 * being defined. The classic example: create
2390 * emp(name=text,mgr=emp)
2393 else if (get_typrelid((Type)type($$->name)) != InvalidOid)
2394 /* (Eventually add in here that the set can only
2395 * contain one element.)
2416 $$ = makeNode(TypeName);
2417 $$->name = xlateSqlType($1);
2421 generic: Id { $$ = $1; }
2422 | TYPE_P { $$ = xlateSqlType("type"); }
2423 | DOUBLE PRECISION { $$ = xlateSqlType("float8"); }
2426 /* SQL92 numeric data types
2427 * Check FLOAT() precision limits assuming IEEE floating types.
2428 * Provide rudimentary DECIMAL() and NUMERIC() implementations
2429 * by checking parameters and making sure they match what is possible with INTEGER.
2430 * - thomas 1997-09-18
2432 Numeric: FLOAT opt_float
2434 $$ = makeNode(TypeName);
2435 $$->name = xlateSqlType($2);
2437 | DECIMAL opt_decimal
2439 $$ = makeNode(TypeName);
2440 $$->name = xlateSqlType("integer");
2442 | NUMERIC opt_numeric
2444 $$ = makeNode(TypeName);
2445 $$->name = xlateSqlType("integer");
2449 opt_float: '(' Iconst ')'
2452 elog(WARN,"precision for FLOAT must be at least 1",NULL);
2454 $$ = xlateSqlType("float4");
2456 $$ = xlateSqlType("float8");
2458 elog(WARN,"precision for FLOAT must be less than 16",NULL);
2462 $$ = xlateSqlType("float8");
2466 opt_numeric: '(' Iconst ',' Iconst ')'
2469 elog(WARN,"NUMERIC precision %d must be 9",$2);
2471 elog(WARN,"NUMERIC scale %d must be zero",$4);
2476 elog(WARN,"NUMERIC precision %d must be 9",$2);
2484 opt_decimal: '(' Iconst ',' Iconst ')'
2487 elog(WARN,"DECIMAL precision %d exceeds implementation limit of 9",$2);
2489 elog(WARN,"DECIMAL scale %d must be zero",$4);
2495 elog(WARN,"DECIMAL precision %d exceeds implementation limit of 9",$2);
2504 /* SQL92 character data types
2505 * The following implements CHAR() and VARCHAR().
2506 * We do it here instead of the 'Generic' production
2507 * because we don't want to allow arrays of VARCHAR().
2508 * I haven't thought about whether that will work or not.
2511 Character: character '(' Iconst ')'
2513 $$ = makeNode(TypeName);
2514 if (!strcasecmp($1, "char"))
2515 $$->name = xlateSqlType("bpchar");
2516 else if (!strcasecmp($1, "varchar"))
2517 $$->name = xlateSqlType("varchar");
2519 yyerror("parse error");
2521 elog(WARN,"length for '%s' type must be at least 1",$1);
2523 /* we can store a char() of length up to the size
2524 * of a page (8KB) - page headers and friends but
2525 * just to be safe here... - ay 6/95
2526 * XXX note this hardcoded limit - thomas 1997-07-13
2528 elog(WARN,"length for type '%s' cannot exceed 4096",$1);
2530 /* we actually implement this sort of like a varlen, so
2531 * the first 4 bytes is the length. (the difference
2532 * between this and "text" is that we blank-pad and
2533 * truncate where necessary
2535 $$->typlen = 4 + $3;
2539 $$ = makeNode(TypeName);
2540 $$->name = xlateSqlType($1);
2544 character: CHARACTER opt_varying opt_charset opt_collate
2547 if (($3 == NULL) || (strcasecmp($3, "sql_text") == 0)) {
2548 if ($2) type = xlateSqlType("varchar");
2549 else type = xlateSqlType("char");
2552 c = palloc(strlen("var") + strlen($3) + 1);
2555 type = xlateSqlType(c);
2557 type = xlateSqlType($3);
2561 elog(WARN,"COLLATE %s not yet implemented",$4);
2564 | CHAR opt_varying { $$ = xlateSqlType($2? "varchar": "char"); }
2565 | VARCHAR { $$ = xlateSqlType("varchar"); }
2566 | NATIONAL CHARACTER opt_varying { $$ = xlateSqlType($3? "varchar": "char"); }
2567 | NCHAR opt_varying { $$ = xlateSqlType($2? "varchar": "char"); }
2570 opt_varying: VARYING { $$ = TRUE; }
2571 | /*EMPTY*/ { $$ = FALSE; }
2574 opt_charset: CHARACTER SET ColId { $$ = $3; }
2575 | /*EMPTY*/ { $$ = NULL; }
2578 opt_collate: COLLATE ColId { $$ = $2; }
2579 | /*EMPTY*/ { $$ = NULL; }
2584 $$ = makeNode(TypeName);
2585 $$->name = xlateSqlType($1);
2587 | TIMESTAMP opt_timezone
2589 $$ = makeNode(TypeName);
2590 $$->name = xlateSqlType("timestamp");
2595 $$ = makeNode(TypeName);
2596 $$->name = xlateSqlType("time");
2598 | INTERVAL opt_interval
2600 $$ = makeNode(TypeName);
2601 $$->name = xlateSqlType("interval");
2605 datetime: YEAR_P { $$ = "year"; }
2606 | MONTH_P { $$ = "month"; }
2607 | DAY_P { $$ = "day"; }
2608 | HOUR_P { $$ = "hour"; }
2609 | MINUTE_P { $$ = "minute"; }
2610 | SECOND_P { $$ = "second"; }
2613 opt_timezone: WITH TIME ZONE { $$ = TRUE; }
2614 | /*EMPTY*/ { $$ = FALSE; }
2617 opt_interval: datetime { $$ = lcons($1, NIL); }
2618 | YEAR_P TO MONTH_P { $$ = NIL; }
2619 | DAY_P TO HOUR_P { $$ = NIL; }
2620 | DAY_P TO MINUTE_P { $$ = NIL; }
2621 | DAY_P TO SECOND_P { $$ = NIL; }
2622 | HOUR_P TO MINUTE_P { $$ = NIL; }
2623 | HOUR_P TO SECOND_P { $$ = NIL; }
2624 | /* EMPTY */ { $$ = NIL; }
2628 /*****************************************************************************
2630 * expression grammar, still needs some cleanup
2632 *****************************************************************************/
2634 a_expr_or_null: a_expr
2638 A_Const *n = makeNode(A_Const);
2639 n->val.type = T_Null;
2643 a_expr: attr opt_indirection
2645 $1->indirection = $2;
2650 | '-' a_expr %prec UMINUS
2651 { $$ = makeA_Expr(OP, "-", NULL, $2); }
2653 { $$ = makeA_Expr(OP, "+", $1, $3); }
2655 { $$ = makeA_Expr(OP, "-", $1, $3); }
2657 { $$ = makeA_Expr(OP, "/", $1, $3); }
2659 { $$ = makeA_Expr(OP, "*", $1, $3); }
2661 { $$ = makeA_Expr(OP, "<", $1, $3); }
2663 { $$ = makeA_Expr(OP, ">", $1, $3); }
2665 { $$ = makeA_Expr(OP, "=", $1, $3); }
2667 { $$ = makeA_Expr(OP, ":", NULL, $2); }
2669 { $$ = makeA_Expr(OP, ";", NULL, $2); }
2671 { $$ = makeA_Expr(OP, "|", NULL, $2); }
2672 | AexprConst TYPECAST Typename
2674 /* AexprConst can be either A_Const or ParamNo */
2675 if (nodeTag($1) == T_A_Const)
2676 ((A_Const *)$1)->typename = $3;
2678 ((ParamNo *)$1)->typename = $3;
2681 | CAST a_expr AS Typename
2684 /* AexprConst can be either A_Const or ParamNo */
2685 if (nodeTag($2) == T_A_Const) {
2686 ((A_Const *)$2)->typename = $4;
2687 } else if (nodeTag($2) == T_Param) {
2688 ((ParamNo *)$2)->typename = $4;
2689 /* otherwise, try to transform to a function call */
2691 FuncCall *n = makeNode(FuncCall);
2692 n->funcname = $4->name;
2693 n->args = lcons($2,NIL);
2697 | '(' a_expr_or_null ')'
2700 { $$ = makeA_Expr(OP, $2, $1, $3); }
2701 | a_expr LIKE a_expr
2702 { $$ = makeA_Expr(OP, "~~", $1, $3); }
2703 | a_expr NOT LIKE a_expr
2704 { $$ = makeA_Expr(OP, "!~~", $1, $4); }
2706 { $$ = makeA_Expr(OP, $1, NULL, $2); }
2708 { $$ = makeA_Expr(OP, $2, $1, NULL); }
2711 /* could be a column name or a relation_name */
2712 Ident *n = makeNode(Ident);
2714 n->indirection = NULL;
2719 FuncCall *n = makeNode(FuncCall);
2720 Ident *star = makeNode(Ident);
2722 /* cheap hack for aggregate (eg. count) */
2725 n->args = lcons(star, NIL);
2730 FuncCall *n = makeNode(FuncCall);
2737 A_Const *n = makeNode(A_Const);
2738 TypeName *t = makeNode(TypeName);
2740 n->val.type = T_String;
2741 n->val.val.str = "now";
2744 t->name = xlateSqlType("date");
2751 A_Const *n = makeNode(A_Const);
2752 TypeName *t = makeNode(TypeName);
2754 n->val.type = T_String;
2755 n->val.val.str = "now";
2758 t->name = xlateSqlType("time");
2763 | CURRENT_TIME '(' Iconst ')'
2765 FuncCall *n = makeNode(FuncCall);
2766 A_Const *s = makeNode(A_Const);
2767 TypeName *t = makeNode(TypeName);
2769 n->funcname = xlateSqlType("time");
2770 n->args = lcons(s, NIL);
2772 s->val.type = T_String;
2773 s->val.val.str = "now";
2776 t->name = xlateSqlType("time");
2780 elog(NOTICE,"CURRENT_TIME(p) precision must be zero",NULL);
2786 A_Const *n = makeNode(A_Const);
2787 TypeName *t = makeNode(TypeName);
2789 n->val.type = T_String;
2790 n->val.val.str = "now";
2793 t->name = xlateSqlType("timestamp");
2798 | CURRENT_TIMESTAMP '(' Iconst ')'
2800 FuncCall *n = makeNode(FuncCall);
2801 A_Const *s = makeNode(A_Const);
2802 TypeName *t = makeNode(TypeName);
2804 n->funcname = xlateSqlType("timestamp");
2805 n->args = lcons(s, NIL);
2807 s->val.type = T_String;
2808 s->val.val.str = "now";
2811 t->name = xlateSqlType("timestamp");
2815 elog(NOTICE,"CURRENT_TIMESTAMP(p) precision must be zero",NULL);
2821 FuncCall *n = makeNode(FuncCall);
2822 n->funcname = "getpgusername";
2826 /* We probably need to define an "exists" node,
2827 * since the optimizer could choose to find only one match.
2828 * Perhaps the first implementation could just check for
2829 * count(*) > 0? - thomas 1997-07-19
2831 | EXISTS '(' SubSelect ')'
2833 elog(WARN,"EXISTS not yet implemented",NULL);
2836 | EXTRACT '(' extract_list ')'
2838 FuncCall *n = makeNode(FuncCall);
2839 n->funcname = "date_part";
2843 | POSITION '(' position_list ')'
2845 FuncCall *n = makeNode(FuncCall);
2846 n->funcname = "strpos";
2850 | SUBSTRING '(' substr_list ')'
2852 FuncCall *n = makeNode(FuncCall);
2853 n->funcname = "substr";
2857 /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
2858 | TRIM '(' BOTH trim_list ')'
2860 FuncCall *n = makeNode(FuncCall);
2861 n->funcname = "btrim";
2865 | TRIM '(' LEADING trim_list ')'
2867 FuncCall *n = makeNode(FuncCall);
2868 n->funcname = "ltrim";
2872 | TRIM '(' TRAILING trim_list ')'
2874 FuncCall *n = makeNode(FuncCall);
2875 n->funcname = "rtrim";
2879 | TRIM '(' trim_list ')'
2881 FuncCall *n = makeNode(FuncCall);
2882 n->funcname = "btrim";
2886 | name '(' expr_list ')'
2888 FuncCall *n = makeNode(FuncCall);
2894 { $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
2896 { $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
2898 { $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); }
2899 | a_expr IS NOT NULL_P
2900 { $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); }
2903 A_Const *n = makeNode(A_Const);
2904 n->val.type = T_String;
2905 n->val.val.str = "t";
2906 $$ = makeA_Expr(OP, "=", $1, (Node *)n);
2910 A_Const *n = makeNode(A_Const);
2911 n->val.type = T_String;
2912 n->val.val.str = "f";
2913 $$ = makeA_Expr(OP, "=", $1, (Node *)n);
2915 | a_expr IS NOT TRUE_P
2917 A_Const *n = makeNode(A_Const);
2918 n->val.type = T_String;
2919 n->val.val.str = "f";
2920 $$ = makeA_Expr(OP, "=", $1, (Node *)n);
2922 | a_expr IS NOT FALSE_P
2924 A_Const *n = makeNode(A_Const);
2925 n->val.type = T_String;
2926 n->val.val.str = "t";
2927 $$ = makeA_Expr(OP, "=", $1, (Node *)n);
2929 | a_expr BETWEEN AexprConst AND AexprConst
2931 $$ = makeA_Expr(AND, NULL,
2932 makeA_Expr(OP, ">=", $1, $3),
2933 makeA_Expr(OP, "<=", $1, $5));
2935 | a_expr NOT BETWEEN AexprConst AND AexprConst
2937 $$ = makeA_Expr(OR, NULL,
2938 makeA_Expr(OP, "<", $1, $4),
2939 makeA_Expr(OP, ">", $1, $6));
2941 | a_expr IN { saved_In_Expr = $1; } '(' in_expr ')'
2943 | a_expr NOT IN { saved_In_Expr = $1; } '(' not_in_expr ')'
2946 { $$ = makeA_Expr(AND, NULL, $1, $3); }
2948 { $$ = makeA_Expr(OR, NULL, $1, $3); }
2950 { $$ = makeA_Expr(NOT, NULL, NULL, $2); }
2953 opt_indirection: '[' a_expr ']' opt_indirection
2955 A_Indices *ai = makeNode(A_Indices);
2960 | '[' a_expr ':' a_expr ']' opt_indirection
2962 A_Indices *ai = makeNode(A_Indices);
2971 expr_list: a_expr_or_null
2972 { $$ = lcons($1, NIL); }
2973 | expr_list ',' a_expr_or_null
2974 { $$ = lappend($1, $3); }
2975 | expr_list USING a_expr
2976 { $$ = lappend($1, $3); }
2979 extract_list: datetime FROM a_expr
2981 A_Const *n = makeNode(A_Const);
2982 n->val.type = T_String;
2983 n->val.val.str = $1;
2985 printf( "string is %s\n", $1);
2987 $$ = lappend(lcons((Node *)n,NIL), $3);
2993 position_list: position_expr IN position_expr
2994 { $$ = makeList($3, $1, -1); }
2999 position_expr: attr opt_indirection
3001 $1->indirection = $2;
3006 | '-' position_expr %prec UMINUS
3007 { $$ = makeA_Expr(OP, "-", NULL, $2); }
3008 | position_expr '+' position_expr
3009 { $$ = makeA_Expr(OP, "+", $1, $3); }
3010 | position_expr '-' position_expr
3011 { $$ = makeA_Expr(OP, "-", $1, $3); }
3012 | position_expr '/' position_expr
3013 { $$ = makeA_Expr(OP, "/", $1, $3); }
3014 | position_expr '*' position_expr
3015 { $$ = makeA_Expr(OP, "*", $1, $3); }
3017 { $$ = makeA_Expr(OP, "|", NULL, $2); }
3018 | AexprConst TYPECAST Typename
3020 /* AexprConst can be either A_Const or ParamNo */
3021 if (nodeTag($1) == T_A_Const)
3022 ((A_Const *)$1)->typename = $3;
3024 ((ParamNo *)$1)->typename = $3;
3027 | CAST position_expr AS Typename
3030 /* AexprConst can be either A_Const or ParamNo */
3031 if (nodeTag($2) == T_A_Const) {
3032 ((A_Const *)$2)->typename = $4;
3033 } else if (nodeTag($2) == T_Param) {
3034 ((ParamNo *)$2)->typename = $4;
3035 /* otherwise, try to transform to a function call */
3037 FuncCall *n = makeNode(FuncCall);
3038 n->funcname = $4->name;
3039 n->args = lcons($2,NIL);
3043 | '(' position_expr ')'
3045 | position_expr Op position_expr
3046 { $$ = makeA_Expr(OP, $2, $1, $3); }
3048 { $$ = makeA_Expr(OP, $1, NULL, $2); }
3050 { $$ = makeA_Expr(OP, $2, $1, NULL); }
3053 /* could be a column name or a relation_name */
3054 Ident *n = makeNode(Ident);
3056 n->indirection = NULL;
3061 FuncCall *n = makeNode(FuncCall);
3066 | POSITION '(' position_list ')'
3068 FuncCall *n = makeNode(FuncCall);
3069 n->funcname = "strpos";
3073 | SUBSTRING '(' substr_list ')'
3075 FuncCall *n = makeNode(FuncCall);
3076 n->funcname = "substr";
3080 /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
3081 | TRIM '(' BOTH trim_list ')'
3083 FuncCall *n = makeNode(FuncCall);
3084 n->funcname = "btrim";
3088 | TRIM '(' LEADING trim_list ')'
3090 FuncCall *n = makeNode(FuncCall);
3091 n->funcname = "ltrim";
3095 | TRIM '(' TRAILING trim_list ')'
3097 FuncCall *n = makeNode(FuncCall);
3098 n->funcname = "rtrim";
3102 | TRIM '(' trim_list ')'
3104 FuncCall *n = makeNode(FuncCall);
3105 n->funcname = "btrim";
3109 | name '(' expr_list ')'
3111 FuncCall *n = makeNode(FuncCall);
3118 substr_list: expr_list substr_from substr_for
3120 $$ = nconc(nconc($1,$2),$3);
3126 substr_from: FROM expr_list
3130 A_Const *n = makeNode(A_Const);
3131 n->val.type = T_Integer;
3132 n->val.val.ival = 1;
3133 $$ = lcons((Node *)n,NIL);
3137 substr_for: FOR expr_list
3143 trim_list: a_expr FROM expr_list
3144 { $$ = lappend($3, $1); }
3153 elog(WARN,"IN (SUBSELECT) not yet implemented",NULL);
3160 in_expr_nodes: AexprConst
3161 { $$ = makeA_Expr(OP, "=", saved_In_Expr, $1); }
3162 | in_expr_nodes ',' AexprConst
3163 { $$ = makeA_Expr(OR, NULL, $1,
3164 makeA_Expr(OP, "=", saved_In_Expr, $3));
3168 not_in_expr: SubSelect
3170 elog(WARN,"NOT IN (SUBSELECT) not yet implemented",NULL);
3177 not_in_expr_nodes: AexprConst
3178 { $$ = makeA_Expr(OP, "<>", saved_In_Expr, $1); }
3179 | not_in_expr_nodes ',' AexprConst
3180 { $$ = makeA_Expr(AND, NULL, $1,
3181 makeA_Expr(OP, "<>", saved_In_Expr, $3));
3185 attr: relation_name '.' attrs
3187 $$ = makeNode(Attr);
3191 $$->indirection = NULL;
3195 $$ = makeNode(Attr);
3199 $$->indirection = NULL;
3204 { $$ = lcons(makeString($1), NIL); }
3205 | attrs '.' attr_name
3206 { $$ = lappend($1, makeString($3)); }
3208 { $$ = lappend($1, makeString("*")); }
3212 /*****************************************************************************
3216 *****************************************************************************/
3218 res_target_list: res_target_list ',' res_target_el
3219 { $$ = lappend($1,$3); }
3221 { $$ = lcons($1, NIL); }
3224 ResTarget *rt = makeNode(ResTarget);
3225 Attr *att = makeNode(Attr);
3227 att->paramNo = NULL;
3229 att->indirection = NIL;
3231 rt->indirection = NULL;
3232 rt->val = (Node *)att;
3233 $$ = lcons(rt, NIL);
3237 res_target_el: ColId opt_indirection '=' a_expr_or_null
3239 $$ = makeNode(ResTarget);
3241 $$->indirection = $2;
3242 $$->val = (Node *)$4;
3244 | attr opt_indirection
3246 $$ = makeNode(ResTarget);
3248 $$->indirection = $2;
3249 $$->val = (Node *)$1;
3251 | relation_name '.' '*'
3253 Attr *att = makeNode(Attr);
3255 att->paramNo = NULL;
3256 att->attrs = lcons(makeString("*"), NIL);
3257 att->indirection = NIL;
3258 $$ = makeNode(ResTarget);
3260 $$->indirection = NULL;
3261 $$->val = (Node *)att;
3266 ** target list for select.
3267 ** should get rid of the other but is still needed by the defunct retrieve into
3268 ** and update (uses a subset)
3270 res_target_list2: res_target_list2 ',' res_target_el2
3271 { $$ = lappend($1, $3); }
3273 { $$ = lcons($1, NIL); }
3276 /* AS is not optional because shift/red conflict with unary ops */
3277 res_target_el2: a_expr_or_null AS ColLabel
3279 $$ = makeNode(ResTarget);
3281 $$->indirection = NULL;
3282 $$->val = (Node *)$1;
3286 $$ = makeNode(ResTarget);
3288 $$->indirection = NULL;
3289 $$->val = (Node *)$1;
3291 | relation_name '.' '*'
3293 Attr *att = makeNode(Attr);
3295 att->paramNo = NULL;
3296 att->attrs = lcons(makeString("*"), NIL);
3297 att->indirection = NIL;
3298 $$ = makeNode(ResTarget);
3300 $$->indirection = NULL;
3301 $$->val = (Node *)att;
3305 Attr *att = makeNode(Attr);
3307 att->paramNo = NULL;
3309 att->indirection = NIL;
3310 $$ = makeNode(ResTarget);
3312 $$->indirection = NULL;
3313 $$->val = (Node *)att;
3317 opt_id: ColId { $$ = $1; }
3318 | /* EMPTY */ { $$ = NULL; }
3321 relation_name: SpecialRuleRelation
3324 StrNCpy(saved_relname, $1, NAMEDATALEN);
3328 /* disallow refs to magic system tables */
3329 if (strcmp(LogRelationName, $1) == 0
3330 || strcmp(VariableRelationName, $1) == 0
3331 || strcmp(TimeRelationName, $1) == 0
3332 || strcmp(MagicRelationName, $1) == 0)
3333 elog(WARN,"%s cannot be accessed by users",$1);
3336 StrNCpy(saved_relname, $1, NAMEDATALEN);
3340 database_name: ColId { $$ = $1; };
3341 access_method: Id { $$ = $1; };
3342 attr_name: ColId { $$ = $1; };
3343 class: Id { $$ = $1; };
3344 index_name: ColId { $$ = $1; };
3347 * Include date/time keywords as SQL92 extension.
3348 * Include TYPE as a SQL92 unreserved keyword. - thomas 1997-10-05
3350 name: ColId { $$ = $1; };
3352 date: Sconst { $$ = $1; };
3353 file_name: Sconst { $$ = $1; };
3354 recipe_name: Id { $$ = $1; };
3357 * Include TRUE/FALSE for SQL3 support. - thomas 1997-10-24
3361 A_Const *n = makeNode(A_Const);
3362 n->val.type = T_Integer;
3363 n->val.val.ival = $1;
3368 A_Const *n = makeNode(A_Const);
3369 n->val.type = T_Float;
3370 n->val.val.dval = $1;
3375 A_Const *n = makeNode(A_Const);
3376 n->val.type = T_String;
3377 n->val.val.str = $1;
3381 { $$ = (Node *)$1; }
3384 A_Const *n = makeNode(A_Const);
3385 n->val.type = T_String;
3386 n->val.val.str = "t";
3391 A_Const *n = makeNode(A_Const);
3392 n->val.type = T_String;
3393 n->val.val.str = "f";
3400 $$ = makeNode(ParamNo);
3405 NumConst: Iconst { $$ = makeInteger($1); }
3406 | FCONST { $$ = makeFloat($1); }
3409 Iconst: ICONST { $$ = $1; };
3410 Sconst: SCONST { $$ = $1; };
3412 /* Column and type identifier
3413 * Does not include explicit datetime types
3414 * since these must be decoupled in Typename syntax.
3415 * Use ColId for most identifiers. - thomas 1997-10-21
3417 Id: IDENT { $$ = $1; };
3419 /* Column identifier
3420 * Include date/time keywords as SQL92 extension.
3421 * Include TYPE as a SQL92 unreserved keyword. - thomas 1997-10-05
3423 ColId: Id { $$ = $1; }
3424 | datetime { $$ = $1; }
3425 | TIME { $$ = "time"; }
3426 | TYPE_P { $$ = "type"; }
3430 * Allowed labels in "AS" clauses.
3431 * Include TRUE/FALSE SQL3 reserved words for Postgres backward
3432 * compatibility. Cannot allow this for column names since the
3433 * syntax would not distinguish between the constant value and
3434 * a column name. - thomas 1997-10-24
3436 ColLabel: ColId { $$ = $1; }
3437 | TRUE_P { $$ = "true"; }
3438 | FALSE_P { $$ = "false"; }
3441 SpecialRuleRelation: CURRENT
3446 elog(WARN,"CURRENT used in non-rule query",NULL);
3453 elog(WARN,"NEW used in non-rule query",NULL);
3462 static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr)
3464 A_Expr *a = makeNode(A_Expr);
3473 * Convert alternate type names to internal Postgres types.
3474 * Do not convert "float", since that is handled elsewhere
3475 * for FLOAT(p) syntax.
3478 xlateSqlType(char *name)
3480 if (!strcasecmp(name,"int") ||
3481 !strcasecmp(name,"integer"))
3483 else if (!strcasecmp(name, "smallint"))
3485 else if (!strcasecmp(name, "real"))
3487 else if (!strcasecmp(name, "interval"))
3489 else if (!strcasecmp(name, "boolean"))
3493 } /* xlateSqlName() */
3495 void parser_init(Oid *typev, int nargs)
3497 QueryIsRule = FALSE;
3498 saved_relname[0]= '\0';
3499 saved_In_Expr = NULL;
3501 param_type_init(typev, nargs);
3504 /* FlattenStringList()
3505 * Traverse list of string nodes and convert to a single string.
3506 * Used for reconstructing string form of complex expressions.
3508 * Allocate at least one byte for terminator.
3511 FlattenStringList(List *list)
3519 nlist = length(list);
3521 printf( "list has %d elements\n", nlist);
3525 v = (Value *)lfirst(l);
3529 printf( "sp is x%8p; length of %s is %d\n", sp, sp, strlen(sp));
3535 s = (char*) palloc(len+1);
3540 v = (Value *)lfirst(l);
3544 printf( "length of %s is %d\n", sp, strlen(sp));
3547 if (l != NIL) strcat(s," ");
3552 printf( "flattened string is \"%s\"\n", s);
3556 } /* FlattenStringList() */
3558 /* makeConstantList()
3559 * Convert constant value node into string node.
3562 makeConstantList( A_Const *n)
3564 char *defval = NULL;
3566 printf( "in AexprConst\n");
3568 if (nodeTag(n) != T_A_Const) {
3569 elog(WARN,"Cannot handle non-constant parameter",NULL);
3571 } else if (n->val.type == T_Float) {
3573 printf( "AexprConst float is %f\n", n->val.val.dval);
3575 defval = (char*) palloc(20+1);
3576 sprintf( defval, "%g", n->val.val.dval);
3578 } else if (n->val.type == T_Integer) {
3580 printf( "AexprConst integer is %ld\n", n->val.val.ival);
3582 defval = (char*) palloc(20+1);
3583 sprintf( defval, "%ld", n->val.val.ival);
3585 } else if (n->val.type == T_String) {
3588 printf( "AexprConst string is \"%s\"\n", n->val.val.str);
3591 defval = (char*) palloc(strlen( ((A_Const *) n)->val.val.str) + 3);
3592 strcpy( defval, "'");
3593 strcat( defval, ((A_Const *) n)->val.val.str);
3594 strcat( defval, "'");
3597 elog(WARN,"Internal error: cannot encode node",NULL);
3601 printf( "AexprConst argument is \"%s\"\n", defval);
3604 return( lcons( makeString(defval), NIL));
3605 } /* makeConstantList() */