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