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