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