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