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