]> granicus.if.org Git - postgresql/blob - src/backend/parser/gram.y
Fix for "default = '...'" in CREATE TYPE
[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.40 1997/08/28 05:02:01 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         |  DEFAULT '=' def_arg
720                 {
721                     $$ = makeNode(DefElem);
722                     $$->defname = (char*) palloc (8);
723                     strcpy ($$->defname, "default");
724                     $$->arg = (Node *)$3;
725                 }
726         ;
727
728 def_arg:  Id                    {  $$ = (Node *)makeString($1); }
729         | all_Op                {  $$ = (Node *)makeString($1); }
730         | NumConst              {  $$ = (Node *)$1; /* already a Value */ }
731         | Sconst                {  $$ = (Node *)makeString($1); }
732         | SETOF Id              { 
733                                    TypeName *n = makeNode(TypeName);
734                                    n->name = $2;
735                                    n->setof = TRUE;
736                                    n->arrayBounds = NULL;
737                                    $$ = (Node *)n;
738                                 }                               
739         ;
740
741
742 /*****************************************************************************
743  *
744  *      QUERY:  
745  *              destroy <relname1> [, <relname2> .. <relnameN> ]
746  *
747  *****************************************************************************/
748
749 DestroyStmt:    DROP TABLE relation_name_list
750                 { 
751                     DestroyStmt *n = makeNode(DestroyStmt);
752                     n->relNames = $3;
753                     n->sequence = false;
754                     $$ = (Node *)n;
755                 }
756         |       DROP SEQUENCE relation_name_list
757                 { 
758                     DestroyStmt *n = makeNode(DestroyStmt);
759                     n->relNames = $3;
760                     n->sequence = true;
761                     $$ = (Node *)n;
762                 }
763         ;
764
765
766 /*****************************************************************************
767  *
768  *      QUERY:
769  *              fetch [forward | backward] [number | all ] [ in <portalname> ]
770  *
771  *****************************************************************************/
772
773 FetchStmt:  FETCH opt_direction fetch_how_many opt_portal_name
774                 {
775                     FetchStmt *n = makeNode(FetchStmt);
776                     n->direction = $2;
777                     n->howMany = $3;
778                     n->portalname = $4;
779                     $$ = (Node *)n;
780                 }
781         ;
782
783 opt_direction:  FORWARD                         { $$ = FORWARD; }
784         | BACKWARD                              { $$ = BACKWARD; }
785         | /*EMPTY*/                             { $$ = FORWARD; /* default */ }
786         ;
787
788 fetch_how_many:  Iconst                 
789                { $$ = $1;
790                  if ($1 <= 0) elog(WARN,"Please specify nonnegative count for fetch"); }
791         |  ALL                          { $$ = 0; /* 0 means fetch all tuples*/}
792         |  /*EMPTY*/                    { $$ = 1; /*default*/ }
793         ;
794
795 /*****************************************************************************
796  *
797  *      QUERY:
798  *              GRANT [privileges] ON [relation_name_list] TO [GROUP] grantee
799  *
800  *****************************************************************************/
801
802 GrantStmt: GRANT privileges ON relation_name_list TO grantee opt_with_grant
803            {
804                 $$ = (Node*)makeAclStmt($2,$4,$6,'+');
805                 free($2);
806                 free($6);
807            }
808            ;
809
810 privileges:  ALL PRIVILEGES
811                 {
812                  $$ = aclmakepriv("rwaR",0);
813                 }
814            | ALL
815                 {
816                  $$ = aclmakepriv("rwaR",0);
817                 }
818            | operation_commalist {
819                 $$ = $1;
820                 }
821            ;
822
823 operation_commalist: operation {
824                         $$ = aclmakepriv("",$1);
825                         }
826                    | operation_commalist ',' operation
827                         {
828                                 $$ = aclmakepriv($1,$3);
829                                 free($1);
830                         }
831                    ;
832
833 operation:    SELECT  {
834                 $$ = ACL_MODE_RD_CHR;
835                 }
836             | INSERT {
837                 $$ = ACL_MODE_AP_CHR;
838                 }
839             | UPDATE {
840                 $$ = ACL_MODE_WR_CHR;
841                 }
842             | DELETE {
843                 $$ = ACL_MODE_WR_CHR;
844                 }
845             | RULE {
846                 $$ = ACL_MODE_RU_CHR;
847                 }
848             ;
849
850 grantee:      PUBLIC {
851                 $$ = aclmakeuser("A","");
852                 }
853             | GROUP Id {
854                 $$ = aclmakeuser("G",$2);
855                 }
856             | Id {
857                 $$ = aclmakeuser("U",$1);
858                 }
859             ;
860
861 opt_with_grant : /* empty */
862             |   WITH GRANT OPTION 
863                 {
864                     yyerror("WITH GRANT OPTION is not supported.  Only relation owners can set privileges");
865                 }
866             ;
867 /*****************************************************************************
868  *
869  *      QUERY:
870  *              REVOKE [privileges] ON [relation_name] FROM [user]
871  *
872  *****************************************************************************/
873
874 RevokeStmt: REVOKE privileges ON relation_name_list FROM grantee
875               {
876                 $$ = (Node*)makeAclStmt($2,$4,$6,'-');
877                 free($2);
878                 free($6);
879               }
880             ;
881
882 /*****************************************************************************
883  *
884  *      QUERY:
885  *              move [<dirn>] [<whereto>] [<portalname>]
886  *
887  *****************************************************************************/
888
889 MoveStmt:  MOVE opt_direction opt_move_where opt_portal_name
890                 { 
891                     MoveStmt *n = makeNode(MoveStmt);
892                     n->direction = $2;
893                     n->to = FALSE;
894                     n->where = $3;
895                     n->portalname = $4;
896                     $$ = (Node *)n;
897                 }
898         |  MOVE opt_direction TO Iconst opt_portal_name
899                 { 
900                     MoveStmt *n = makeNode(MoveStmt);
901                     n->direction = $2;
902                     n->to = TRUE;
903                     n->where = $4;
904                     n->portalname = $5;
905                     $$ = (Node *)n;
906                 }
907         ;
908
909 opt_move_where: Iconst                          { $$ = $1; }
910         | /*EMPTY*/                             { $$ = 1; /* default */ }
911         ;
912
913 opt_portal_name: IN name                        { $$ = $2;}
914         | /*EMPTY*/                             { $$ = NULL; }
915         ;
916
917
918 /*****************************************************************************
919  *
920  *      QUERY:
921  *              define [archive] index <indexname> on <relname>
922  *                using <access> "(" (<col> with <op>)+ ")" [with
923  *                <target_list>]
924  *
925  *  [where <qual>] is not supported anymore
926  *****************************************************************************/
927
928 IndexStmt:  CREATE index_opt_unique INDEX index_name ON relation_name
929             access_method_clause '(' index_params ')' opt_with
930                 {
931                     /* should check that access_method is valid,
932                        etc ... but doesn't */
933                     IndexStmt *n = makeNode(IndexStmt);
934                     n->unique = $2;
935                     n->idxname = $4;
936                     n->relname = $6;
937                     n->accessMethod = $7;
938                     n->indexParams = $9;
939                     n->withClause = $11;
940                     n->whereClause = NULL;
941                     $$ = (Node *)n;
942                 }
943         ;
944
945 access_method_clause:   USING access_method      { $$ = $2; }
946                       | /* empty -- 'btree' is default access method */
947                                                  { $$ = "btree"; }
948         ;
949
950 index_opt_unique: UNIQUE                                 { $$ = TRUE; }
951                   | /*empty*/                            { $$ = FALSE; }
952         ;
953
954 /*****************************************************************************
955  *
956  *      QUERY:
957  *              extend index <indexname> [where <qual>]
958  *
959  *****************************************************************************/
960
961 ExtendStmt:  EXTEND INDEX index_name where_clause
962                 {
963                     ExtendStmt *n = makeNode(ExtendStmt);
964                     n->idxname = $3;
965                     n->whereClause = $4;
966                     $$ = (Node *)n;
967                 }
968         ;
969
970 /*****************************************************************************
971  *
972  *      QUERY:
973  *              execute recipe <recipeName> 
974  *
975  *****************************************************************************/
976
977 RecipeStmt:  EXECUTE RECIPE recipe_name 
978                 {
979                     RecipeStmt *n;
980                     if (!IsTransactionBlock())
981                         elog(WARN, "EXECUTE RECIPE may only be used in begin/end transaction blocks.");
982
983                     n = makeNode(RecipeStmt);
984                     n->recipeName = $3;
985                     $$ = (Node *)n;
986                 }
987         ;
988
989
990 /*****************************************************************************
991  *
992  *      QUERY:
993  *              define function <fname>
994  *                     (language = <lang>, returntype = <typename> 
995  *                      [, arch_pct = <percentage | pre-defined>]
996  *                      [, disk_pct = <percentage | pre-defined>]
997  *                      [, byte_pct = <percentage | pre-defined>]
998  *                      [, perbyte_cpu = <int | pre-defined>]
999  *                      [, percall_cpu = <int | pre-defined>]
1000  *                      [, iscachable])
1001  *                      [arg is (<type-1> { , <type-n>})]
1002  *                      as <filename or code in language as appropriate>
1003  *
1004  *****************************************************************************/
1005
1006 ProcedureStmt:  CREATE FUNCTION def_name def_args 
1007                    RETURNS def_arg opt_with AS Sconst LANGUAGE Sconst
1008                 {
1009                     ProcedureStmt *n = makeNode(ProcedureStmt);
1010                     n->funcname = $3;
1011                     n->defArgs = $4;
1012                     n->returnType = (Node *)$6;
1013                     n->withClause = $7;
1014                     n->as = $9;
1015                     n->language = $11;
1016                     $$ = (Node *)n;
1017                 };
1018
1019 opt_with:  WITH definition                      { $$ = $2; }
1020         |  /* EMPTY */                          { $$ = NIL; }
1021         ;
1022
1023 def_args:  '(' def_name_list ')'                { $$ = $2; }
1024         |  '(' ')'                              { $$ = NIL; }
1025         ;
1026
1027 def_name_list:  name_list;      
1028
1029
1030 /*****************************************************************************
1031  *
1032  *      QUERY:
1033  *              purge <relname> [before <date>] [after <date>]
1034  *                or
1035  *              purge <relname>  [after<date>][before <date>] 
1036  *      
1037  *****************************************************************************/
1038
1039 PurgeStmt:  PURGE relation_name purge_quals
1040                 { 
1041                     $3->relname = $2;
1042                     $$ = (Node *)$3;
1043                 }
1044         ;
1045
1046 purge_quals:  before_clause
1047                 { 
1048                     $$ = makeNode(PurgeStmt);
1049                     $$->beforeDate = $1;
1050                     $$->afterDate = NULL;
1051                 }
1052         |  after_clause
1053                 { 
1054                     $$ = makeNode(PurgeStmt);
1055                     $$->beforeDate = NULL;
1056                     $$->afterDate = $1;
1057                 }
1058         |  before_clause after_clause
1059                 { 
1060                     $$ = makeNode(PurgeStmt);
1061                     $$->beforeDate = $1;
1062                     $$->afterDate = $2;
1063                 }
1064         |  after_clause before_clause
1065                 { 
1066                     $$ = makeNode(PurgeStmt);
1067                     $$->beforeDate = $2;
1068                     $$->afterDate = $1;
1069                 }
1070         |  /*EMPTY*/
1071                 { 
1072                     $$ = makeNode(PurgeStmt);
1073                     $$->beforeDate = NULL;
1074                     $$->afterDate = NULL;
1075                 }
1076         ;
1077
1078 before_clause:  BEFORE date             { $$ = $2; }
1079 after_clause:   AFTER date              { $$ = $2; }
1080
1081
1082 /*****************************************************************************
1083  *
1084  *      QUERY:
1085  *
1086  *      remove function <funcname>
1087  *              (REMOVE FUNCTION "funcname" (arg1, arg2, ...))
1088  *      remove aggregate <aggname>
1089  *              (REMOVE AGGREGATE "aggname" "aggtype")
1090  *      remove operator <opname>
1091  *              (REMOVE OPERATOR "opname" (leftoperand_typ rightoperand_typ))
1092  *      remove type <typename>
1093  *              (REMOVE TYPE "typename")
1094  *      remove rule <rulename>
1095  *              (REMOVE RULE "rulename")
1096  *
1097  *****************************************************************************/
1098
1099 RemoveStmt:  DROP remove_type name
1100                 {
1101                     RemoveStmt *n = makeNode(RemoveStmt);
1102                     n->removeType = $2;
1103                     n->name = $3;
1104                     $$ = (Node *)n;
1105                 }
1106         ;
1107
1108 remove_type:  Type                              {  $$ = P_TYPE; }
1109         |  INDEX                                {  $$ = INDEX; }
1110         |  RULE                                 {  $$ = RULE; }
1111         |  VIEW                                 {  $$ = VIEW; }
1112         ;
1113
1114 RemoveAggrStmt:  DROP AGGREGATE name aggr_argtype
1115                 {
1116                         RemoveAggrStmt *n = makeNode(RemoveAggrStmt);
1117                         n->aggname = $3;
1118                         n->aggtype = $4;
1119                         $$ = (Node *)n;
1120                 }
1121         ;
1122
1123 aggr_argtype:  name                             { $$ = $1; }
1124         |  '*'                                  { $$ = NULL; }
1125         ;
1126
1127 RemoveFuncStmt:  DROP FUNCTION name '(' func_argtypes ')'
1128                 {
1129                     RemoveFuncStmt *n = makeNode(RemoveFuncStmt);
1130                     n->funcname = $3;
1131                     n->args = $5;
1132                     $$ = (Node *)n;
1133                 }
1134           ;
1135
1136 func_argtypes:  name_list                       { $$ = $1; }
1137         |  /*EMPTY*/                            { $$ = NIL; }
1138         ;
1139
1140 RemoveOperStmt:  DROP OPERATOR all_Op '(' oper_argtypes ')'
1141                 {
1142                     RemoveOperStmt *n = makeNode(RemoveOperStmt);
1143                     n->opname = $3;
1144                     n->args = $5;
1145                     $$ = (Node *)n;
1146                 }
1147         ;
1148
1149 all_Op: Op | MathOp;
1150
1151 MathOp:    '+'          { $$ = "+"; }
1152         |  '-'          { $$ = "-"; }
1153         |  '*'          { $$ = "*"; }
1154         |  '/'          { $$ = "/"; }
1155         |  '<'          { $$ = "<"; }
1156         |  '>'          { $$ = ">"; }
1157         |  '='          { $$ = "="; }
1158         ;
1159
1160 oper_argtypes:  name    
1161                 { 
1162                    elog(WARN, "parser: argument type missing (use NONE for unary operators)");
1163                 }
1164         | name ',' name
1165                 { $$ = makeList(makeString($1), makeString($3), -1); }
1166         | NONE ',' name         /* left unary */
1167                 { $$ = makeList(NULL, makeString($3), -1); }
1168         | name ',' NONE         /* right unary */
1169                 { $$ = makeList(makeString($1), NULL, -1); }
1170         ;
1171
1172 /*****************************************************************************
1173  *
1174  *      QUERY:   
1175  *              rename <attrname1> in <relname> [*] to <attrname2>
1176  *              rename <relname1> to <relname2>
1177  *      
1178  *****************************************************************************/
1179
1180 RenameStmt:  ALTER TABLE relation_name opt_inh_star 
1181                   RENAME opt_column opt_name TO name
1182                 { 
1183                     RenameStmt *n = makeNode(RenameStmt);
1184                     n->relname = $3;
1185                     n->inh = $4;
1186                     n->column = $7;
1187                     n->newname = $9;
1188                     $$ = (Node *)n;
1189                 }
1190         ;
1191
1192 opt_name:  name                         { $$ = $1; }
1193         |  /*EMPTY*/                    { $$ = NULL; }
1194         ;
1195
1196 opt_column:  COLUMN                     { $$ = COLUMN; }
1197         | /*EMPTY*/                     { $$ = 0; }
1198         ;
1199
1200
1201 /*****************************************************************************
1202  *       
1203  *      QUERY:  Define Rewrite Rule , Define Tuple Rule 
1204  *              Define Rule <old rules >
1205  *
1206  *      only rewrite rule is supported -- ay 9/94
1207  *       
1208  *****************************************************************************/
1209
1210 RuleStmt:  CREATE RULE name AS 
1211            { QueryIsRule=TRUE; }
1212            ON event TO event_object where_clause
1213            DO opt_instead OptStmtList
1214                 {
1215                     RuleStmt *n = makeNode(RuleStmt);
1216                     n->rulename = $3;
1217                     n->event = $7;
1218                     n->object = $9;
1219                     n->whereClause = $10;
1220                     n->instead = $12;
1221                     n->actions = $13;
1222                     $$ = (Node *)n;
1223                 }
1224         ;
1225
1226 OptStmtList:  NOTHING                   { $$ = NIL; }
1227         | OptimizableStmt               { $$ = lcons($1, NIL); }        
1228         | '[' OptStmtBlock ']'          { $$ = $2; }
1229         ;
1230
1231 OptStmtBlock:  OptStmtMulti
1232                {  $$ = $1; }
1233         |  OptimizableStmt
1234                 { $$ = lcons($1, NIL); }
1235         ;
1236         
1237 OptStmtMulti:  OptStmtMulti OptimizableStmt ';'
1238                {  $$ = lappend($1, $2); }
1239         |  OptStmtMulti OptimizableStmt
1240                {  $$ = lappend($1, $2); }
1241         |  OptimizableStmt ';'
1242                 { $$ = lcons($1, NIL); }
1243         ;
1244         
1245 event_object: relation_name '.' attr_name
1246                 { 
1247                     $$ = makeNode(Attr);
1248                     $$->relname = $1;
1249                     $$->paramNo = NULL;
1250                     $$->attrs = lcons(makeString($3), NIL);
1251                     $$->indirection = NIL;
1252                 }
1253         | relation_name
1254                 {
1255                     $$ = makeNode(Attr);
1256                     $$->relname = $1;
1257                     $$->paramNo = NULL;
1258                     $$->attrs = NIL;
1259                     $$->indirection = NIL;
1260                 }
1261         ;
1262
1263 /* change me to select, update, etc. some day */
1264 event:  SELECT                          { $$ = CMD_SELECT; }
1265         | UPDATE                        { $$ = CMD_UPDATE; }
1266         | DELETE                        { $$ = CMD_DELETE; }
1267         | INSERT                        { $$ = CMD_INSERT; }
1268          ;
1269
1270 opt_instead:  INSTEAD                   { $$ = TRUE; }
1271         | /* EMPTY */                   { $$ = FALSE; }
1272         ;
1273
1274
1275 /*****************************************************************************
1276  *
1277  *      QUERY:
1278  *              NOTIFY <relation_name>  can appear both in rule bodies and
1279  *              as a query-level command
1280  *
1281  *****************************************************************************/
1282
1283 NotifyStmt: NOTIFY relation_name 
1284                 {
1285                     NotifyStmt *n = makeNode(NotifyStmt);
1286                     n->relname = $2;
1287                     $$ = (Node *)n;
1288                 }
1289         ;
1290
1291 ListenStmt: LISTEN relation_name 
1292                 {
1293                     ListenStmt *n = makeNode(ListenStmt);
1294                     n->relname = $2;
1295                     $$ = (Node *)n;
1296                 }
1297 ;
1298
1299
1300 /*****************************************************************************
1301  *
1302  *      Transactions:
1303  *
1304  *      abort transaction
1305  *              (ABORT)
1306  *      begin transaction
1307  *              (BEGIN)
1308  *      end transaction
1309  *              (END)
1310  *      
1311  *****************************************************************************/
1312
1313 TransactionStmt:  ABORT_TRANS TRANSACTION
1314                 { 
1315                     TransactionStmt *n = makeNode(TransactionStmt); 
1316                     n->command = ABORT_TRANS; 
1317                     $$ = (Node *)n;
1318                 }
1319         | BEGIN_TRANS TRANSACTION
1320                 { 
1321                     TransactionStmt *n = makeNode(TransactionStmt); 
1322                     n->command = BEGIN_TRANS;
1323                     $$ = (Node *)n;
1324                 }
1325         | BEGIN_TRANS WORK
1326                 {
1327                     TransactionStmt *n = makeNode(TransactionStmt); 
1328                     n->command = BEGIN_TRANS;
1329                     $$ = (Node *)n;
1330                 }
1331         | COMMIT WORK
1332                 {
1333                     TransactionStmt *n = makeNode(TransactionStmt); 
1334                     n->command = END_TRANS;
1335                     $$ = (Node *)n;
1336                 }
1337         | END_TRANS TRANSACTION
1338                 { 
1339                     TransactionStmt *n = makeNode(TransactionStmt); 
1340                     n->command = END_TRANS;
1341                     $$ = (Node *)n;
1342                 }
1343         | ROLLBACK WORK
1344                 {
1345                     TransactionStmt *n = makeNode(TransactionStmt); 
1346                     n->command = ABORT_TRANS;
1347                     $$ = (Node *)n;
1348                 }
1349
1350         | ABORT_TRANS
1351                 { 
1352                     TransactionStmt *n = makeNode(TransactionStmt); 
1353                     n->command = ABORT_TRANS; 
1354                     $$ = (Node *)n;
1355                 }
1356         | BEGIN_TRANS
1357                 { 
1358                     TransactionStmt *n = makeNode(TransactionStmt); 
1359                     n->command = BEGIN_TRANS;
1360                     $$ = (Node *)n;
1361                 }
1362         | COMMIT
1363                 {
1364                     TransactionStmt *n = makeNode(TransactionStmt); 
1365                     n->command = END_TRANS;
1366                     $$ = (Node *)n;
1367                 }
1368
1369         | END_TRANS
1370                 { 
1371                     TransactionStmt *n = makeNode(TransactionStmt); 
1372                     n->command = END_TRANS;
1373                     $$ = (Node *)n;
1374                 }
1375         | ROLLBACK
1376                 {
1377                     TransactionStmt *n = makeNode(TransactionStmt); 
1378                     n->command = ABORT_TRANS;
1379                     $$ = (Node *)n;
1380                 }
1381         ;
1382
1383
1384 /*****************************************************************************
1385  *
1386  *      QUERY:
1387  *              define view <viewname> '('target-list ')' [where <quals> ]
1388  *
1389  *****************************************************************************/
1390
1391 ViewStmt:  CREATE VIEW name AS RetrieveStmt
1392                 { 
1393                     ViewStmt *n = makeNode(ViewStmt);
1394                     n->viewname = $3;
1395                     n->query = (Query *)$5;
1396                     $$ = (Node *)n;
1397                 }
1398         ;
1399
1400
1401 /*****************************************************************************
1402  *
1403  *      QUERY:
1404  *              load "filename"
1405  *
1406  *****************************************************************************/
1407
1408 LoadStmt: LOAD file_name
1409                 { 
1410                     LoadStmt *n = makeNode(LoadStmt);
1411                     n->filename = $2;
1412                     $$ = (Node *)n;
1413                 }
1414         ;
1415
1416
1417 /*****************************************************************************
1418  *
1419  *      QUERY:
1420  *              createdb dbname
1421  *
1422  *****************************************************************************/
1423
1424 CreatedbStmt:  CREATE DATABASE database_name
1425                 {
1426                     CreatedbStmt *n = makeNode(CreatedbStmt);
1427                     n->dbname = $3;
1428                     $$ = (Node *)n;
1429                 }
1430         ;
1431
1432
1433 /*****************************************************************************
1434  *
1435  *      QUERY:
1436  *              destroydb dbname
1437  *
1438  *****************************************************************************/
1439
1440 DestroydbStmt:  DROP DATABASE database_name
1441                 {
1442                     DestroydbStmt *n = makeNode(DestroydbStmt);
1443                     n->dbname = $3;
1444                     $$ = (Node *)n;
1445                 }
1446         ;
1447
1448
1449 /*****************************************************************************
1450  *
1451  *      QUERY:
1452  *              cluster <index_name> on <relation_name>
1453  *
1454  *****************************************************************************/
1455
1456 ClusterStmt:  CLUSTER index_name ON relation_name 
1457                 {
1458                    ClusterStmt *n = makeNode(ClusterStmt);
1459                    n->relname = $4;
1460                    n->indexname = $2;
1461                    $$ = (Node*)n;
1462                 }
1463         ;
1464
1465 /*****************************************************************************
1466  *
1467  *      QUERY:
1468  *              vacuum
1469  *
1470  *****************************************************************************/
1471
1472 VacuumStmt:  VACUUM opt_verbose opt_analyze
1473                {
1474                    VacuumStmt *n = makeNode(VacuumStmt);
1475                    n->verbose = $2;
1476                    n->analyze = $3;
1477                    n->vacrel = NULL;
1478                    n->va_spec = NIL;
1479                    $$ = (Node *)n;
1480                }
1481          | VACUUM opt_verbose relation_name opt_analyze opt_va_list
1482                {
1483                    VacuumStmt *n = makeNode(VacuumStmt);
1484                    n->verbose = $2;
1485                    n->analyze = $4;
1486                    n->vacrel = $3;
1487                    n->va_spec = $5;
1488                    if ( $5 != NIL && !$4 )
1489                         elog (WARN, "parser: syntax error at or near \"(\"");
1490                    $$ = (Node *)n;
1491                }
1492        ;
1493
1494 opt_verbose:  VERBOSE                   { $$ = TRUE; }
1495         | /* EMPTY */                   { $$ = FALSE; }
1496         ;
1497
1498 opt_analyze:  ANALYZE                   { $$ = TRUE; }
1499         | /* EMPTY */                   { $$ = FALSE; }
1500         ;
1501
1502 opt_va_list: '(' va_list ')'
1503                 { $$ = $2; }
1504         | /* EMPTY */
1505                 { $$ = NIL; }
1506         ;       
1507
1508 va_list: name
1509                 { $$=lcons($1,NIL); }
1510         | va_list ',' name
1511                 { $$=lappend($1,$3); }
1512         ;       
1513        
1514 /*****************************************************************************
1515  *
1516  *      QUERY:
1517  *              EXPLAIN query
1518  *
1519  *****************************************************************************/
1520
1521 ExplainStmt:  EXPLAIN opt_verbose OptimizableStmt
1522                 {
1523                     ExplainStmt *n = makeNode(ExplainStmt);
1524                     n->verbose = $2;
1525                     n->query = (Query*)$3;
1526                     $$ = (Node *)n;
1527                 }
1528         ;
1529
1530 /*****************************************************************************
1531  *                                                                           *
1532  *      Optimizable Stmts:                                                   *
1533  *                                                                           *
1534  *      one of the five queries processed by the planner                     *
1535  *                                                                           *
1536  *      [ultimately] produces query-trees as specified                       *
1537  *      in the query-spec document in ~postgres/ref                          *
1538  *                                                                           *
1539  *****************************************************************************/
1540
1541 OptimizableStmt:  RetrieveStmt
1542         | CursorStmt    
1543         | ReplaceStmt
1544         | AppendStmt
1545         | NotifyStmt
1546         | DeleteStmt                    /* by default all are $$=$1 */
1547         ;
1548
1549
1550 /*****************************************************************************
1551  *
1552  *      QUERY:
1553  *              INSERT STATEMENTS
1554  *  
1555  *****************************************************************************/
1556
1557 AppendStmt:  INSERT INTO relation_name opt_column_list insert_rest
1558                 {
1559                     $5->relname = $3;
1560                     $5->cols = $4;
1561                     $$ = (Node *)$5;
1562                 }
1563         ;
1564
1565 insert_rest: VALUES '(' res_target_list2 ')'
1566                 {
1567                     $$ = makeNode(AppendStmt);
1568                     $$->targetList = $3;
1569                     $$->fromClause = NIL;
1570                     $$->whereClause = NULL;
1571                 }
1572         | SELECT res_target_list2 from_clause where_clause
1573                 {
1574                     $$ = makeNode(AppendStmt);
1575                     $$->targetList = $2;
1576                     $$->fromClause = $3;
1577                     $$->whereClause = $4;
1578                 }
1579         ;
1580
1581 opt_column_list: '(' columnList ')'             { $$ = $2; }
1582         | /*EMPTY*/                             { $$ = NIL; }
1583         ;
1584
1585 columnList:     
1586           columnList ',' columnElem
1587                 { $$ = lappend($1, $3); }
1588         | columnElem
1589                 { $$ = lcons($1, NIL); }
1590         ;
1591
1592 columnElem: Id opt_indirection
1593                 {
1594                     Ident *id = makeNode(Ident);
1595                     id->name = $1;
1596                     id->indirection = $2;
1597                     $$ = (Node *)id;
1598                 }
1599         ;
1600
1601 /*****************************************************************************
1602  *
1603  *      QUERY:
1604  *              DELETE STATEMENTS
1605  *
1606  *****************************************************************************/
1607    
1608 DeleteStmt:  DELETE FROM relation_name
1609              where_clause
1610                 {
1611                     DeleteStmt *n = makeNode(DeleteStmt);
1612                     n->relname = $3;
1613                     n->whereClause = $4;
1614                     $$ = (Node *)n;
1615                 }
1616         ;
1617
1618
1619 /*****************************************************************************
1620  *
1621  *      QUERY:
1622  *              ReplaceStmt (UPDATE)
1623  *
1624  *****************************************************************************/
1625
1626 ReplaceStmt:  UPDATE relation_name 
1627               SET res_target_list
1628               from_clause
1629               where_clause
1630                 {
1631                     ReplaceStmt *n = makeNode(ReplaceStmt);
1632                     n->relname = $2;
1633                     n->targetList = $4;
1634                     n->fromClause = $5;
1635                     n->whereClause = $6;
1636                     $$ = (Node *)n;
1637                 }
1638         ;
1639                  
1640
1641 /*****************************************************************************
1642  *
1643  *      QUERY:
1644  *              CURSOR STATEMENTS
1645  *
1646  *****************************************************************************/
1647
1648 CursorStmt:  DECLARE name opt_binary CURSOR FOR 
1649              SELECT opt_unique res_target_list2 
1650              from_clause where_clause group_clause sort_clause
1651                 {
1652                     CursorStmt *n = makeNode(CursorStmt);
1653
1654                     /* from PORTAL name */
1655                     /*
1656                      *  15 august 1991 -- since 3.0 postgres does locking
1657                      *  right, we discovered that portals were violating
1658                      *  locking protocol.  portal locks cannot span xacts.
1659                      *  as a short-term fix, we installed the check here. 
1660                      *                          -- mao
1661                      */
1662                     if (!IsTransactionBlock())
1663                         elog(WARN, "Named portals may only be used in begin/end transaction blocks.");
1664
1665                     n->portalname = $2;
1666                     n->binary = $3;
1667                     n->unique = $7;
1668                     n->targetList = $8;
1669                     n->fromClause = $9;
1670                     n->whereClause = $10;
1671                     n->groupClause = $11;
1672                     n->sortClause = $12;
1673                     $$ = (Node *)n;
1674                 }
1675         ;
1676
1677
1678 /*****************************************************************************
1679  *
1680  *      QUERY:
1681  *              SELECT STATEMENTS
1682  *
1683  *****************************************************************************/
1684
1685 RetrieveStmt:  SELECT opt_unique res_target_list2
1686                result from_clause where_clause 
1687                group_clause having_clause
1688                sort_clause
1689                 {
1690                     RetrieveStmt *n = makeNode(RetrieveStmt);
1691                     n->unique = $2;
1692                     n->targetList = $3;
1693                     n->into = $4;
1694                     n->fromClause = $5;
1695                     n->whereClause = $6;
1696                     n->groupClause = $7;
1697                     n->havingClause = $8;
1698                     n->sortClause = $9;
1699                     $$ = (Node *)n;
1700                 }
1701         ;
1702
1703 result:  INTO TABLE relation_name
1704                 {  $$= $3;  /* should check for archive level */  }
1705         | /*EMPTY*/
1706                 {  $$ = NULL;  }
1707         ;
1708
1709 opt_unique:  DISTINCT           { $$ = "*"; }
1710         | DISTINCT ON Id        { $$ = $3; }
1711         | /*EMPTY*/             { $$ = NULL;}
1712         ;
1713
1714 sort_clause:  ORDER BY sortby_list                      { $$ = $3; }
1715         |  /*EMPTY*/                            { $$ = NIL; }
1716         ;
1717
1718 sortby_list:  sortby
1719                 { $$ = lcons($1, NIL); }
1720         | sortby_list ',' sortby
1721                 { $$ = lappend($1, $3); }
1722         ;
1723
1724 sortby:  Id OptUseOp
1725                 { 
1726                     $$ = makeNode(SortGroupBy);
1727                     $$->resno = 0;
1728                     $$->range = NULL;
1729                     $$->name = $1;
1730                     $$->useOp = $2;
1731                 }
1732         | Id '.' Id OptUseOp
1733                 {
1734                     $$ = makeNode(SortGroupBy);
1735                     $$->resno = 0;
1736                     $$->range = $1;
1737                     $$->name = $3;
1738                     $$->useOp = $4;
1739                 }
1740         | Iconst OptUseOp
1741                 {
1742                     $$ = makeNode(SortGroupBy);
1743                     $$->resno = $1;
1744                     $$->range = NULL;
1745                     $$->name = NULL;
1746                     $$->useOp = $2;
1747                 }
1748         ;
1749
1750 OptUseOp:  USING Op                             { $$ = $2; }
1751         |  USING '<'                            { $$ = "<"; }
1752         |  USING '>'                            { $$ = ">"; }
1753         |  ASC                                  { $$ = "<"; }
1754         |  DESC                                 { $$ = ">"; }
1755         |  /*EMPTY*/                            { $$ = "<"; /*default*/ }
1756         ;
1757
1758 index_params: index_list                        { $$ = $1; }
1759         | func_index                            { $$ = lcons($1,NIL); }
1760         ;
1761
1762 index_list:
1763           index_list ',' index_elem
1764                 { $$ = lappend($1, $3); }
1765         | index_elem
1766                 { $$ = lcons($1, NIL); }
1767         ;
1768
1769 func_index: name '(' name_list ')' opt_type opt_class
1770                 {
1771                     $$ = makeNode(IndexElem);
1772                     $$->name = $1;
1773                     $$->args = $3;
1774                     $$->class = $6;
1775                     $$->tname = $5;
1776                 }
1777           ;
1778
1779 index_elem:  attr_name opt_type opt_class
1780                 {
1781                     $$ = makeNode(IndexElem);
1782                     $$->name = $1;
1783                     $$->args = NIL;
1784                     $$->class = $3;
1785                     $$->tname = $2;
1786                 }
1787         ;
1788
1789 opt_type: ':' Typename                          { $$ = $2;}
1790         |  /*EMPTY*/                            { $$ = NULL;}
1791         ;
1792
1793 opt_class:  class
1794         |  WITH class                           { $$ = $2; }
1795         |  /*EMPTY*/                            { $$ = NULL; }
1796         ;
1797
1798 /*
1799  *  jimmy bell-style recursive queries aren't supported in the
1800  *  current system.
1801  *
1802  *  ...however, recursive addattr and rename supported.  make special 
1803  *  cases for these.
1804  * 
1805  *  XXX i believe '*' should be the default behavior, but...
1806  */
1807 opt_inh_star: '*'                       { $$ = TRUE; }
1808         |  /*EMPTY*/                    { $$ = FALSE; }
1809         ;
1810
1811 relation_name_list:     name_list ;
1812
1813 name_list: name                         
1814                 { $$=lcons(makeString($1),NIL); }
1815         | name_list ',' name            
1816                 { $$=lappend($1,makeString($3)); }
1817         ;       
1818
1819 group_clause: GROUP BY groupby_list             { $$ = $3; }
1820         | /*EMPTY*/                             { $$ = NIL; }
1821         ;
1822
1823 groupby_list: groupby                           { $$ = lcons($1, NIL); }
1824         | groupby_list ',' groupby              { $$ = lappend($1, $3); }
1825         ;
1826
1827 groupby:  Id
1828                 {
1829                     $$ = makeNode(SortGroupBy);
1830                     $$->resno = 0;
1831                     $$->range = NULL;
1832                     $$->name = $1;
1833                     $$->useOp = NULL;
1834                 }
1835         | Id '.' Id
1836                 {
1837                     $$ = makeNode(SortGroupBy);
1838                     $$->resno = 0;
1839                     $$->range = $1;
1840                     $$->name = $3;
1841                     $$->useOp = NULL;
1842                 }
1843         | Iconst
1844                 {
1845                     $$ = makeNode(SortGroupBy);
1846                     $$->resno = $1;
1847                     $$->range = NULL;
1848                     $$->name = NULL;
1849                     $$->useOp = NULL;
1850                 }
1851         ;
1852
1853 having_clause: HAVING a_expr                    { $$ = $2; }
1854         | /*EMPTY*/                             { $$ = NULL; }
1855         ;
1856
1857 /*****************************************************************************
1858  *  
1859  *  clauses common to all Optimizable Stmts:
1860  *      from_clause     -
1861  *      where_clause    -
1862  *      
1863  *****************************************************************************/
1864
1865 from_clause:  FROM from_list                    { $$ = $2; }
1866         | /*EMPTY*/                             { $$ = NIL; }
1867         ;
1868
1869 from_list:  from_list ',' from_val
1870                 { $$ = lappend($1, $3); }
1871         |  from_val
1872                 { $$ = lcons($1, NIL); }
1873         ;
1874
1875 from_val:  relation_expr AS var_name
1876                 {
1877                     $$ = makeNode(RangeVar);
1878                     $$->relExpr = $1;
1879                     $$->name = $3;
1880                 }       
1881         | relation_expr var_name
1882                 {
1883                     $$ = makeNode(RangeVar);
1884                     $$->relExpr = $1;
1885                     $$->name = $2;
1886                 }
1887         | relation_expr
1888                 {
1889                     $$ = makeNode(RangeVar);
1890                     $$->relExpr = $1;
1891                     $$->name = NULL;
1892                 }
1893         ;
1894
1895 where_clause:  WHERE a_expr             { $$ = $2; }
1896         | /*EMPTY*/                     { $$ = NULL;  /* no qualifiers */ } 
1897         ;
1898
1899 relation_expr:  relation_name
1900                 { 
1901                     /* normal relations */
1902                     $$ = makeNode(RelExpr);
1903                     $$->relname = $1;
1904                     $$->inh = FALSE;
1905                     $$->timeRange = NULL;
1906                 }
1907         | relation_name '*'               %prec '='
1908                 { 
1909                     /* inheiritance query */
1910                     $$ = makeNode(RelExpr);
1911                     $$->relname = $1;
1912                     $$->inh = TRUE;
1913                     $$->timeRange = NULL;
1914                 }
1915         | relation_name time_range 
1916                 { 
1917                     /* time-qualified query */
1918                     $$ = makeNode(RelExpr);
1919                     $$->relname = $1;
1920                     $$->inh = FALSE;
1921                     $$->timeRange = $2;
1922                 }
1923         ;
1924
1925           
1926 time_range:  '[' opt_range_start ',' opt_range_end ']'
1927                 { 
1928                     $$ = makeNode(TimeRange);
1929                     $$->startDate = $2;
1930                     $$->endDate = $4;
1931                 }
1932         | '[' date ']'
1933                 { 
1934                     $$ = makeNode(TimeRange);
1935                     $$->startDate = $2;
1936                     $$->endDate = NULL;
1937                 }
1938         ;
1939
1940 opt_range_start:  date
1941         |  /*EMPTY*/                            { $$ = "epoch"; }
1942         ;
1943
1944 opt_range_end:  date
1945         |  /*EMPTY*/                            { $$ = "now"; }
1946         ;
1947
1948 opt_array_bounds:  '[' ']' nest_array_bounds
1949                 {  $$ = lcons(makeInteger(-1), $3); }
1950         | '[' Iconst ']' nest_array_bounds
1951                 {  $$ = lcons(makeInteger($2), $4); }
1952         | /* EMPTY */                           
1953                 {  $$ = NIL; }
1954         ;
1955
1956 nest_array_bounds:  '[' ']' nest_array_bounds
1957                 {  $$ = lcons(makeInteger(-1), $3); }
1958         | '[' Iconst ']' nest_array_bounds 
1959                 {  $$ = lcons(makeInteger($2), $4); }
1960         | /*EMPTY*/
1961                 {  $$ = NIL; }
1962         ;
1963
1964 typname:  name  
1965                 {
1966                     char *tname = xlateSqlType($1);
1967                     $$ = makeNode(TypeName);
1968                     $$->name = tname;
1969
1970                     /* Is this the name of a complex type? If so, implement
1971                      * it as a set.
1972                      */
1973                     if (!strcmp(saved_relname, tname)) {
1974                         /* This attr is the same type as the relation 
1975                          * being defined. The classic example: create
1976                          * emp(name=text,mgr=emp)
1977                          */
1978                         $$->setof = TRUE;
1979                     }else if (get_typrelid((Type)type(tname))
1980                                 != InvalidOid) {
1981                          /* (Eventually add in here that the set can only 
1982                           * contain one element.)
1983                           */
1984                         $$->setof = TRUE;
1985                     } else {
1986                         $$->setof = FALSE;
1987                     }
1988                 }
1989         | SETOF name
1990                 {
1991                     $$ = makeNode(TypeName);
1992                     $$->name = $2;
1993                     $$->setof = TRUE;
1994                 }
1995         ;
1996
1997 Typename:  typname opt_array_bounds             
1998                 { 
1999                     $$ = $1;
2000                     $$->arrayBounds = $2;
2001                 }
2002         | name '(' Iconst ')'
2003                 {
2004                     /*
2005                      * The following implements char() and varchar().
2006                      * We do it here instead of the 'typname:' production
2007                      * because we don't want to allow arrays of varchar().
2008                      * I haven't thought about whether that will work or not.
2009                       *                             - ay 6/95
2010                      */
2011                     $$ = makeNode(TypeName);
2012                     if (!strcasecmp($1, "char")) {
2013                         $$->name = "bpchar"; /*  strdup("bpchar"); */
2014                     } else if (!strcasecmp($1, "varchar")) {
2015                         $$->name = "varchar"; /* strdup("varchar"); */
2016                     } else {
2017                         yyerror("parse error");
2018                     }
2019                     if ($3 < 1) {
2020                         elog(WARN, "length for '%s' type must be at least 1",
2021                              $1);
2022                     } else if ($3 > 4096) {
2023                         /* we can store a char() of length up to the size
2024                            of a page (8KB) - page headers and friends but
2025                            just to be safe here...  - ay 6/95 */
2026                         elog(WARN, "length for '%s' type cannot exceed 4096",
2027                              $1);
2028                     }
2029                     /* we actually implement this sort of like a varlen, so
2030                        the first 4 bytes is the length. (the difference
2031                        between this and "text" is that we blank-pad and 
2032                        truncate where necessary */
2033                     $$->typlen = 4 + $3;
2034                 }
2035         ;
2036
2037
2038 /*****************************************************************************
2039  *
2040  *  expression grammar, still needs some cleanup
2041  *
2042  *****************************************************************************/
2043
2044 a_expr_or_null: a_expr
2045                 { $$ = $1;}
2046         | Pnull
2047                 {       
2048                     A_Const *n = makeNode(A_Const);
2049                     n->val.type = T_Null;
2050                     $$ = (Node *)n;
2051                 }
2052                 
2053 a_expr:  attr opt_indirection
2054                 {
2055                     $1->indirection = $2;
2056                     $$ = (Node *)$1;
2057                 }
2058         | AexprConst
2059                 {   $$ = $1;  }
2060         | '-' a_expr %prec UMINUS
2061                 {   $$ = makeA_Expr(OP, "-", NULL, $2); }
2062         | a_expr '+' a_expr
2063                 {   $$ = makeA_Expr(OP, "+", $1, $3); }
2064         | a_expr '-' a_expr
2065                 {   $$ = makeA_Expr(OP, "-", $1, $3); }
2066         | a_expr '/' a_expr
2067                 {   $$ = makeA_Expr(OP, "/", $1, $3); }
2068         | a_expr '*' a_expr
2069                 {   $$ = makeA_Expr(OP, "*", $1, $3); }
2070         | a_expr '<' a_expr
2071                 {   $$ = makeA_Expr(OP, "<", $1, $3); }
2072         | a_expr '>' a_expr
2073                 {   $$ = makeA_Expr(OP, ">", $1, $3); }
2074         | a_expr '=' a_expr
2075                 {   $$ = makeA_Expr(OP, "=", $1, $3); }
2076         | ':' a_expr
2077                 {   $$ = makeA_Expr(OP, ":", NULL, $2); }
2078         | ';' a_expr
2079                 {   $$ = makeA_Expr(OP, ";", NULL, $2); }
2080         | '|' a_expr
2081                 {   $$ = makeA_Expr(OP, "|", NULL, $2); }
2082         | AexprConst TYPECAST Typename
2083                 { 
2084                     /* AexprConst can be either A_Const or ParamNo */
2085                     if (nodeTag($1) == T_A_Const) {
2086                         ((A_Const *)$1)->typename = $3;
2087                     }else {
2088                         ((ParamNo *)$1)->typename = $3;
2089                     }
2090                     $$ = (Node *)$1;
2091                 }
2092         | CAST AexprConst AS Typename
2093                 {
2094                     /* AexprConst can be either A_Const or ParamNo */
2095                     if (nodeTag($2) == T_A_Const) {
2096                         ((A_Const *)$2)->typename = $4;
2097                     }else {
2098                         ((ParamNo *)$2)->typename = $4;
2099                     }
2100                     $$ = (Node *)$2;
2101                 }
2102         | '(' a_expr_or_null ')'
2103                 {   $$ = $2; }
2104         | a_expr Op a_expr
2105                 {   $$ = makeA_Expr(OP, $2, $1, $3); }
2106         | a_expr LIKE a_expr
2107                 {   $$ = makeA_Expr(OP, "~~", $1, $3); }
2108         | a_expr NOT LIKE a_expr
2109                 {   $$ = makeA_Expr(OP, "!~~", $1, $4); }
2110         | Op a_expr
2111                 {   $$ = makeA_Expr(OP, $1, NULL, $2); }
2112         | a_expr Op
2113                 {   $$ = makeA_Expr(OP, $2, $1, NULL); }
2114         | Id
2115                 {   /* could be a column name or a relation_name */
2116                     Ident *n = makeNode(Ident);
2117                     n->name = $1;
2118                     n->indirection = NULL;
2119                     $$ = (Node *)n;
2120                 }
2121         | name '(' '*' ')'
2122                 {
2123                     FuncCall *n = makeNode(FuncCall);
2124                     Ident *star = makeNode(Ident);
2125
2126                     /* cheap hack for aggregate (eg. count) */
2127                     star->name = "oid"; 
2128                     n->funcname = $1;
2129                     n->args = lcons(star, NIL);
2130                     $$ = (Node *)n;
2131                 }
2132         | name '(' ')'
2133                 {
2134                     FuncCall *n = makeNode(FuncCall);
2135                     n->funcname = $1;
2136                     n->args = NIL;
2137                     $$ = (Node *)n;
2138                 }
2139         | name '(' expr_list ')'
2140                 {
2141                     FuncCall *n = makeNode(FuncCall);
2142                     n->funcname = $1;
2143                     n->args = $3;
2144                     $$ = (Node *)n;
2145                 }
2146         | a_expr ISNULL
2147                 {   $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
2148         | a_expr IS PNULL
2149                 {   $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
2150         | a_expr NOTNULL
2151                 {   $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); }
2152         | a_expr IS NOT PNULL
2153                 {   $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); }
2154         | a_expr BETWEEN AexprConst AND AexprConst
2155                 {   $$ = makeA_Expr(AND, NULL,
2156                         makeA_Expr(OP, ">=", $1, $3),
2157                         makeA_Expr(OP, "<=", $1,$5));
2158                 }
2159         | a_expr NOT BETWEEN AexprConst AND AexprConst
2160                 {   $$ = makeA_Expr(OR, NULL,
2161                         makeA_Expr(OP, "<", $1, $4),
2162                         makeA_Expr(OP, ">", $1, $6));
2163                 }
2164         | a_expr IN { saved_In_Expr = $1; } '(' in_expr_nodes ')'
2165                 {   $$ = $5; }
2166         | a_expr NOT IN { saved_In_Expr = $1; } '(' not_in_expr_nodes ')'
2167                 {   $$ = $6; }
2168         | a_expr AND a_expr
2169                 {   $$ = makeA_Expr(AND, NULL, $1, $3); }
2170         | a_expr OR a_expr
2171                 {   $$ = makeA_Expr(OR, NULL, $1, $3); }
2172         | NOT a_expr
2173                 {   $$ = makeA_Expr(NOT, NULL, NULL, $2); }
2174         ;
2175
2176 opt_indirection:  '[' a_expr ']' opt_indirection 
2177                 {
2178                     A_Indices *ai = makeNode(A_Indices);
2179                     ai->lidx = NULL;
2180                     ai->uidx = $2;
2181                     $$ = lcons(ai, $4);
2182                 }
2183         | '[' a_expr ':' a_expr ']' opt_indirection 
2184                 {
2185                     A_Indices *ai = makeNode(A_Indices);
2186                     ai->lidx = $2;
2187                     ai->uidx = $4;
2188                     $$ = lcons(ai, $6);
2189                 }
2190         | /* EMPTY */                   
2191                 {   $$ = NIL; }
2192         ;
2193    
2194 expr_list: a_expr_or_null
2195                 { $$ = lcons($1, NIL); }
2196         |  expr_list ',' a_expr_or_null
2197                 { $$ = lappend($1, $3); }
2198         ;
2199
2200 in_expr_nodes: AexprConst
2201                 {   $$ = makeA_Expr(OP, "=", saved_In_Expr, $1); }
2202         |  in_expr_nodes ',' AexprConst
2203                 {   $$ = makeA_Expr(OR, NULL, $1,
2204                         makeA_Expr(OP, "=", saved_In_Expr, $3));
2205                 }
2206         ;
2207
2208 not_in_expr_nodes: AexprConst
2209                 {   $$ = makeA_Expr(OP, "<>", saved_In_Expr, $1); }
2210         |  not_in_expr_nodes ',' AexprConst
2211                 {   $$ = makeA_Expr(AND, NULL, $1,
2212                         makeA_Expr(OP, "<>", saved_In_Expr, $3));
2213                 }
2214         ;
2215
2216 attr:  relation_name '.' attrs
2217                 {
2218                     $$ = makeNode(Attr);
2219                     $$->relname = $1;
2220                     $$->paramNo = NULL;
2221                     $$->attrs = $3;
2222                     $$->indirection = NULL;
2223                 }
2224         | ParamNo '.' attrs
2225                 {
2226                     $$ = makeNode(Attr);
2227                     $$->relname = NULL;
2228                     $$->paramNo = $1;
2229                     $$->attrs = $3;
2230                     $$->indirection = NULL;
2231                 }
2232         ;
2233
2234 attrs:    attr_name                             
2235                 { $$ = lcons(makeString($1), NIL); }
2236         | attrs '.' attr_name             
2237                 { $$ = lappend($1, makeString($3)); }
2238         | attrs '.' '*'
2239                 { $$ = lappend($1, makeString("*")); }
2240         ;
2241
2242
2243 /*****************************************************************************
2244  *
2245  *  target lists
2246  *
2247  *****************************************************************************/
2248
2249 res_target_list:  res_target_list ',' res_target_el     
2250                 {   $$ = lappend($1,$3);  }
2251         | res_target_el                         
2252                 {   $$ = lcons($1, NIL);  }
2253         | '*'
2254                 {
2255                     ResTarget *rt = makeNode(ResTarget);
2256                     Attr *att = makeNode(Attr);
2257                     att->relname = "*";
2258                     att->paramNo = NULL;
2259                     att->attrs = NULL;
2260                     att->indirection = NIL;
2261                     rt->name = NULL;
2262                     rt->indirection = NULL;
2263                     rt->val = (Node *)att;
2264                     $$ = lcons(rt, NIL);
2265                 }
2266         ;
2267
2268 res_target_el: Id opt_indirection '=' a_expr_or_null
2269                 {
2270                     $$ = makeNode(ResTarget);
2271                     $$->name = $1;
2272                     $$->indirection = $2;
2273                     $$->val = (Node *)$4;
2274                 }
2275         | attr opt_indirection
2276                 {
2277                     $$ = makeNode(ResTarget);
2278                     $$->name = NULL;
2279                     $$->indirection = $2;
2280                     $$->val = (Node *)$1;
2281                 }
2282         | relation_name '.' '*'
2283                 {   
2284                     Attr *att = makeNode(Attr);
2285                     att->relname = $1;
2286                     att->paramNo = NULL;
2287                     att->attrs = lcons(makeString("*"), NIL);
2288                     att->indirection = NIL;
2289                     $$ = makeNode(ResTarget);
2290                     $$->name = NULL;
2291                     $$->indirection = NULL;
2292                     $$->val = (Node *)att;
2293                 }
2294         ;                
2295
2296 /*
2297 ** target list for select.
2298 ** should get rid of the other but is still needed by the defunct retrieve into
2299 ** and update (uses a subset)
2300 */
2301 res_target_list2:
2302           res_target_list2 ',' res_target_el2   
2303                 {   $$ = lappend($1, $3);  }
2304         | res_target_el2                        
2305                 {   $$ = lcons($1, NIL);  }
2306         ;
2307
2308 /* AS is not optional because shift/red conflict with unary ops */
2309 res_target_el2: a_expr AS Id 
2310                 {
2311                     $$ = makeNode(ResTarget);
2312                     $$->name = $3;
2313                     $$->indirection = NULL;
2314                     $$->val = (Node *)$1;
2315                 }
2316         | a_expr_or_null
2317                 {
2318                     $$ = makeNode(ResTarget);
2319                     $$->name = NULL;
2320                     $$->indirection = NULL;
2321                     $$->val = (Node *)$1;
2322                 }
2323         | relation_name '.' '*'
2324                 {
2325                     Attr *att = makeNode(Attr);
2326                     att->relname = $1;
2327                     att->paramNo = NULL;
2328                     att->attrs = lcons(makeString("*"), NIL);
2329                     att->indirection = NIL;
2330                     $$ = makeNode(ResTarget);
2331                     $$->name = NULL;
2332                     $$->indirection = NULL;
2333                     $$->val = (Node *)att;
2334                 }
2335         | '*'
2336                 {
2337                     Attr *att = makeNode(Attr);
2338                     att->relname = "*";
2339                     att->paramNo = NULL;
2340                     att->attrs = NULL;
2341                     att->indirection = NIL;
2342                     $$ = makeNode(ResTarget);
2343                     $$->name = NULL;
2344                     $$->indirection = NULL;
2345                     $$->val = (Node *)att;
2346                 }
2347         ;
2348
2349 opt_id:  Id                                     { $$ = $1; }
2350         | /* EMPTY */                           { $$ = NULL; }
2351         ;
2352
2353 relation_name:  SpecialRuleRelation
2354                 {
2355                    $$ = $1;
2356                    strNcpy(saved_relname, $1, NAMEDATALEN-1);
2357                 }
2358         | Id
2359                 {
2360                     /* disallow refs to magic system tables */
2361                     if (strcmp(LogRelationName, $1) == 0
2362                        || strcmp(VariableRelationName, $1) == 0
2363                        || strcmp(TimeRelationName, $1) == 0
2364                        || strcmp(MagicRelationName, $1) == 0) {
2365                         elog(WARN, "%s cannot be accessed by users", $1);
2366                     } else {
2367                         $$ = $1;
2368                     }
2369                     strNcpy(saved_relname, $1, NAMEDATALEN-1);
2370                 }
2371         ;
2372
2373 database_name:          Id              { $$ = $1; };
2374 access_method:          Id              { $$ = $1; };
2375 attr_name:              Id              { $$ = $1; };
2376 class:                  Id              { $$ = $1; };
2377 index_name:             Id              { $$ = $1; };
2378 var_name:               Id              { $$ = $1; };
2379 name:                   Id              { $$ = $1; };
2380
2381 date:                   Sconst          { $$ = $1; };
2382 file_name:              Sconst          { $$ = $1; };
2383 recipe_name:            Id              { $$ = $1; };
2384
2385 AexprConst:  Iconst
2386                 {  
2387                     A_Const *n = makeNode(A_Const);
2388                     n->val.type = T_Integer;
2389                     n->val.val.ival = $1;
2390                     $$ = (Node *)n;
2391                 }
2392         | FCONST
2393                 {  
2394                     A_Const *n = makeNode(A_Const);
2395                     n->val.type = T_Float;
2396                     n->val.val.dval = $1;
2397                     $$ = (Node *)n;
2398                 }
2399         | Sconst
2400                 {  
2401                     A_Const *n = makeNode(A_Const);
2402                     n->val.type = T_String;
2403                     n->val.val.str = $1;
2404                     $$ = (Node *)n;
2405                 }
2406         | ParamNo
2407                 {   $$ = (Node *)$1;  }
2408         ;
2409
2410 ParamNo:  PARAM
2411                 {
2412                     $$ = makeNode(ParamNo);
2413                     $$->number = $1;
2414                 }
2415         ;
2416
2417 NumConst:  Iconst                       { $$ = makeInteger($1); }
2418         |  FCONST                       { $$ = makeFloat($1); }
2419         ;
2420
2421 Iconst:  ICONST                         { $$ = $1; };
2422 Sconst:  SCONST                         { $$ = $1; };
2423
2424 Id:  IDENT                              { $$ = $1; };
2425
2426 SpecialRuleRelation:  CURRENT
2427                 { 
2428                     if (QueryIsRule)
2429                         $$ = "*CURRENT*";
2430                     else 
2431                         elog(WARN,"CURRENT used in non-rule query");
2432                 }
2433         | NEW
2434                 { 
2435                     if (QueryIsRule)
2436                         $$ = "*NEW*";
2437                     else 
2438                         elog(WARN,"NEW used in non-rule query"); 
2439                 }
2440         ;
2441
2442 Type:   P_TYPE;
2443 Pnull:  PNULL;
2444
2445
2446 %%
2447
2448 static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr)
2449 {
2450     A_Expr *a = makeNode(A_Expr);
2451     a->oper = oper;
2452     a->opname = opname;
2453     a->lexpr = lexpr;
2454     a->rexpr = rexpr;
2455     return (Node *)a;
2456 }
2457
2458 static char *
2459 xlateSqlType(char *name)
2460 {
2461     if (!strcasecmp(name,"int") ||
2462         !strcasecmp(name,"integer"))
2463         return "int4"; /* strdup("int4") --   strdup leaks memory here */
2464     else if (!strcasecmp(name, "smallint"))
2465         return "int2";
2466     else if (!strcasecmp(name, "float") ||
2467              !strcasecmp(name, "real"))
2468         return "float8";
2469     else
2470         return name;
2471 }
2472
2473 void parser_init(Oid *typev, int nargs)
2474 {
2475     QueryIsRule = false;
2476     saved_relname[0]= '\0';
2477     saved_In_Expr = NULL;
2478     
2479     param_type_init(typev, nargs);
2480 }
2481