]> granicus.if.org Git - postgresql/blob - src/backend/parser/gram.y
Lex/yacc source cleanup like indent.
[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.43 1997/09/08 03:19:57 momjian 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  *
24  *        if you use list, make sure the datum is a node so that the printing
25  *        routines work
26  *
27  * WARNING
28  *        sometimes we assign constants to makeStrings. Make sure we don't free
29  *        those.
30  *
31  *-------------------------------------------------------------------------
32  */
33 #include <string.h>
34 #include <ctype.h>
35
36 #include "postgres.h"
37 #include "nodes/parsenodes.h"
38 #include "parser/gramparse.h"
39 #include "parser/catalog_utils.h"
40 #include "parser/parse_query.h"
41 #include "storage/smgr.h"
42 #include "utils/acl.h"
43 #include "catalog/catname.h"
44 #include "utils/elog.h"
45 #include "access/xact.h"
46
47 static char saved_relname[NAMEDATALEN];  /* need this for complex attributes */
48 static bool QueryIsRule = FALSE;
49 static Node *saved_In_Expr;
50 extern List *parsetree;
51
52 extern int CurScanPosition(void);
53 extern int DefaultStartPosition;
54 extern int CheckStartPosition;
55 extern char *parseString;
56
57 /*
58  * If you need access to certain yacc-generated variables and find that
59  * they're static by default, uncomment the next line.  (this is not a
60  * problem, yet.)
61  */
62 /*#define __YYSCLASS*/
63
64 static char *xlateSqlType(char *);
65 static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
66
67 /* old versions of flex define this as a macro */
68 #if defined(yywrap)
69 #undef yywrap
70 #endif /* yywrap */
71 %}
72
73
74 %union
75 {
76         double                          dval;
77         int                                     ival;
78         char                            chr;
79         char                            *str;
80         bool                            boolean;
81         List                            *list;
82         Node                            *node;
83         Value                           *value;
84
85         Attr                            *attr;
86
87         ColumnDef                       *coldef;
88         ConstraintDef           *constrdef;
89         TypeName                        *typnam;
90         DefElem                         *defelt;
91         ParamString                     *param;
92         SortGroupBy                     *sortgroupby;
93         IndexElem                       *ielem;
94         RangeVar                        *range;
95         RelExpr                         *relexp;
96         TimeRange                       *trange;
97         A_Indices                       *aind;
98         ResTarget                       *target;
99         ParamNo                         *paramno;
100
101         VersionStmt                     *vstmt;
102         DefineStmt                      *dstmt;
103         PurgeStmt                       *pstmt;
104         RuleStmt                        *rstmt;
105         AppendStmt                      *astmt;
106 }
107
108 %type <node>    stmt,
109                 AddAttrStmt, ClosePortalStmt,
110                 CopyStmt, CreateStmt, CreateSeqStmt, DefineStmt, DestroyStmt,
111                 ExtendStmt, FetchStmt,  GrantStmt, CreateTrigStmt, DropTrigStmt,
112                 IndexStmt, MoveStmt, ListenStmt, OptimizableStmt,
113                 ProcedureStmt, PurgeStmt,
114                 RecipeStmt, RemoveAggrStmt, RemoveOperStmt, RemoveFuncStmt, RemoveStmt,
115                 RenameStmt, RevokeStmt, RuleStmt, TransactionStmt, ViewStmt, LoadStmt,
116                 CreatedbStmt, DestroydbStmt, VacuumStmt, RetrieveStmt, CursorStmt,
117                 ReplaceStmt, AppendStmt, NotifyStmt, DeleteStmt, ClusterStmt,
118                 ExplainStmt, VariableSetStmt, VariableShowStmt, VariableResetStmt
119
120 %type <str>             txname
121 %type <node>    SubSelect
122 %type <str>             join_clause, join_type, join_outer, join_spec
123 %type <boolean> join_qual, TriggerActionTime, TriggerForSpec
124
125 %type <str>             datetime, TriggerEvents, TriggerFuncArg
126
127 %type <str>             relation_name, copy_file_name, copy_delimiter, def_name,
128                 database_name, access_method_clause, access_method, attr_name,
129                 class, index_name, name, file_name, recipe_name,
130                 var_name, aggr_argtype, OptDefault
131
132 %type <constrdef>               ConstraintElem, ConstraintDef
133
134 %type <str>             opt_id, opt_portal_name,
135                 before_clause, after_clause, all_Op, MathOp, opt_name, opt_unique,
136                 result, OptUseOp, opt_class, opt_range_start, opt_range_end,
137                 SpecialRuleRelation
138
139 %type <str>             privileges, operation_commalist, grantee
140 %type <chr>             operation, TriggerOneEvent
141
142 %type <list>    stmtblock, stmtmulti,
143                 relation_name_list, OptTableElementList, tableElementList,
144                 OptInherit, OptConstraint, ConstraintList, definition,
145                 opt_with, def_args, def_name_list, func_argtypes,
146                 oper_argtypes, OptStmtList, OptStmtBlock, OptStmtMulti,
147                 opt_column_list, columnList, opt_va_list, va_list,
148                 sort_clause, sortby_list, index_params, index_list, name_list,
149                 from_clause, from_list, opt_array_bounds, nest_array_bounds,
150                 expr_list, default_expr_list, attrs, res_target_list, res_target_list2,
151                 def_list, opt_indirection, group_clause, groupby_list, TriggerFuncArgs
152
153 %type <list>    union_clause, select_list
154 %type <list>    join_list
155 %type <sortgroupby>             join_using
156
157 %type <list>    extract_list, position_list
158 %type <list>    substr_list, substr_from, substr_for, trim_list
159 %type <list>    interval_opts
160
161 %type <boolean> opt_inh_star, opt_binary, opt_instead, opt_with_col, opt_with_copy,
162                                 index_opt_unique, opt_verbose, opt_analyze, opt_null
163
164 %type <ival>    copy_dirn, archive_type, OptArchiveType, OptArchiveLocation,
165                 def_type, opt_direction, remove_type, opt_column, event
166
167 %type <ival>    OptLocation, opt_move_where, fetch_how_many
168
169 %type <list>    OptSeqList
170 %type <defelt>  OptSeqElem
171
172 %type <dstmt>   def_rest
173 %type <pstmt>   purge_quals
174 %type <astmt>   insert_rest
175
176 %type <typnam>  Typename, typname, opt_type
177 %type <coldef>  columnDef
178 %type <defelt>  def_elem
179 %type <node>    def_arg, columnElem, where_clause,
180                                 a_expr, a_expr_or_null, AexprConst,
181                                 default_expr, default_expr_or_null,
182                                 in_expr_nodes, not_in_expr_nodes,
183                                 having_clause
184 %type <value>   NumConst
185 %type <attr>    event_object, attr
186 %type <sortgroupby>             groupby
187 %type <sortgroupby>             sortby
188 %type <ielem>   index_elem, func_index
189 %type <range>   from_val
190 %type <relexp>  relation_expr
191 %type <trange>  time_range
192 %type <target>  res_target_el, res_target_el2
193 %type <paramno> ParamNo
194
195 %type <ival>    Iconst
196 %type <str>             Sconst
197 %type <str>             Id, date, var_value, zone_value
198 %type <str>             ColId
199
200
201 /*
202  * If you make any token changes, remember to:
203  *              - use "yacc -d" and update parse.h
204  *              - update the keyword table in parser/keywords.c
205  */
206
207 /* Keywords */
208 %token  ABORT_TRANS, ACL, ADD, AFTER, AGGREGATE, ALL, ALTER, ANALYZE,
209                 AND, APPEND, ARCHIVE, ARCH_STORE, AS, ASC,
210                 BACKWARD, BEFORE, BEGIN_TRANS, BETWEEN, BINARY, BOTH, BY,
211                 CAST, CHANGE, CHECK, CLOSE, CLUSTER, COLUMN, COMMIT, CONSTRAINT, COPY, CREATE, CROSS,
212                 CURRENT, CURSOR, DATABASE, DAYINTERVAL, DECLARE, DEFAULT, DELETE, DELIMITERS, DESC,
213                 DISTINCT, DO, DROP, END_TRANS, EXISTS, EXTEND, EXTRACT,
214                 FETCH, FOR, FORWARD, FROM, FULL, FUNCTION, GRANT, GROUP,
215                 HAVING, HEAVY, HOURINTERVAL,
216                 IN, INDEX, INHERITS, INNERJOIN, INSERT, INSTEAD, INTERVAL, INTO, IS, ISNULL,
217                 JOIN, LANGUAGE, LEADING, LEFT, LIGHT, LISTEN, LOAD, LOCAL,
218                 MERGE, MINUTEINTERVAL, MONTHINTERVAL, MOVE,
219                 NATURAL, NEW, NONE, NOT, NOTHING, NOTIFY, NOTNULL,
220                 OIDS, ON, OPERATOR, OPTION, OR, ORDER, OUTERJOIN,
221                 PNULL, POSITION, PRIVILEGES, PROCEDURE, PUBLIC, PURGE, P_TYPE,
222                 RENAME, REPLACE, RESET, RETRIEVE, RETURNS, REVOKE, RIGHT, ROLLBACK, RULE,
223                 SECONDINTERVAL, SELECT, SET, SETOF, SHOW, STDIN, STDOUT, STORE, SUBSTRING,
224                 TABLE, TIME, TO, TRAILING, TRANSACTION, TRIGGER, TRIM,
225                 UNION, UNIQUE, UPDATE, USING, VACUUM, VALUES,
226                 VERBOSE, VERSION, VIEW, WHERE, WITH, WORK, YEARINTERVAL, ZONE
227 %token  EXECUTE, RECIPE, EXPLAIN, LIKE, SEQUENCE
228
229 /* Special keywords, not in the query language - see the "lex" file */
230 %token <str>    IDENT, SCONST, Op
231 %token <ival>   ICONST, PARAM
232 %token <dval>   FCONST
233
234 /* these are not real. they are here so that they gets generated as #define's*/
235 %token                  OP
236
237 /* precedence */
238 %left   OR
239 %left   AND
240 %right  NOT
241 %right  '='
242 %nonassoc LIKE
243 %nonassoc BETWEEN
244 %nonassoc IN
245 %nonassoc Op
246 %nonassoc NOTNULL
247 %nonassoc ISNULL
248 %nonassoc IS
249 %left   '+' '-'
250 %left   '*' '/'
251 %left   '|'                             /* this is the relation union op, not logical or */
252 %right  ':'                             /* Unary Operators              */
253 %left   ';'                             /* end of statement or natural log        */
254 %nonassoc  '<' '>'
255 %right   UMINUS
256 %left   '.'
257 %left   '[' ']'
258 %nonassoc TYPECAST
259 %nonassoc REDUCE
260 %left   UNION
261 %%
262
263 stmtblock: stmtmulti
264                                 { parsetree = $1; }
265                 |  stmt
266                                 { parsetree = lcons($1,NIL); }
267                 ;
268
269 stmtmulti: stmtmulti stmt ';'
270                                 { $$ = lappend($1, $2); }
271                 |  stmtmulti stmt
272                                 { $$ = lappend($1, $2); }
273                 |  stmt ';'
274                                 { $$ = lcons($1,NIL); }
275                 ;
276
277 stmt :    AddAttrStmt
278                 | ClosePortalStmt
279                 | CopyStmt
280                 | CreateStmt
281                 | CreateSeqStmt
282                 | CreateTrigStmt
283                 | ClusterStmt
284                 | DefineStmt
285                 | DestroyStmt
286                 | DropTrigStmt
287                 | ExtendStmt
288                 | ExplainStmt
289                 | FetchStmt
290                 | GrantStmt
291                 | IndexStmt
292                 | MoveStmt
293                 | ListenStmt
294                 | ProcedureStmt
295                 | PurgeStmt
296                 | RecipeStmt
297                 | RemoveAggrStmt
298                 | RemoveOperStmt
299                 | RemoveFuncStmt
300                 | RemoveStmt
301                 | RenameStmt
302                 | RevokeStmt
303                 | OptimizableStmt
304                 | RuleStmt
305                 | TransactionStmt
306                 | ViewStmt
307                 | LoadStmt
308                 | CreatedbStmt
309                 | DestroydbStmt
310                 | VacuumStmt
311                 | VariableSetStmt
312                 | VariableShowStmt
313                 | VariableResetStmt
314                 ;
315
316 /*****************************************************************************
317  *
318  * Set PG internal variable
319  *        SET var_name TO 'var_value'
320  *
321  *****************************************************************************/
322
323 VariableSetStmt:  SET var_name TO var_value
324                                 {
325                                         VariableSetStmt *n = makeNode(VariableSetStmt);
326                                         n->name  = $2;
327                                         n->value = $4;
328                                         $$ = (Node *) n;
329                                 }
330                 |  SET var_name '=' var_value
331                                 {
332                                         VariableSetStmt *n = makeNode(VariableSetStmt);
333                                         n->name  = $2;
334                                         n->value = $4;
335                                         $$ = (Node *) n;
336                                 }
337                 |  SET TIME ZONE zone_value
338                                 {
339                                         VariableSetStmt *n = makeNode(VariableSetStmt);
340                                         n->name  = "timezone";
341                                         n->value = $4;
342                                         $$ = (Node *) n;
343                                 }
344                 ;
345
346 var_value:              Sconst                  { $$ = $1; }
347                 ;
348
349 zone_value:  Sconst                             { $$ = $1; }
350                 | LOCAL                                 { $$ = NULL; }
351                 ;
352
353 VariableShowStmt:  SHOW var_name
354                                 {
355                                         VariableShowStmt *n = makeNode(VariableShowStmt);
356                                         n->name  = $2;
357                                         $$ = (Node *) n;
358                                 }
359                 ;
360
361 VariableResetStmt:      RESET var_name
362                                 {
363                                         VariableResetStmt *n = makeNode(VariableResetStmt);
364                                         n->name  = $2;
365                                         $$ = (Node *) n;
366                                 }
367                 ;
368
369 /*****************************************************************************
370  *
371  *              QUERY :
372  *                              addattr ( attr1 = type1 .. attrn = typen ) to <relname> [*]
373  *
374  *****************************************************************************/
375
376 AddAttrStmt:  ALTER TABLE relation_name opt_inh_star ADD COLUMN columnDef
377                                 {
378                                         AddAttrStmt *n = makeNode(AddAttrStmt);
379                                         n->relname = $3;
380                                         n->inh = $4;
381                                         n->colDef = $7;
382                                         $$ = (Node *)n;
383                                 }
384                 ;
385
386 /* Column definition might include WITH TIME ZONE, but only for the data types
387  *      called out in SQL92 date/time definitions. So, check explicitly for "timestamp"
388  * and "time". - thomas 1997-07-14
389  */
390 columnDef:      Id Typename opt_with_col OptDefault opt_null
391                                 {
392                                         $$ = makeNode(ColumnDef);
393                                         $$->colname = $1;
394                                         $$->typename = $2;
395                                         $$->typename->timezone = $3;
396                                         $$->defval = $4;
397                                         $$->is_not_null = $5;
398                                         if ($$->typename->timezone
399                                          && (strcasecmp($$->typename->name, "timestamp")
400                                           && strcasecmp($$->typename->name, "time")))
401                                                 elog(NOTICE,"%s does not use WITH TIME ZONE",$$->typename->name);
402                                 }
403                 ;
404
405 OptDefault:  DEFAULT default_expr
406                                 {
407                                         int deflen = CurScanPosition() - DefaultStartPosition;
408                                         char *defval;
409
410                                         defval = (char*) palloc (deflen + 1);
411                                         memcpy (defval, parseString + DefaultStartPosition,
412                                                         deflen);
413                                         defval[deflen] = 0;
414                                         $$ = defval;
415                                 }
416                 |  /*EMPTY*/                    { $$ = NULL; }
417                 ;
418
419 default_expr_or_null: default_expr
420                                 { $$ = $1;}
421                 | Pnull
422                                 {
423                                         A_Const *n = makeNode(A_Const);
424                                         n->val.type = T_Null;
425                                         $$ = (Node *)n;
426                                 }
427
428 default_expr:   AexprConst
429                                 {
430                                         if (nodeTag($1) != T_A_Const)
431                                                 elog (WARN, "Cannot handle parameter in DEFAULT");
432                                         $$ = $1;
433                                 }
434                 | '-' default_expr %prec UMINUS
435                                 {       $$ = makeA_Expr(OP, "-", NULL, $2); }
436                 | default_expr '+' default_expr
437                                 {       $$ = makeA_Expr(OP, "+", $1, $3); }
438                 | default_expr '-' default_expr
439                                 {       $$ = makeA_Expr(OP, "-", $1, $3); }
440                 | default_expr '/' default_expr
441                                 {       $$ = makeA_Expr(OP, "/", $1, $3); }
442                 | default_expr '*' default_expr
443                                 {       $$ = makeA_Expr(OP, "*", $1, $3); }
444                 | default_expr '<' default_expr
445                                 {       $$ = makeA_Expr(OP, "<", $1, $3); }
446                 | default_expr '>' default_expr
447                                 {       $$ = makeA_Expr(OP, ">", $1, $3); }
448                 | default_expr '=' default_expr
449                                 {       $$ = makeA_Expr(OP, "=", $1, $3); }
450                 | ':' default_expr
451                                 {       $$ = makeA_Expr(OP, ":", NULL, $2); }
452                 | ';' default_expr
453                                 {       $$ = makeA_Expr(OP, ";", NULL, $2); }
454                 | '|' default_expr
455                                 {       $$ = makeA_Expr(OP, "|", NULL, $2); }
456                 | AexprConst TYPECAST Typename
457                                 {
458                                         /* AexprConst can be either A_Const or ParamNo */
459                                         if (nodeTag($1) == T_A_Const)
460                                                 ((A_Const *)$1)->typename = $3;
461                                         else
462                                                 elog (WARN, "Cannot handle parameter in DEFAULT");
463                                         $$ = (Node *)$1;
464                                 }
465                 | CAST AexprConst AS Typename
466                                 {
467                                         /* AexprConst can be either A_Const or ParamNo */
468                                         if (nodeTag($2) == T_A_Const)
469                                                 ((A_Const *)$2)->typename = $4;
470                                         else
471                                                 elog (WARN, "Cannot handle parameter in DEFAULT");
472                                         $$ = (Node *)$2;
473                                 }
474                 | '(' default_expr ')'
475                                 {       $$ = $2; }
476                 | default_expr Op default_expr
477                                 {       $$ = makeA_Expr(OP, $2, $1, $3); }
478                 | Op default_expr
479                                 {       $$ = makeA_Expr(OP, $1, NULL, $2); }
480                 | default_expr Op
481                                 {       $$ = makeA_Expr(OP, $2, $1, NULL); }
482                 | name '(' ')'
483                                 {
484                                         FuncCall *n = makeNode(FuncCall);
485                                         n->funcname = $1;
486                                         n->args = NIL;
487                                         $$ = (Node *)n;
488                                 }
489                 | name '(' default_expr_list ')'
490                                 {
491                                         FuncCall *n = makeNode(FuncCall);
492                                         n->funcname = $1;
493                                         n->args = $3;
494                                         $$ = (Node *)n;
495                                 }
496                 ;
497
498 default_expr_list: default_expr_or_null
499                                 { $$ = lcons($1, NIL); }
500                 |  default_expr_list ',' default_expr_or_null
501                                 { $$ = lappend($1, $3); }
502                 ;
503
504 opt_null: NOT PNULL                             { $$ = true; }
505                 | NOTNULL                               { $$ = true; }
506                 | /* EMPTY */                   { $$ = false; }
507                 ;
508
509 opt_with_col:  WITH TIME ZONE                                   { $$ = TRUE; }
510                 |  /* EMPTY */                                                  { $$ = FALSE; }
511                 ;
512
513 /*****************************************************************************
514  *
515  *              QUERY :
516  *                              close <optname>
517  *
518  *****************************************************************************/
519
520 ClosePortalStmt:  CLOSE opt_id
521                                 {
522                                         ClosePortalStmt *n = makeNode(ClosePortalStmt);
523                                         n->portalname = $2;
524                                         $$ = (Node *)n;
525                                 }
526                 ;
527
528
529 /*****************************************************************************
530  *
531  *              QUERY :
532  *                              COPY [BINARY] <relname> FROM/TO
533  *                              [USING DELIMITERS <delimiter>]
534  *
535  *****************************************************************************/
536
537 CopyStmt:  COPY opt_binary relation_name opt_with_copy copy_dirn copy_file_name copy_delimiter
538                                 {
539                                         CopyStmt *n = makeNode(CopyStmt);
540                                         n->binary = $2;
541                                         n->relname = $3;
542                                         n->oids = $4;
543                                         n->direction = $5;
544                                         n->filename = $6;
545                                         n->delimiter = $7;
546                                         $$ = (Node *)n;
547                                 }
548                 ;
549
550 copy_dirn:      TO
551                                 { $$ = TO; }
552                 |  FROM
553                                 { $$ = FROM; }
554                 ;
555
556 /*
557  * copy_file_name NULL indicates stdio is used. Whether stdin or stdout is
558  * used depends on the direction. (It really doesn't make sense to copy from
559  * stdout. We silently correct the "typo".               - AY 9/94
560  */
561 copy_file_name:  Sconst                                                 { $$ = $1; }
562                 | STDIN                                                                 { $$ = NULL; }
563                 | STDOUT                                                                { $$ = NULL; }
564                 ;
565
566 opt_binary: BINARY                                                              { $$ = TRUE; }
567                 |  /*EMPTY*/                                                    { $$ = FALSE; }
568                 ;
569
570 opt_with_copy:  WITH OIDS                                               { $$ = TRUE; }
571                 |  /* EMPTY */                                                  { $$ = FALSE; }
572                 ;
573
574 /*
575  * the default copy delimiter is tab but the user can configure it
576  */
577 copy_delimiter: USING DELIMITERS Sconst { $$ = $3;}
578                 | /* EMPTY */  { $$ = "\t"; }
579                 ;
580
581
582 /*****************************************************************************
583  *
584  *              QUERY :
585  *                              CREATE relname
586  *
587  *****************************************************************************/
588
589 CreateStmt:  CREATE TABLE relation_name '(' OptTableElementList ')'
590                                 OptInherit OptConstraint OptArchiveType OptLocation
591                                 OptArchiveLocation
592                                 {
593                                         CreateStmt *n = makeNode(CreateStmt);
594                                         n->relname = $3;
595                                         n->tableElts = $5;
596                                         n->inhRelnames = $7;
597                                         n->constraints = $8;
598                                         n->archiveType = $9;
599                                         n->location = $10;
600                                         n->archiveLoc = $11;
601                                         $$ = (Node *)n;
602                                 }
603                 ;
604
605 OptTableElementList:  tableElementList                  { $$ = $1; }
606                 | /* EMPTY */                                                   { $$ = NULL; }
607                 ;
608
609 tableElementList :
610                   tableElementList ',' columnDef
611                                 { $$ = lappend($1, $3); }
612                 | columnDef
613                                 { $$ = lcons($1, NIL); }
614                 ;
615
616
617 OptArchiveType:  ARCHIVE '=' archive_type                               { $$ = $3; }
618                 | /*EMPTY*/                                                                             { $$ = ARCH_NONE; }
619                 ;
620
621 archive_type:  HEAVY                                                                    { $$ = ARCH_HEAVY; }
622                 | LIGHT                                                                                 { $$ = ARCH_LIGHT; }
623                 | NONE                                                                                  { $$ = ARCH_NONE; }
624                 ;
625
626 OptLocation:  STORE '=' Sconst
627                                 {  $$ = smgrin($3);  }
628                 | /*EMPTY*/
629                                 {  $$ = -1;  }
630                 ;
631
632 OptArchiveLocation: ARCH_STORE '=' Sconst
633                                 {  $$ = smgrin($3);  }
634                 | /*EMPTY*/
635                                 {  $$ = -1;  }
636                 ;
637
638 OptInherit:  INHERITS '(' relation_name_list ')'                { $$ = $3; }
639                 |  /*EMPTY*/                                                                    { $$ = NIL; }
640                 ;
641
642 OptConstraint:  ConstraintList                  { $$ = $1; }
643                 |                               { $$ = NULL; }
644                 ;
645
646 ConstraintList :
647                   ConstraintList ',' ConstraintElem
648                                 { $$ = lappend($1, $3); }
649                 | ConstraintElem
650                                 { $$ = lcons($1, NIL); }
651                 ;
652
653 ConstraintElem:
654                 CONSTRAINT name ConstraintDef
655                                 {
656                                                 $3->name = $2;
657                                                 $$ = $3;
658                                 }
659                 | ConstraintDef                 { $$ = $1; }
660                 ;
661
662 ConstraintDef:  CHECK a_expr
663                                 {
664                                         ConstraintDef *constr = palloc (sizeof(ConstraintDef));
665                                         int chklen = CurScanPosition() - CheckStartPosition;
666                                         char *check;
667
668                                         check = (char*) palloc (chklen + 1);
669                                         memcpy (check,
670                                                                 parseString + CheckStartPosition,
671                                                                 chklen);
672                                         check[chklen] = 0;
673                                         constr->type = CONSTR_CHECK;
674                                         constr->name = NULL;
675                                         constr->def = (void*) check;
676                                         $$ = constr;
677                                 }
678                 ;
679
680 /*****************************************************************************
681  *
682  *              QUERY :
683  *                              CREATE SEQUENCE seqname
684  *
685  *****************************************************************************/
686
687 CreateSeqStmt:  CREATE SEQUENCE relation_name OptSeqList
688                                 {
689                                         CreateSeqStmt *n = makeNode(CreateSeqStmt);
690                                         n->seqname = $3;
691                                         n->options = $4;
692                                         $$ = (Node *)n;
693                                 }
694                 ;
695
696 OptSeqList:
697                                 OptSeqList OptSeqElem
698                                 { $$ = lappend($1, $2); }
699                 |               { $$ = NIL; }
700                 ;
701
702 OptSeqElem:             IDENT NumConst
703                                 {
704                                         $$ = makeNode(DefElem);
705                                         $$->defname = $1;
706                                         $$->arg = (Node *)$2;
707                                 }
708                 |               IDENT
709                                 {
710                                         $$ = makeNode(DefElem);
711                                         $$->defname = $1;
712                                         $$->arg = (Node *)NULL;
713                                 }
714                 ;
715
716
717 /*****************************************************************************
718  *
719  *              QUERIES :
720  *                              CREATE TRIGGER ...
721  *                              DROP TRIGGER ...
722  *
723  *****************************************************************************/
724
725 CreateTrigStmt: CREATE TRIGGER name TriggerActionTime TriggerEvents ON
726                                 relation_name TriggerForSpec EXECUTE PROCEDURE
727                                 name '(' TriggerFuncArgs ')'
728                                 {
729                                         CreateTrigStmt *n = makeNode(CreateTrigStmt);
730                                         n->trigname = $3;
731                                         n->relname = $7;
732                                         n->funcname = $11;
733                                         n->args = $13;
734                                         n->before = $4;
735                                         n->row = $8;
736                                         memcpy (n->actions, $5, 4);
737                                         $$ = (Node *)n;
738                                 }
739                 ;
740
741 TriggerActionTime:              BEFORE  { $$ = true; }
742                                 |               AFTER   { $$ = false; }
743                 ;
744
745 TriggerEvents:  TriggerOneEvent
746                                         {
747                                                         char *e = palloc (4);
748                                                         e[0] = $1; e[1] = 0; $$ = e;
749                                         }
750                                 | TriggerOneEvent OR TriggerOneEvent
751                                         {
752                                                         char *e = palloc (4);
753                                                         e[0] = $1; e[1] = $3; e[2] = 0; $$ = e;
754                                         }
755                                 | TriggerOneEvent OR TriggerOneEvent OR TriggerOneEvent
756                                         {
757                                                         char *e = palloc (4);
758                                                         e[0] = $1; e[1] = $3; e[2] = $5; e[3] = 0;
759                                                         $$ = e;
760                                         }
761                 ;
762
763 TriggerOneEvent:                INSERT  { $$ = 'i'; }
764                                 |               DELETE  { $$ = 'd'; }
765                                 |               UPDATE  { $$ = 'u'; }
766                 ;
767
768 TriggerForSpec: FOR name name
769                                 {
770                                                 if ( strcmp ($2, "each") != 0 )
771                                                                 elog (WARN, "parser: syntax error near %s", $2);
772                                                 if ( strcmp ($3, "row") == 0 )
773                                                                 $$ = true;
774                                                 else if ( strcmp ($3, "statement") == 0 )
775                                                                 $$ = false;
776                                                 else
777                                                                 elog (WARN, "parser: syntax error near %s", $3);
778                                 }
779                 ;
780
781 TriggerFuncArgs: TriggerFuncArg
782                                 { $$ = lcons($1, NIL); }
783                 |  TriggerFuncArgs ',' TriggerFuncArg
784                                 { $$ = lappend($1, $3); }
785                 |  /* EMPTY */  { $$ = NIL; }
786                 ;
787
788 TriggerFuncArg: ICONST
789                                 {
790                                                 char *s = (char *) palloc (256);
791                                                 sprintf (s, "%d", $1);
792                                                 $$ = s;
793                                 }
794                                 | Sconst                {  $$ = $1; }
795                 ;
796
797 DropTrigStmt:   DROP TRIGGER name ON relation_name
798                                 {
799                                         DropTrigStmt *n = makeNode(DropTrigStmt);
800                                         n->trigname = $3;
801                                         n->relname = $5;
802                                         $$ = (Node *) n;
803                                 }
804                 ;
805
806 /*****************************************************************************
807  *
808  *              QUERY :
809  *                              define (type,operator,aggregate)
810  *
811  *****************************************************************************/
812
813 DefineStmt:  CREATE def_type def_rest
814                                 {
815                                         $3->defType = $2;
816                                         $$ = (Node *)$3;
817                                 }
818                 ;
819
820 def_rest:  def_name definition
821                                 {
822                                         $$ = makeNode(DefineStmt);
823                                         $$->defname = $1;
824                                         $$->definition = $2;
825                                 }
826                 ;
827
828 def_type:  OPERATOR                                                             { $$ = OPERATOR; }
829                 |  Type                                                                 { $$ = P_TYPE; }
830                 |  AGGREGATE                                                    { $$ = AGGREGATE; }
831                 ;
832
833 def_name:  Id   |  MathOp |  Op
834                 ;
835
836
837 definition:  '(' def_list ')'                                   { $$ = $2; }
838                 ;
839
840
841 def_list:  def_elem
842                                 { $$ = lcons($1, NIL); }
843                 |  def_list ',' def_elem
844                                 { $$ = lappend($1, $3); }
845                 ;
846
847 def_elem:  def_name '=' def_arg
848                                 {
849                                         $$ = makeNode(DefElem);
850                                         $$->defname = $1;
851                                         $$->arg = (Node *)$3;
852                                 }
853                 |  def_name
854                                 {
855                                         $$ = makeNode(DefElem);
856                                         $$->defname = $1;
857                                         $$->arg = (Node *)NULL;
858                                 }
859                 |  DEFAULT '=' def_arg
860                                 {
861                                         $$ = makeNode(DefElem);
862                                         $$->defname = (char*) palloc (8);
863                                         strcpy ($$->defname, "default");
864                                         $$->arg = (Node *)$3;
865                                 }
866                 ;
867
868 def_arg:  Id                                    {  $$ = (Node *)makeString($1); }
869                 | all_Op                                {  $$ = (Node *)makeString($1); }
870                 | NumConst                              {  $$ = (Node *)$1; /* already a Value */ }
871                 | Sconst                                {  $$ = (Node *)makeString($1); }
872                 | SETOF Id                              {
873                                                                    TypeName *n = makeNode(TypeName);
874                                                                    n->name = $2;
875                                                                    n->setof = TRUE;
876                                                                    n->arrayBounds = NULL;
877                                                                    $$ = (Node *)n;
878                                                                 }
879                 ;
880
881
882 /*****************************************************************************
883  *
884  *              QUERY:
885  *                              destroy <relname1> [, <relname2> .. <relnameN> ]
886  *
887  *****************************************************************************/
888
889 DestroyStmt:    DROP TABLE relation_name_list
890                                 {
891                                         DestroyStmt *n = makeNode(DestroyStmt);
892                                         n->relNames = $3;
893                                         n->sequence = false;
894                                         $$ = (Node *)n;
895                                 }
896                 |               DROP SEQUENCE relation_name_list
897                                 {
898                                         DestroyStmt *n = makeNode(DestroyStmt);
899                                         n->relNames = $3;
900                                         n->sequence = true;
901                                         $$ = (Node *)n;
902                                 }
903                 ;
904
905
906 /*****************************************************************************
907  *
908  *              QUERY:
909  *                              fetch [forward | backward] [number | all ] [ in <portalname> ]
910  *
911  *****************************************************************************/
912
913 FetchStmt:      FETCH opt_direction fetch_how_many opt_portal_name
914                                 {
915                                         FetchStmt *n = makeNode(FetchStmt);
916                                         n->direction = $2;
917                                         n->howMany = $3;
918                                         n->portalname = $4;
919                                         $$ = (Node *)n;
920                                 }
921                 ;
922
923 opt_direction:  FORWARD                                                 { $$ = FORWARD; }
924                 | BACKWARD                                                              { $$ = BACKWARD; }
925                 | /*EMPTY*/                                                             { $$ = FORWARD; /* default */ }
926                 ;
927
928 fetch_how_many:  Iconst
929                            { $$ = $1;
930                                  if ($1 <= 0) elog(WARN,"Please specify nonnegative count for fetch"); }
931                 |  ALL                                                  { $$ = 0; /* 0 means fetch all tuples*/}
932                 |  /*EMPTY*/                                    { $$ = 1; /*default*/ }
933                 ;
934
935 /*****************************************************************************
936  *
937  *              QUERY:
938  *                              GRANT [privileges] ON [relation_name_list] TO [GROUP] grantee
939  *
940  *****************************************************************************/
941
942 GrantStmt: GRANT privileges ON relation_name_list TO grantee opt_with_grant
943                                 {
944                                         $$ = (Node*)makeAclStmt($2,$4,$6,'+');
945                                         free($2);
946                                         free($6);
947                                 }
948                 ;
949
950 privileges:  ALL PRIVILEGES
951                                 {
952                                  $$ = aclmakepriv("rwaR",0);
953                                 }
954                 | ALL
955                                 {
956                                  $$ = aclmakepriv("rwaR",0);
957                                 }
958                 | operation_commalist
959                                 {
960                                  $$ = $1;
961                                 }
962                 ;
963
964 operation_commalist: operation
965                                 {
966                                                 $$ = aclmakepriv("",$1);
967                                 }
968                 | operation_commalist ',' operation
969                                 {
970                                                 $$ = aclmakepriv($1,$3);
971                                                 free($1);
972                                 }
973                 ;
974
975 operation:        SELECT
976                                 {
977                                                 $$ = ACL_MODE_RD_CHR;
978                                 }
979                 | INSERT
980                                 {
981                                                 $$ = ACL_MODE_AP_CHR;
982                                 }
983                 | UPDATE
984                                 {
985                                                 $$ = ACL_MODE_WR_CHR;
986                                 }
987                 | DELETE
988                                 {
989                                                 $$ = ACL_MODE_WR_CHR;
990                                 }
991                         | RULE
992                                 {
993                                                 $$ = ACL_MODE_RU_CHR;
994                                 }
995                 ;
996
997 grantee:  PUBLIC
998                                 {
999                                                 $$ = aclmakeuser("A","");
1000                                 }
1001                 | GROUP Id
1002                                 {
1003                                                 $$ = aclmakeuser("G",$2);
1004                                 }
1005                 | Id
1006                                 {
1007                                                 $$ = aclmakeuser("U",$1);
1008                                 }
1009                 ;
1010
1011 opt_with_grant : /* empty */
1012                 |       WITH GRANT OPTION
1013                                 {
1014                                         yyerror("WITH GRANT OPTION is not supported.  Only relation owners can set privileges");
1015                                 }
1016                 ;
1017
1018 /*****************************************************************************
1019  *
1020  *              QUERY:
1021  *                              REVOKE [privileges] ON [relation_name] FROM [user]
1022  *
1023  *****************************************************************************/
1024
1025 RevokeStmt: REVOKE privileges ON relation_name_list FROM grantee
1026                                 {
1027                                         $$ = (Node*)makeAclStmt($2,$4,$6,'-');
1028                                         free($2);
1029                                         free($6);
1030                                 }
1031                 ;
1032
1033 /*****************************************************************************
1034  *
1035  *              QUERY:
1036  *                              move [<dirn>] [<whereto>] [<portalname>]
1037  *
1038  *****************************************************************************/
1039
1040 MoveStmt:  MOVE opt_direction opt_move_where opt_portal_name
1041                                 {
1042                                         MoveStmt *n = makeNode(MoveStmt);
1043                                         n->direction = $2;
1044                                         n->to = FALSE;
1045                                         n->where = $3;
1046                                         n->portalname = $4;
1047                                         $$ = (Node *)n;
1048                                 }
1049                 |  MOVE opt_direction TO Iconst opt_portal_name
1050                                 {
1051                                         MoveStmt *n = makeNode(MoveStmt);
1052                                         n->direction = $2;
1053                                         n->to = TRUE;
1054                                         n->where = $4;
1055                                         n->portalname = $5;
1056                                         $$ = (Node *)n;
1057                                 }
1058                 ;
1059
1060 opt_move_where: Iconst                                  { $$ = $1; }
1061                 | /*EMPTY*/                                             { $$ = 1; /* default */ }
1062                 ;
1063
1064 opt_portal_name: IN name                                { $$ = $2;}
1065                 | /*EMPTY*/                                             { $$ = NULL; }
1066                 ;
1067
1068
1069 /*****************************************************************************
1070  *
1071  *              QUERY:
1072  *                              define [archive] index <indexname> on <relname>
1073  *                                using <access> "(" (<col> with <op>)+ ")" [with
1074  *                                <target_list>]
1075  *
1076  *      [where <qual>] is not supported anymore
1077  *****************************************************************************/
1078
1079 IndexStmt:      CREATE index_opt_unique INDEX index_name ON relation_name
1080                         access_method_clause '(' index_params ')' opt_with
1081                                 {
1082                                         /* should check that access_method is valid,
1083                                            etc ... but doesn't */
1084                                         IndexStmt *n = makeNode(IndexStmt);
1085                                         n->unique = $2;
1086                                         n->idxname = $4;
1087                                         n->relname = $6;
1088                                         n->accessMethod = $7;
1089                                         n->indexParams = $9;
1090                                         n->withClause = $11;
1091                                         n->whereClause = NULL;
1092                                         $$ = (Node *)n;
1093                                 }
1094                 ;
1095
1096 access_method_clause:   USING access_method              { $$ = $2; }
1097                                           | /* empty -- 'btree' is default access method */
1098                                                                                                  { $$ = "btree"; }
1099                 ;
1100
1101 index_opt_unique: UNIQUE                                                 { $$ = TRUE; }
1102                                   | /*empty*/                                    { $$ = FALSE; }
1103                 ;
1104
1105 /*****************************************************************************
1106  *
1107  *              QUERY:
1108  *                              extend index <indexname> [where <qual>]
1109  *
1110  *****************************************************************************/
1111
1112 ExtendStmt:  EXTEND INDEX index_name where_clause
1113                                 {
1114                                         ExtendStmt *n = makeNode(ExtendStmt);
1115                                         n->idxname = $3;
1116                                         n->whereClause = $4;
1117                                         $$ = (Node *)n;
1118                                 }
1119                 ;
1120
1121 /*****************************************************************************
1122  *
1123  *              QUERY:
1124  *                              execute recipe <recipeName>
1125  *
1126  *****************************************************************************/
1127
1128 RecipeStmt:  EXECUTE RECIPE recipe_name
1129                                 {
1130                                         RecipeStmt *n;
1131                                         if (!IsTransactionBlock())
1132                                                 elog(WARN, "EXECUTE RECIPE may only be used in begin/end transaction blocks.");
1133
1134                                         n = makeNode(RecipeStmt);
1135                                         n->recipeName = $3;
1136                                         $$ = (Node *)n;
1137                                 }
1138                 ;
1139
1140
1141 /*****************************************************************************
1142  *
1143  *              QUERY:
1144  *                              define function <fname>
1145  *                                         (language = <lang>, returntype = <typename>
1146  *                                              [, arch_pct = <percentage | pre-defined>]
1147  *                                              [, disk_pct = <percentage | pre-defined>]
1148  *                                              [, byte_pct = <percentage | pre-defined>]
1149  *                                              [, perbyte_cpu = <int | pre-defined>]
1150  *                                              [, percall_cpu = <int | pre-defined>]
1151  *                                              [, iscachable])
1152  *                                              [arg is (<type-1> { , <type-n>})]
1153  *                                              as <filename or code in language as appropriate>
1154  *
1155  *****************************************************************************/
1156
1157 ProcedureStmt:  CREATE FUNCTION def_name def_args
1158                                    RETURNS def_arg opt_with AS Sconst LANGUAGE Sconst
1159                                 {
1160                                         ProcedureStmt *n = makeNode(ProcedureStmt);
1161                                         n->funcname = $3;
1162                                         n->defArgs = $4;
1163                                         n->returnType = (Node *)$6;
1164                                         n->withClause = $7;
1165                                         n->as = $9;
1166                                         n->language = $11;
1167                                         $$ = (Node *)n;
1168                                 };
1169
1170 opt_with:  WITH definition                                              { $$ = $2; }
1171                 |  /* EMPTY */                                                  { $$ = NIL; }
1172                 ;
1173
1174 def_args:  '(' def_name_list ')'                                { $$ = $2; }
1175                 |  '(' ')'                                                              { $$ = NIL; }
1176                 ;
1177
1178 def_name_list:  name_list;
1179
1180
1181 /*****************************************************************************
1182  *
1183  *              QUERY:
1184  *                              purge <relname> [before <date>] [after <date>]
1185  *                                or
1186  *                              purge <relname>  [after <date>] [before <date>]
1187  *
1188  *****************************************************************************/
1189
1190 PurgeStmt:      PURGE relation_name purge_quals
1191                                 {
1192                                         $3->relname = $2;
1193                                         $$ = (Node *)$3;
1194                                 }
1195                 ;
1196
1197 purge_quals:  before_clause
1198                                 {
1199                                         $$ = makeNode(PurgeStmt);
1200                                         $$->beforeDate = $1;
1201                                         $$->afterDate = NULL;
1202                                 }
1203                 |  after_clause
1204                                 {
1205                                         $$ = makeNode(PurgeStmt);
1206                                         $$->beforeDate = NULL;
1207                                         $$->afterDate = $1;
1208                                 }
1209                 |  before_clause after_clause
1210                                 {
1211                                         $$ = makeNode(PurgeStmt);
1212                                         $$->beforeDate = $1;
1213                                         $$->afterDate = $2;
1214                                 }
1215                 |  after_clause before_clause
1216                                 {
1217                                         $$ = makeNode(PurgeStmt);
1218                                         $$->beforeDate = $2;
1219                                         $$->afterDate = $1;
1220                                 }
1221                 |  /*EMPTY*/
1222                                 {
1223                                         $$ = makeNode(PurgeStmt);
1224                                         $$->beforeDate = NULL;
1225                                         $$->afterDate = NULL;
1226                                 }
1227                 ;
1228
1229 before_clause:  BEFORE date                             { $$ = $2; }
1230 after_clause:   AFTER date                              { $$ = $2; }
1231
1232
1233 /*****************************************************************************
1234  *
1235  *              QUERY:
1236  *
1237  *              remove function <funcname>
1238  *                              (REMOVE FUNCTION "funcname" (arg1, arg2, ...))
1239  *              remove aggregate <aggname>
1240  *                              (REMOVE AGGREGATE "aggname" "aggtype")
1241  *              remove operator <opname>
1242  *                              (REMOVE OPERATOR "opname" (leftoperand_typ rightoperand_typ))
1243  *              remove type <typename>
1244  *                              (REMOVE TYPE "typename")
1245  *              remove rule <rulename>
1246  *                              (REMOVE RULE "rulename")
1247  *
1248  *****************************************************************************/
1249
1250 RemoveStmt:  DROP remove_type name
1251                                 {
1252                                         RemoveStmt *n = makeNode(RemoveStmt);
1253                                         n->removeType = $2;
1254                                         n->name = $3;
1255                                         $$ = (Node *)n;
1256                                 }
1257                 ;
1258
1259 remove_type:  Type                                                              {  $$ = P_TYPE; }
1260                 |  INDEX                                                                {  $$ = INDEX; }
1261                 |  RULE                                                                 {  $$ = RULE; }
1262                 |  VIEW                                                                 {  $$ = VIEW; }
1263                 ;
1264
1265 RemoveAggrStmt:  DROP AGGREGATE name aggr_argtype
1266                                 {
1267                                                 RemoveAggrStmt *n = makeNode(RemoveAggrStmt);
1268                                                 n->aggname = $3;
1269                                                 n->aggtype = $4;
1270                                                 $$ = (Node *)n;
1271                                 }
1272                 ;
1273
1274 aggr_argtype:  name                                                             { $$ = $1; }
1275                 |  '*'                                                                  { $$ = NULL; }
1276                 ;
1277
1278 RemoveFuncStmt:  DROP FUNCTION name '(' func_argtypes ')'
1279                                 {
1280                                         RemoveFuncStmt *n = makeNode(RemoveFuncStmt);
1281                                         n->funcname = $3;
1282                                         n->args = $5;
1283                                         $$ = (Node *)n;
1284                                 }
1285                 ;
1286
1287 func_argtypes:  name_list                                               { $$ = $1; }
1288                 |  /*EMPTY*/                                                    { $$ = NIL; }
1289                 ;
1290
1291 RemoveOperStmt:  DROP OPERATOR all_Op '(' oper_argtypes ')'
1292                                 {
1293                                         RemoveOperStmt *n = makeNode(RemoveOperStmt);
1294                                         n->opname = $3;
1295                                         n->args = $5;
1296                                         $$ = (Node *)n;
1297                                 }
1298                 ;
1299
1300 all_Op: Op | MathOp;
1301
1302 MathOp:    '+'                  { $$ = "+"; }
1303                 |  '-'                  { $$ = "-"; }
1304                 |  '*'                  { $$ = "*"; }
1305                 |  '/'                  { $$ = "/"; }
1306                 |  '<'                  { $$ = "<"; }
1307                 |  '>'                  { $$ = ">"; }
1308                 |  '='                  { $$ = "="; }
1309                 ;
1310
1311 oper_argtypes:  name
1312                                 {
1313                                    elog(WARN, "parser: argument type missing (use NONE for unary operators)");
1314                                 }
1315                 | name ',' name
1316                                 { $$ = makeList(makeString($1), makeString($3), -1); }
1317                 | NONE ',' name                 /* left unary */
1318                                 { $$ = makeList(NULL, makeString($3), -1); }
1319                 | name ',' NONE                 /* right unary */
1320                                 { $$ = makeList(makeString($1), NULL, -1); }
1321                 ;
1322
1323 /*****************************************************************************
1324  *
1325  *              QUERY:
1326  *                              rename <attrname1> in <relname> [*] to <attrname2>
1327  *                              rename <relname1> to <relname2>
1328  *
1329  *****************************************************************************/
1330
1331 RenameStmt:  ALTER TABLE relation_name opt_inh_star
1332                                   RENAME opt_column opt_name TO name
1333                                 {
1334                                         RenameStmt *n = makeNode(RenameStmt);
1335                                         n->relname = $3;
1336                                         n->inh = $4;
1337                                         n->column = $7;
1338                                         n->newname = $9;
1339                                         $$ = (Node *)n;
1340                                 }
1341                 ;
1342
1343 opt_name:  name                                                 { $$ = $1; }
1344                 |  /*EMPTY*/                                    { $$ = NULL; }
1345                 ;
1346
1347 opt_column:  COLUMN                                             { $$ = COLUMN; }
1348                 | /*EMPTY*/                                             { $$ = 0; }
1349                 ;
1350
1351
1352 /*****************************************************************************
1353  *
1354  *              QUERY:  Define Rewrite Rule , Define Tuple Rule
1355  *                              Define Rule <old rules >
1356  *
1357  *              only rewrite rule is supported -- ay 9/94
1358  *
1359  *****************************************************************************/
1360
1361 RuleStmt:  CREATE RULE name AS
1362                    { QueryIsRule=TRUE; }
1363                    ON event TO event_object where_clause
1364                    DO opt_instead OptStmtList
1365                                 {
1366                                         RuleStmt *n = makeNode(RuleStmt);
1367                                         n->rulename = $3;
1368                                         n->event = $7;
1369                                         n->object = $9;
1370                                         n->whereClause = $10;
1371                                         n->instead = $12;
1372                                         n->actions = $13;
1373                                         $$ = (Node *)n;
1374                                 }
1375                 ;
1376
1377 OptStmtList:  NOTHING                                   { $$ = NIL; }
1378                 | OptimizableStmt                               { $$ = lcons($1, NIL); }
1379                 | '[' OptStmtBlock ']'                  { $$ = $2; }
1380                 ;
1381
1382 OptStmtBlock:  OptStmtMulti
1383                                 {  $$ = $1; }
1384                 |  OptimizableStmt
1385                                 { $$ = lcons($1, NIL); }
1386                 ;
1387
1388 OptStmtMulti:  OptStmtMulti OptimizableStmt ';'
1389                                 {  $$ = lappend($1, $2); }
1390                 |  OptStmtMulti OptimizableStmt
1391                                 {  $$ = lappend($1, $2); }
1392                 |  OptimizableStmt ';'
1393                                 { $$ = lcons($1, NIL); }
1394                 ;
1395
1396 event_object: relation_name '.' attr_name
1397                                 {
1398                                         $$ = makeNode(Attr);
1399                                         $$->relname = $1;
1400                                         $$->paramNo = NULL;
1401                                         $$->attrs = lcons(makeString($3), NIL);
1402                                         $$->indirection = NIL;
1403                                 }
1404                 | relation_name
1405                                 {
1406                                         $$ = makeNode(Attr);
1407                                         $$->relname = $1;
1408                                         $$->paramNo = NULL;
1409                                         $$->attrs = NIL;
1410                                         $$->indirection = NIL;
1411                                 }
1412                 ;
1413
1414 /* change me to select, update, etc. some day */
1415 event:  SELECT                                                  { $$ = CMD_SELECT; }
1416                 | UPDATE                                                { $$ = CMD_UPDATE; }
1417                 | DELETE                                                { $$ = CMD_DELETE; }
1418                 | INSERT                                                { $$ = CMD_INSERT; }
1419                  ;
1420
1421 opt_instead:  INSTEAD                                   { $$ = TRUE; }
1422                 | /* EMPTY */                                   { $$ = FALSE; }
1423                 ;
1424
1425
1426 /*****************************************************************************
1427  *
1428  *              QUERY:
1429  *                              NOTIFY <relation_name>  can appear both in rule bodies and
1430  *                              as a query-level command
1431  *
1432  *****************************************************************************/
1433
1434 NotifyStmt: NOTIFY relation_name
1435                                 {
1436                                         NotifyStmt *n = makeNode(NotifyStmt);
1437                                         n->relname = $2;
1438                                         $$ = (Node *)n;
1439                                 }
1440                 ;
1441
1442 ListenStmt: LISTEN relation_name
1443                                 {
1444                                         ListenStmt *n = makeNode(ListenStmt);
1445                                         n->relname = $2;
1446                                         $$ = (Node *)n;
1447                                 }
1448 ;
1449
1450
1451 /*****************************************************************************
1452  *
1453  *              Transactions:
1454  *
1455  *              abort transaction
1456  *                              (ABORT)
1457  *              begin transaction
1458  *                              (BEGIN)
1459  *              end transaction
1460  *                              (END)
1461  *
1462  *****************************************************************************/
1463
1464 TransactionStmt:  ABORT_TRANS TRANSACTION
1465                                 {
1466                                         TransactionStmt *n = makeNode(TransactionStmt);
1467                                         n->command = ABORT_TRANS;
1468                                         $$ = (Node *)n;
1469                                 }
1470                 | BEGIN_TRANS TRANSACTION
1471                                 {
1472                                         TransactionStmt *n = makeNode(TransactionStmt);
1473                                         n->command = BEGIN_TRANS;
1474                                         $$ = (Node *)n;
1475                                 }
1476                 | BEGIN_TRANS WORK
1477                                 {
1478                                         TransactionStmt *n = makeNode(TransactionStmt);
1479                                         n->command = BEGIN_TRANS;
1480                                         $$ = (Node *)n;
1481                                 }
1482                 | COMMIT WORK
1483                                 {
1484                                         TransactionStmt *n = makeNode(TransactionStmt);
1485                                         n->command = END_TRANS;
1486                                         $$ = (Node *)n;
1487                                 }
1488                 | END_TRANS TRANSACTION
1489                                 {
1490                                         TransactionStmt *n = makeNode(TransactionStmt);
1491                                         n->command = END_TRANS;
1492                                         $$ = (Node *)n;
1493                                 }
1494                 | ROLLBACK WORK
1495                                 {
1496                                         TransactionStmt *n = makeNode(TransactionStmt);
1497                                         n->command = ABORT_TRANS;
1498                                         $$ = (Node *)n;
1499                                 }
1500
1501                 | ABORT_TRANS
1502                                 {
1503                                         TransactionStmt *n = makeNode(TransactionStmt);
1504                                         n->command = ABORT_TRANS;
1505                                         $$ = (Node *)n;
1506                                 }
1507                 | BEGIN_TRANS
1508                                 {
1509                                         TransactionStmt *n = makeNode(TransactionStmt);
1510                                         n->command = BEGIN_TRANS;
1511                                         $$ = (Node *)n;
1512                                 }
1513                 | COMMIT
1514                                 {
1515                                         TransactionStmt *n = makeNode(TransactionStmt);
1516                                         n->command = END_TRANS;
1517                                         $$ = (Node *)n;
1518                                 }
1519
1520                 | END_TRANS
1521                                 {
1522                                         TransactionStmt *n = makeNode(TransactionStmt);
1523                                         n->command = END_TRANS;
1524                                         $$ = (Node *)n;
1525                                 }
1526                 | ROLLBACK
1527                                 {
1528                                         TransactionStmt *n = makeNode(TransactionStmt);
1529                                         n->command = ABORT_TRANS;
1530                                         $$ = (Node *)n;
1531                                 }
1532                 ;
1533
1534
1535 /*****************************************************************************
1536  *
1537  *              QUERY:
1538  *                              define view <viewname> '('target-list ')' [where <quals> ]
1539  *
1540  *****************************************************************************/
1541
1542 ViewStmt:  CREATE VIEW name AS RetrieveStmt
1543                                 {
1544                                         ViewStmt *n = makeNode(ViewStmt);
1545                                         n->viewname = $3;
1546                                         n->query = (Query *)$5;
1547                                         $$ = (Node *)n;
1548                                 }
1549                 ;
1550
1551
1552 /*****************************************************************************
1553  *
1554  *              QUERY:
1555  *                              load "filename"
1556  *
1557  *****************************************************************************/
1558
1559 LoadStmt: LOAD file_name
1560                                 {
1561                                         LoadStmt *n = makeNode(LoadStmt);
1562                                         n->filename = $2;
1563                                         $$ = (Node *)n;
1564                                 }
1565                 ;
1566
1567
1568 /*****************************************************************************
1569  *
1570  *              QUERY:
1571  *                              createdb dbname
1572  *
1573  *****************************************************************************/
1574
1575 CreatedbStmt:  CREATE DATABASE database_name
1576                                 {
1577                                         CreatedbStmt *n = makeNode(CreatedbStmt);
1578                                         n->dbname = $3;
1579                                         $$ = (Node *)n;
1580                                 }
1581                 ;
1582
1583
1584 /*****************************************************************************
1585  *
1586  *              QUERY:
1587  *                              destroydb dbname
1588  *
1589  *****************************************************************************/
1590
1591 DestroydbStmt:  DROP DATABASE database_name
1592                                 {
1593                                         DestroydbStmt *n = makeNode(DestroydbStmt);
1594                                         n->dbname = $3;
1595                                         $$ = (Node *)n;
1596                                 }
1597                 ;
1598
1599
1600 /*****************************************************************************
1601  *
1602  *              QUERY:
1603  *                              cluster <index_name> on <relation_name>
1604  *
1605  *****************************************************************************/
1606
1607 ClusterStmt:  CLUSTER index_name ON relation_name
1608                                 {
1609                                    ClusterStmt *n = makeNode(ClusterStmt);
1610                                    n->relname = $4;
1611                                    n->indexname = $2;
1612                                    $$ = (Node*)n;
1613                                 }
1614                 ;
1615
1616 /*****************************************************************************
1617  *
1618  *              QUERY:
1619  *                              vacuum
1620  *
1621  *****************************************************************************/
1622
1623 VacuumStmt:  VACUUM opt_verbose opt_analyze
1624                                 {
1625                                         VacuumStmt *n = makeNode(VacuumStmt);
1626                                         n->verbose = $2;
1627                                         n->analyze = $3;
1628                                         n->vacrel = NULL;
1629                                         n->va_spec = NIL;
1630                                         $$ = (Node *)n;
1631                                 }
1632                 | VACUUM opt_verbose relation_name opt_analyze opt_va_list
1633                                 {
1634                                         VacuumStmt *n = makeNode(VacuumStmt);
1635                                         n->verbose = $2;
1636                                         n->analyze = $4;
1637                                         n->vacrel = $3;
1638                                         n->va_spec = $5;
1639                                         if ( $5 != NIL && !$4 )
1640                                                 elog (WARN, "parser: syntax error at or near \"(\"");
1641                                         $$ = (Node *)n;
1642                                 }
1643                 ;
1644
1645 opt_verbose:  VERBOSE                                   { $$ = TRUE; }
1646                 | /* EMPTY */                                   { $$ = FALSE; }
1647                 ;
1648
1649 opt_analyze:  ANALYZE                                   { $$ = TRUE; }
1650                 | /* EMPTY */                                   { $$ = FALSE; }
1651                 ;
1652
1653 opt_va_list: '(' va_list ')'
1654                                 { $$ = $2; }
1655                 | /* EMPTY */
1656                                 { $$ = NIL; }
1657                 ;
1658
1659 va_list: name
1660                                 { $$=lcons($1,NIL); }
1661                 | va_list ',' name
1662                                 { $$=lappend($1,$3); }
1663                 ;
1664
1665 /*****************************************************************************
1666  *
1667  *              QUERY:
1668  *                              EXPLAIN query
1669  *
1670  *****************************************************************************/
1671
1672 ExplainStmt:  EXPLAIN opt_verbose OptimizableStmt
1673                                 {
1674                                         ExplainStmt *n = makeNode(ExplainStmt);
1675                                         n->verbose = $2;
1676                                         n->query = (Query*)$3;
1677                                         $$ = (Node *)n;
1678                                 }
1679                 ;
1680
1681 /*****************************************************************************
1682  *                                                                                                                                                       *
1683  *              Optimizable Stmts:                                                                                                       *
1684  *                                                                                                                                                       *
1685  *              one of the five queries processed by the planner                                         *
1686  *                                                                                                                                                       *
1687  *              [ultimately] produces query-trees as specified                                           *
1688  *              in the query-spec document in ~postgres/ref                                                      *
1689  *                                                                                                                                                       *
1690  *****************************************************************************/
1691
1692 OptimizableStmt:  RetrieveStmt
1693                 | CursorStmt
1694                 | ReplaceStmt
1695                 | AppendStmt
1696                 | NotifyStmt
1697                 | DeleteStmt                                    /* by default all are $$=$1 */
1698                 ;
1699
1700
1701 /*****************************************************************************
1702  *
1703  *              QUERY:
1704  *                              INSERT STATEMENTS
1705  *
1706  *****************************************************************************/
1707
1708 AppendStmt:  INSERT INTO relation_name opt_column_list insert_rest
1709                                 {
1710                                         $5->relname = $3;
1711                                         $5->cols = $4;
1712                                         $$ = (Node *)$5;
1713                                 }
1714                 ;
1715
1716 insert_rest: VALUES '(' res_target_list2 ')'
1717                                 {
1718                                         $$ = makeNode(AppendStmt);
1719                                         $$->targetList = $3;
1720                                         $$->fromClause = NIL;
1721                                         $$->whereClause = NULL;
1722                                 }
1723                 | SELECT res_target_list2 from_clause where_clause
1724                                 {
1725                                         $$ = makeNode(AppendStmt);
1726                                         $$->targetList = $2;
1727                                         $$->fromClause = $3;
1728                                         $$->whereClause = $4;
1729                                 }
1730                 ;
1731
1732 opt_column_list: '(' columnList ')'                             { $$ = $2; }
1733                 | /*EMPTY*/                                                             { $$ = NIL; }
1734                 ;
1735
1736 columnList:
1737                   columnList ',' columnElem
1738                                 { $$ = lappend($1, $3); }
1739                 | columnElem
1740                                 { $$ = lcons($1, NIL); }
1741                 ;
1742
1743 columnElem: Id opt_indirection
1744                                 {
1745                                         Ident *id = makeNode(Ident);
1746                                         id->name = $1;
1747                                         id->indirection = $2;
1748                                         $$ = (Node *)id;
1749                                 }
1750                 ;
1751
1752 /*****************************************************************************
1753  *
1754  *              QUERY:
1755  *                              DELETE STATEMENTS
1756  *
1757  *****************************************************************************/
1758
1759 DeleteStmt:  DELETE FROM relation_name
1760                          where_clause
1761                                 {
1762                                         DeleteStmt *n = makeNode(DeleteStmt);
1763                                         n->relname = $3;
1764                                         n->whereClause = $4;
1765                                         $$ = (Node *)n;
1766                                 }
1767                 ;
1768
1769
1770 /*****************************************************************************
1771  *
1772  *              QUERY:
1773  *                              ReplaceStmt (UPDATE)
1774  *
1775  *****************************************************************************/
1776
1777 ReplaceStmt:  UPDATE relation_name
1778                           SET res_target_list
1779                           from_clause
1780                           where_clause
1781                                 {
1782                                         ReplaceStmt *n = makeNode(ReplaceStmt);
1783                                         n->relname = $2;
1784                                         n->targetList = $4;
1785                                         n->fromClause = $5;
1786                                         n->whereClause = $6;
1787                                         $$ = (Node *)n;
1788                                 }
1789                 ;
1790
1791
1792 /*****************************************************************************
1793  *
1794  *              QUERY:
1795  *                              CURSOR STATEMENTS
1796  *
1797  *****************************************************************************/
1798
1799 CursorStmt:  DECLARE name opt_binary CURSOR FOR
1800                          SELECT opt_unique res_target_list2
1801                          from_clause where_clause group_clause sort_clause
1802                                 {
1803                                         CursorStmt *n = makeNode(CursorStmt);
1804
1805                                         /* from PORTAL name */
1806                                         /*
1807                                          *      15 august 1991 -- since 3.0 postgres does locking
1808                                          *      right, we discovered that portals were violating
1809                                          *      locking protocol.  portal locks cannot span xacts.
1810                                          *      as a short-term fix, we installed the check here.
1811                                          *                                                      -- mao
1812                                          */
1813                                         if (!IsTransactionBlock())
1814                                                 elog(WARN, "Named portals may only be used in begin/end transaction blocks.");
1815
1816                                         n->portalname = $2;
1817                                         n->binary = $3;
1818                                         n->unique = $7;
1819                                         n->targetList = $8;
1820                                         n->fromClause = $9;
1821                                         n->whereClause = $10;
1822                                         n->groupClause = $11;
1823                                         n->sortClause = $12;
1824                                         $$ = (Node *)n;
1825                                 }
1826                 ;
1827
1828
1829 /*****************************************************************************
1830  *
1831  *              QUERY:
1832  *                              SELECT STATEMENTS
1833  *
1834  *****************************************************************************/
1835
1836 /******************************************************************************
1837 RetrieveStmt:  SELECT opt_unique res_target_list2
1838                            result from_clause where_clause
1839                            group_clause having_clause
1840                            sort_clause
1841                                 {
1842                                         RetrieveStmt *n = makeNode(RetrieveStmt);
1843                                         n->unique = $2;
1844                                         n->targetList = $3;
1845                                         n->into = $4;
1846                                         n->fromClause = $5;
1847                                         n->whereClause = $6;
1848                                         n->groupClause = $7;
1849                                         n->havingClause = $8;
1850                                         n->sortClause = $9;
1851                                         $$ = (Node *)n;
1852                                 }
1853                 ;
1854
1855 RetrieveStmt:  Select UNION select_list sort_clause
1856                 | Select sort_clause
1857 Select:  SELECT opt_unique res_target_list2
1858                            result from_clause where_clause
1859                            group_clause having_clause
1860                                 {
1861                                         Select *n = makeNode(Select);
1862                                         n->unique = $2;
1863                                         n->targetList = $3;
1864                                         n->into = $4;
1865                                         n->fromClause = $5;
1866                                         n->whereClause = $6;
1867                                         n->groupClause = $7;
1868                                         n->havingClause = $8;
1869                                         $$ = (Node *)n;
1870                                 }
1871                 ;
1872 ******************************************************************************/
1873
1874 RetrieveStmt:  SELECT opt_unique res_target_list2
1875                            result from_clause where_clause
1876                            group_clause having_clause
1877                            union_clause sort_clause
1878                                 {
1879                                         RetrieveStmt *n = makeNode(RetrieveStmt);
1880                                         n->unique = $2;
1881                                         n->targetList = $3;
1882                                         n->into = $4;
1883                                         n->fromClause = $5;
1884                                         n->whereClause = $6;
1885                                         n->groupClause = $7;
1886                                         n->havingClause = $8;
1887                                         n->selectClause = $9;
1888                                         n->sortClause = $10;
1889                                         $$ = (Node *)n;
1890                                 }
1891                 ;
1892
1893 union_clause:  UNION select_list                                { $$ = $2; }
1894                 |  /*EMPTY*/                                                    { $$ = NIL; }
1895                 ;
1896
1897 select_list:  select_list UNION SubSelect
1898                                 { $$ = lappend($1, $3); }
1899                 | SubSelect
1900                                 { $$ = lcons($1, NIL); }
1901                 ;
1902
1903 SubSelect:      SELECT opt_unique res_target_list2
1904                            result from_clause where_clause
1905                            group_clause having_clause
1906                                 {
1907                                         SubSelect *n = makeNode(SubSelect);
1908                                         n->unique = $2;
1909                                         n->targetList = $3;
1910                                         n->fromClause = $5;
1911                                         n->whereClause = $6;
1912                                         n->groupClause = $7;
1913                                         n->havingClause = $8;
1914                                         $$ = (Node *)n;
1915                                 }
1916                 ;
1917
1918 result:  INTO TABLE relation_name
1919                                 {  $$= $3;      /* should check for archive level */  }
1920                 | /*EMPTY*/
1921                                 {  $$ = NULL;  }
1922                 ;
1923
1924 opt_unique:  DISTINCT                   { $$ = "*"; }
1925                 | DISTINCT ON Id                { $$ = $3; }
1926                 | /*EMPTY*/                             { $$ = NULL;}
1927                 ;
1928
1929 sort_clause:  ORDER BY sortby_list                              { $$ = $3; }
1930                 |  /*EMPTY*/                                                    { $$ = NIL; }
1931                 ;
1932
1933 sortby_list:  sortby
1934                                 { $$ = lcons($1, NIL); }
1935                 | sortby_list ',' sortby
1936                                 { $$ = lappend($1, $3); }
1937                 ;
1938
1939 sortby:  Id OptUseOp
1940                                 {
1941                                         $$ = makeNode(SortGroupBy);
1942                                         $$->resno = 0;
1943                                         $$->range = NULL;
1944                                         $$->name = $1;
1945                                         $$->useOp = $2;
1946                                 }
1947                 | Id '.' Id OptUseOp
1948                                 {
1949                                         $$ = makeNode(SortGroupBy);
1950                                         $$->resno = 0;
1951                                         $$->range = $1;
1952                                         $$->name = $3;
1953                                         $$->useOp = $4;
1954                                 }
1955                 | Iconst OptUseOp
1956                                 {
1957                                         $$ = makeNode(SortGroupBy);
1958                                         $$->resno = $1;
1959                                         $$->range = NULL;
1960                                         $$->name = NULL;
1961                                         $$->useOp = $2;
1962                                 }
1963                 ;
1964
1965 OptUseOp:  USING Op                                                             { $$ = $2; }
1966                 |  USING '<'                                                    { $$ = "<"; }
1967                 |  USING '>'                                                    { $$ = ">"; }
1968                 |  ASC                                                                  { $$ = "<"; }
1969                 |  DESC                                                                 { $$ = ">"; }
1970                 |  /*EMPTY*/                                                    { $$ = "<"; /*default*/ }
1971                 ;
1972
1973 index_params: index_list                                                { $$ = $1; }
1974                 | func_index                                                    { $$ = lcons($1,NIL); }
1975                 ;
1976
1977 index_list:
1978                   index_list ',' index_elem
1979                                 { $$ = lappend($1, $3); }
1980                 | index_elem
1981                                 { $$ = lcons($1, NIL); }
1982                 ;
1983
1984 func_index: name '(' name_list ')' opt_type opt_class
1985                                 {
1986                                         $$ = makeNode(IndexElem);
1987                                         $$->name = $1;
1988                                         $$->args = $3;
1989                                         $$->class = $6;
1990                                         $$->tname = $5;
1991                                 }
1992                   ;
1993
1994 index_elem:  attr_name opt_type opt_class
1995                                 {
1996                                         $$ = makeNode(IndexElem);
1997                                         $$->name = $1;
1998                                         $$->args = NIL;
1999                                         $$->class = $3;
2000                                         $$->tname = $2;
2001                                 }
2002                 ;
2003
2004 opt_type: ':' Typename                                                  { $$ = $2;}
2005                 |  /*EMPTY*/                                                    { $$ = NULL;}
2006                 ;
2007
2008 opt_class:      class
2009                 |  WITH class                                                   { $$ = $2; }
2010                 |  /*EMPTY*/                                                    { $$ = NULL; }
2011                 ;
2012
2013 /*
2014  *      jimmy bell-style recursive queries aren't supported in the
2015  *      current system.
2016  *
2017  *      ...however, recursive addattr and rename supported.  make special
2018  *      cases for these.
2019  *
2020  *      XXX i believe '*' should be the default behavior, but...
2021  */
2022 opt_inh_star: '*'                                               { $$ = TRUE; }
2023                 |  /*EMPTY*/                                    { $$ = FALSE; }
2024                 ;
2025
2026 relation_name_list:             name_list ;
2027
2028 name_list: name
2029                                 { $$=lcons(makeString($1),NIL); }
2030                 | name_list ',' name
2031                                 { $$=lappend($1,makeString($3)); }
2032                 ;
2033
2034 group_clause: GROUP BY groupby_list                             { $$ = $3; }
2035                 | /*EMPTY*/                                                             { $$ = NIL; }
2036                 ;
2037
2038 groupby_list: groupby                                                   { $$ = lcons($1, NIL); }
2039                 | groupby_list ',' groupby                              { $$ = lappend($1, $3); }
2040                 ;
2041
2042 groupby:  Id
2043                                 {
2044                                         $$ = makeNode(SortGroupBy);
2045                                         $$->resno = 0;
2046                                         $$->range = NULL;
2047                                         $$->name = $1;
2048                                         $$->useOp = NULL;
2049                                 }
2050                 | Id '.' Id
2051                                 {
2052                                         $$ = makeNode(SortGroupBy);
2053                                         $$->resno = 0;
2054                                         $$->range = $1;
2055                                         $$->name = $3;
2056                                         $$->useOp = NULL;
2057                                 }
2058                 | Iconst
2059                                 {
2060                                         $$ = makeNode(SortGroupBy);
2061                                         $$->resno = $1;
2062                                         $$->range = NULL;
2063                                         $$->name = NULL;
2064                                         $$->useOp = NULL;
2065                                 }
2066                 ;
2067
2068 having_clause: HAVING a_expr                                    { $$ = $2; }
2069                 | /*EMPTY*/                                                             { $$ = NULL; }
2070                 ;
2071
2072 /*****************************************************************************
2073  *
2074  *      clauses common to all Optimizable Stmts:
2075  *              from_clause             -
2076  *              where_clause    -
2077  *
2078  *****************************************************************************/
2079
2080 from_clause:  FROM '(' relation_expr join_clause relation_expr join_spec ')'
2081                                 {
2082                                         $$ = NIL;
2083                                         elog(WARN,"JOIN not yet implemented",NULL);
2084                                 }
2085                 | FROM from_list                                                { $$ = $2; }
2086                 | /*EMPTY*/                                                             { $$ = NIL; }
2087                 ;
2088
2089 from_list:      from_list ',' from_val
2090                                 { $$ = lappend($1, $3); }
2091                 |  from_val CROSS JOIN from_val
2092                                 { elog(WARN,"CROSS JOIN not yet implemented",NULL); }
2093                 |  from_val
2094                                 { $$ = lcons($1, NIL); }
2095                 ;
2096
2097 from_val:  relation_expr AS var_name
2098                                 {
2099                                         $$ = makeNode(RangeVar);
2100                                         $$->relExpr = $1;
2101                                         $$->name = $3;
2102                                 }
2103                 | relation_expr var_name
2104                                 {
2105                                         $$ = makeNode(RangeVar);
2106                                         $$->relExpr = $1;
2107                                         $$->name = $2;
2108                                 }
2109                 | relation_expr
2110                                 {
2111                                         $$ = makeNode(RangeVar);
2112                                         $$->relExpr = $1;
2113                                         $$->name = NULL;
2114                                 }
2115                 ;
2116
2117 join_clause:  join_qual join_type JOIN
2118                                 {
2119                                         $$ = NULL;
2120                                 }
2121                 ;
2122
2123 join_qual:      NATURAL                                         { $$ = TRUE; }
2124                 | /*EMPTY*/                                             { $$ = FALSE; }
2125                 ;
2126
2127 join_type:      FULL join_outer
2128                                 { elog(WARN,"FULL OUTER JOIN not yet implemented",NULL); }
2129                 | LEFT join_outer
2130                                 { elog(WARN,"LEFT OUTER JOIN not yet implemented",NULL); }
2131                 | RIGHT join_outer
2132                                 { elog(WARN,"RIGHT OUTER JOIN not yet implemented",NULL); }
2133                 | join_outer
2134                                 { elog(WARN,"OUTER JOIN not yet implemented",NULL); }
2135                 | INNERJOIN
2136                                 { elog(WARN,"INNER JOIN not yet implemented",NULL); }
2137                 | UNION
2138                                 { elog(WARN,"UNION JOIN not yet implemented",NULL); }
2139                 | /*EMPTY*/                                             { $$ = NULL;  /* no qualifiers */ }
2140                 ;
2141
2142 join_outer:  OUTERJOIN                                  { $$ = NULL; }
2143                 | /*EMPTY*/                                             { $$ = NULL;  /* no qualifiers */ }
2144                 ;
2145
2146 join_spec:      ON '(' a_expr ')'                       { $$ = NULL; }
2147                 | USING '(' join_list ')'               { $$ = NULL; }
2148                 | /*EMPTY*/                                             { $$ = NULL;  /* no qualifiers */ }
2149                 ;
2150
2151 join_list: join_using                                                   { $$ = lcons($1, NIL); }
2152                 | join_list ',' join_using                              { $$ = lappend($1, $3); }
2153                 ;
2154
2155 join_using:  Id
2156                                 {
2157                                         $$ = makeNode(SortGroupBy);
2158                                         $$->resno = 0;
2159                                         $$->range = NULL;
2160                                         $$->name = $1;
2161                                         $$->useOp = NULL;
2162                                 }
2163                 | Id '.' Id
2164                                 {
2165                                         $$ = makeNode(SortGroupBy);
2166                                         $$->resno = 0;
2167                                         $$->range = $1;
2168                                         $$->name = $3;
2169                                         $$->useOp = NULL;
2170                                 }
2171                 | Iconst
2172                                 {
2173                                         $$ = makeNode(SortGroupBy);
2174                                         $$->resno = $1;
2175                                         $$->range = NULL;
2176                                         $$->name = NULL;
2177                                         $$->useOp = NULL;
2178                                 }
2179                 ;
2180
2181 where_clause:  WHERE a_expr                             { $$ = $2; }
2182                 | /*EMPTY*/                                             { $$ = NULL;  /* no qualifiers */ }
2183                 ;
2184
2185 relation_expr:  relation_name
2186                                 {
2187                                         /* normal relations */
2188                                         $$ = makeNode(RelExpr);
2189                                         $$->relname = $1;
2190                                         $$->inh = FALSE;
2191                                         $$->timeRange = NULL;
2192                                 }
2193                 | relation_name '*'                               %prec '='
2194                                 {
2195                                         /* inheiritance query */
2196                                         $$ = makeNode(RelExpr);
2197                                         $$->relname = $1;
2198                                         $$->inh = TRUE;
2199                                         $$->timeRange = NULL;
2200                                 }
2201                 | relation_name time_range
2202                                 {
2203                                         /* time-qualified query */
2204                                         $$ = makeNode(RelExpr);
2205                                         $$->relname = $1;
2206                                         $$->inh = FALSE;
2207                                         $$->timeRange = $2;
2208                                 }
2209                 ;
2210
2211
2212 time_range:  '[' opt_range_start ',' opt_range_end ']'
2213                                 {
2214                                         $$ = makeNode(TimeRange);
2215                                         $$->startDate = $2;
2216                                         $$->endDate = $4;
2217                                 }
2218                 | '[' date ']'
2219                                 {
2220                                         $$ = makeNode(TimeRange);
2221                                         $$->startDate = $2;
2222                                         $$->endDate = NULL;
2223                                 }
2224                 ;
2225
2226 opt_range_start:  date
2227                 |  /*EMPTY*/                                                    { $$ = "epoch"; }
2228                 ;
2229
2230 opt_range_end:  date
2231                 |  /*EMPTY*/                                                    { $$ = "now"; }
2232                 ;
2233
2234 opt_array_bounds:  '[' ']' nest_array_bounds
2235                                 {  $$ = lcons(makeInteger(-1), $3); }
2236                 | '[' Iconst ']' nest_array_bounds
2237                                 {  $$ = lcons(makeInteger($2), $4); }
2238                 | /* EMPTY */
2239                                 {  $$ = NIL; }
2240                 ;
2241
2242 nest_array_bounds:      '[' ']' nest_array_bounds
2243                                 {  $$ = lcons(makeInteger(-1), $3); }
2244                 | '[' Iconst ']' nest_array_bounds
2245                                 {  $$ = lcons(makeInteger($2), $4); }
2246                 | /*EMPTY*/
2247                                 {  $$ = NIL; }
2248                 ;
2249
2250 typname:  txname
2251                                 {
2252                                         char *tname = xlateSqlType($1);
2253                                         $$ = makeNode(TypeName);
2254                                         $$->name = tname;
2255
2256                                         /* Is this the name of a complex type? If so, implement
2257                                          * it as a set.
2258                                          */
2259                                         if (!strcmp(saved_relname, tname))
2260                                                 /* This attr is the same type as the relation
2261                                                  * being defined. The classic example: create
2262                                                  * emp(name=text,mgr=emp)
2263                                                  */
2264                                                 $$->setof = TRUE;
2265                                         else if (get_typrelid((Type)type(tname)) != InvalidOid)
2266                                                  /* (Eventually add in here that the set can only
2267                                                   * contain one element.)
2268                                                   */
2269                                                 $$->setof = TRUE;
2270                                         else
2271                                                 $$->setof = FALSE;
2272                                 }
2273                 | SETOF txname
2274                                 {
2275                                         char *tname = xlateSqlType($2);
2276                                         $$ = makeNode(TypeName);
2277                                         $$->name = tname;
2278                                         $$->setof = TRUE;
2279                                 }
2280                 ;
2281
2282 txname:  Id                                                             { $$ = $1; }
2283                 | TIME                                                  { $$ = "time"; }
2284                 | INTERVAL interval_opts                { $$ = "interval"; }
2285                 ;
2286
2287 interval_opts:  YEARINTERVAL                                    { $$ = lcons("year", NIL); }
2288                 | MONTHINTERVAL                                                 { $$ = NIL; }
2289                 | DAYINTERVAL                                                   { $$ = NIL; }
2290                 | HOURINTERVAL                                                  { $$ = NIL; }
2291                 | MINUTEINTERVAL                                                { $$ = NIL; }
2292                 | SECONDINTERVAL                                                { $$ = NIL; }
2293                 | YEARINTERVAL TO MONTHINTERVAL                 { $$ = NIL; }
2294                 | DAYINTERVAL TO HOURINTERVAL                   { $$ = NIL; }
2295                 | DAYINTERVAL TO MINUTEINTERVAL                 { $$ = NIL; }
2296                 | DAYINTERVAL TO SECONDINTERVAL                 { $$ = NIL; }
2297                 | HOURINTERVAL TO MINUTEINTERVAL                { $$ = NIL; }
2298                 | HOURINTERVAL TO SECONDINTERVAL                { $$ = NIL; }
2299                 | /* EMPTY */                                                   { $$ = NIL; }
2300                 ;
2301
2302 Typename:  typname opt_array_bounds
2303                                 {
2304                                         $$ = $1;
2305                                         $$->arrayBounds = $2;
2306                                 }
2307                 | txname '(' Iconst ')'
2308                                 {
2309                                         /*
2310                                          * This block gets hit when the parser is passed a query
2311                                          * which contains only spaces (e.g. from psql type "  \g").
2312                                          * Let's check explicitly for a zero-length argument
2313                                          * here, and do nothing if so. This seems to fix the problem.
2314                                          * - thomas 1997-07-13
2315                                          */
2316                                         if (strlen($1) > 0)
2317                                         {
2318
2319                                                 /*
2320                                                  * The following implements char() and varchar().
2321                                                  * We do it here instead of the 'typname:' production
2322                                                  * because we don't want to allow arrays of varchar().
2323                                                  * I haven't thought about whether that will work or not.
2324                                                  *                                                         - ay 6/95
2325                                                  */
2326                                                 $$ = makeNode(TypeName);
2327                                                 if (!strcasecmp($1, "char"))
2328                                                         $$->name = "bpchar"; /*  strdup("bpchar"); */
2329                                                 else if (!strcasecmp($1, "varchar"))
2330                                                         $$->name = "varchar"; /* strdup("varchar"); */
2331                                                 else
2332                                                         yyerror("parse error");
2333                                                 if ($3 < 1)
2334                                                         elog(WARN, "length for '%s' type must be at least 1",$1);
2335                                                 else if ($3 > 4096)
2336                                                         /* we can store a char() of length up to the size
2337                                                          * of a page (8KB) - page headers and friends but
2338                                                          * just to be safe here...      - ay 6/95
2339                                                          * XXX note this hardcoded limit - thomas 1997-07-13
2340                                                          */
2341                                                         elog(WARN, "length for '%s' type cannot exceed 4096",$1);
2342
2343                                                 /* we actually implement this sort of like a varlen, so
2344                                                  * the first 4 bytes is the length. (the difference
2345                                                  * between this and "text" is that we blank-pad and
2346                                                  * truncate where necessary
2347                                                  */
2348                                                 $$->typlen = 4 + $3;
2349
2350                                         }
2351                                 }
2352                 ;
2353
2354
2355 /*****************************************************************************
2356  *
2357  *      expression grammar, still needs some cleanup
2358  *
2359  *****************************************************************************/
2360
2361 a_expr_or_null: a_expr
2362                                 { $$ = $1;}
2363                 | Pnull
2364                                 {
2365                                         A_Const *n = makeNode(A_Const);
2366                                         n->val.type = T_Null;
2367                                         $$ = (Node *)n;
2368                                 }
2369
2370 a_expr:  attr opt_indirection
2371                                 {
2372                                         $1->indirection = $2;
2373                                         $$ = (Node *)$1;
2374                                 }
2375                 | AexprConst
2376                                 {       $$ = $1;  }
2377                 | '-' a_expr %prec UMINUS
2378                                 {       $$ = makeA_Expr(OP, "-", NULL, $2); }
2379                 | a_expr '+' a_expr
2380                                 {       $$ = makeA_Expr(OP, "+", $1, $3); }
2381                 | a_expr '-' a_expr
2382                                 {       $$ = makeA_Expr(OP, "-", $1, $3); }
2383                 | a_expr '/' a_expr
2384                                 {       $$ = makeA_Expr(OP, "/", $1, $3); }
2385                 | a_expr '*' a_expr
2386                                 {       $$ = makeA_Expr(OP, "*", $1, $3); }
2387                 | a_expr '<' a_expr
2388                                 {       $$ = makeA_Expr(OP, "<", $1, $3); }
2389                 | a_expr '>' a_expr
2390                                 {       $$ = makeA_Expr(OP, ">", $1, $3); }
2391                 | a_expr '=' a_expr
2392                                 {       $$ = makeA_Expr(OP, "=", $1, $3); }
2393                 | ':' a_expr
2394                                 {       $$ = makeA_Expr(OP, ":", NULL, $2); }
2395                 | ';' a_expr
2396                                 {       $$ = makeA_Expr(OP, ";", NULL, $2); }
2397                 | '|' a_expr
2398                                 {       $$ = makeA_Expr(OP, "|", NULL, $2); }
2399                 | AexprConst TYPECAST Typename
2400                                 {
2401                                         /* AexprConst can be either A_Const or ParamNo */
2402                                         if (nodeTag($1) == T_A_Const)
2403                                                 ((A_Const *)$1)->typename = $3;
2404                                         else
2405                                                 ((ParamNo *)$1)->typename = $3;
2406                                         $$ = (Node *)$1;
2407                                 }
2408                 | CAST AexprConst AS Typename
2409                                 {
2410                                         /* AexprConst can be either A_Const or ParamNo */
2411                                         if (nodeTag($2) == T_A_Const)
2412                                                 ((A_Const *)$2)->typename = $4;
2413                                         else
2414                                                 ((ParamNo *)$2)->typename = $4;
2415                                         $$ = (Node *)$2;
2416                                 }
2417                 | '(' a_expr_or_null ')'
2418                                 {       $$ = $2; }
2419                 | a_expr Op a_expr
2420                                 {       $$ = makeA_Expr(OP, $2, $1, $3); }
2421                 | a_expr LIKE a_expr
2422                                 {       $$ = makeA_Expr(OP, "~~", $1, $3); }
2423                 | a_expr NOT LIKE a_expr
2424                                 {       $$ = makeA_Expr(OP, "!~~", $1, $4); }
2425                 | Op a_expr
2426                                 {       $$ = makeA_Expr(OP, $1, NULL, $2); }
2427                 | a_expr Op
2428                                 {       $$ = makeA_Expr(OP, $2, $1, NULL); }
2429                 | Id
2430                                 {
2431                                         /* could be a column name or a relation_name */
2432                                         Ident *n = makeNode(Ident);
2433                                         n->name = $1;
2434                                         n->indirection = NULL;
2435                                         $$ = (Node *)n;
2436                                 }
2437                 | name '(' '*' ')'
2438                                 {
2439                                         FuncCall *n = makeNode(FuncCall);
2440                                         Ident *star = makeNode(Ident);
2441
2442                                         /* cheap hack for aggregate (eg. count) */
2443                                         star->name = "oid";
2444                                         n->funcname = $1;
2445                                         n->args = lcons(star, NIL);
2446                                         $$ = (Node *)n;
2447                                 }
2448                 | name '(' ')'
2449                                 {
2450                                         FuncCall *n = makeNode(FuncCall);
2451                                         n->funcname = $1;
2452                                         n->args = NIL;
2453                                         $$ = (Node *)n;
2454                                 }
2455                 /* We probably need to define an "exists" node,
2456                  *      since the optimizer could choose to find only one match.
2457                  * Perhaps the first implementation could just check for
2458                  *      count(*) > 0? - thomas 1997-07-19
2459                  */
2460                 | EXISTS '(' SubSelect ')'
2461                                 {
2462                                         elog(WARN,"EXISTS not yet supported",NULL);
2463                                         $$ = $3;
2464                                 }
2465                 | EXTRACT '(' extract_list ')'
2466                                 {
2467                                         FuncCall *n = makeNode(FuncCall);
2468                                         n->funcname = "date_part";
2469                                         n->args = $3;
2470                                         $$ = (Node *)n;
2471                                 }
2472                 | POSITION '(' position_list ')'
2473                                 {
2474                                         FuncCall *n = makeNode(FuncCall);
2475                                         n->funcname = "strpos";
2476                                         n->args = $3;
2477                                         $$ = (Node *)n;
2478                                 }
2479                 | SUBSTRING '(' substr_list ')'
2480                                 {
2481                                         FuncCall *n = makeNode(FuncCall);
2482                                         n->funcname = "substr";
2483                                         n->args = $3;
2484                                         $$ = (Node *)n;
2485                                 }
2486                 /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
2487                 | TRIM '(' BOTH trim_list ')'
2488                                 {
2489                                         FuncCall *n = makeNode(FuncCall);
2490                                         n->funcname = "btrim";
2491                                         n->args = $4;
2492                                         $$ = (Node *)n;
2493                                 }
2494                 | TRIM '(' LEADING trim_list ')'
2495                                 {
2496                                         FuncCall *n = makeNode(FuncCall);
2497                                         n->funcname = "ltrim";
2498                                         n->args = $4;
2499                                         $$ = (Node *)n;
2500                                 }
2501                 | TRIM '(' TRAILING trim_list ')'
2502                                 {
2503                                         FuncCall *n = makeNode(FuncCall);
2504                                         n->funcname = "rtrim";
2505                                         n->args = $4;
2506                                         $$ = (Node *)n;
2507                                 }
2508                 | TRIM '(' trim_list ')'
2509                                 {
2510                                         FuncCall *n = makeNode(FuncCall);
2511                                         n->funcname = "btrim";
2512                                         n->args = $3;
2513                                         $$ = (Node *)n;
2514                                 }
2515                 | name '(' expr_list ')'
2516                                 {
2517                                         FuncCall *n = makeNode(FuncCall);
2518                                         n->funcname = $1;
2519                                         n->args = $3;
2520                                         $$ = (Node *)n;
2521                                 }
2522                 | a_expr ISNULL
2523                                 {       $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
2524                 | a_expr IS PNULL
2525                                 {       $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
2526                 | a_expr NOTNULL
2527                                 {       $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); }
2528                 | a_expr IS NOT PNULL
2529                                 {       $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); }
2530                 | a_expr BETWEEN AexprConst AND AexprConst
2531                                 {
2532                                         $$ = makeA_Expr(AND, NULL,
2533                                                 makeA_Expr(OP, ">=", $1, $3),
2534                                                 makeA_Expr(OP, "<=", $1, $5));
2535                                 }
2536                 | a_expr NOT BETWEEN AexprConst AND AexprConst
2537                                 {
2538                                         $$ = makeA_Expr(OR, NULL,
2539                                                 makeA_Expr(OP, "<", $1, $4),
2540                                                 makeA_Expr(OP, ">", $1, $6));
2541                                 }
2542                 | a_expr IN { saved_In_Expr = $1; } '(' in_expr_nodes ')'
2543                                 {       $$ = $5; }
2544                 | a_expr NOT IN { saved_In_Expr = $1; } '(' not_in_expr_nodes ')'
2545                                 {       $$ = $6; }
2546                 | a_expr AND a_expr
2547                                 {       $$ = makeA_Expr(AND, NULL, $1, $3); }
2548                 | a_expr OR a_expr
2549                                 {       $$ = makeA_Expr(OR, NULL, $1, $3); }
2550                 | NOT a_expr
2551                                 {       $$ = makeA_Expr(NOT, NULL, NULL, $2); }
2552                 ;
2553
2554 opt_indirection:  '[' a_expr ']' opt_indirection
2555                                 {
2556                                         A_Indices *ai = makeNode(A_Indices);
2557                                         ai->lidx = NULL;
2558                                         ai->uidx = $2;
2559                                         $$ = lcons(ai, $4);
2560                                 }
2561                 | '[' a_expr ':' a_expr ']' opt_indirection
2562                                 {
2563                                         A_Indices *ai = makeNode(A_Indices);
2564                                         ai->lidx = $2;
2565                                         ai->uidx = $4;
2566                                         $$ = lcons(ai, $6);
2567                                 }
2568                 | /* EMPTY */
2569                                 {       $$ = NIL; }
2570                 ;
2571
2572 expr_list: a_expr_or_null
2573                                 { $$ = lcons($1, NIL); }
2574                 |  expr_list ',' a_expr_or_null
2575                                 { $$ = lappend($1, $3); }
2576                 |  expr_list USING a_expr
2577                                 { $$ = lappend($1, $3); }
2578                 ;
2579
2580 extract_list: datetime FROM a_expr
2581                                 {
2582                                         A_Const *n = makeNode(A_Const);
2583                                         n->val.type = T_String;
2584                                         n->val.val.str = $1;
2585 printf( "string is %s\n", $1);
2586                                         $$ = lappend(lcons((Node *)n,NIL), $3);
2587                                 }
2588                 | /* EMPTY */
2589                                 {       $$ = NIL; }
2590                 ;
2591
2592 position_list: a_expr IN expr_list
2593                                 {       $$ = lappend($3, $1); }
2594                 | /* EMPTY */
2595                                 {       $$ = NIL; }
2596                 ;
2597
2598 substr_list: expr_list substr_from substr_for
2599                                 {
2600                                         $$ = $1;
2601                                         if ($2 != NULL) $$ = lappend($$, $2);
2602                                         if ($3 != NULL) $$ = lappend($$, $3);
2603                                 }
2604                 | /* EMPTY */
2605                                 {       $$ = NIL; }
2606                 ;
2607
2608 substr_from: FROM expr_list
2609                                 {       $$ = $2; }
2610                 | /* EMPTY */
2611                                 {       $$ = NIL; }
2612                 ;
2613
2614 substr_for: FOR expr_list
2615                                 {       $$ = $2; }
2616                 | /* EMPTY */
2617                                 {       $$ = NIL; }
2618                 ;
2619
2620 trim_list: a_expr FROM expr_list
2621                                 { $$ = lappend($3, $1); }
2622                 |  FROM expr_list
2623                                 { $$ = $2; }
2624                 |  expr_list
2625                                 { $$ = $1; }
2626                 ;
2627
2628 in_expr_nodes: AexprConst
2629                                 {       $$ = makeA_Expr(OP, "=", saved_In_Expr, $1); }
2630                 |  in_expr_nodes ',' AexprConst
2631                                 {       $$ = makeA_Expr(OR, NULL, $1,
2632                                                 makeA_Expr(OP, "=", saved_In_Expr, $3));
2633                                 }
2634                 ;
2635
2636 not_in_expr_nodes: AexprConst
2637                                 {       $$ = makeA_Expr(OP, "<>", saved_In_Expr, $1); }
2638                 |  not_in_expr_nodes ',' AexprConst
2639                                 {       $$ = makeA_Expr(AND, NULL, $1,
2640                                                 makeA_Expr(OP, "<>", saved_In_Expr, $3));
2641                                 }
2642                 ;
2643
2644 attr:  relation_name '.' attrs
2645                                 {
2646                                         $$ = makeNode(Attr);
2647                                         $$->relname = $1;
2648                                         $$->paramNo = NULL;
2649                                         $$->attrs = $3;
2650                                         $$->indirection = NULL;
2651                                 }
2652                 | ParamNo '.' attrs
2653                                 {
2654                                         $$ = makeNode(Attr);
2655                                         $$->relname = NULL;
2656                                         $$->paramNo = $1;
2657                                         $$->attrs = $3;
2658                                         $$->indirection = NULL;
2659                                 }
2660                 ;
2661
2662 attrs:    attr_name
2663                                 { $$ = lcons(makeString($1), NIL); }
2664                 | attrs '.' attr_name
2665                                 { $$ = lappend($1, makeString($3)); }
2666                 | attrs '.' '*'
2667                                 { $$ = lappend($1, makeString("*")); }
2668                 ;
2669
2670 datetime:  YEARINTERVAL                                                 { $$ = "year"; }
2671                 | MONTHINTERVAL                                                 { $$ = "month"; }
2672                 | DAYINTERVAL                                                   { $$ = "day"; }
2673                 | HOURINTERVAL                                                  { $$ = "hour"; }
2674                 | MINUTEINTERVAL                                                { $$ = "minute"; }
2675                 | SECONDINTERVAL                                                { $$ = "second"; }
2676                 ;
2677
2678 /*****************************************************************************
2679  *
2680  *      target lists
2681  *
2682  *****************************************************************************/
2683
2684 res_target_list:  res_target_list ',' res_target_el
2685                                 {       $$ = lappend($1,$3);  }
2686                 | res_target_el
2687                                 {       $$ = lcons($1, NIL);  }
2688                 | '*'
2689                                 {
2690                                         ResTarget *rt = makeNode(ResTarget);
2691                                         Attr *att = makeNode(Attr);
2692                                         att->relname = "*";
2693                                         att->paramNo = NULL;
2694                                         att->attrs = NULL;
2695                                         att->indirection = NIL;
2696                                         rt->name = NULL;
2697                                         rt->indirection = NULL;
2698                                         rt->val = (Node *)att;
2699                                         $$ = lcons(rt, NIL);
2700                                 }
2701                 ;
2702
2703 res_target_el: Id opt_indirection '=' a_expr_or_null
2704                                 {
2705                                         $$ = makeNode(ResTarget);
2706                                         $$->name = $1;
2707                                         $$->indirection = $2;
2708                                         $$->val = (Node *)$4;
2709                                 }
2710                 | attr opt_indirection
2711                                 {
2712                                         $$ = makeNode(ResTarget);
2713                                         $$->name = NULL;
2714                                         $$->indirection = $2;
2715                                         $$->val = (Node *)$1;
2716                                 }
2717                 | relation_name '.' '*'
2718                                 {
2719                                         Attr *att = makeNode(Attr);
2720                                         att->relname = $1;
2721                                         att->paramNo = NULL;
2722                                         att->attrs = lcons(makeString("*"), NIL);
2723                                         att->indirection = NIL;
2724                                         $$ = makeNode(ResTarget);
2725                                         $$->name = NULL;
2726                                         $$->indirection = NULL;
2727                                         $$->val = (Node *)att;
2728                                 }
2729                 ;
2730
2731 /*
2732 ** target list for select.
2733 ** should get rid of the other but is still needed by the defunct retrieve into
2734 ** and update (uses a subset)
2735 */
2736 res_target_list2: res_target_list2 ',' res_target_el2
2737                                 {       $$ = lappend($1, $3);  }
2738                 | res_target_el2
2739                                 {       $$ = lcons($1, NIL);  }
2740                 ;
2741
2742 /* AS is not optional because shift/red conflict with unary ops */
2743 res_target_el2: a_expr AS ColId
2744                                 {
2745                                         $$ = makeNode(ResTarget);
2746                                         $$->name = $3;
2747                                         $$->indirection = NULL;
2748                                         $$->val = (Node *)$1;
2749                                 }
2750                 | a_expr_or_null
2751                                 {
2752                                         $$ = makeNode(ResTarget);
2753                                         $$->name = NULL;
2754                                         $$->indirection = NULL;
2755                                         $$->val = (Node *)$1;
2756                                 }
2757                 | relation_name '.' '*'
2758                                 {
2759                                         Attr *att = makeNode(Attr);
2760                                         att->relname = $1;
2761                                         att->paramNo = NULL;
2762                                         att->attrs = lcons(makeString("*"), NIL);
2763                                         att->indirection = NIL;
2764                                         $$ = makeNode(ResTarget);
2765                                         $$->name = NULL;
2766                                         $$->indirection = NULL;
2767                                         $$->val = (Node *)att;
2768                                 }
2769                 | '*'
2770                                 {
2771                                         Attr *att = makeNode(Attr);
2772                                         att->relname = "*";
2773                                         att->paramNo = NULL;
2774                                         att->attrs = NULL;
2775                                         att->indirection = NIL;
2776                                         $$ = makeNode(ResTarget);
2777                                         $$->name = NULL;
2778                                         $$->indirection = NULL;
2779                                         $$->val = (Node *)att;
2780                                 }
2781                 ;
2782
2783 opt_id:  Id                                                                             { $$ = $1; }
2784                 | /* EMPTY */                                                   { $$ = NULL; }
2785                 ;
2786
2787 relation_name:  SpecialRuleRelation
2788                                 {
2789                                         $$ = $1;
2790                                         strNcpy(saved_relname, $1, NAMEDATALEN-1);
2791                                 }
2792                 | ColId
2793                                 {
2794                                         /* disallow refs to magic system tables */
2795                                         if (strcmp(LogRelationName, $1) == 0
2796                                            || strcmp(VariableRelationName, $1) == 0
2797                                            || strcmp(TimeRelationName, $1) == 0
2798                                            || strcmp(MagicRelationName, $1) == 0)
2799                                                 elog(WARN, "%s cannot be accessed by users", $1);
2800                                         else
2801                                                 $$ = $1;
2802                                         strNcpy(saved_relname, $1, NAMEDATALEN-1);
2803                                 }
2804                 ;
2805
2806 database_name:                  Id                              { $$ = $1; };
2807 access_method:                  Id                              { $$ = $1; };
2808 attr_name:                              ColId                   { $$ = $1; };
2809 class:                                  Id                              { $$ = $1; };
2810 index_name:                             Id                              { $$ = $1; };
2811 var_name:                               Id                              { $$ = $1; };
2812 name:                                   Id                              { $$ = $1; };
2813
2814 date:                                   Sconst                  { $$ = $1; };
2815 file_name:                              Sconst                  { $$ = $1; };
2816 recipe_name:                    Id                              { $$ = $1; };
2817
2818 AexprConst:  Iconst
2819                                 {
2820                                         A_Const *n = makeNode(A_Const);
2821                                         n->val.type = T_Integer;
2822                                         n->val.val.ival = $1;
2823                                         $$ = (Node *)n;
2824                                 }
2825                 | FCONST
2826                                 {
2827                                         A_Const *n = makeNode(A_Const);
2828                                         n->val.type = T_Float;
2829                                         n->val.val.dval = $1;
2830                                         $$ = (Node *)n;
2831                                 }
2832                 | Sconst
2833                                 {
2834                                         A_Const *n = makeNode(A_Const);
2835                                         n->val.type = T_String;
2836                                         n->val.val.str = $1;
2837                                         $$ = (Node *)n;
2838                                 }
2839                 | ParamNo
2840                                 {       $$ = (Node *)$1;  }
2841                 ;
2842
2843 ParamNo:  PARAM
2844                                 {
2845                                         $$ = makeNode(ParamNo);
2846                                         $$->number = $1;
2847                                 }
2848                 ;
2849
2850 NumConst:  Iconst                                               { $$ = makeInteger($1); }
2851                 |  FCONST                                               { $$ = makeFloat($1); }
2852                 ;
2853
2854 Iconst:  ICONST                                                 { $$ = $1; };
2855 Sconst:  SCONST                                                 { $$ = $1; };
2856
2857 Id:  IDENT                                                              { $$ = $1; };
2858
2859 ColId:  Id                                                              { $$ = $1; }
2860                 | datetime                                              { $$ = $1; }
2861                 ;
2862
2863 SpecialRuleRelation:  CURRENT
2864                                 {
2865                                         if (QueryIsRule)
2866                                                 $$ = "*CURRENT*";
2867                                         else
2868                                                 elog(WARN,"CURRENT used in non-rule query");
2869                                 }
2870                 | NEW
2871                                 {
2872                                         if (QueryIsRule)
2873                                                 $$ = "*NEW*";
2874                                         else
2875                                                 elog(WARN,"NEW used in non-rule query");
2876                                 }
2877                 ;
2878
2879 Type:   P_TYPE;
2880 Pnull:  PNULL;
2881
2882
2883 %%
2884
2885 static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr)
2886 {
2887         A_Expr *a = makeNode(A_Expr);
2888         a->oper = oper;
2889         a->opname = opname;
2890         a->lexpr = lexpr;
2891         a->rexpr = rexpr;
2892         return (Node *)a;
2893 }
2894
2895 static char *
2896 xlateSqlType(char *name)
2897 {
2898         if (!strcasecmp(name,"int") ||
2899                 !strcasecmp(name,"integer"))
2900                 return "int4"; /* strdup("int4") --   strdup leaks memory here */
2901         else if (!strcasecmp(name, "smallint"))
2902                 return "int2";
2903         else if (!strcasecmp(name, "float") ||
2904                          !strcasecmp(name, "real"))
2905                 return "float8";
2906         else if (!strcasecmp(name, "interval"))
2907                 return "timespan";
2908         else
2909                 return name;
2910 }
2911
2912 void parser_init(Oid *typev, int nargs)
2913 {
2914         QueryIsRule = false;
2915         saved_relname[0]= '\0';
2916         saved_In_Expr = NULL;
2917
2918         param_type_init(typev, nargs);
2919 }