]> granicus.if.org Git - postgresql/blob - src/backend/parser/gram.y
Update UNION and subselect syntax.
[postgresql] / src / backend / parser / gram.y
1 %{ /* -*-text-*- */
2
3 /*#define YYDEBUG 1*/
4 /*-------------------------------------------------------------------------
5  *
6  * gram.y--
7  *        POSTGRES SQL YACC rules/actions
8  *
9  * Copyright (c) 1994, Regents of the University of California
10  *
11  *
12  * IDENTIFICATION
13  *        $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.68 1997/11/17 16:37:24 thomas Exp $
14  *
15  * HISTORY
16  *        AUTHOR                        DATE                    MAJOR EVENT
17  *        Andrew Yu                     Sept, 1994              POSTQUEL to SQL conversion
18  *        Andrew Yu                     Oct, 1994               lispy code conversion
19  *
20  * NOTES
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.
25  *
26  *        if you use list, make sure the datum is a node so that the printing
27  *        routines work
28  *
29  * WARNING
30  *        sometimes we assign constants to makeStrings. Make sure we don't free
31  *        those.
32  *
33  *-------------------------------------------------------------------------
34  */
35 #include <string.h>
36 #include <ctype.h>
37
38 #include "postgres.h"
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"
49
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;
54
55 /*
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
58  * problem, yet.)
59  */
60 /*#define __YYSCLASS*/
61
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);
66 static char *fmtId(char *rawid);
67 static Node *makeIndexable(char *opname, Node *lexpr, Node *rexpr);
68
69 /* old versions of flex define this as a macro */
70 #if defined(yywrap)
71 #undef yywrap
72 #endif /* yywrap */
73 %}
74
75
76 %union
77 {
78         double                          dval;
79         int                                     ival;
80         char                            chr;
81         char                            *str;
82         bool                            boolean;
83         List                            *list;
84         Node                            *node;
85         Value                           *value;
86
87         Attr                            *attr;
88
89         ColumnDef                       *coldef;
90         ConstraintDef           *constrdef;
91         TypeName                        *typnam;
92         DefElem                         *defelt;
93         ParamString                     *param;
94         SortGroupBy                     *sortgroupby;
95         IndexElem                       *ielem;
96         RangeVar                        *range;
97         RelExpr                         *relexp;
98         TimeRange                       *trange;
99         A_Indices                       *aind;
100         ResTarget                       *target;
101         ParamNo                         *paramno;
102
103         VersionStmt                     *vstmt;
104         DefineStmt                      *dstmt;
105         PurgeStmt                       *pstmt;
106         RuleStmt                        *rstmt;
107         AppendStmt                      *astmt;
108 }
109
110 %type <node>    stmt,
111                 AddAttrStmt, ClosePortalStmt,
112                 CopyStmt, CreateStmt, CreateSeqStmt, DefineStmt, DestroyStmt,
113                 ExtendStmt, FetchStmt,  GrantStmt, CreateTrigStmt, DropTrigStmt,
114                 CreatePLangStmt, DropPLangStmt,
115                 IndexStmt, ListenStmt, OptimizableStmt,
116                 ProcedureStmt, PurgeStmt,
117                 RecipeStmt, RemoveAggrStmt, RemoveOperStmt, RemoveFuncStmt, RemoveStmt,
118                 RenameStmt, RevokeStmt, RuleStmt, TransactionStmt, ViewStmt, LoadStmt,
119                 CreatedbStmt, DestroydbStmt, VacuumStmt, RetrieveStmt, CursorStmt,
120                 ReplaceStmt, AppendStmt, NotifyStmt, DeleteStmt, ClusterStmt,
121                 ExplainStmt, VariableSetStmt, VariableShowStmt, VariableResetStmt
122
123 %type <str>             opt_database, location
124
125 %type <node>    SubSelect
126 %type <str>             join_expr, join_outer, join_spec
127 %type <boolean> TriggerActionTime, TriggerForSpec, PLangTrusted
128
129 %type <str>             TriggerEvents, TriggerFuncArg
130
131 %type <str>             relation_name, copy_file_name, copy_delimiter, def_name,
132                 database_name, access_method_clause, access_method, attr_name,
133                 class, index_name, name, file_name, recipe_name, aggr_argtype
134
135 %type <str>             opt_id, opt_portal_name,
136                 before_clause, after_clause, all_Op, MathOp, opt_name, opt_unique,
137                 result, OptUseOp, opt_class, opt_range_start, opt_range_end,
138                 SpecialRuleRelation
139
140 %type <str>             privileges, operation_commalist, grantee
141 %type <chr>             operation, TriggerOneEvent
142
143 %type <list>    stmtblock, stmtmulti,
144                 relation_name_list, OptTableElementList, tableElementList,
145                 OptInherit, OptConstraint, ConstraintList, definition,
146                 opt_with, def_args, def_name_list, func_argtypes,
147                 oper_argtypes, OptStmtList, OptStmtBlock, OptStmtMulti,
148                 opt_column_list, columnList, opt_va_list, va_list,
149                 sort_clause, sortby_list, index_params, index_list, name_list,
150                 from_clause, from_list, opt_array_bounds, nest_array_bounds,
151                 expr_list, attrs, res_target_list, res_target_list2,
152                 def_list, opt_indirection, group_clause, groupby_list, TriggerFuncArgs
153
154 %type <list>    union_clause, select_list
155 %type <list>    join_list
156 %type <sortgroupby>
157                                 join_using
158 %type <boolean> opt_union
159
160 %type <node>    position_expr
161 %type <list>    extract_list, position_list
162 %type <list>    substr_list, substr_from, substr_for, trim_list
163 %type <list>    opt_interval
164
165 %type <boolean> opt_inh_star, opt_binary, opt_instead, opt_with_copy,
166                                 index_opt_unique, opt_verbose, opt_analyze
167
168 %type <ival>    copy_dirn, archive_type, OptArchiveType, OptArchiveLocation,
169                 def_type, opt_direction, remove_type, opt_column, event
170
171 %type <ival>    OptLocation, fetch_how_many
172
173 %type <list>    OptSeqList
174 %type <defelt>  OptSeqElem
175
176 %type <dstmt>   def_rest
177 %type <pstmt>   purge_quals
178 %type <astmt>   insert_rest
179
180 %type <coldef>  columnDef, alter_clause
181 %type <defelt>  def_elem
182 %type <node>    def_arg, columnElem, where_clause,
183                                 a_expr, a_expr_or_null, AexprConst,
184                                 in_expr, in_expr_nodes, not_in_expr, not_in_expr_nodes,
185                                 having_clause
186 %type <value>   NumConst
187 %type <attr>    event_object, attr
188 %type <sortgroupby>             groupby
189 %type <sortgroupby>             sortby
190 %type <ielem>   index_elem, func_index
191 %type <range>   from_val
192 %type <relexp>  relation_expr
193 %type <trange>  time_range
194 %type <target>  res_target_el, res_target_el2
195 %type <paramno> ParamNo
196
197 %type <typnam>  Typename, opt_type, Array, Generic, Character, Datetime, Numeric
198 %type <str>             generic, character, datetime
199 %type <str>             opt_charset, opt_collate
200 %type <str>             opt_float, opt_numeric, opt_decimal
201 %type <boolean> opt_varying, opt_timezone
202
203 %type <ival>    Iconst
204 %type <str>             Sconst
205 %type <str>             Id, date, var_value, zone_value
206 %type <str>             ColId, ColLabel
207
208 %type <constrdef>       ConstraintElem, ConstraintDef
209
210 %type <list>    constraint_elem
211 %type <list>    default_expr
212 %type <str>             opt_default
213 %type <boolean> opt_constraint
214 %type <list>    key_actions, key_action
215 %type <str>             key_match, key_reference
216
217 /*
218  * If you make any token changes, remember to:
219  *              - use "yacc -d" and update parse.h
220  *              - update the keyword table in parser/keywords.c
221  */
222
223 /* Reserved word tokens
224  * SQL92 syntax has many type-specific constructs.
225  * So, go ahead and make these types reserved words,
226  *  and call-out the syntax explicitly.
227  * This gets annoying when trying to also retain Postgres' nice
228  *  type-extensible features, but we don't really have a choice.
229  * - thomas 1997-10-11
230  */
231
232 /* Keywords (in SQL92 reserved words) */
233 %token  ACTION, ADD, ALL, ALTER, AND, AS, ASC,
234                 BEGIN_TRANS, BETWEEN, BOTH, BY,
235                 CASCADE, CAST, CHAR, CHARACTER, CHECK, CLOSE, COLLATE, COLUMN, COMMIT, 
236                 CONSTRAINT, CREATE, CROSS, CURRENT, CURRENT_DATE, CURRENT_TIME, 
237                 CURRENT_TIMESTAMP, CURRENT_USER, CURSOR,
238                 DAY_P, DECIMAL, DECLARE, DEFAULT, DELETE, DESC, DISTINCT, DOUBLE, DROP,
239                 END_TRANS, EXECUTE, EXISTS, EXTRACT,
240                 FETCH, FLOAT, FOR, FOREIGN, FROM, FULL,
241                 GRANT, GROUP, HAVING, HOUR_P,
242                 IN, INNER_P, INSERT, INTERVAL, INTO, IS,
243                 JOIN, KEY, LANGUAGE, LEADING, LEFT, LIKE, LOCAL,
244                 MATCH, MINUTE_P, MONTH_P,
245                 NATIONAL, NATURAL, NCHAR, NO, NOT, NOTIFY, NOTNULL, NULL_P, NUMERIC,
246                 ON, OPTION, OR, ORDER, OUTER_P,
247                 PARTIAL, POSITION, PRECISION, PRIMARY, PRIVILEGES, PROCEDURE, PUBLIC,
248                 REFERENCES, REVOKE, RIGHT, ROLLBACK,
249                 SECOND_P, SELECT, SET, SUBSTRING,
250                 TABLE, TIME, TIMESTAMP, TO, TRAILING, TRANSACTION, TRIM,
251                 UNION, UNIQUE, UPDATE, USING,
252                 VALUES, VARCHAR, VARYING, VERBOSE, VERSION, VIEW,
253                 WHERE, WITH, WORK, YEAR_P, ZONE
254
255 /* Keywords (in SQL3 reserved words) */
256 %token  FALSE_P, TRIGGER, TRUE_P
257
258 /* Keywords (in SQL92 non-reserved words) */
259 %token  TYPE_P
260
261 /* Keywords for Postgres support (not in SQL92 reserved words) */
262 %token  ABORT_TRANS, ACL, AFTER, AGGREGATE, ANALYZE,
263                 APPEND, ARCHIVE, ARCH_STORE,
264                 BACKWARD, BEFORE, BINARY, CHANGE, CLUSTER, COPY,
265                 DATABASE, DELIMITERS, DO, EXPLAIN, EXTEND,
266                 FORWARD, FUNCTION, HANDLER, HEAVY,
267                 INDEX, INHERITS, INSTEAD, ISNULL,
268                 LANCOMPILER, LIGHT, LISTEN, LOAD, LOCATION, MERGE, MOVE,
269                 NEW, NONE, NOTHING, OIDS, OPERATOR, PROCEDURAL, PURGE,
270                 RECIPE, RENAME, REPLACE, RESET, RETRIEVE, RETURNS, RULE,
271                 SEQUENCE, SETOF, SHOW, STDIN, STDOUT, STORE, TRUSTED, 
272                 VACUUM, VERBOSE, VERSION
273
274 /* Special keywords, not in the query language - see the "lex" file */
275 %token <str>    IDENT, SCONST, Op
276 %token <ival>   ICONST, PARAM
277 %token <dval>   FCONST
278
279 /* these are not real. they are here so that they get generated as #define's*/
280 %token                  OP
281
282 /* precedence */
283 %left           OR
284 %left           AND
285 %right          NOT
286 %right          '='
287 %nonassoc       LIKE
288 %nonassoc       BETWEEN
289 %nonassoc       IN
290 %nonassoc       Op
291 %nonassoc       NOTNULL
292 %nonassoc       ISNULL
293 %nonassoc       IS
294 %left           '+' '-'
295 %left           '*' '/'
296 %left           '|'                             /* this is the relation union op, not logical or */
297 /* Unary Operators */
298 %right          ':'
299 %left           ';'                             /* end of statement or natural log */
300 %nonassoc       '<' '>'
301 %right          UMINUS
302 %left           '.'
303 %left           '[' ']'
304 %nonassoc       TYPECAST
305 %nonassoc       REDUCE
306 %left           UNION
307 %%
308
309 stmtblock:  stmtmulti
310                                 { parsetree = $1; }
311                 | stmt
312                                 { parsetree = lcons($1,NIL); }
313                 ;
314
315 stmtmulti:  stmtmulti stmt ';'
316                                 { $$ = lappend($1, $2); }
317                 | stmtmulti stmt
318                                 { $$ = lappend($1, $2); }
319                 | stmt ';'
320                                 { $$ = lcons($1,NIL); }
321                 ;
322
323 stmt :    AddAttrStmt
324                 | ClosePortalStmt
325                 | CopyStmt
326                 | CreateStmt
327                 | CreateSeqStmt
328                 | CreatePLangStmt
329                 | CreateTrigStmt
330                 | ClusterStmt
331                 | DefineStmt
332                 | DestroyStmt
333                 | DropPLangStmt
334                 | DropTrigStmt
335                 | ExtendStmt
336                 | ExplainStmt
337                 | FetchStmt
338                 | GrantStmt
339                 | IndexStmt
340                 | ListenStmt
341                 | ProcedureStmt
342                 | PurgeStmt
343                 | RecipeStmt
344                 | RemoveAggrStmt
345                 | RemoveOperStmt
346                 | RemoveFuncStmt
347                 | RemoveStmt
348                 | RenameStmt
349                 | RevokeStmt
350                 | OptimizableStmt
351                 | RuleStmt
352                 | TransactionStmt
353                 | ViewStmt
354                 | LoadStmt
355                 | CreatedbStmt
356                 | DestroydbStmt
357                 | VacuumStmt
358                 | VariableSetStmt
359                 | VariableShowStmt
360                 | VariableResetStmt
361                 ;
362
363
364 /*****************************************************************************
365  *
366  * Set PG internal variable
367  *        SET name TO 'var_value'
368  * Include SQL92 syntax (thomas 1997-10-22):
369  *    SET TIME ZONE 'var_value'
370  *
371  *****************************************************************************/
372
373 VariableSetStmt:  SET ColId TO var_value
374                                 {
375                                         VariableSetStmt *n = makeNode(VariableSetStmt);
376                                         n->name  = $2;
377                                         n->value = $4;
378                                         $$ = (Node *) n;
379                                 }
380                 | SET ColId '=' var_value
381                                 {
382                                         VariableSetStmt *n = makeNode(VariableSetStmt);
383                                         n->name  = $2;
384                                         n->value = $4;
385                                         $$ = (Node *) n;
386                                 }
387                 | SET TIME ZONE zone_value
388                                 {
389                                         VariableSetStmt *n = makeNode(VariableSetStmt);
390                                         n->name  = "timezone";
391                                         n->value = $4;
392                                         $$ = (Node *) n;
393                                 }
394                 ;
395
396 var_value:  Sconst                      { $$ = $1; }
397                 | DEFAULT                       { $$ = NULL; }
398                 ;
399
400 zone_value:  Sconst                     { $$ = $1; }
401                 | DEFAULT                       { $$ = NULL; }
402                 | LOCAL                         { $$ = "default"; }
403                 ;
404
405 VariableShowStmt:  SHOW ColId
406                                 {
407                                         VariableShowStmt *n = makeNode(VariableShowStmt);
408                                         n->name  = $2;
409                                         $$ = (Node *) n;
410                                 }
411                 | SHOW TIME ZONE
412                                 {
413                                         VariableShowStmt *n = makeNode(VariableShowStmt);
414                                         n->name  = "timezone";
415                                         $$ = (Node *) n;
416                                 }
417                 ;
418
419 VariableResetStmt:      RESET ColId
420                                 {
421                                         VariableResetStmt *n = makeNode(VariableResetStmt);
422                                         n->name  = $2;
423                                         $$ = (Node *) n;
424                                 }
425                 | RESET TIME ZONE
426                                 {
427                                         VariableResetStmt *n = makeNode(VariableResetStmt);
428                                         n->name  = "timezone";
429                                         $$ = (Node *) n;
430                                 }
431                 ;
432
433
434 /*****************************************************************************
435  *
436  *              QUERY :
437  *                              addattr ( attr1 = type1 .. attrn = typen ) to <relname> [*]
438  *
439  *****************************************************************************/
440
441 AddAttrStmt:  ALTER TABLE relation_name opt_inh_star alter_clause
442                                 {
443                                         AddAttrStmt *n = makeNode(AddAttrStmt);
444                                         n->relname = $3;
445                                         n->inh = $4;
446                                         n->colDef = $5;
447                                         $$ = (Node *)n;
448                                 }
449                 ;
450
451 alter_clause:  ADD opt_column columnDef
452                                 {
453                                         $$ = $3;
454                                 }
455                         | ADD '(' tableElementList ')'
456                                 {
457                                         ColumnDef *lp = lfirst($3);
458
459                                         if (length($3) != 1)
460                                                 elog(WARN,"ALTER TABLE/ADD() allows one column only",NULL);
461                                         $$ = lp;
462                                 }
463                         | DROP opt_column ColId
464                                 {       elog(WARN,"ALTER TABLE/DROP COLUMN not yet implemented",NULL); }
465                         | ALTER opt_column ColId SET opt_default
466                                 {       elog(WARN,"ALTER TABLE/ALTER COLUMN/SET DEFAULT not yet implemented",NULL); }
467                         | ALTER opt_column ColId DROP DEFAULT
468                                 {       elog(WARN,"ALTER TABLE/ALTER COLUMN/DROP DEFAULT not yet implemented",NULL); }
469                         | ADD ConstraintElem
470                                 {       elog(WARN,"ALTER TABLE/ADD CONSTRAINT not yet implemented",NULL); }
471                 ;
472
473 columnDef:  ColId Typename opt_default opt_constraint
474                                 {
475                                         $$ = makeNode(ColumnDef);
476                                         $$->colname = $1;
477                                         $$->typename = $2;
478                                         $$->defval = $3;
479                                         $$->is_not_null = $4;
480                                 }
481                 ;
482
483 opt_default:  DEFAULT default_expr
484                                 {
485                                         $$ = FlattenStringList($2);
486                                 }
487                         | /*EMPTY*/             { $$ = NULL; }
488         ;
489
490 default_expr:  AexprConst
491                                 {       $$ = makeConstantList((A_Const *) $1); }
492                         | Pnull
493                                 {       $$ = lcons( makeString("NULL"), NIL); }
494                         | '-' default_expr %prec UMINUS
495                                 {       $$ = lcons( makeString( "-"), $2); }
496                         | default_expr '+' default_expr
497                                 {       $$ = nconc( $1, lcons( makeString( "+"), $3)); }
498                         | default_expr '-' default_expr
499                                 {       $$ = nconc( $1, lcons( makeString( "-"), $3)); }
500                         | default_expr '/' default_expr
501                                 {       $$ = nconc( $1, lcons( makeString( "/"), $3)); }
502                         | default_expr '*' default_expr
503                                 {       $$ = nconc( $1, lcons( makeString( "*"), $3)); }
504                         | default_expr '=' default_expr
505                                 {       elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
506                         | default_expr '<' default_expr
507                                 {       elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
508                         | default_expr '>' default_expr
509                                 {       elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
510                         | ':' default_expr
511                                 {       $$ = lcons( makeString( ":"), $2); }
512                         | ';' default_expr
513                                 {       $$ = lcons( makeString( ";"), $2); }
514                         | '|' default_expr
515                                 {       $$ = lcons( makeString( "|"), $2); }
516                         | default_expr TYPECAST Typename
517                                 {
518                                         $3->name = fmtId($3->name);
519                                         $$ = nconc( lcons( makeString( "CAST"), $1), makeList( makeString("AS"), $3, -1));
520                                 }
521                         | CAST default_expr AS Typename
522                                 {
523                                         $4->name = fmtId($4->name);
524                                         $$ = nconc( lcons( makeString( "CAST"), $2), makeList( makeString("AS"), $4, -1));
525                                 }
526                         | '(' default_expr ')'
527                                 {       $$ = lappend( lcons( makeString( "("), $2), makeString( ")")); }
528                         | name '(' default_expr ')'
529                                 {
530                                         $$ = makeList( makeString($1), makeString("("), -1);
531                                         $$ = nconc( $$, $3);
532                                         $$ = lappend( $$, makeString(")"));
533                                 }
534                         | name '(' ')'
535                                 {
536                                         $$ = makeList( makeString($1), makeString("("), -1);
537                                         $$ = lappend( $$, makeString(")"));
538                                 }
539                         | default_expr Op default_expr
540                                 {
541                                         if (!strcmp("<=", $2) || !strcmp(">=", $2))
542                                                 elog(WARN,"boolean expressions not supported in DEFAULT",NULL);
543                                         $$ = nconc( $1, lcons( makeString( $2), $3));
544                                 }
545                         | Op default_expr
546                                 {       $$ = lcons( makeString( $1), $2); }
547                         | default_expr Op
548                                 {       $$ = lappend( $1, makeString( $2)); }
549                         /* XXX - thomas 1997-10-07 v6.2 function-specific code to be changed */
550                         | CURRENT_DATE
551                                 {       $$ = lcons( makeString( "date( 'current'::datetime + '0 sec')"), NIL); }
552                         | CURRENT_TIME
553                                 {       $$ = lcons( makeString( "'now'::time"), NIL); }
554                         | CURRENT_TIME '(' Iconst ')'
555                                 {
556                                         if ($3 != 0)
557                                                 elog(NOTICE,"CURRENT_TIME(p) precision must be zero",NULL);
558                                         $$ = lcons( makeString( "'now'::time"), NIL);
559                                 }
560                         | CURRENT_TIMESTAMP
561                                 {       $$ = lcons( makeString( "now()"), NIL); }
562                         | CURRENT_TIMESTAMP '(' Iconst ')'
563                                 {
564                                         if ($3 != 0)
565                                                 elog(NOTICE,"CURRENT_TIMESTAMP(p) precision must be zero",NULL);
566                                         $$ = lcons( makeString( "now()"), NIL);
567                                 }
568                         | CURRENT_USER
569                                 {       $$ = lcons( makeString( "CURRENT_USER"), NIL); }
570                 ;
571
572 opt_constraint:  NOT NULL_P                                             { $$ = TRUE; }
573                         | NOTNULL                                                       { $$ = TRUE; }
574                         | UNIQUE
575                                 {
576                                         elog(WARN,"CREATE TABLE/UNIQUE not yet implemented",NULL);
577                                         $$ = FALSE;
578                                 }
579                         | PRIMARY KEY
580                                 {
581                                         elog(WARN,"CREATE TABLE/PRIMARY KEY not yet implemented",NULL);
582                                         $$ = FALSE;
583                                 }
584                         | REFERENCES ColId opt_column_list key_match key_actions
585                                 {
586                                         elog(WARN,"CREATE TABLE/FOREIGN KEY not yet implemented",NULL);
587                                         $$ = FALSE;
588                                 }
589                         | /* EMPTY */                                           { $$ = FALSE; }
590                 ;
591
592
593 /*****************************************************************************
594  *
595  *              QUERY :
596  *                              close <optname>
597  *
598  *****************************************************************************/
599
600 ClosePortalStmt:  CLOSE opt_id
601                                 {
602                                         ClosePortalStmt *n = makeNode(ClosePortalStmt);
603                                         n->portalname = $2;
604                                         $$ = (Node *)n;
605                                 }
606                 ;
607
608
609 /*****************************************************************************
610  *
611  *              QUERY :
612  *                              COPY [BINARY] <relname> FROM/TO
613  *                              [USING DELIMITERS <delimiter>]
614  *
615  *****************************************************************************/
616
617 CopyStmt:  COPY opt_binary relation_name opt_with_copy copy_dirn copy_file_name copy_delimiter
618                                 {
619                                         CopyStmt *n = makeNode(CopyStmt);
620                                         n->binary = $2;
621                                         n->relname = $3;
622                                         n->oids = $4;
623                                         n->direction = $5;
624                                         n->filename = $6;
625                                         n->delimiter = $7;
626                                         $$ = (Node *)n;
627                                 }
628                 ;
629
630 copy_dirn:      TO
631                                 { $$ = TO; }
632                 | FROM
633                                 { $$ = FROM; }
634                 ;
635
636 /*
637  * copy_file_name NULL indicates stdio is used. Whether stdin or stdout is
638  * used depends on the direction. (It really doesn't make sense to copy from
639  * stdout. We silently correct the "typo".               - AY 9/94
640  */
641 copy_file_name:  Sconst                                                 { $$ = $1; }
642                 | STDIN                                                                 { $$ = NULL; }
643                 | STDOUT                                                                { $$ = NULL; }
644                 ;
645
646 opt_binary:  BINARY                                                             { $$ = TRUE; }
647                 | /*EMPTY*/                                                             { $$ = FALSE; }
648                 ;
649
650 opt_with_copy:  WITH OIDS                                               { $$ = TRUE; }
651                 | /* EMPTY */                                                   { $$ = FALSE; }
652                 ;
653
654 /*
655  * the default copy delimiter is tab but the user can configure it
656  */
657 copy_delimiter:  USING DELIMITERS Sconst { $$ = $3;}
658                 | /* EMPTY */  { $$ = "\t"; }
659                 ;
660
661
662 /*****************************************************************************
663  *
664  *              QUERY :
665  *                              CREATE relname
666  *
667  *****************************************************************************/
668
669 CreateStmt:  CREATE TABLE relation_name '(' OptTableElementList ')'
670                                 OptInherit OptConstraint OptArchiveType OptLocation
671                                 OptArchiveLocation
672                                 {
673                                         CreateStmt *n = makeNode(CreateStmt);
674                                         n->relname = $3;
675                                         n->tableElts = $5;
676                                         n->inhRelnames = $7;
677                                         n->constraints = $8;
678                                         n->archiveType = $9;
679                                         n->location = $10;
680                                         n->archiveLoc = $11;
681                                         $$ = (Node *)n;
682                                 }
683                 ;
684
685 OptTableElementList:  tableElementList                  { $$ = $1; }
686                 | /* EMPTY */                                                   { $$ = NULL; }
687                 ;
688
689 tableElementList :
690                   tableElementList ',' columnDef
691                                 { $$ = lappend($1, $3); }
692                 | columnDef
693                                 { $$ = lcons($1, NIL); }
694                 ;
695
696
697 OptArchiveType:  ARCHIVE '=' archive_type                               { $$ = $3; }
698                 | /*EMPTY*/                                                                             { $$ = ARCH_NONE; }
699                 ;
700
701 archive_type:  HEAVY                                                                    { $$ = ARCH_HEAVY; }
702                 | LIGHT                                                                                 { $$ = ARCH_LIGHT; }
703                 | NONE                                                                                  { $$ = ARCH_NONE; }
704                 ;
705
706 OptLocation:  STORE '=' Sconst
707                                 {  $$ = smgrin($3);  }
708                 | /*EMPTY*/
709                                 {  $$ = -1;  }
710                 ;
711
712 OptArchiveLocation:  ARCH_STORE '=' Sconst
713                                 {  $$ = smgrin($3);  }
714                 | /*EMPTY*/
715                                 {  $$ = -1;  }
716                 ;
717
718 OptInherit:  INHERITS '(' relation_name_list ')'                { $$ = $3; }
719                 | /*EMPTY*/                                                                             { $$ = NIL; }
720                 ;
721
722 OptConstraint:  ConstraintList                                                  { $$ = $1; }
723                 | /*EMPTY*/                                                                             { $$ = NULL; }
724                 ;
725
726 ConstraintList:
727                   ConstraintList ',' ConstraintElem
728                                 { $$ = lappend($1, $3); }
729                 | ConstraintElem
730                                 { $$ = lcons($1, NIL); }
731                 ;
732
733 ConstraintElem:
734                 CONSTRAINT name ConstraintDef
735                                 {
736                                                 $3->name = fmtId($2);
737                                                 $$ = $3;
738                                 }
739                 | ConstraintDef                 { $$ = $1; }
740                 ;
741
742 ConstraintDef:  CHECK constraint_elem
743                                 {
744                                         ConstraintDef *constr = palloc (sizeof(ConstraintDef));
745                                         constr->type = CONSTR_CHECK;
746                                         constr->name = NULL;
747                                         constr->def = FlattenStringList($2);
748                                         $$ = constr;
749                                 }
750                 | UNIQUE '(' columnList ')'
751                                 {       elog(WARN,"CREATE TABLE/UNIQUE not yet implemented",NULL); }
752                 | PRIMARY KEY '(' columnList ')'
753                                 {       elog(WARN,"CREATE TABLE/PRIMARY KEY not yet implemented",NULL); }
754                 | FOREIGN KEY '(' columnList ')' REFERENCES ColId opt_column_list key_match key_actions
755                                 {       elog(WARN,"CREATE TABLE/FOREIGN KEY not yet implemented",NULL); }
756                 ;
757
758 constraint_elem:  AexprConst
759                                 {       $$ = makeConstantList((A_Const *) $1); }
760                         | Pnull
761                                 {       $$ = lcons( makeString("NULL"), NIL); }
762                         | ColId
763                                 {
764                                         $$ = lcons( makeString(fmtId($1)), NIL);
765                                 }
766                         | '-' constraint_elem %prec UMINUS
767                                 {       $$ = lcons( makeString( "-"), $2); }
768                         | constraint_elem '+' constraint_elem
769                                 {       $$ = nconc( $1, lcons( makeString( "+"), $3)); }
770                         | constraint_elem '-' constraint_elem
771                                 {       $$ = nconc( $1, lcons( makeString( "-"), $3)); }
772                         | constraint_elem '/' constraint_elem
773                                 {       $$ = nconc( $1, lcons( makeString( "/"), $3)); }
774                         | constraint_elem '*' constraint_elem
775                                 {       $$ = nconc( $1, lcons( makeString( "*"), $3)); }
776                         | constraint_elem '=' constraint_elem
777                                 {       $$ = nconc( $1, lcons( makeString( "="), $3)); }
778                         | constraint_elem '<' constraint_elem
779                                 {       $$ = nconc( $1, lcons( makeString( "<"), $3)); }
780                         | constraint_elem '>' constraint_elem
781                                 {       $$ = nconc( $1, lcons( makeString( ">"), $3)); }
782                         | ':' constraint_elem
783                                 {       $$ = lcons( makeString( ":"), $2); }
784                         | ';' constraint_elem
785                                 {       $$ = lcons( makeString( ";"), $2); }
786                         | '|' constraint_elem
787                                 {       $$ = lcons( makeString( "|"), $2); }
788                         | constraint_elem TYPECAST Typename
789                                 {
790                                         $3->name = fmtId($3->name);
791                                         $$ = nconc( lcons( makeString( "CAST"), $1), makeList( makeString("AS"), $3, -1));
792                                 }
793                         | CAST constraint_elem AS Typename
794                                 {
795                                         $4->name = fmtId($4->name);
796                                         $$ = nconc( lcons( makeString( "CAST"), $2), makeList( makeString("AS"), $4, -1));
797                                 }
798                         | '(' constraint_elem ')'
799                                 {       $$ = lappend( lcons( makeString( "("), $2), makeString( ")")); }
800                         | name '(' constraint_elem ')'
801                                 {
802                                         $$ = makeList( makeString($1), makeString("("), -1);
803                                         $$ = nconc( $$, $3);
804                                         $$ = lappend( $$, makeString(")"));
805                                 }
806                         | constraint_elem Op constraint_elem
807                                 {       $$ = nconc( $1, lcons( makeString( $2), $3)); }
808                         | constraint_elem AND constraint_elem
809                                 {       $$ = nconc( $1, lcons( makeString( "AND"), $3)); }
810                         | constraint_elem OR constraint_elem
811                                 {       $$ = nconc( $1, lcons( makeString( "OR"), $3)); }
812                         | Op constraint_elem
813                                 {       $$ = lcons( makeString( $1), $2); }
814                         | constraint_elem Op
815                                 {       $$ = lappend( $1, makeString( $2)); }
816                         | constraint_elem IS TRUE_P
817                                 {       $$ = lappend( $1, makeString( "IS TRUE")); }
818                         | constraint_elem IS FALSE_P
819                                 {       $$ = lappend( $1, makeString( "IS FALSE")); }
820                         | constraint_elem IS NOT TRUE_P
821                                 {       $$ = lappend( $1, makeString( "IS NOT TRUE")); }
822                         | constraint_elem IS NOT FALSE_P
823                                 {       $$ = lappend( $1, makeString( "IS NOT FALSE")); }
824                 ;
825
826 key_match:  MATCH FULL                                  { $$ = NULL; }
827                 | MATCH PARTIAL                                 { $$ = NULL; }
828                 | /*EMPTY*/                                             { $$ = NULL; }
829                 ;
830
831 key_actions:  key_action key_action             { $$ = NIL; }
832                 | key_action                                    { $$ = NIL; }
833                 | /*EMPTY*/                                             { $$ = NIL; }
834                 ;
835
836 key_action:  ON DELETE key_reference    { $$ = NIL; }
837                 | ON UPDATE key_reference               { $$ = NIL; }
838                 ;
839
840 key_reference:  NO ACTION                               { $$ = NULL; }
841                 | CASCADE                                               { $$ = NULL; }
842                 | SET DEFAULT                                   { $$ = NULL; }
843                 | SET NULL_P                                    { $$ = NULL; }
844                 ;
845
846
847 /*****************************************************************************
848  *
849  *              QUERY :
850  *                              CREATE SEQUENCE seqname
851  *
852  *****************************************************************************/
853
854 CreateSeqStmt:  CREATE SEQUENCE relation_name OptSeqList
855                                 {
856                                         CreateSeqStmt *n = makeNode(CreateSeqStmt);
857                                         n->seqname = $3;
858                                         n->options = $4;
859                                         $$ = (Node *)n;
860                                 }
861                 ;
862
863 OptSeqList:
864                                 OptSeqList OptSeqElem
865                                 { $$ = lappend($1, $2); }
866                 |               { $$ = NIL; }
867                 ;
868
869 OptSeqElem:             IDENT NumConst
870                                 {
871                                         $$ = makeNode(DefElem);
872                                         $$->defname = $1;
873                                         $$->arg = (Node *)$2;
874                                 }
875                 |               IDENT
876                                 {
877                                         $$ = makeNode(DefElem);
878                                         $$->defname = $1;
879                                         $$->arg = (Node *)NULL;
880                                 }
881                 ;
882
883 /*****************************************************************************
884  *
885  *              QUERIES :
886  *                              CREATE PROCEDURAL LANGUAGE ...
887  *                              DROP PROCEDURAL LANGUAGE ...
888  *
889  *****************************************************************************/
890
891 CreatePLangStmt:  CREATE PLangTrusted PROCEDURAL LANGUAGE Sconst 
892                         HANDLER def_name LANCOMPILER Sconst
893                         {
894                                 CreatePLangStmt *n = makeNode(CreatePLangStmt);
895                                 n->plname = $5;
896                                 n->plhandler = $7;
897                                 n->plcompiler = $9;
898                                 n->pltrusted = $2;
899                                 $$ = (Node *)n;
900                         }
901                 ;
902
903 PLangTrusted:           TRUSTED { $$ = TRUE; }
904                         |       { $$ = FALSE; }
905
906 DropPLangStmt:  DROP PROCEDURAL LANGUAGE Sconst
907                         {
908                                 DropPLangStmt *n = makeNode(DropPLangStmt);
909                                 n->plname = $4;
910                                 $$ = (Node *)n;
911                         }
912                 ;
913
914 /*****************************************************************************
915  *
916  *              QUERIES :
917  *                              CREATE TRIGGER ...
918  *                              DROP TRIGGER ...
919  *
920  *****************************************************************************/
921
922 CreateTrigStmt:  CREATE TRIGGER name TriggerActionTime TriggerEvents ON
923                                 relation_name TriggerForSpec EXECUTE PROCEDURE
924                                 name '(' TriggerFuncArgs ')'
925                                 {
926                                         CreateTrigStmt *n = makeNode(CreateTrigStmt);
927                                         n->trigname = $3;
928                                         n->relname = $7;
929                                         n->funcname = $11;
930                                         n->args = $13;
931                                         n->before = $4;
932                                         n->row = $8;
933                                         memcpy (n->actions, $5, 4);
934                                         $$ = (Node *)n;
935                                 }
936                 ;
937
938 TriggerActionTime:              BEFORE  { $$ = TRUE; }
939                                 |               AFTER   { $$ = FALSE; }
940                 ;
941
942 TriggerEvents:  TriggerOneEvent
943                                         {
944                                                         char *e = palloc (4);
945                                                         e[0] = $1; e[1] = 0; $$ = e;
946                                         }
947                                 | TriggerOneEvent OR TriggerOneEvent
948                                         {
949                                                         char *e = palloc (4);
950                                                         e[0] = $1; e[1] = $3; e[2] = 0; $$ = e;
951                                         }
952                                 | TriggerOneEvent OR TriggerOneEvent OR TriggerOneEvent
953                                         {
954                                                         char *e = palloc (4);
955                                                         e[0] = $1; e[1] = $3; e[2] = $5; e[3] = 0;
956                                                         $$ = e;
957                                         }
958                 ;
959
960 TriggerOneEvent:                INSERT  { $$ = 'i'; }
961                                 |               DELETE  { $$ = 'd'; }
962                                 |               UPDATE  { $$ = 'u'; }
963                 ;
964
965 TriggerForSpec:  FOR name name
966                                 {
967                                                 if ( strcmp ($2, "each") != 0 )
968                                                                 elog(WARN,"parser: syntax error near %s",$2);
969                                                 if ( strcmp ($3, "row") == 0 )
970                                                                 $$ = TRUE;
971                                                 else if ( strcmp ($3, "statement") == 0 )
972                                                                 $$ = FALSE;
973                                                 else
974                                                                 elog(WARN,"parser: syntax error near %s",$3);
975                                 }
976                 ;
977
978 TriggerFuncArgs:  TriggerFuncArg
979                                 { $$ = lcons($1, NIL); }
980                 | TriggerFuncArgs ',' TriggerFuncArg
981                                 { $$ = lappend($1, $3); }
982                 | /*EMPTY*/
983                                 { $$ = NIL; }
984                 ;
985
986 TriggerFuncArg:  ICONST
987                                         {
988                                                 char *s = (char *) palloc (256);
989                                                 sprintf (s, "%d", $1);
990                                                 $$ = s;
991                                         }
992                                 | FCONST
993                                         {
994                                                 char *s = (char *) palloc (256);
995                                                 sprintf (s, "%g", $1);
996                                                 $$ = s;
997                                         }
998                                 | Sconst                {  $$ = $1; }
999                                 | IDENT                 {  $$ = $1; }
1000                 ;
1001
1002 DropTrigStmt:   DROP TRIGGER name ON relation_name
1003                                 {
1004                                         DropTrigStmt *n = makeNode(DropTrigStmt);
1005                                         n->trigname = $3;
1006                                         n->relname = $5;
1007                                         $$ = (Node *) n;
1008                                 }
1009                 ;
1010
1011
1012 /*****************************************************************************
1013  *
1014  *              QUERY :
1015  *                              define (type,operator,aggregate)
1016  *
1017  *****************************************************************************/
1018
1019 DefineStmt:  CREATE def_type def_rest
1020                                 {
1021                                         $3->defType = $2;
1022                                         $$ = (Node *)$3;
1023                                 }
1024                 ;
1025
1026 def_rest:  def_name definition
1027                                 {
1028                                         $$ = makeNode(DefineStmt);
1029                                         $$->defname = $1;
1030                                         $$->definition = $2;
1031                                 }
1032                 ;
1033
1034 def_type:  OPERATOR                                                     { $$ = OPERATOR; }
1035                 | Type                                                          { $$ = TYPE_P; }
1036                 | AGGREGATE                                                     { $$ = AGGREGATE; }
1037                 ;
1038
1039 def_name:  PROCEDURE                                            { $$ = "procedure"; }
1040                 | JOIN                                                          { $$ = "join"; }
1041                 | ColId                                                         { $$ = $1; }
1042                 | MathOp                                                        { $$ = $1; }
1043                 | Op                                                            { $$ = $1; }
1044                 ;
1045
1046 definition:  '(' def_list ')'                           { $$ = $2; }
1047                 ;
1048
1049 def_list:  def_elem                                                     { $$ = lcons($1, NIL); }
1050                 | def_list ',' def_elem                         { $$ = lappend($1, $3); }
1051                 ;
1052
1053 def_elem:  def_name '=' def_arg
1054                                 {
1055                                         $$ = makeNode(DefElem);
1056                                         $$->defname = $1;
1057                                         $$->arg = (Node *)$3;
1058                                 }
1059                 | def_name
1060                                 {
1061                                         $$ = makeNode(DefElem);
1062                                         $$->defname = $1;
1063                                         $$->arg = (Node *)NULL;
1064                                 }
1065                 | DEFAULT '=' def_arg
1066                                 {
1067                                         $$ = makeNode(DefElem);
1068                                         $$->defname = "default";
1069                                         $$->arg = (Node *)$3;
1070                                 }
1071                 ;
1072
1073 def_arg:  ColId                                                 {  $$ = (Node *)makeString($1); }
1074                 | all_Op                                                {  $$ = (Node *)makeString($1); }
1075                 | NumConst                                              {  $$ = (Node *)$1; /* already a Value */ }
1076                 | Sconst                                                {  $$ = (Node *)makeString($1); }
1077                 | SETOF ColId
1078                                 {
1079                                         TypeName *n = makeNode(TypeName);
1080                                         n->name = $2;
1081                                         n->setof = TRUE;
1082                                         n->arrayBounds = NULL;
1083                                         $$ = (Node *)n;
1084                                 }
1085                 | DOUBLE                                                {  $$ = (Node *)makeString("double"); }
1086                 ;
1087
1088
1089 /*****************************************************************************
1090  *
1091  *              QUERY:
1092  *                              destroy <relname1> [, <relname2> .. <relnameN> ]
1093  *
1094  *****************************************************************************/
1095
1096 DestroyStmt:  DROP TABLE relation_name_list
1097                                 {
1098                                         DestroyStmt *n = makeNode(DestroyStmt);
1099                                         n->relNames = $3;
1100                                         n->sequence = FALSE;
1101                                         $$ = (Node *)n;
1102                                 }
1103                 | DROP SEQUENCE relation_name_list
1104                                 {
1105                                         DestroyStmt *n = makeNode(DestroyStmt);
1106                                         n->relNames = $3;
1107                                         n->sequence = TRUE;
1108                                         $$ = (Node *)n;
1109                                 }
1110                 ;
1111
1112
1113 /*****************************************************************************
1114  *
1115  *              QUERY:
1116  *                      fetch/move [forward | backward] [number | all ] [ in <portalname> ]
1117  *
1118  *****************************************************************************/
1119
1120 FetchStmt:      FETCH opt_direction fetch_how_many opt_portal_name
1121                                 {
1122                                         FetchStmt *n = makeNode(FetchStmt);
1123                                         n->direction = $2;
1124                                         n->howMany = $3;
1125                                         n->portalname = $4;
1126                                         n->ismove = false;
1127                                         $$ = (Node *)n;
1128                                 }
1129                 |       MOVE opt_direction fetch_how_many opt_portal_name
1130                                 {
1131                                         FetchStmt *n = makeNode(FetchStmt);
1132                                         n->direction = $2;
1133                                         n->howMany = $3;
1134                                         n->portalname = $4;
1135                                         n->ismove = TRUE;
1136                                         $$ = (Node *)n;
1137                                 }
1138                 ;
1139
1140 opt_direction:  FORWARD                                                 { $$ = FORWARD; }
1141                 | BACKWARD                                                              { $$ = BACKWARD; }
1142                 | /*EMPTY*/                                                             { $$ = FORWARD; /* default */ }
1143                 ;
1144
1145 fetch_how_many:  Iconst
1146                            { $$ = $1;
1147                                  if ($1 <= 0) elog(WARN,"Please specify nonnegative count for fetch",NULL); }
1148                 | ALL                                                   { $$ = 0; /* 0 means fetch all tuples*/}
1149                 | /*EMPTY*/                                             { $$ = 1; /*default*/ }
1150                 ;
1151
1152 opt_portal_name:  IN name                               { $$ = $2;}
1153                 | /*EMPTY*/                                             { $$ = NULL; }
1154                 ;
1155
1156
1157 /*****************************************************************************
1158  *
1159  *              QUERY:
1160  *                              GRANT [privileges] ON [relation_name_list] TO [GROUP] grantee
1161  *
1162  *****************************************************************************/
1163
1164 GrantStmt:  GRANT privileges ON relation_name_list TO grantee opt_with_grant
1165                                 {
1166                                         $$ = (Node*)makeAclStmt($2,$4,$6,'+');
1167                                         free($2);
1168                                         free($6);
1169                                 }
1170                 ;
1171
1172 privileges:  ALL PRIVILEGES
1173                                 {
1174                                  $$ = aclmakepriv("rwaR",0);
1175                                 }
1176                 | ALL
1177                                 {
1178                                  $$ = aclmakepriv("rwaR",0);
1179                                 }
1180                 | operation_commalist
1181                                 {
1182                                  $$ = $1;
1183                                 }
1184                 ;
1185
1186 operation_commalist:  operation
1187                                 {
1188                                                 $$ = aclmakepriv("",$1);
1189                                 }
1190                 | operation_commalist ',' operation
1191                                 {
1192                                                 $$ = aclmakepriv($1,$3);
1193                                                 free($1);
1194                                 }
1195                 ;
1196
1197 operation:  SELECT
1198                                 {
1199                                                 $$ = ACL_MODE_RD_CHR;
1200                                 }
1201                 | INSERT
1202                                 {
1203                                                 $$ = ACL_MODE_AP_CHR;
1204                                 }
1205                 | UPDATE
1206                                 {
1207                                                 $$ = ACL_MODE_WR_CHR;
1208                                 }
1209                 | DELETE
1210                                 {
1211                                                 $$ = ACL_MODE_WR_CHR;
1212                                 }
1213                 | RULE
1214                                 {
1215                                                 $$ = ACL_MODE_RU_CHR;
1216                                 }
1217                 ;
1218
1219 grantee:  PUBLIC
1220                                 {
1221                                                 $$ = aclmakeuser("A","");
1222                                 }
1223                 | GROUP ColId
1224                                 {
1225                                                 $$ = aclmakeuser("G",$2);
1226                                 }
1227                 | ColId
1228                                 {
1229                                                 $$ = aclmakeuser("U",$1);
1230                                 }
1231                 ;
1232
1233 opt_with_grant:  WITH GRANT OPTION
1234                                 {
1235                                         yyerror("WITH GRANT OPTION is not supported.  Only relation owners can set privileges");
1236                                  }
1237                 | /*EMPTY*/
1238                 ;
1239
1240
1241 /*****************************************************************************
1242  *
1243  *              QUERY:
1244  *                              REVOKE [privileges] ON [relation_name] FROM [user]
1245  *
1246  *****************************************************************************/
1247
1248 RevokeStmt:  REVOKE privileges ON relation_name_list FROM grantee
1249                                 {
1250                                         $$ = (Node*)makeAclStmt($2,$4,$6,'-');
1251                                         free($2);
1252                                         free($6);
1253                                 }
1254                 ;
1255
1256
1257 /*****************************************************************************
1258  *
1259  *              QUERY:
1260  *                              define [archive] index <indexname> on <relname>
1261  *                                using <access> "(" (<col> with <op>)+ ")" [with
1262  *                                <target_list>]
1263  *
1264  *      [where <qual>] is not supported anymore
1265  *****************************************************************************/
1266
1267 IndexStmt:      CREATE index_opt_unique INDEX index_name ON relation_name
1268                         access_method_clause '(' index_params ')' opt_with
1269                                 {
1270                                         /* should check that access_method is valid,
1271                                            etc ... but doesn't */
1272                                         IndexStmt *n = makeNode(IndexStmt);
1273                                         n->unique = $2;
1274                                         n->idxname = $4;
1275                                         n->relname = $6;
1276                                         n->accessMethod = $7;
1277                                         n->indexParams = $9;
1278                                         n->withClause = $11;
1279                                         n->whereClause = NULL;
1280                                         $$ = (Node *)n;
1281                                 }
1282                 ;
1283
1284 index_opt_unique:  UNIQUE                                               { $$ = TRUE; }
1285                 | /*EMPTY*/                                                             { $$ = FALSE; }
1286                 ;
1287
1288 access_method_clause:  USING access_method              { $$ = $2; }
1289                 | /*EMPTY*/                                                             { $$ = "btree"; }
1290                 ;
1291
1292 index_params:  index_list                                               { $$ = $1; }
1293                 | func_index                                                    { $$ = lcons($1,NIL); }
1294                 ;
1295
1296 index_list:  index_list ',' index_elem                  { $$ = lappend($1, $3); }
1297                 | index_elem                                                    { $$ = lcons($1, NIL); }
1298                 ;
1299
1300 func_index:  name '(' name_list ')' opt_type opt_class
1301                                 {
1302                                         $$ = makeNode(IndexElem);
1303                                         $$->name = $1;
1304                                         $$->args = $3;
1305                                         $$->class = $6;
1306                                         $$->tname = $5;
1307                                 }
1308                   ;
1309
1310 index_elem:  attr_name opt_type opt_class
1311                                 {
1312                                         $$ = makeNode(IndexElem);
1313                                         $$->name = $1;
1314                                         $$->args = NIL;
1315                                         $$->class = $3;
1316                                         $$->tname = $2;
1317                                 }
1318                 ;
1319
1320 opt_type:  ':' Typename                                                 { $$ = $2;}
1321                 | FOR Typename                                                  { $$ = $2;}
1322                 | /*EMPTY*/                                                             { $$ = NULL;}
1323                 ;
1324
1325 /* opt_class "WITH class" conflicts with preceeding opt_type
1326  *  for Typename of "TIMESTAMP WITH TIME ZONE"
1327  * So, remove "WITH class" from the syntax. OK??
1328  * - thomas 1997-10-12
1329  *              | WITH class                                                    { $$ = $2; }
1330  */
1331 opt_class:  class                                                               { $$ = $1; }
1332                 | USING class                                                   { $$ = $2; }
1333                 | /*EMPTY*/                                                             { $$ = NULL; }
1334                 ;
1335
1336
1337 /*****************************************************************************
1338  *
1339  *              QUERY:
1340  *                              extend index <indexname> [where <qual>]
1341  *
1342  *****************************************************************************/
1343
1344 ExtendStmt:  EXTEND INDEX index_name where_clause
1345                                 {
1346                                         ExtendStmt *n = makeNode(ExtendStmt);
1347                                         n->idxname = $3;
1348                                         n->whereClause = $4;
1349                                         $$ = (Node *)n;
1350                                 }
1351                 ;
1352
1353
1354 /*****************************************************************************
1355  *
1356  *              QUERY:
1357  *                              execute recipe <recipeName>
1358  *
1359  *****************************************************************************/
1360
1361 RecipeStmt:  EXECUTE RECIPE recipe_name
1362                                 {
1363                                         RecipeStmt *n;
1364                                         if (!IsTransactionBlock())
1365                                                 elog(WARN,"EXECUTE RECIPE may only be used in begin/end transaction blocks",NULL);
1366
1367                                         n = makeNode(RecipeStmt);
1368                                         n->recipeName = $3;
1369                                         $$ = (Node *)n;
1370                                 }
1371                 ;
1372
1373
1374 /*****************************************************************************
1375  *
1376  *              QUERY:
1377  *                              define function <fname>
1378  *                                         (language = <lang>, returntype = <typename>
1379  *                                              [, arch_pct = <percentage | pre-defined>]
1380  *                                              [, disk_pct = <percentage | pre-defined>]
1381  *                                              [, byte_pct = <percentage | pre-defined>]
1382  *                                              [, perbyte_cpu = <int | pre-defined>]
1383  *                                              [, percall_cpu = <int | pre-defined>]
1384  *                                              [, iscachable])
1385  *                                              [arg is (<type-1> { , <type-n>})]
1386  *                                              as <filename or code in language as appropriate>
1387  *
1388  *****************************************************************************/
1389
1390 ProcedureStmt:  CREATE FUNCTION def_name def_args
1391                          RETURNS def_arg opt_with AS Sconst LANGUAGE Sconst
1392                                 {
1393                                         ProcedureStmt *n = makeNode(ProcedureStmt);
1394                                         n->funcname = $3;
1395                                         n->defArgs = $4;
1396                                         n->returnType = (Node *)$6;
1397                                         n->withClause = $7;
1398                                         n->as = $9;
1399                                         n->language = $11;
1400                                         $$ = (Node *)n;
1401                                 };
1402
1403 opt_with:  WITH definition                                              { $$ = $2; }
1404                 | /* EMPTY */                                                   { $$ = NIL; }
1405                 ;
1406
1407 def_args:  '(' def_name_list ')'                                { $$ = $2; }
1408                 | '(' ')'                                                               { $$ = NIL; }
1409                 ;
1410
1411 def_name_list:  name_list;
1412
1413
1414 /*****************************************************************************
1415  *
1416  *              QUERY:
1417  *                              purge <relname> [before <date>] [after <date>]
1418  *                                or
1419  *                              purge <relname>  [after <date>] [before <date>]
1420  *
1421  *****************************************************************************/
1422
1423 PurgeStmt:      PURGE relation_name purge_quals
1424                                 {
1425                                         $3->relname = $2;
1426                                         $$ = (Node *)$3;
1427                                 }
1428                 ;
1429
1430 purge_quals:  before_clause
1431                                 {
1432                                         $$ = makeNode(PurgeStmt);
1433                                         $$->beforeDate = $1;
1434                                         $$->afterDate = NULL;
1435                                 }
1436                 | after_clause
1437                                 {
1438                                         $$ = makeNode(PurgeStmt);
1439                                         $$->beforeDate = NULL;
1440                                         $$->afterDate = $1;
1441                                 }
1442                 | before_clause after_clause
1443                                 {
1444                                         $$ = makeNode(PurgeStmt);
1445                                         $$->beforeDate = $1;
1446                                         $$->afterDate = $2;
1447                                 }
1448                 | after_clause before_clause
1449                                 {
1450                                         $$ = makeNode(PurgeStmt);
1451                                         $$->beforeDate = $2;
1452                                         $$->afterDate = $1;
1453                                 }
1454                 | /*EMPTY*/
1455                                 {
1456                                         $$ = makeNode(PurgeStmt);
1457                                         $$->beforeDate = NULL;
1458                                         $$->afterDate = NULL;
1459                                 }
1460                 ;
1461
1462 before_clause:  BEFORE date                             { $$ = $2; }
1463 after_clause:   AFTER date                              { $$ = $2; }
1464
1465
1466 /*****************************************************************************
1467  *
1468  *              QUERY:
1469  *
1470  *              remove function <funcname>
1471  *                              (REMOVE FUNCTION "funcname" (arg1, arg2, ...))
1472  *              remove aggregate <aggname>
1473  *                              (REMOVE AGGREGATE "aggname" "aggtype")
1474  *              remove operator <opname>
1475  *                              (REMOVE OPERATOR "opname" (leftoperand_typ rightoperand_typ))
1476  *              remove type <typename>
1477  *                              (REMOVE TYPE "typename")
1478  *              remove rule <rulename>
1479  *                              (REMOVE RULE "rulename")
1480  *
1481  *****************************************************************************/
1482
1483 RemoveStmt:  DROP remove_type name
1484                                 {
1485                                         RemoveStmt *n = makeNode(RemoveStmt);
1486                                         n->removeType = $2;
1487                                         n->name = $3;
1488                                         $$ = (Node *)n;
1489                                 }
1490                 ;
1491
1492 remove_type:  Type                                                              {  $$ = TYPE_P; }
1493                 | INDEX                                                                 {  $$ = INDEX; }
1494                 | RULE                                                                  {  $$ = RULE; }
1495                 | VIEW                                                                  {  $$ = VIEW; }
1496                 ;
1497
1498 RemoveAggrStmt:  DROP AGGREGATE name aggr_argtype
1499                                 {
1500                                                 RemoveAggrStmt *n = makeNode(RemoveAggrStmt);
1501                                                 n->aggname = $3;
1502                                                 n->aggtype = $4;
1503                                                 $$ = (Node *)n;
1504                                 }
1505                 ;
1506
1507 aggr_argtype:  name                                                             { $$ = $1; }
1508                 | '*'                                                                   { $$ = NULL; }
1509                 ;
1510
1511 RemoveFuncStmt:  DROP FUNCTION name '(' func_argtypes ')'
1512                                 {
1513                                         RemoveFuncStmt *n = makeNode(RemoveFuncStmt);
1514                                         n->funcname = $3;
1515                                         n->args = $5;
1516                                         $$ = (Node *)n;
1517                                 }
1518                 ;
1519
1520 func_argtypes:  name_list                                               { $$ = $1; }
1521                 | /*EMPTY*/                                                             { $$ = NIL; }
1522                 ;
1523
1524 RemoveOperStmt:  DROP OPERATOR all_Op '(' oper_argtypes ')'
1525                                 {
1526                                         RemoveOperStmt *n = makeNode(RemoveOperStmt);
1527                                         n->opname = $3;
1528                                         n->args = $5;
1529                                         $$ = (Node *)n;
1530                                 }
1531                 ;
1532
1533 all_Op:  Op | MathOp;
1534
1535 MathOp: '+'                             { $$ = "+"; }
1536                 | '-'                   { $$ = "-"; }
1537                 | '*'                   { $$ = "*"; }
1538                 | '/'                   { $$ = "/"; }
1539                 | '<'                   { $$ = "<"; }
1540                 | '>'                   { $$ = ">"; }
1541                 | '='                   { $$ = "="; }
1542                 ;
1543
1544 oper_argtypes:  name
1545                                 {
1546                                    elog(WARN,"parser: argument type missing (use NONE for unary operators)",NULL);
1547                                 }
1548                 | name ',' name
1549                                 { $$ = makeList(makeString($1), makeString($3), -1); }
1550                 | NONE ',' name                 /* left unary */
1551                                 { $$ = makeList(NULL, makeString($3), -1); }
1552                 | name ',' NONE                 /* right unary */
1553                                 { $$ = makeList(makeString($1), NULL, -1); }
1554                 ;
1555
1556
1557 /*****************************************************************************
1558  *
1559  *              QUERY:
1560  *                              rename <attrname1> in <relname> [*] to <attrname2>
1561  *                              rename <relname1> to <relname2>
1562  *
1563  *****************************************************************************/
1564
1565 RenameStmt:  ALTER TABLE relation_name opt_inh_star
1566                                   RENAME opt_column opt_name TO name
1567                                 {
1568                                         RenameStmt *n = makeNode(RenameStmt);
1569                                         n->relname = $3;
1570                                         n->inh = $4;
1571                                         n->column = $7;
1572                                         n->newname = $9;
1573                                         $$ = (Node *)n;
1574                                 }
1575                 ;
1576
1577 opt_name:  name                                                 { $$ = $1; }
1578                 | /*EMPTY*/                                             { $$ = NULL; }
1579                 ;
1580
1581 opt_column:  COLUMN                                             { $$ = COLUMN; }
1582                 | /*EMPTY*/                                             { $$ = 0; }
1583                 ;
1584
1585
1586 /*****************************************************************************
1587  *
1588  *              QUERY:  Define Rewrite Rule , Define Tuple Rule
1589  *                              Define Rule <old rules >
1590  *
1591  *              only rewrite rule is supported -- ay 9/94
1592  *
1593  *****************************************************************************/
1594
1595 RuleStmt:  CREATE RULE name AS
1596                    { QueryIsRule=TRUE; }
1597                    ON event TO event_object where_clause
1598                    DO opt_instead OptStmtList
1599                                 {
1600                                         RuleStmt *n = makeNode(RuleStmt);
1601                                         n->rulename = $3;
1602                                         n->event = $7;
1603                                         n->object = $9;
1604                                         n->whereClause = $10;
1605                                         n->instead = $12;
1606                                         n->actions = $13;
1607                                         $$ = (Node *)n;
1608                                 }
1609                 ;
1610
1611 OptStmtList:  NOTHING                                   { $$ = NIL; }
1612                 | OptimizableStmt                               { $$ = lcons($1, NIL); }
1613                 | '[' OptStmtBlock ']'                  { $$ = $2; }
1614                 ;
1615
1616 OptStmtBlock:  OptStmtMulti
1617                                 {  $$ = $1; }
1618                 | OptimizableStmt
1619                                 { $$ = lcons($1, NIL); }
1620                 ;
1621
1622 OptStmtMulti:  OptStmtMulti OptimizableStmt ';'
1623                                 {  $$ = lappend($1, $2); }
1624                 | OptStmtMulti OptimizableStmt
1625                                 {  $$ = lappend($1, $2); }
1626                 | OptimizableStmt ';'
1627                                 { $$ = lcons($1, NIL); }
1628                 ;
1629
1630 event_object:  relation_name '.' attr_name
1631                                 {
1632                                         $$ = makeNode(Attr);
1633                                         $$->relname = $1;
1634                                         $$->paramNo = NULL;
1635                                         $$->attrs = lcons(makeString($3), NIL);
1636                                         $$->indirection = NIL;
1637                                 }
1638                 | relation_name
1639                                 {
1640                                         $$ = makeNode(Attr);
1641                                         $$->relname = $1;
1642                                         $$->paramNo = NULL;
1643                                         $$->attrs = NIL;
1644                                         $$->indirection = NIL;
1645                                 }
1646                 ;
1647
1648 /* change me to select, update, etc. some day */
1649 event:  SELECT                                                  { $$ = CMD_SELECT; }
1650                 | UPDATE                                                { $$ = CMD_UPDATE; }
1651                 | DELETE                                                { $$ = CMD_DELETE; }
1652                 | INSERT                                                { $$ = CMD_INSERT; }
1653                  ;
1654
1655 opt_instead:  INSTEAD                                   { $$ = TRUE; }
1656                 | /* EMPTY */                                   { $$ = FALSE; }
1657                 ;
1658
1659
1660 /*****************************************************************************
1661  *
1662  *              QUERY:
1663  *                              NOTIFY <relation_name>  can appear both in rule bodies and
1664  *                              as a query-level command
1665  *
1666  *****************************************************************************/
1667
1668 NotifyStmt:  NOTIFY relation_name
1669                                 {
1670                                         NotifyStmt *n = makeNode(NotifyStmt);
1671                                         n->relname = $2;
1672                                         $$ = (Node *)n;
1673                                 }
1674                 ;
1675
1676 ListenStmt:  LISTEN relation_name
1677                                 {
1678                                         ListenStmt *n = makeNode(ListenStmt);
1679                                         n->relname = $2;
1680                                         $$ = (Node *)n;
1681                                 }
1682 ;
1683
1684
1685 /*****************************************************************************
1686  *
1687  *              Transactions:
1688  *
1689  *              abort transaction
1690  *                              (ABORT)
1691  *              begin transaction
1692  *                              (BEGIN)
1693  *              end transaction
1694  *                              (END)
1695  *
1696  *****************************************************************************/
1697
1698 TransactionStmt:  ABORT_TRANS TRANSACTION
1699                                 {
1700                                         TransactionStmt *n = makeNode(TransactionStmt);
1701                                         n->command = ABORT_TRANS;
1702                                         $$ = (Node *)n;
1703                                 }
1704                 | BEGIN_TRANS TRANSACTION
1705                                 {
1706                                         TransactionStmt *n = makeNode(TransactionStmt);
1707                                         n->command = BEGIN_TRANS;
1708                                         $$ = (Node *)n;
1709                                 }
1710                 | BEGIN_TRANS WORK
1711                                 {
1712                                         TransactionStmt *n = makeNode(TransactionStmt);
1713                                         n->command = BEGIN_TRANS;
1714                                         $$ = (Node *)n;
1715                                 }
1716                 | COMMIT WORK
1717                                 {
1718                                         TransactionStmt *n = makeNode(TransactionStmt);
1719                                         n->command = END_TRANS;
1720                                         $$ = (Node *)n;
1721                                 }
1722                 | END_TRANS TRANSACTION
1723                                 {
1724                                         TransactionStmt *n = makeNode(TransactionStmt);
1725                                         n->command = END_TRANS;
1726                                         $$ = (Node *)n;
1727                                 }
1728                 | ROLLBACK WORK
1729                                 {
1730                                         TransactionStmt *n = makeNode(TransactionStmt);
1731                                         n->command = ABORT_TRANS;
1732                                         $$ = (Node *)n;
1733                                 }
1734
1735                 | ABORT_TRANS
1736                                 {
1737                                         TransactionStmt *n = makeNode(TransactionStmt);
1738                                         n->command = ABORT_TRANS;
1739                                         $$ = (Node *)n;
1740                                 }
1741                 | BEGIN_TRANS
1742                                 {
1743                                         TransactionStmt *n = makeNode(TransactionStmt);
1744                                         n->command = BEGIN_TRANS;
1745                                         $$ = (Node *)n;
1746                                 }
1747                 | COMMIT
1748                                 {
1749                                         TransactionStmt *n = makeNode(TransactionStmt);
1750                                         n->command = END_TRANS;
1751                                         $$ = (Node *)n;
1752                                 }
1753
1754                 | END_TRANS
1755                                 {
1756                                         TransactionStmt *n = makeNode(TransactionStmt);
1757                                         n->command = END_TRANS;
1758                                         $$ = (Node *)n;
1759                                 }
1760                 | ROLLBACK
1761                                 {
1762                                         TransactionStmt *n = makeNode(TransactionStmt);
1763                                         n->command = ABORT_TRANS;
1764                                         $$ = (Node *)n;
1765                                 }
1766                 ;
1767
1768
1769 /*****************************************************************************
1770  *
1771  *              QUERY:
1772  *                              define view <viewname> '('target-list ')' [where <quals> ]
1773  *
1774  *****************************************************************************/
1775
1776 ViewStmt:  CREATE VIEW name AS RetrieveStmt
1777                                 {
1778                                         ViewStmt *n = makeNode(ViewStmt);
1779                                         n->viewname = $3;
1780                                         n->query = (Query *)$5;
1781                                         $$ = (Node *)n;
1782                                 }
1783                 ;
1784
1785
1786 /*****************************************************************************
1787  *
1788  *              QUERY:
1789  *                              load "filename"
1790  *
1791  *****************************************************************************/
1792
1793 LoadStmt:  LOAD file_name
1794                                 {
1795                                         LoadStmt *n = makeNode(LoadStmt);
1796                                         n->filename = $2;
1797                                         $$ = (Node *)n;
1798                                 }
1799                 ;
1800
1801
1802 /*****************************************************************************
1803  *
1804  *              QUERY:
1805  *                              createdb dbname
1806  *
1807  *****************************************************************************/
1808
1809 CreatedbStmt:  CREATE DATABASE database_name opt_database
1810                                 {
1811                                         CreatedbStmt *n = makeNode(CreatedbStmt);
1812                                         n->dbname = $3;
1813                                         n->dbpath = $4;
1814                                         $$ = (Node *)n;
1815                                 }
1816                 ;
1817
1818 opt_database:  WITH LOCATION '=' location               { $$ = $4; }
1819                 | /*EMPTY*/                                                             { $$ = NULL; }
1820                 ;
1821
1822 location:  Sconst                                                               { $$ = $1; }
1823                 | DEFAULT                                                               { $$ = NULL; }
1824                 | /*EMPTY*/                                                             { $$ = NULL; }
1825                 ;
1826
1827 /*****************************************************************************
1828  *
1829  *              QUERY:
1830  *                              destroydb dbname
1831  *
1832  *****************************************************************************/
1833
1834 DestroydbStmt:  DROP DATABASE database_name
1835                                 {
1836                                         DestroydbStmt *n = makeNode(DestroydbStmt);
1837                                         n->dbname = $3;
1838                                         $$ = (Node *)n;
1839                                 }
1840                 ;
1841
1842
1843 /*****************************************************************************
1844  *
1845  *              QUERY:
1846  *                              cluster <index_name> on <relation_name>
1847  *
1848  *****************************************************************************/
1849
1850 ClusterStmt:  CLUSTER index_name ON relation_name
1851                                 {
1852                                    ClusterStmt *n = makeNode(ClusterStmt);
1853                                    n->relname = $4;
1854                                    n->indexname = $2;
1855                                    $$ = (Node*)n;
1856                                 }
1857                 ;
1858
1859
1860 /*****************************************************************************
1861  *
1862  *              QUERY:
1863  *                              vacuum
1864  *
1865  *****************************************************************************/
1866
1867 VacuumStmt:  VACUUM opt_verbose opt_analyze
1868                                 {
1869                                         VacuumStmt *n = makeNode(VacuumStmt);
1870                                         n->verbose = $2;
1871                                         n->analyze = $3;
1872                                         n->vacrel = NULL;
1873                                         n->va_spec = NIL;
1874                                         $$ = (Node *)n;
1875                                 }
1876                 | VACUUM opt_verbose relation_name opt_analyze opt_va_list
1877                                 {
1878                                         VacuumStmt *n = makeNode(VacuumStmt);
1879                                         n->verbose = $2;
1880                                         n->analyze = $4;
1881                                         n->vacrel = $3;
1882                                         n->va_spec = $5;
1883                                         if ( $5 != NIL && !$4 )
1884                                                 elog(WARN,"parser: syntax error at or near \"(\"",NULL);
1885                                         $$ = (Node *)n;
1886                                 }
1887                 ;
1888
1889 opt_verbose:  VERBOSE                                                   { $$ = TRUE; }
1890                 | /* EMPTY */                                                   { $$ = FALSE; }
1891                 ;
1892
1893 opt_analyze:  ANALYZE                                                   { $$ = TRUE; }
1894                 | /* EMPTY */                                                   { $$ = FALSE; }
1895                 ;
1896
1897 opt_va_list:  '(' va_list ')'
1898                                 { $$ = $2; }
1899                 | /* EMPTY */
1900                                 { $$ = NIL; }
1901                 ;
1902
1903 va_list:  name
1904                                 { $$=lcons($1,NIL); }
1905                 | va_list ',' name
1906                                 { $$=lappend($1,$3); }
1907                 ;
1908
1909
1910 /*****************************************************************************
1911  *
1912  *              QUERY:
1913  *                              EXPLAIN query
1914  *
1915  *****************************************************************************/
1916
1917 ExplainStmt:  EXPLAIN opt_verbose OptimizableStmt
1918                                 {
1919                                         ExplainStmt *n = makeNode(ExplainStmt);
1920                                         n->verbose = $2;
1921                                         n->query = (Query*)$3;
1922                                         $$ = (Node *)n;
1923                                 }
1924                 ;
1925
1926
1927 /*****************************************************************************
1928  *                                                                                                                                                       *
1929  *              Optimizable Stmts:                                                                                                       *
1930  *                                                                                                                                                       *
1931  *              one of the five queries processed by the planner                                         *
1932  *                                                                                                                                                       *
1933  *              [ultimately] produces query-trees as specified                                           *
1934  *              in the query-spec document in ~postgres/ref                                                      *
1935  *                                                                                                                                                       *
1936  *****************************************************************************/
1937
1938 OptimizableStmt:  RetrieveStmt
1939                 | CursorStmt
1940                 | ReplaceStmt
1941                 | AppendStmt
1942                 | NotifyStmt
1943                 | DeleteStmt                                    /* by default all are $$=$1 */
1944                 ;
1945
1946
1947 /*****************************************************************************
1948  *
1949  *              QUERY:
1950  *                              INSERT STATEMENTS
1951  *
1952  *****************************************************************************/
1953
1954 AppendStmt:  INSERT INTO relation_name opt_column_list insert_rest
1955                                 {
1956                                         $5->relname = $3;
1957                                         $5->cols = $4;
1958                                         $$ = (Node *)$5;
1959                                 }
1960                 ;
1961
1962 insert_rest:  VALUES '(' res_target_list2 ')'
1963                                 {
1964                                         $$ = makeNode(AppendStmt);
1965                                         $$->targetList = $3;
1966                                         $$->fromClause = NIL;
1967                                         $$->whereClause = NULL;
1968                                 }
1969                 | SELECT res_target_list2 from_clause where_clause
1970                                 {
1971                                         $$ = makeNode(AppendStmt);
1972                                         $$->targetList = $2;
1973                                         $$->fromClause = $3;
1974                                         $$->whereClause = $4;
1975                                 }
1976                 ;
1977
1978 opt_column_list:  '(' columnList ')'                    { $$ = $2; }
1979                 | /*EMPTY*/                                                             { $$ = NIL; }
1980                 ;
1981
1982 columnList:
1983                   columnList ',' columnElem
1984                                 { $$ = lappend($1, $3); }
1985                 | columnElem
1986                                 { $$ = lcons($1, NIL); }
1987                 ;
1988
1989 columnElem:  ColId opt_indirection
1990                                 {
1991                                         Ident *id = makeNode(Ident);
1992                                         id->name = $1;
1993                                         id->indirection = $2;
1994                                         $$ = (Node *)id;
1995                                 }
1996                 ;
1997
1998
1999 /*****************************************************************************
2000  *
2001  *              QUERY:
2002  *                              DELETE STATEMENTS
2003  *
2004  *****************************************************************************/
2005
2006 DeleteStmt:  DELETE FROM relation_name
2007                          where_clause
2008                                 {
2009                                         DeleteStmt *n = makeNode(DeleteStmt);
2010                                         n->relname = $3;
2011                                         n->whereClause = $4;
2012                                         $$ = (Node *)n;
2013                                 }
2014                 ;
2015
2016
2017 /*****************************************************************************
2018  *
2019  *              QUERY:
2020  *                              ReplaceStmt (UPDATE)
2021  *
2022  *****************************************************************************/
2023
2024 ReplaceStmt:  UPDATE relation_name
2025                           SET res_target_list
2026                           from_clause
2027                           where_clause
2028                                 {
2029                                         ReplaceStmt *n = makeNode(ReplaceStmt);
2030                                         n->relname = $2;
2031                                         n->targetList = $4;
2032                                         n->fromClause = $5;
2033                                         n->whereClause = $6;
2034                                         $$ = (Node *)n;
2035                                 }
2036                 ;
2037
2038
2039 /*****************************************************************************
2040  *
2041  *              QUERY:
2042  *                              CURSOR STATEMENTS
2043  *
2044  *****************************************************************************/
2045
2046 CursorStmt:  DECLARE name opt_binary CURSOR FOR
2047                          SELECT opt_unique res_target_list2
2048                          from_clause where_clause group_clause sort_clause
2049                                 {
2050                                         CursorStmt *n = makeNode(CursorStmt);
2051
2052                                         /* from PORTAL name */
2053                                         /*
2054                                          *      15 august 1991 -- since 3.0 postgres does locking
2055                                          *      right, we discovered that portals were violating
2056                                          *      locking protocol.  portal locks cannot span xacts.
2057                                          *      as a short-term fix, we installed the check here.
2058                                          *                                                      -- mao
2059                                          */
2060                                         if (!IsTransactionBlock())
2061                                                 elog(WARN,"Named portals may only be used in begin/end transaction blocks",NULL);
2062
2063                                         n->portalname = $2;
2064                                         n->binary = $3;
2065                                         n->unique = $7;
2066                                         n->targetList = $8;
2067                                         n->fromClause = $9;
2068                                         n->whereClause = $10;
2069                                         n->groupClause = $11;
2070                                         n->sortClause = $12;
2071                                         $$ = (Node *)n;
2072                                 }
2073                 ;
2074
2075
2076 /*****************************************************************************
2077  *
2078  *              QUERY:
2079  *                              SELECT STATEMENTS
2080  *
2081  *****************************************************************************/
2082
2083 RetrieveStmt:  SELECT opt_unique res_target_list2
2084                          result from_clause where_clause
2085                          group_clause having_clause
2086                          union_clause sort_clause
2087                                 {
2088                                         RetrieveStmt *n = makeNode(RetrieveStmt);
2089                                         n->unique = $2;
2090                                         n->targetList = $3;
2091                                         n->into = $4;
2092                                         n->fromClause = $5;
2093                                         n->whereClause = $6;
2094                                         n->groupClause = $7;
2095                                         n->havingClause = $8;
2096                                         n->selectClause = $9;
2097                                         n->sortClause = $10;
2098                                         $$ = (Node *)n;
2099                                 }
2100                 ;
2101
2102 union_clause:  UNION opt_union select_list              { $$ = $3; }
2103                 | /*EMPTY*/                                                             { $$ = NIL; }
2104                 ;
2105
2106 select_list:  select_list UNION opt_union SubSelect
2107                                 { $$ = lappend($1, $4); }
2108                 | SubSelect
2109                                 { $$ = lcons($1, NIL); }
2110                 ;
2111
2112 SubSelect:      SELECT opt_unique res_target_list2
2113                          from_clause where_clause
2114                          group_clause having_clause
2115                                 {
2116                                         SubSelect *n = makeNode(SubSelect);
2117                                         n->unique = $2;
2118                                         n->targetList = $3;
2119                                         n->fromClause = $4;
2120                                         n->whereClause = $5;
2121                                         n->groupClause = $6;
2122                                         n->havingClause = $7;
2123                                         $$ = (Node *)n;
2124                                 }
2125                 ;
2126
2127 result:  INTO TABLE relation_name
2128                                 {  $$= $3;      /* should check for archive level */  }
2129                 | /*EMPTY*/
2130                                 {  $$ = NULL;  }
2131                 ;
2132
2133 opt_union:  ALL                                                                 { $$ = TRUE; }
2134                 | /*EMPTY*/                                                             { $$ = FALSE; }
2135                 ;
2136
2137 opt_unique:  DISTINCT                                                   { $$ = "*"; }
2138                 | DISTINCT ON ColId                                             { $$ = $3; }
2139                 | ALL                                                                   { $$ = NULL; }
2140                 | /*EMPTY*/                                                             { $$ = NULL; }
2141                 ;
2142
2143 sort_clause:  ORDER BY sortby_list                              { $$ = $3; }
2144                 | /*EMPTY*/                                                             { $$ = NIL; }
2145                 ;
2146
2147 sortby_list:  sortby                                                    { $$ = lcons($1, NIL); }
2148                 | sortby_list ',' sortby                                { $$ = lappend($1, $3); }
2149                 ;
2150
2151 sortby:  ColId OptUseOp
2152                                 {
2153                                         $$ = makeNode(SortGroupBy);
2154                                         $$->resno = 0;
2155                                         $$->range = NULL;
2156                                         $$->name = $1;
2157                                         $$->useOp = $2;
2158                                 }
2159                 | ColId '.' ColId OptUseOp
2160                                 {
2161                                         $$ = makeNode(SortGroupBy);
2162                                         $$->resno = 0;
2163                                         $$->range = $1;
2164                                         $$->name = $3;
2165                                         $$->useOp = $4;
2166                                 }
2167                 | Iconst OptUseOp
2168                                 {
2169                                         $$ = makeNode(SortGroupBy);
2170                                         $$->resno = $1;
2171                                         $$->range = NULL;
2172                                         $$->name = NULL;
2173                                         $$->useOp = $2;
2174                                 }
2175                 ;
2176
2177 OptUseOp:  USING Op                                                             { $$ = $2; }
2178                 | USING '<'                                                             { $$ = "<"; }
2179                 | USING '>'                                                             { $$ = ">"; }
2180                 | ASC                                                                   { $$ = "<"; }
2181                 | DESC                                                                  { $$ = ">"; }
2182                 | /*EMPTY*/                                                             { $$ = "<"; /*default*/ }
2183                 ;
2184
2185 /*
2186  *      jimmy bell-style recursive queries aren't supported in the
2187  *      current system.
2188  *
2189  *      ...however, recursive addattr and rename supported.  make special
2190  *      cases for these.
2191  *
2192  *      XXX i believe '*' should be the default behavior, but...
2193  */
2194 opt_inh_star:  '*'                                                              { $$ = TRUE; }
2195                 | /*EMPTY*/                                                             { $$ = FALSE; }
2196                 ;
2197
2198 relation_name_list:  name_list;
2199
2200 name_list:  name
2201                                 {       $$ = lcons(makeString($1),NIL); }
2202                 | name_list ',' name
2203                                 {       $$ = lappend($1,makeString($3)); }
2204                 ;
2205
2206 group_clause:  GROUP BY groupby_list                    { $$ = $3; }
2207                 | /*EMPTY*/                                                             { $$ = NIL; }
2208                 ;
2209
2210 groupby_list:  groupby                                                  { $$ = lcons($1, NIL); }
2211                 | groupby_list ',' groupby                              { $$ = lappend($1, $3); }
2212                 ;
2213
2214 groupby:  ColId
2215                                 {
2216                                         $$ = makeNode(SortGroupBy);
2217                                         $$->resno = 0;
2218                                         $$->range = NULL;
2219                                         $$->name = $1;
2220                                         $$->useOp = NULL;
2221                                 }
2222                 | ColId '.' ColId
2223                                 {
2224                                         $$ = makeNode(SortGroupBy);
2225                                         $$->resno = 0;
2226                                         $$->range = $1;
2227                                         $$->name = $3;
2228                                         $$->useOp = NULL;
2229                                 }
2230                 | Iconst
2231                                 {
2232                                         $$ = makeNode(SortGroupBy);
2233                                         $$->resno = $1;
2234                                         $$->range = NULL;
2235                                         $$->name = NULL;
2236                                         $$->useOp = NULL;
2237                                 }
2238                 ;
2239
2240 having_clause:  HAVING a_expr                                   { $$ = $2; }
2241                 | /*EMPTY*/                                                             { $$ = NULL; }
2242                 ;
2243
2244
2245 /*****************************************************************************
2246  *
2247  *      clauses common to all Optimizable Stmts:
2248  *              from_clause             -
2249  *              where_clause    -
2250  *
2251  *****************************************************************************/
2252
2253 from_clause:  FROM '(' relation_expr join_expr JOIN relation_expr join_spec ')'
2254                                 {
2255                                         $$ = NIL;
2256                                         elog(WARN,"JOIN not yet implemented",NULL);
2257                                 }
2258                 | FROM from_list                                                { $$ = $2; }
2259                 | /*EMPTY*/                                                             { $$ = NIL; }
2260                 ;
2261
2262 from_list:      from_list ',' from_val
2263                                 { $$ = lappend($1, $3); }
2264                 | from_val CROSS JOIN from_val
2265                                 { elog(WARN,"CROSS JOIN not yet implemented",NULL); }
2266                 | from_val
2267                                 { $$ = lcons($1, NIL); }
2268                 ;
2269
2270 from_val:  relation_expr AS ColLabel
2271                                 {
2272                                         $$ = makeNode(RangeVar);
2273                                         $$->relExpr = $1;
2274                                         $$->name = $3;
2275                                 }
2276                 | relation_expr ColId
2277                                 {
2278                                         $$ = makeNode(RangeVar);
2279                                         $$->relExpr = $1;
2280                                         $$->name = $2;
2281                                 }
2282                 | relation_expr
2283                                 {
2284                                         $$ = makeNode(RangeVar);
2285                                         $$->relExpr = $1;
2286                                         $$->name = NULL;
2287                                 }
2288                 ;
2289
2290 join_expr:  NATURAL join_expr                                   { $$ = NULL; }
2291                 | FULL join_outer
2292                                 { elog(WARN,"FULL OUTER JOIN not yet implemented",NULL); }
2293                 | LEFT join_outer
2294                                 { elog(WARN,"LEFT OUTER JOIN not yet implemented",NULL); }
2295                 | RIGHT join_outer
2296                                 { elog(WARN,"RIGHT OUTER JOIN not yet implemented",NULL); }
2297                 | OUTER_P
2298                                 { elog(WARN,"OUTER JOIN not yet implemented",NULL); }
2299                 | INNER_P
2300                                 { elog(WARN,"INNER JOIN not yet implemented",NULL); }
2301                 | UNION
2302                                 { elog(WARN,"UNION JOIN not yet implemented",NULL); }
2303                 | /*EMPTY*/
2304                                 { elog(WARN,"INNER JOIN not yet implemented",NULL); }
2305                 ;
2306
2307 join_outer:  OUTER_P                                                    { $$ = NULL; }
2308                 | /*EMPTY*/                                                             { $$ = NULL;  /* no qualifiers */ }
2309                 ;
2310
2311 join_spec:      ON '(' a_expr ')'                                       { $$ = NULL; }
2312                 | USING '(' join_list ')'                               { $$ = NULL; }
2313                 | /*EMPTY*/                                                             { $$ = NULL;  /* no qualifiers */ }
2314                 ;
2315
2316 join_list:  join_using                                                  { $$ = lcons($1, NIL); }
2317                 | join_list ',' join_using                              { $$ = lappend($1, $3); }
2318                 ;
2319
2320 join_using:  ColId
2321                                 {
2322                                         $$ = makeNode(SortGroupBy);
2323                                         $$->resno = 0;
2324                                         $$->range = NULL;
2325                                         $$->name = $1;
2326                                         $$->useOp = NULL;
2327                                 }
2328                 | ColId '.' ColId
2329                                 {
2330                                         $$ = makeNode(SortGroupBy);
2331                                         $$->resno = 0;
2332                                         $$->range = $1;
2333                                         $$->name = $3;
2334                                         $$->useOp = NULL;
2335                                 }
2336                 | Iconst
2337                                 {
2338                                         $$ = makeNode(SortGroupBy);
2339                                         $$->resno = $1;
2340                                         $$->range = NULL;
2341                                         $$->name = NULL;
2342                                         $$->useOp = NULL;
2343                                 }
2344                 ;
2345
2346 where_clause:  WHERE a_expr                                             { $$ = $2; }
2347                 | /*EMPTY*/                                                             { $$ = NULL;  /* no qualifiers */ }
2348                 ;
2349
2350 relation_expr:  relation_name
2351                                 {
2352                                         /* normal relations */
2353                                         $$ = makeNode(RelExpr);
2354                                         $$->relname = $1;
2355                                         $$->inh = FALSE;
2356                                         $$->timeRange = NULL;
2357                                 }
2358                 | relation_name '*'                               %prec '='
2359                                 {
2360                                         /* inheiritance query */
2361                                         $$ = makeNode(RelExpr);
2362                                         $$->relname = $1;
2363                                         $$->inh = TRUE;
2364                                         $$->timeRange = NULL;
2365                                 }
2366                 | relation_name time_range
2367                                 {
2368                                         /* time-qualified query */
2369                                         $$ = makeNode(RelExpr);
2370                                         $$->relname = $1;
2371                                         $$->inh = FALSE;
2372                                         $$->timeRange = $2;
2373                                 }
2374                 ;
2375
2376 /* Time travel
2377  * Range specification clause.
2378  */
2379 time_range:  '[' opt_range_start ',' opt_range_end ']'
2380                                 {
2381                                         $$ = makeNode(TimeRange);
2382                                         $$->startDate = $2;
2383                                         $$->endDate = $4;
2384                                         elog (WARN, "time travel is no longer available");
2385                                 }
2386                 | '[' date ']'
2387                                 {
2388                                         $$ = makeNode(TimeRange);
2389                                         $$->startDate = $2;
2390                                         $$->endDate = NULL;
2391                                         elog (WARN, "time travel is no longer available");
2392                                 }
2393                 ;
2394
2395 opt_range_start:  date
2396                 | /*EMPTY*/                                                             { $$ = "epoch"; }
2397                 ;
2398
2399 opt_range_end:  date
2400                 | /*EMPTY*/                                                             { $$ = "now"; }
2401                 ;
2402
2403 opt_array_bounds:  '[' ']' nest_array_bounds
2404                                 {  $$ = lcons(makeInteger(-1), $3); }
2405                 | '[' Iconst ']' nest_array_bounds
2406                                 {  $$ = lcons(makeInteger($2), $4); }
2407                 | /* EMPTY */
2408                                 {  $$ = NIL; }
2409                 ;
2410
2411 nest_array_bounds:      '[' ']' nest_array_bounds
2412                                 {  $$ = lcons(makeInteger(-1), $3); }
2413                 | '[' Iconst ']' nest_array_bounds
2414                                 {  $$ = lcons(makeInteger($2), $4); }
2415                 | /*EMPTY*/
2416                                 {  $$ = NIL; }
2417                 ;
2418
2419
2420 /*****************************************************************************
2421  *
2422  *      Type syntax
2423  *              SQL92 introduces a large amount of type-specific syntax.
2424  *              Define individual clauses to handle these cases, and use
2425  *               the generic case to handle regular type-extensible Postgres syntax.
2426  *              - thomas 1997-10-10
2427  *
2428  *****************************************************************************/
2429
2430 Typename:  Array opt_array_bounds
2431                                 {
2432                                         $$ = $1;
2433                                         $$->arrayBounds = $2;
2434
2435                                         /* Is this the name of a complex type? If so, implement
2436                                          * it as a set.
2437                                          */
2438                                         if (!strcmp(saved_relname, $$->name))
2439                                                 /* This attr is the same type as the relation
2440                                                  * being defined. The classic example: create
2441                                                  * emp(name=text,mgr=emp)
2442                                                  */
2443                                                 $$->setof = TRUE;
2444                                         else if (get_typrelid((Type)type($$->name)) != InvalidOid)
2445                                                  /* (Eventually add in here that the set can only
2446                                                   * contain one element.)
2447                                                   */
2448                                                 $$->setof = TRUE;
2449                                         else
2450                                                 $$->setof = FALSE;
2451                                 }
2452                 | Character
2453                 | SETOF Array
2454                                 {
2455                                         $$ = $2;
2456                                         $$->setof = TRUE;
2457                                 }
2458                 ;
2459
2460 Array:  Generic
2461                 | Datetime
2462                 | Numeric
2463                 ;
2464
2465 Generic:  generic
2466                                 {
2467                                         $$ = makeNode(TypeName);
2468                                         $$->name = xlateSqlType($1);
2469                                 }
2470                 ;
2471
2472 generic:  Id                                                                    { $$ = $1; }
2473                 | TYPE_P                                                                { $$ = xlateSqlType("type"); }
2474                 | DOUBLE PRECISION                                              { $$ = xlateSqlType("float8"); }
2475                 ;
2476
2477 /* SQL92 numeric data types
2478  * Check FLOAT() precision limits assuming IEEE floating types.
2479  * Provide rudimentary DECIMAL() and NUMERIC() implementations
2480  *  by checking parameters and making sure they match what is possible with INTEGER.
2481  * - thomas 1997-09-18
2482  */
2483 Numeric:  FLOAT opt_float
2484                                 {
2485                                         $$ = makeNode(TypeName);
2486                                         $$->name = xlateSqlType($2);
2487                                 }
2488                 | DECIMAL opt_decimal
2489                                 {
2490                                         $$ = makeNode(TypeName);
2491                                         $$->name = xlateSqlType("integer");
2492                                 }
2493                 | NUMERIC opt_numeric
2494                                 {
2495                                         $$ = makeNode(TypeName);
2496                                         $$->name = xlateSqlType("integer");
2497                                 }
2498                 ;
2499
2500 opt_float:  '(' Iconst ')'
2501                                 {
2502                                         if ($2 < 1)
2503                                                 elog(WARN,"precision for FLOAT must be at least 1",NULL);
2504                                         else if ($2 < 7)
2505                                                 $$ = xlateSqlType("float4");
2506                                         else if ($2 < 16)
2507                                                 $$ = xlateSqlType("float8");
2508                                         else
2509                                                 elog(WARN,"precision for FLOAT must be less than 16",NULL);
2510                                 }
2511                 | /*EMPTY*/
2512                                 {
2513                                         $$ = xlateSqlType("float8");
2514                                 }
2515                 ;
2516
2517 opt_numeric:  '(' Iconst ',' Iconst ')'
2518                                 {
2519                                         if ($2 != 9)
2520                                                 elog(WARN,"NUMERIC precision %d must be 9",$2);
2521                                         if ($4 != 0)
2522                                                 elog(WARN,"NUMERIC scale %d must be zero",$4);
2523                                 }
2524                 | '(' Iconst ')'
2525                                 {
2526                                         if ($2 != 9)
2527                                                 elog(WARN,"NUMERIC precision %d must be 9",$2);
2528                                 }
2529                 | /*EMPTY*/
2530                                 {
2531                                         $$ = NULL;
2532                                 }
2533                 ;
2534
2535 opt_decimal:  '(' Iconst ',' Iconst ')'
2536                                 {
2537                                         if ($2 > 9)
2538                                                 elog(WARN,"DECIMAL precision %d exceeds implementation limit of 9",$2);
2539                                         if ($4 != 0)
2540                                                 elog(WARN,"DECIMAL scale %d must be zero",$4);
2541                                         $$ = NULL;
2542                                 }
2543                 | '(' Iconst ')'
2544                                 {
2545                                         if ($2 > 9)
2546                                                 elog(WARN,"DECIMAL precision %d exceeds implementation limit of 9",$2);
2547                                         $$ = NULL;
2548                                 }
2549                 | /*EMPTY*/
2550                                 {
2551                                         $$ = NULL;
2552                                 }
2553                 ;
2554
2555 /* SQL92 character data types
2556  * The following implements CHAR() and VARCHAR().
2557  * We do it here instead of the 'Generic' production
2558  * because we don't want to allow arrays of VARCHAR().
2559  * I haven't thought about whether that will work or not.
2560  *                                                              - ay 6/95
2561  */
2562 Character:  character '(' Iconst ')'
2563                                 {
2564                                         $$ = makeNode(TypeName);
2565                                         if (!strcasecmp($1, "char"))
2566                                                 $$->name = xlateSqlType("bpchar");
2567                                         else if (!strcasecmp($1, "varchar"))
2568                                                 $$->name = xlateSqlType("varchar");
2569                                         else
2570                                                 yyerror("parse error");
2571                                         if ($3 < 1)
2572                                                 elog(WARN,"length for '%s' type must be at least 1",$1);
2573                                         else if ($3 > 4096)
2574                                                 /* we can store a char() of length up to the size
2575                                                  * of a page (8KB) - page headers and friends but
2576                                                  * just to be safe here...      - ay 6/95
2577                                                  * XXX note this hardcoded limit - thomas 1997-07-13
2578                                                  */
2579                                                 elog(WARN,"length for type '%s' cannot exceed 4096",$1);
2580
2581                                         /* we actually implement this sort of like a varlen, so
2582                                          * the first 4 bytes is the length. (the difference
2583                                          * between this and "text" is that we blank-pad and
2584                                          * truncate where necessary
2585                                          */
2586                                         $$->typlen = 4 + $3;
2587                                 }
2588                 | character
2589                                 {
2590                                         $$ = makeNode(TypeName);
2591                                         $$->name = xlateSqlType($1);
2592                                 }
2593                 ;
2594
2595 character:  CHARACTER opt_varying opt_charset opt_collate
2596                                 {
2597                                         char *type, *c;
2598                                         if (($3 == NULL) || (strcasecmp($3, "sql_text") == 0)) {
2599                                                 if ($2) type = xlateSqlType("varchar");
2600                                                 else type = xlateSqlType("char");
2601                                         } else {
2602                                                 if ($2) {
2603                                                         c = palloc(strlen("var") + strlen($3) + 1);
2604                                                         strcpy(c, "var");
2605                                                         strcat(c, $3);
2606                                                         type = xlateSqlType(c);
2607                                                 } else {
2608                                                         type = xlateSqlType($3);
2609                                                 }
2610                                         };
2611                                         if ($4 != NULL)
2612                                         elog(WARN,"COLLATE %s not yet implemented",$4);
2613                                         $$ = type;
2614                                 }
2615                 | CHAR opt_varying                                              { $$ = xlateSqlType($2? "varchar": "char"); }
2616                 | VARCHAR                                                               { $$ = xlateSqlType("varchar"); }
2617                 | NATIONAL CHARACTER opt_varying                { $$ = xlateSqlType($3? "varchar": "char"); }
2618                 | NCHAR opt_varying                                             { $$ = xlateSqlType($2? "varchar": "char"); }
2619                 ;
2620
2621 opt_varying:  VARYING                                                   { $$ = TRUE; }
2622                 | /*EMPTY*/                                                             { $$ = FALSE; }
2623                 ;
2624
2625 opt_charset:  CHARACTER SET ColId                               { $$ = $3; }
2626                 | /*EMPTY*/                                                             { $$ = NULL; }
2627                 ;
2628
2629 opt_collate:  COLLATE ColId                                             { $$ = $2; }
2630                 | /*EMPTY*/                                                             { $$ = NULL; }
2631                 ;
2632
2633 Datetime:  datetime
2634                                 {
2635                                         $$ = makeNode(TypeName);
2636                                         $$->name = xlateSqlType($1);
2637                                 }
2638                 | TIMESTAMP opt_timezone
2639                                 {
2640                                         $$ = makeNode(TypeName);
2641                                         $$->name = xlateSqlType("timestamp");
2642                                         $$->timezone = $2;
2643                                 }
2644                 | TIME
2645                                 {
2646                                         $$ = makeNode(TypeName);
2647                                         $$->name = xlateSqlType("time");
2648                                 }
2649                 | INTERVAL opt_interval
2650                                 {
2651                                         $$ = makeNode(TypeName);
2652                                         $$->name = xlateSqlType("interval");
2653                                 }
2654                 ;
2655
2656 datetime:  YEAR_P                                                               { $$ = "year"; }
2657                 | MONTH_P                                                               { $$ = "month"; }
2658                 | DAY_P                                                                 { $$ = "day"; }
2659                 | HOUR_P                                                                { $$ = "hour"; }
2660                 | MINUTE_P                                                              { $$ = "minute"; }
2661                 | SECOND_P                                                              { $$ = "second"; }
2662                 ;
2663
2664 opt_timezone:  WITH TIME ZONE                                   { $$ = TRUE; }
2665                 | /*EMPTY*/                                                             { $$ = FALSE; }
2666                 ;
2667
2668 opt_interval:  datetime                                                 { $$ = lcons($1, NIL); }
2669                 | YEAR_P TO MONTH_P                                             { $$ = NIL; }
2670                 | DAY_P TO HOUR_P                                               { $$ = NIL; }
2671                 | DAY_P TO MINUTE_P                                             { $$ = NIL; }
2672                 | DAY_P TO SECOND_P                                             { $$ = NIL; }
2673                 | HOUR_P TO MINUTE_P                                    { $$ = NIL; }
2674                 | HOUR_P TO SECOND_P                                    { $$ = NIL; }
2675                 | /* EMPTY */                                                   { $$ = NIL; }
2676                 ;
2677
2678
2679 /*****************************************************************************
2680  *
2681  *      expression grammar, still needs some cleanup
2682  *
2683  *****************************************************************************/
2684
2685 a_expr_or_null:  a_expr
2686                                 { $$ = $1;}
2687                 | Pnull
2688                                 {
2689                                         A_Const *n = makeNode(A_Const);
2690                                         n->val.type = T_Null;
2691                                         $$ = (Node *)n;
2692                                 }
2693
2694 a_expr:  attr opt_indirection
2695                                 {
2696                                         $1->indirection = $2;
2697                                         $$ = (Node *)$1;
2698                                 }
2699                 | AexprConst
2700                                 {       $$ = $1;  }
2701                 | '-' a_expr %prec UMINUS
2702                                 {       $$ = makeA_Expr(OP, "-", NULL, $2); }
2703                 | a_expr '+' a_expr
2704                                 {       $$ = makeA_Expr(OP, "+", $1, $3); }
2705                 | a_expr '-' a_expr
2706                                 {       $$ = makeA_Expr(OP, "-", $1, $3); }
2707                 | a_expr '/' a_expr
2708                                 {       $$ = makeA_Expr(OP, "/", $1, $3); }
2709                 | a_expr '*' a_expr
2710                                 {       $$ = makeA_Expr(OP, "*", $1, $3); }
2711                 | a_expr '<' a_expr
2712                                 {       $$ = makeA_Expr(OP, "<", $1, $3); }
2713                 | a_expr '>' a_expr
2714                                 {       $$ = makeA_Expr(OP, ">", $1, $3); }
2715                 | a_expr '=' a_expr
2716                                 {       $$ = makeA_Expr(OP, "=", $1, $3); }
2717                 | ':' a_expr
2718                                 {       $$ = makeA_Expr(OP, ":", NULL, $2); }
2719                 | ';' a_expr
2720                                 {       $$ = makeA_Expr(OP, ";", NULL, $2); }
2721                 | '|' a_expr
2722                                 {       $$ = makeA_Expr(OP, "|", NULL, $2); }
2723                 | AexprConst TYPECAST Typename
2724                                 {
2725                                         /* AexprConst can be either A_Const or ParamNo */
2726                                         if (nodeTag($1) == T_A_Const)
2727                                                 ((A_Const *)$1)->typename = $3;
2728                                         else
2729                                                 ((ParamNo *)$1)->typename = $3;
2730                                         $$ = (Node *)$1;
2731                                 }
2732                 | CAST a_expr AS Typename
2733                                 {
2734                                         $$ = (Node *)$2;
2735                                         /* AexprConst can be either A_Const or ParamNo */
2736                                         if (nodeTag($2) == T_A_Const) {
2737                                                 ((A_Const *)$2)->typename = $4;
2738                                         } else if (nodeTag($2) == T_Param) {
2739                                                 ((ParamNo *)$2)->typename = $4;
2740                                         /* otherwise, try to transform to a function call */
2741                                         } else {
2742                                                 FuncCall *n = makeNode(FuncCall);
2743                                                 n->funcname = $4->name;
2744                                                 n->args = lcons($2,NIL);
2745                                                 $$ = (Node *)n;
2746                                         }
2747                                 }
2748                 | '(' a_expr_or_null ')'
2749                                 {       $$ = $2; }
2750                 | a_expr Op a_expr
2751                                 {       $$ = makeIndexable($2,$1,$3);   }
2752                 | a_expr LIKE a_expr
2753                                 {       $$ = makeIndexable("~~", $1, $3); }
2754                 | a_expr NOT LIKE a_expr
2755                                 {       $$ = makeA_Expr(OP, "!~~", $1, $4); }
2756                 | Op a_expr
2757                                 {       $$ = makeA_Expr(OP, $1, NULL, $2); }
2758                 | a_expr Op
2759                                 {       $$ = makeA_Expr(OP, $2, $1, NULL); }
2760                 | ColId
2761                                 {
2762                                         /* could be a column name or a relation_name */
2763                                         Ident *n = makeNode(Ident);
2764                                         n->name = $1;
2765                                         n->indirection = NULL;
2766                                         $$ = (Node *)n;
2767                                 }
2768                 | name '(' '*' ')'
2769                                 {
2770                                         FuncCall *n = makeNode(FuncCall);
2771                                         Ident *star = makeNode(Ident);
2772
2773                                         /* cheap hack for aggregate (eg. count) */
2774                                         star->name = "oid";
2775                                         n->funcname = $1;
2776                                         n->args = lcons(star, NIL);
2777                                         $$ = (Node *)n;
2778                                 }
2779                 | name '(' ')'
2780                                 {
2781                                         FuncCall *n = makeNode(FuncCall);
2782                                         n->funcname = $1;
2783                                         n->args = NIL;
2784                                         $$ = (Node *)n;
2785                                 }
2786                 | CURRENT_DATE
2787                                 {
2788                                         A_Const *n = makeNode(A_Const);
2789                                         TypeName *t = makeNode(TypeName);
2790
2791                                         n->val.type = T_String;
2792                                         n->val.val.str = "now";
2793                                         n->typename = t;
2794
2795                                         t->name = xlateSqlType("date");
2796                                         t->setof = FALSE;
2797
2798                                         $$ = (Node *)n;
2799                                 }
2800                 | CURRENT_TIME
2801                                 {
2802                                         A_Const *n = makeNode(A_Const);
2803                                         TypeName *t = makeNode(TypeName);
2804
2805                                         n->val.type = T_String;
2806                                         n->val.val.str = "now";
2807                                         n->typename = t;
2808
2809                                         t->name = xlateSqlType("time");
2810                                         t->setof = FALSE;
2811
2812                                         $$ = (Node *)n;
2813                                 }
2814                 | CURRENT_TIME '(' Iconst ')'
2815                                 {
2816                                         FuncCall *n = makeNode(FuncCall);
2817                                         A_Const *s = makeNode(A_Const);
2818                                         TypeName *t = makeNode(TypeName);
2819
2820                                         n->funcname = xlateSqlType("time");
2821                                         n->args = lcons(s, NIL);
2822
2823                                         s->val.type = T_String;
2824                                         s->val.val.str = "now";
2825                                         s->typename = t;
2826
2827                                         t->name = xlateSqlType("time");
2828                                         t->setof = FALSE;
2829
2830                                         if ($3 != 0)
2831                                                 elog(NOTICE,"CURRENT_TIME(p) precision must be zero",NULL);
2832
2833                                         $$ = (Node *)n;
2834                                 }
2835                 | CURRENT_TIMESTAMP
2836                                 {
2837                                         A_Const *n = makeNode(A_Const);
2838                                         TypeName *t = makeNode(TypeName);
2839
2840                                         n->val.type = T_String;
2841                                         n->val.val.str = "now";
2842                                         n->typename = t;
2843
2844                                         t->name = xlateSqlType("timestamp");
2845                                         t->setof = FALSE;
2846
2847                                         $$ = (Node *)n;
2848                                 }
2849                 | CURRENT_TIMESTAMP '(' Iconst ')'
2850                                 {
2851                                         FuncCall *n = makeNode(FuncCall);
2852                                         A_Const *s = makeNode(A_Const);
2853                                         TypeName *t = makeNode(TypeName);
2854
2855                                         n->funcname = xlateSqlType("timestamp");
2856                                         n->args = lcons(s, NIL);
2857
2858                                         s->val.type = T_String;
2859                                         s->val.val.str = "now";
2860                                         s->typename = t;
2861
2862                                         t->name = xlateSqlType("timestamp");
2863                                         t->setof = FALSE;
2864
2865                                         if ($3 != 0)
2866                                                 elog(NOTICE,"CURRENT_TIMESTAMP(p) precision must be zero",NULL);
2867
2868                                         $$ = (Node *)n;
2869                                 }
2870                 | CURRENT_USER
2871                                 {
2872                                         FuncCall *n = makeNode(FuncCall);
2873                                         n->funcname = "getpgusername";
2874                                         n->args = NIL;
2875                                         $$ = (Node *)n;
2876                                 }
2877                 /* We probably need to define an "exists" node,
2878                  *      since the optimizer could choose to find only one match.
2879                  * Perhaps the first implementation could just check for
2880                  *      count(*) > 0? - thomas 1997-07-19
2881                  */
2882                 | EXISTS '(' SubSelect ')'
2883                                 {
2884                                         elog(WARN,"EXISTS not yet implemented",NULL);
2885                                         $$ = $3;
2886                                 }
2887                 | EXTRACT '(' extract_list ')'
2888                                 {
2889                                         FuncCall *n = makeNode(FuncCall);
2890                                         n->funcname = "date_part";
2891                                         n->args = $3;
2892                                         $$ = (Node *)n;
2893                                 }
2894                 | POSITION '(' position_list ')'
2895                                 {
2896                                         FuncCall *n = makeNode(FuncCall);
2897                                         n->funcname = "strpos";
2898                                         n->args = $3;
2899                                         $$ = (Node *)n;
2900                                 }
2901                 | SUBSTRING '(' substr_list ')'
2902                                 {
2903                                         FuncCall *n = makeNode(FuncCall);
2904                                         n->funcname = "substr";
2905                                         n->args = $3;
2906                                         $$ = (Node *)n;
2907                                 }
2908                 /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
2909                 | TRIM '(' BOTH trim_list ')'
2910                                 {
2911                                         FuncCall *n = makeNode(FuncCall);
2912                                         n->funcname = "btrim";
2913                                         n->args = $4;
2914                                         $$ = (Node *)n;
2915                                 }
2916                 | TRIM '(' LEADING trim_list ')'
2917                                 {
2918                                         FuncCall *n = makeNode(FuncCall);
2919                                         n->funcname = "ltrim";
2920                                         n->args = $4;
2921                                         $$ = (Node *)n;
2922                                 }
2923                 | TRIM '(' TRAILING trim_list ')'
2924                                 {
2925                                         FuncCall *n = makeNode(FuncCall);
2926                                         n->funcname = "rtrim";
2927                                         n->args = $4;
2928                                         $$ = (Node *)n;
2929                                 }
2930                 | TRIM '(' trim_list ')'
2931                                 {
2932                                         FuncCall *n = makeNode(FuncCall);
2933                                         n->funcname = "btrim";
2934                                         n->args = $3;
2935                                         $$ = (Node *)n;
2936                                 }
2937                 | name '(' expr_list ')'
2938                                 {
2939                                         FuncCall *n = makeNode(FuncCall);
2940                                         n->funcname = $1;
2941                                         n->args = $3;
2942                                         $$ = (Node *)n;
2943                                 }
2944                 | a_expr ISNULL
2945                                 {       $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
2946                 | a_expr IS NULL_P
2947                                 {       $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
2948                 | a_expr NOTNULL
2949                                 {       $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); }
2950                 | a_expr IS NOT NULL_P
2951                                 {       $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); }
2952                 | a_expr IS TRUE_P
2953                                 {
2954                                         FuncCall *n = makeNode(FuncCall);
2955                                         n->funcname = "istrue";
2956                                         n->args = lcons($1,NIL);
2957                                         $$ = (Node *)n;
2958                                 }
2959                 | a_expr IS FALSE_P
2960                                 {
2961                                         FuncCall *n = makeNode(FuncCall);
2962                                         n->funcname = "isfalse";
2963                                         n->args = lcons($1,NIL);
2964                                         $$ = (Node *)n;
2965                                 }
2966                 | a_expr IS NOT TRUE_P
2967                                 {
2968                                         FuncCall *n = makeNode(FuncCall);
2969                                         n->funcname = "isfalse";
2970                                         n->args = lcons($1,NIL);
2971                                         $$ = (Node *)n;
2972                                 }
2973                 | a_expr IS NOT FALSE_P
2974                                 {
2975                                         FuncCall *n = makeNode(FuncCall);
2976                                         n->funcname = "istrue";
2977                                         n->args = lcons($1,NIL);
2978                                         $$ = (Node *)n;
2979                                 }
2980                 | a_expr BETWEEN AexprConst AND AexprConst
2981                                 {
2982                                         $$ = makeA_Expr(AND, NULL,
2983                                                 makeA_Expr(OP, ">=", $1, $3),
2984                                                 makeA_Expr(OP, "<=", $1, $5));
2985                                 }
2986                 | a_expr NOT BETWEEN AexprConst AND AexprConst
2987                                 {
2988                                         $$ = makeA_Expr(OR, NULL,
2989                                                 makeA_Expr(OP, "<", $1, $4),
2990                                                 makeA_Expr(OP, ">", $1, $6));
2991                                 }
2992                 | a_expr IN { saved_In_Expr = $1; } '(' in_expr ')'
2993                                 {       $$ = $5; }
2994                 | a_expr NOT IN { saved_In_Expr = $1; } '(' not_in_expr ')'
2995                                 {       $$ = $6; }
2996                 | a_expr AND a_expr
2997                                 {       $$ = makeA_Expr(AND, NULL, $1, $3); }
2998                 | a_expr OR a_expr
2999                                 {       $$ = makeA_Expr(OR, NULL, $1, $3); }
3000                 | NOT a_expr
3001                                 {       $$ = makeA_Expr(NOT, NULL, NULL, $2); }
3002                 ;
3003
3004 opt_indirection:  '[' a_expr ']' opt_indirection
3005                                 {
3006                                         A_Indices *ai = makeNode(A_Indices);
3007                                         ai->lidx = NULL;
3008                                         ai->uidx = $2;
3009                                         $$ = lcons(ai, $4);
3010                                 }
3011                 | '[' a_expr ':' a_expr ']' opt_indirection
3012                                 {
3013                                         A_Indices *ai = makeNode(A_Indices);
3014                                         ai->lidx = $2;
3015                                         ai->uidx = $4;
3016                                         $$ = lcons(ai, $6);
3017                                 }
3018                 | /* EMPTY */
3019                                 {       $$ = NIL; }
3020                 ;
3021
3022 expr_list:  a_expr_or_null
3023                                 { $$ = lcons($1, NIL); }
3024                 | expr_list ',' a_expr_or_null
3025                                 { $$ = lappend($1, $3); }
3026                 | expr_list USING a_expr
3027                                 { $$ = lappend($1, $3); }
3028                 ;
3029
3030 extract_list:  datetime FROM a_expr
3031                                 {
3032                                         A_Const *n = makeNode(A_Const);
3033                                         n->val.type = T_String;
3034                                         n->val.val.str = $1;
3035                                         $$ = lappend(lcons((Node *)n,NIL), $3);
3036                                 }
3037                 | /* EMPTY */
3038                                 {       $$ = NIL; }
3039                 ;
3040
3041 position_list:  position_expr IN position_expr
3042                                 {       $$ = makeList($3, $1, -1); }
3043                 | /* EMPTY */
3044                                 {       $$ = NIL; }
3045                 ;
3046
3047 position_expr:  attr opt_indirection
3048                                 {
3049                                         $1->indirection = $2;
3050                                         $$ = (Node *)$1;
3051                                 }
3052                 | AexprConst
3053                                 {       $$ = $1;  }
3054                 | '-' position_expr %prec UMINUS
3055                                 {       $$ = makeA_Expr(OP, "-", NULL, $2); }
3056                 | position_expr '+' position_expr
3057                                 {       $$ = makeA_Expr(OP, "+", $1, $3); }
3058                 | position_expr '-' position_expr
3059                                 {       $$ = makeA_Expr(OP, "-", $1, $3); }
3060                 | position_expr '/' position_expr
3061                                 {       $$ = makeA_Expr(OP, "/", $1, $3); }
3062                 | position_expr '*' position_expr
3063                                 {       $$ = makeA_Expr(OP, "*", $1, $3); }
3064                 | '|' position_expr
3065                                 {       $$ = makeA_Expr(OP, "|", NULL, $2); }
3066                 | AexprConst TYPECAST Typename
3067                                 {
3068                                         /* AexprConst can be either A_Const or ParamNo */
3069                                         if (nodeTag($1) == T_A_Const)
3070                                                 ((A_Const *)$1)->typename = $3;
3071                                         else
3072                                                 ((ParamNo *)$1)->typename = $3;
3073                                         $$ = (Node *)$1;
3074                                 }
3075                 | CAST position_expr AS Typename
3076                                 {
3077                                         $$ = (Node *)$2;
3078                                         /* AexprConst can be either A_Const or ParamNo */
3079                                         if (nodeTag($2) == T_A_Const) {
3080                                                 ((A_Const *)$2)->typename = $4;
3081                                         } else if (nodeTag($2) == T_Param) {
3082                                                 ((ParamNo *)$2)->typename = $4;
3083                                         /* otherwise, try to transform to a function call */
3084                                         } else {
3085                                                 FuncCall *n = makeNode(FuncCall);
3086                                                 n->funcname = $4->name;
3087                                                 n->args = lcons($2,NIL);
3088                                                 $$ = (Node *)n;
3089                                         }
3090                                 }
3091                 | '(' position_expr ')'
3092                                 {       $$ = $2; }
3093                 | position_expr Op position_expr
3094                                 {       $$ = makeA_Expr(OP, $2, $1, $3); }
3095                 | Op position_expr
3096                                 {       $$ = makeA_Expr(OP, $1, NULL, $2); }
3097                 | position_expr Op
3098                                 {       $$ = makeA_Expr(OP, $2, $1, NULL); }
3099                 | ColId
3100                                 {
3101                                         /* could be a column name or a relation_name */
3102                                         Ident *n = makeNode(Ident);
3103                                         n->name = $1;
3104                                         n->indirection = NULL;
3105                                         $$ = (Node *)n;
3106                                 }
3107                 | name '(' ')'
3108                                 {
3109                                         FuncCall *n = makeNode(FuncCall);
3110                                         n->funcname = $1;
3111                                         n->args = NIL;
3112                                         $$ = (Node *)n;
3113                                 }
3114                 | POSITION '(' position_list ')'
3115                                 {
3116                                         FuncCall *n = makeNode(FuncCall);
3117                                         n->funcname = "strpos";
3118                                         n->args = $3;
3119                                         $$ = (Node *)n;
3120                                 }
3121                 | SUBSTRING '(' substr_list ')'
3122                                 {
3123                                         FuncCall *n = makeNode(FuncCall);
3124                                         n->funcname = "substr";
3125                                         n->args = $3;
3126                                         $$ = (Node *)n;
3127                                 }
3128                 /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
3129                 | TRIM '(' BOTH trim_list ')'
3130                                 {
3131                                         FuncCall *n = makeNode(FuncCall);
3132                                         n->funcname = "btrim";
3133                                         n->args = $4;
3134                                         $$ = (Node *)n;
3135                                 }
3136                 | TRIM '(' LEADING trim_list ')'
3137                                 {
3138                                         FuncCall *n = makeNode(FuncCall);
3139                                         n->funcname = "ltrim";
3140                                         n->args = $4;
3141                                         $$ = (Node *)n;
3142                                 }
3143                 | TRIM '(' TRAILING trim_list ')'
3144                                 {
3145                                         FuncCall *n = makeNode(FuncCall);
3146                                         n->funcname = "rtrim";
3147                                         n->args = $4;
3148                                         $$ = (Node *)n;
3149                                 }
3150                 | TRIM '(' trim_list ')'
3151                                 {
3152                                         FuncCall *n = makeNode(FuncCall);
3153                                         n->funcname = "btrim";
3154                                         n->args = $3;
3155                                         $$ = (Node *)n;
3156                                 }
3157                 | name '(' expr_list ')'
3158                                 {
3159                                         FuncCall *n = makeNode(FuncCall);
3160                                         n->funcname = $1;
3161                                         n->args = $3;
3162                                         $$ = (Node *)n;
3163                                 }
3164                 ;
3165
3166 substr_list:  expr_list substr_from substr_for
3167                                 {
3168                                         $$ = nconc(nconc($1,$2),$3);
3169                                 }
3170                 | /* EMPTY */
3171                                 {       $$ = NIL; }
3172                 ;
3173
3174 substr_from:  FROM expr_list
3175                                 {       $$ = $2; }
3176                 | /* EMPTY */
3177                                 {
3178                                         A_Const *n = makeNode(A_Const);
3179                                         n->val.type = T_Integer;
3180                                         n->val.val.ival = 1;
3181                                         $$ = lcons((Node *)n,NIL);
3182                                 }
3183                 ;
3184
3185 substr_for:  FOR expr_list
3186                                 {       $$ = $2; }
3187                 | /* EMPTY */
3188                                 {       $$ = NIL; }
3189                 ;
3190
3191 trim_list:  a_expr FROM expr_list
3192                                 { $$ = lappend($3, $1); }
3193                 | FROM expr_list
3194                                 { $$ = $2; }
3195                 | expr_list
3196                                 { $$ = $1; }
3197                 ;
3198
3199 in_expr:  SubSelect
3200                                 {
3201                                         elog(WARN,"IN (SUBSELECT) not yet implemented",NULL);
3202                                         $$ = $1;
3203                                 }
3204                 | in_expr_nodes
3205                                 {       $$ = $1; }
3206                 ;
3207
3208 in_expr_nodes:  AexprConst
3209                                 {       $$ = makeA_Expr(OP, "=", saved_In_Expr, $1); }
3210                 | in_expr_nodes ',' AexprConst
3211                                 {       $$ = makeA_Expr(OR, NULL, $1,
3212                                                 makeA_Expr(OP, "=", saved_In_Expr, $3));
3213                                 }
3214                 ;
3215
3216 not_in_expr:  SubSelect
3217                                 {
3218                                         elog(WARN,"NOT IN (SUBSELECT) not yet implemented",NULL);
3219                                         $$ = $1;
3220                                 }
3221                 | not_in_expr_nodes
3222                                 {       $$ = $1; }
3223                 ;
3224
3225 not_in_expr_nodes:  AexprConst
3226                                 {       $$ = makeA_Expr(OP, "<>", saved_In_Expr, $1); }
3227                 | not_in_expr_nodes ',' AexprConst
3228                                 {       $$ = makeA_Expr(AND, NULL, $1,
3229                                                 makeA_Expr(OP, "<>", saved_In_Expr, $3));
3230                                 }
3231                 ;
3232
3233 attr:  relation_name '.' attrs
3234                                 {
3235                                         $$ = makeNode(Attr);
3236                                         $$->relname = $1;
3237                                         $$->paramNo = NULL;
3238                                         $$->attrs = $3;
3239                                         $$->indirection = NULL;
3240                                 }
3241                 | ParamNo '.' attrs
3242                                 {
3243                                         $$ = makeNode(Attr);
3244                                         $$->relname = NULL;
3245                                         $$->paramNo = $1;
3246                                         $$->attrs = $3;
3247                                         $$->indirection = NULL;
3248                                 }
3249                 ;
3250
3251 attrs:    attr_name
3252                                 { $$ = lcons(makeString($1), NIL); }
3253                 | attrs '.' attr_name
3254                                 { $$ = lappend($1, makeString($3)); }
3255                 | attrs '.' '*'
3256                                 { $$ = lappend($1, makeString("*")); }
3257                 ;
3258
3259
3260 /*****************************************************************************
3261  *
3262  *      target lists
3263  *
3264  *****************************************************************************/
3265
3266 res_target_list:  res_target_list ',' res_target_el
3267                                 {       $$ = lappend($1,$3);  }
3268                 | res_target_el
3269                                 {       $$ = lcons($1, NIL);  }
3270                 | '*'
3271                                 {
3272                                         ResTarget *rt = makeNode(ResTarget);
3273                                         Attr *att = makeNode(Attr);
3274                                         att->relname = "*";
3275                                         att->paramNo = NULL;
3276                                         att->attrs = NULL;
3277                                         att->indirection = NIL;
3278                                         rt->name = NULL;
3279                                         rt->indirection = NULL;
3280                                         rt->val = (Node *)att;
3281                                         $$ = lcons(rt, NIL);
3282                                 }
3283                 ;
3284
3285 res_target_el:  ColId opt_indirection '=' a_expr_or_null
3286                                 {
3287                                         $$ = makeNode(ResTarget);
3288                                         $$->name = $1;
3289                                         $$->indirection = $2;
3290                                         $$->val = (Node *)$4;
3291                                 }
3292                 | attr opt_indirection
3293                                 {
3294                                         $$ = makeNode(ResTarget);
3295                                         $$->name = NULL;
3296                                         $$->indirection = $2;
3297                                         $$->val = (Node *)$1;
3298                                 }
3299                 | relation_name '.' '*'
3300                                 {
3301                                         Attr *att = makeNode(Attr);
3302                                         att->relname = $1;
3303                                         att->paramNo = NULL;
3304                                         att->attrs = lcons(makeString("*"), NIL);
3305                                         att->indirection = NIL;
3306                                         $$ = makeNode(ResTarget);
3307                                         $$->name = NULL;
3308                                         $$->indirection = NULL;
3309                                         $$->val = (Node *)att;
3310                                 }
3311                 ;
3312
3313 /*
3314 ** target list for select.
3315 ** should get rid of the other but is still needed by the defunct retrieve into
3316 ** and update (uses a subset)
3317 */
3318 res_target_list2:  res_target_list2 ',' res_target_el2
3319                                 {       $$ = lappend($1, $3);  }
3320                 | res_target_el2
3321                                 {       $$ = lcons($1, NIL);  }
3322                 ;
3323
3324 /* AS is not optional because shift/red conflict with unary ops */
3325 res_target_el2:  a_expr_or_null AS ColLabel
3326                                 {
3327                                         $$ = makeNode(ResTarget);
3328                                         $$->name = $3;
3329                                         $$->indirection = NULL;
3330                                         $$->val = (Node *)$1;
3331                                 }
3332                 | a_expr_or_null
3333                                 {
3334                                         $$ = makeNode(ResTarget);
3335                                         $$->name = NULL;
3336                                         $$->indirection = NULL;
3337                                         $$->val = (Node *)$1;
3338                                 }
3339                 | relation_name '.' '*'
3340                                 {
3341                                         Attr *att = makeNode(Attr);
3342                                         att->relname = $1;
3343                                         att->paramNo = NULL;
3344                                         att->attrs = lcons(makeString("*"), NIL);
3345                                         att->indirection = NIL;
3346                                         $$ = makeNode(ResTarget);
3347                                         $$->name = NULL;
3348                                         $$->indirection = NULL;
3349                                         $$->val = (Node *)att;
3350                                 }
3351                 | '*'
3352                                 {
3353                                         Attr *att = makeNode(Attr);
3354                                         att->relname = "*";
3355                                         att->paramNo = NULL;
3356                                         att->attrs = NULL;
3357                                         att->indirection = NIL;
3358                                         $$ = makeNode(ResTarget);
3359                                         $$->name = NULL;
3360                                         $$->indirection = NULL;
3361                                         $$->val = (Node *)att;
3362                                 }
3363                 ;
3364
3365 opt_id:  ColId                                                                  { $$ = $1; }
3366                 | /* EMPTY */                                                   { $$ = NULL; }
3367                 ;
3368
3369 relation_name:  SpecialRuleRelation
3370                                 {
3371                                         $$ = $1;
3372                                         StrNCpy(saved_relname, $1, NAMEDATALEN);
3373                                 }
3374                 | ColId
3375                                 {
3376                                         /* disallow refs to variable system tables */
3377                                         if (strcmp(LogRelationName, $1) == 0
3378                                            || strcmp(VariableRelationName, $1) == 0)
3379                                                 elog(WARN,"%s cannot be accessed by users",$1);
3380                                         else
3381                                                 $$ = $1;
3382                                         StrNCpy(saved_relname, $1, NAMEDATALEN);
3383                                 }
3384                 ;
3385
3386 database_name:                  ColId                   { $$ = $1; };
3387 access_method:                  Id                              { $$ = $1; };
3388 attr_name:                              ColId                   { $$ = $1; };
3389 class:                                  Id                              { $$ = $1; };
3390 index_name:                             ColId                   { $$ = $1; };
3391
3392 /* Functions
3393  * Include date/time keywords as SQL92 extension.
3394  * Include TYPE as a SQL92 unreserved keyword. - thomas 1997-10-05
3395  */
3396 name:                                   ColId                   { $$ = $1; };
3397
3398 date:                                   Sconst                  { $$ = $1; };
3399 file_name:                              Sconst                  { $$ = $1; };
3400 recipe_name:                    Id                              { $$ = $1; };
3401
3402 /* Constants
3403  * Include TRUE/FALSE for SQL3 support. - thomas 1997-10-24
3404  */
3405 AexprConst:  Iconst
3406                                 {
3407                                         A_Const *n = makeNode(A_Const);
3408                                         n->val.type = T_Integer;
3409                                         n->val.val.ival = $1;
3410                                         $$ = (Node *)n;
3411                                 }
3412                 | FCONST
3413                                 {
3414                                         A_Const *n = makeNode(A_Const);
3415                                         n->val.type = T_Float;
3416                                         n->val.val.dval = $1;
3417                                         $$ = (Node *)n;
3418                                 }
3419                 | Sconst
3420                                 {
3421                                         A_Const *n = makeNode(A_Const);
3422                                         n->val.type = T_String;
3423                                         n->val.val.str = $1;
3424                                         $$ = (Node *)n;
3425                                 }
3426                 | Typename Sconst
3427                                 {
3428                                         A_Const *n = makeNode(A_Const);
3429                                         n->typename = $1;
3430                                         n->val.type = T_String;
3431                                         n->val.val.str = $2;
3432                                         $$ = (Node *)n;
3433                                 }
3434                 | ParamNo
3435                                 {       $$ = (Node *)$1;  }
3436                 | TRUE_P
3437                                 {
3438                                         A_Const *n = makeNode(A_Const);
3439                                         n->val.type = T_String;
3440                                         n->val.val.str = "t";
3441                                         $$ = (Node *)n;
3442                                 }
3443                 | FALSE_P
3444                                 {
3445                                         A_Const *n = makeNode(A_Const);
3446                                         n->val.type = T_String;
3447                                         n->val.val.str = "f";
3448                                         $$ = (Node *)n;
3449                                 }
3450                 ;
3451
3452 ParamNo:  PARAM
3453                                 {
3454                                         $$ = makeNode(ParamNo);
3455                                         $$->number = $1;
3456                                 }
3457                 ;
3458
3459 NumConst:  Iconst                                               { $$ = makeInteger($1); }
3460                 | FCONST                                                { $$ = makeFloat($1); }
3461                 ;
3462
3463 Iconst:  ICONST                                                 { $$ = $1; };
3464 Sconst:  SCONST                                                 { $$ = $1; };
3465
3466 /* Column and type identifier
3467  * Does not include explicit datetime types
3468  *  since these must be decoupled in Typename syntax.
3469  * Use ColId for most identifiers. - thomas 1997-10-21
3470  */
3471 Id:  IDENT                                                              { $$ = $1; };
3472
3473 /* Column identifier
3474  * Include date/time keywords as SQL92 extension.
3475  * Include TYPE as a SQL92 unreserved keyword. - thomas 1997-10-05
3476  * Add other keywords. Note that as the syntax expands,
3477  *  some of these keywords will have to be removed from this
3478  *  list due to shift/reduce conflicts in yacc. If so, move
3479  *  down to the ColLabel entity. - thomas 1997-11-06
3480  */
3481 ColId:  Id                                                              { $$ = $1; }
3482                 | datetime                                              { $$ = $1; }
3483                 | ACTION                                                { $$ = "action"; }
3484                 | DATABASE                                              { $$ = "database"; }
3485                 | DELIMITERS                                    { $$ = "delimiters"; }
3486                 | FUNCTION                                              { $$ = "function"; }
3487                 | INDEX                                                 { $$ = "index"; }
3488                 | KEY                                                   { $$ = "key"; }
3489                 | LANGUAGE                                              { $$ = "language"; }
3490                 | LIGHT                                                 { $$ = "light"; }
3491                 | LOCATION                                              { $$ = "location"; }
3492                 | MATCH                                                 { $$ = "match"; }
3493                 | OPERATOR                                              { $$ = "operator"; }
3494                 | OPTION                                                { $$ = "option"; }
3495                 | PRIVILEGES                                    { $$ = "privileges"; }
3496                 | RECIPE                                                { $$ = "recipe"; }
3497                 | TIME                                                  { $$ = "time"; }
3498                 | TRIGGER                                               { $$ = "trigger"; }
3499                 | TYPE_P                                                { $$ = "type"; }
3500                 | VERSION                                               { $$ = "version"; }
3501                 | ZONE                                                  { $$ = "zone"; }
3502                 ;
3503
3504 /* Column label
3505  * Allowed labels in "AS" clauses.
3506  * Include TRUE/FALSE SQL3 reserved words for Postgres backward
3507  *  compatibility. Cannot allow this for column names since the
3508  *  syntax would not distinguish between the constant value and
3509  *  a column name. - thomas 1997-10-24
3510  * Add other keywords to this list. Note that they appear here
3511  *  rather than in ColId if there was a shift/reduce conflict
3512  *  when used as a full identifier. - thomas 1997-11-06
3513  */
3514 ColLabel:  ColId                                                { $$ = $1; }
3515                 | ARCHIVE                                               { $$ = "archive"; }
3516                 | CLUSTER                                               { $$ = "cluster"; }
3517                 | CONSTRAINT                                    { $$ = "constraint"; }
3518                 | CROSS                                                 { $$ = "cross"; }
3519                 | FOREIGN                                               { $$ = "foreign"; }
3520                 | GROUP                                                 { $$ = "group"; }
3521                 | LOAD                                                  { $$ = "load"; }
3522                 | ORDER                                                 { $$ = "order"; }
3523                 | POSITION                                              { $$ = "position"; }
3524                 | PRECISION                                             { $$ = "precision"; }
3525                 | STORE                                                 { $$ = "store"; }
3526                 | TABLE                                                 { $$ = "table"; }
3527                 | TRANSACTION                                   { $$ = "transaction"; }
3528                 | TRUE_P                                                { $$ = "true"; }
3529                 | FALSE_P                                               { $$ = "false"; }
3530                 ;
3531
3532 SpecialRuleRelation:  CURRENT
3533                                 {
3534                                         if (QueryIsRule)
3535                                                 $$ = "*CURRENT*";
3536                                         else
3537                                                 elog(WARN,"CURRENT used in non-rule query",NULL);
3538                                 }
3539                 | NEW
3540                                 {
3541                                         if (QueryIsRule)
3542                                                 $$ = "*NEW*";
3543                                         else
3544                                                 elog(WARN,"NEW used in non-rule query",NULL);
3545                                 }
3546                 ;
3547
3548 Type:   TYPE_P;
3549 Pnull:  NULL_P;
3550
3551 %%
3552
3553 static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr)
3554 {
3555         A_Expr *a = makeNode(A_Expr);
3556         a->oper = oper;
3557         a->opname = opname;
3558         a->lexpr = lexpr;
3559         a->rexpr = rexpr;
3560         return (Node *)a;
3561 }
3562
3563
3564 static Node *makeIndexable(char *opname, Node *lexpr, Node *rexpr)
3565 {
3566         Node *result = NULL;
3567
3568         /* we do this so indexes can be used */
3569         if (strcmp(opname,"~") == 0 ||
3570                 strcmp(opname,"~*") == 0)
3571         {
3572                 if (nodeTag(rexpr) == T_A_Const &&
3573                    ((A_Const *)rexpr)->val.type == T_String &&
3574                    ((A_Const *)rexpr)->val.val.str[0] == '^')
3575                 {
3576                         A_Const *n = (A_Const *)rexpr;
3577                         char *match_least = palloc(strlen(n->val.val.str)+2);
3578                         char *match_most = palloc(strlen(n->val.val.str)+2);
3579                         int pos, match_pos=0;
3580
3581                         /* skip leading ^ */
3582                         for (pos = 1; n->val.val.str[pos]; pos++)
3583                         {
3584                                 if (n->val.val.str[pos] == '.' ||
3585                                         n->val.val.str[pos] == '?' ||
3586                                         n->val.val.str[pos] == '*' ||
3587                                         n->val.val.str[pos] == '[' ||
3588                                         n->val.val.str[pos] == '$' ||
3589                                         (strcmp(opname,"~*") == 0 && isalpha(n->val.val.str[pos])))
3590                                 break;
3591                         if (n->val.val.str[pos] == '\\')
3592                                         pos++;
3593                                 match_least[match_pos] = n->val.val.str[pos];
3594                                 match_most[match_pos++] = n->val.val.str[pos];
3595                         }
3596
3597                         if (match_pos != 0)
3598                         {
3599                                 A_Const *least = makeNode(A_Const);
3600                                 A_Const *most = makeNode(A_Const);
3601                                 
3602                                 /* make strings to be used in index use */
3603                                 match_least[match_pos] = '\0';
3604                                 match_most[match_pos] = '\377';
3605                                 match_most[match_pos+1] = '\0';
3606                                 least->val.type = T_String;
3607                                 least->val.val.str = match_least;
3608                                 most->val.type = T_String;
3609                                 most->val.val.str = match_most;
3610                                 result = makeA_Expr(AND, NULL,
3611                                                 makeA_Expr(OP, "~", lexpr, rexpr),
3612                                                 makeA_Expr(AND, NULL,
3613                                                         makeA_Expr(OP, ">=", lexpr, (Node *)least),
3614                                                         makeA_Expr(OP, "<=", lexpr, (Node *)most)));
3615                         }
3616                 }
3617         }
3618         else if (strcmp(opname,"~~") == 0)
3619         {
3620                 if (nodeTag(rexpr) == T_A_Const &&
3621                    ((A_Const *)rexpr)->val.type == T_String)
3622                 {
3623                         A_Const *n = (A_Const *)rexpr;
3624                         char *match_least = palloc(strlen(n->val.val.str)+2);
3625                         char *match_most = palloc(strlen(n->val.val.str)+2);
3626                         int pos, match_pos=0;
3627         
3628                         for (pos = 0; n->val.val.str[pos]; pos++)
3629                         {
3630                                 if ((n->val.val.str[pos] == '%' &&
3631                                          n->val.val.str[pos+1] != '%') ||
3632                                     (n->val.val.str[pos] == '_' &&
3633                                  n->val.val.str[pos+1] != '_'))
3634                                 break;
3635                         if (n->val.val.str[pos] == '%' ||
3636                                     n->val.val.str[pos] == '_' ||
3637                                     n->val.val.str[pos] == '\\')
3638                                         pos++;
3639                                 match_least[match_pos] = n->val.val.str[pos];
3640                                 match_most[match_pos++] = n->val.val.str[pos];
3641                         }
3642         
3643                         if (match_pos != 0)
3644                         {
3645                                 A_Const *least = makeNode(A_Const);
3646                                 A_Const *most = makeNode(A_Const);
3647                                 
3648                                 /* make strings to be used in index use */
3649                                 match_least[match_pos] = '\0';
3650                                 match_most[match_pos] = '\377';
3651                                 match_most[match_pos+1] = '\0';
3652                                 least->val.type = T_String;
3653                                 least->val.val.str = match_least;
3654                                 most->val.type = T_String;
3655                                 most->val.val.str = match_most;
3656                                 result = makeA_Expr(AND, NULL,
3657                                                 makeA_Expr(OP, "~~", lexpr, rexpr),
3658                                                 makeA_Expr(AND, NULL,
3659                                                         makeA_Expr(OP, ">=", lexpr, (Node *)least),
3660                                                         makeA_Expr(OP, "<=", lexpr, (Node *)most)));
3661                         }
3662                 }
3663         }
3664         
3665         if (result == NULL)
3666                 result = makeA_Expr(OP, opname, lexpr, rexpr);
3667         return result;
3668 } /* makeIndexable() */
3669
3670
3671 /* xlateSqlType()
3672  * Convert alternate type names to internal Postgres types.
3673  * Do not convert "float", since that is handled elsewhere
3674  *  for FLOAT(p) syntax.
3675  */
3676 static char *
3677 xlateSqlType(char *name)
3678 {
3679         if (!strcasecmp(name,"int")
3680          || !strcasecmp(name,"integer"))
3681                 return "int4";
3682         else if (!strcasecmp(name, "smallint"))
3683                 return "int2";
3684         else if (!strcasecmp(name, "real"))
3685                 return "float8";
3686         else if (!strcasecmp(name, "interval"))
3687                 return "timespan";
3688         else if (!strcasecmp(name, "boolean"))
3689                 return "bool";
3690         else
3691                 return name;
3692 } /* xlateSqlName() */
3693
3694
3695 void parser_init(Oid *typev, int nargs)
3696 {
3697         QueryIsRule = FALSE;
3698         saved_relname[0]= '\0';
3699         saved_In_Expr = NULL;
3700
3701         param_type_init(typev, nargs);
3702 }
3703
3704
3705 /* FlattenStringList()
3706  * Traverse list of string nodes and convert to a single string.
3707  * Used for reconstructing string form of complex expressions.
3708  *
3709  * Allocate at least one byte for terminator.
3710  */
3711 static char *
3712 FlattenStringList(List *list)
3713 {
3714         List *l;
3715         Value *v;
3716         char *s;
3717         char *sp;
3718         int nlist, len = 0;
3719
3720         nlist = length(list);
3721         l = list;
3722         while(l != NIL) {
3723                 v = (Value *)lfirst(l);
3724                 sp = v->val.str;
3725                 l = lnext(l);
3726                 len += strlen(sp);
3727         };
3728         len += nlist;
3729
3730         s = (char*) palloc(len+1);
3731         *s = '\0';
3732
3733         l = list;
3734         while(l != NIL) {
3735                 v = (Value *)lfirst(l);
3736                 sp = v->val.str;
3737                 l = lnext(l);
3738                 strcat(s,sp);
3739                 if (l != NIL) strcat(s," ");
3740         };
3741         *(s+len) = '\0';
3742
3743 #ifdef PARSEDEBUG
3744 printf( "flattened string is \"%s\"\n", s);
3745 #endif
3746
3747         return(s);
3748 } /* FlattenStringList() */
3749
3750
3751 /* makeConstantList()
3752  * Convert constant value node into string node.
3753  */
3754 static List *
3755 makeConstantList( A_Const *n)
3756 {
3757         char *defval = NULL;
3758         if (nodeTag(n) != T_A_Const) {
3759                 elog(WARN,"Cannot handle non-constant parameter",NULL);
3760
3761         } else if (n->val.type == T_Float) {
3762                 defval = (char*) palloc(20+1);
3763                 sprintf( defval, "%g", n->val.val.dval);
3764
3765         } else if (n->val.type == T_Integer) {
3766                 defval = (char*) palloc(20+1);
3767                 sprintf( defval, "%ld", n->val.val.ival);
3768
3769         } else if (n->val.type == T_String) {
3770                 defval = (char*) palloc(strlen( ((A_Const *) n)->val.val.str) + 3);
3771                 strcpy( defval, "'");
3772                 strcat( defval, ((A_Const *) n)->val.val.str);
3773                 strcat( defval, "'");
3774
3775         } else {
3776                 elog(WARN,"Internal error in makeConstantList(): cannot encode node",NULL);
3777         };
3778
3779 #ifdef PARSEDEBUG
3780 printf( "AexprConst argument is \"%s\"\n", defval);
3781 #endif
3782
3783         return( lcons( makeString(defval), NIL));
3784 } /* makeConstantList() */
3785
3786
3787 /* fmtId()
3788  * Check input string for non-lowercase/non-numeric characters.
3789  * Returns either input string or input surrounded by double quotes.
3790  */
3791 static char *
3792 fmtId(char *rawid)
3793 {
3794         static char *cp;
3795
3796         for (cp = rawid; *cp != '\0'; cp++)
3797                 if (! (islower(*cp) || isdigit(*cp) || (*cp == '_'))) break;
3798
3799         if (*cp != '\0') {
3800                 cp = palloc(strlen(rawid)+1);
3801                 strcpy(cp,"\"");
3802                 strcat(cp,rawid);
3803                 strcat(cp,"\"");
3804         } else {
3805                 cp = rawid;
3806         };
3807
3808 #ifdef PARSEDEBUG
3809 printf("fmtId- %sconvert %s to %s\n", ((cp == rawid)? "do not ": ""), rawid, cp);
3810 #endif
3811
3812         return(cp);
3813 } /* fmtId() */