]> granicus.if.org Git - postgresql/blob - src/backend/parser/gram.y
MOVE implementation.
[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.53 1997/09/29 05:58:12 vadim Exp $
14  *
15  * HISTORY
16  *        AUTHOR                        DATE                    MAJOR EVENT
17  *        Andrew Yu                     Sept, 1994              POSTQUEL to SQL conversion
18  *        Andrew Yu                     Oct, 1994               lispy code conversion
19  *
20  * NOTES
21  *        CAPITALS are used to represent terminal symbols.
22  *        non-capitals are used to represent non-terminals.
23  *
24  *        if you use list, make sure the datum is a node so that the printing
25  *        routines work
26  *
27  * WARNING
28  *        sometimes we assign constants to makeStrings. Make sure we don't free
29  *        those.
30  *
31  *-------------------------------------------------------------------------
32  */
33 #include <string.h>
34 #include <ctype.h>
35
36 #include "postgres.h"
37 #include "nodes/parsenodes.h"
38 #include "nodes/print.h"
39 #include "parser/gramparse.h"
40 #include "parser/catalog_utils.h"
41 #include "parser/parse_query.h"
42 #include "storage/smgr.h"
43 #include "utils/acl.h"
44 #include "catalog/catname.h"
45 #include "utils/elog.h"
46 #include "access/xact.h"
47
48 static char saved_relname[NAMEDATALEN];  /* need this for complex attributes */
49 static bool QueryIsRule = FALSE;
50 static Node *saved_In_Expr;
51 extern List *parsetree;
52
53 /*
54  * If you need access to certain yacc-generated variables and find that
55  * they're static by default, uncomment the next line.  (this is not a
56  * problem, yet.)
57  */
58 /*#define __YYSCLASS*/
59
60 static char *xlateSqlType(char *);
61 static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
62 static List *makeConstantList( A_Const *node);
63 static char *FlattenStringList(List *list);
64
65 /* old versions of flex define this as a macro */
66 #if defined(yywrap)
67 #undef yywrap
68 #endif /* yywrap */
69 %}
70
71
72 %union
73 {
74         double                          dval;
75         int                                     ival;
76         char                            chr;
77         char                            *str;
78         bool                            boolean;
79         List                            *list;
80         Node                            *node;
81         Value                           *value;
82
83         Attr                            *attr;
84
85         ColumnDef                       *coldef;
86         ConstraintDef           *constrdef;
87         TypeName                        *typnam;
88         DefElem                         *defelt;
89         ParamString                     *param;
90         SortGroupBy                     *sortgroupby;
91         IndexElem                       *ielem;
92         RangeVar                        *range;
93         RelExpr                         *relexp;
94         TimeRange                       *trange;
95         A_Indices                       *aind;
96         ResTarget                       *target;
97         ParamNo                         *paramno;
98
99         VersionStmt                     *vstmt;
100         DefineStmt                      *dstmt;
101         PurgeStmt                       *pstmt;
102         RuleStmt                        *rstmt;
103         AppendStmt                      *astmt;
104 }
105
106 %type <node>    stmt,
107                 AddAttrStmt, ClosePortalStmt,
108                 CopyStmt, CreateStmt, CreateSeqStmt, DefineStmt, DestroyStmt,
109                 ExtendStmt, FetchStmt,  GrantStmt, CreateTrigStmt, DropTrigStmt,
110                 IndexStmt, 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
2314 typname:  txname
2315                                 {
2316                                         char *tname;
2317                                         $$ = makeNode(TypeName);
2318
2319                                         if (!strcasecmp($1, "float"))
2320                                                 tname = xlateSqlType("float8");
2321                                         else if (!strcasecmp($1, "decimal"))
2322                                                 tname = xlateSqlType("integer");
2323                                         else if (!strcasecmp($1, "numeric"))
2324                                                 tname = xlateSqlType("integer");
2325                                         else
2326                                                 tname = xlateSqlType($1);
2327                                         $$->name = tname;
2328
2329                                         /* Is this the name of a complex type? If so, implement
2330                                          * it as a set.
2331                                          */
2332                                         if (!strcmp(saved_relname, tname))
2333                                                 /* This attr is the same type as the relation
2334                                                  * being defined. The classic example: create
2335                                                  * emp(name=text,mgr=emp)
2336                                                  */
2337                                                 $$->setof = TRUE;
2338                                         else if (get_typrelid((Type)type(tname)) != InvalidOid)
2339                                                  /* (Eventually add in here that the set can only
2340                                                   * contain one element.)
2341                                                   */
2342                                                 $$->setof = TRUE;
2343                                         else
2344                                                 $$->setof = FALSE;
2345                                 }
2346                 | SETOF txname
2347                                 {
2348                                         char *tname = xlateSqlType($2);
2349                                         $$ = makeNode(TypeName);
2350                                         $$->name = tname;
2351                                         $$->setof = TRUE;
2352                                 }
2353                 ;
2354
2355 txname:  Id                                                             { $$ = $1; }
2356                 | TIME                                                  { $$ = xlateSqlType("time"); }
2357                 | INTERVAL interval_opts                { $$ = xlateSqlType("interval"); }
2358                 | CHARACTER char_type                   { $$ = $2; }
2359                 | DOUBLE PRECISION                              { $$ = xlateSqlType("float8"); }
2360                 | FLOAT                                                 { $$ = xlateSqlType("float"); }
2361                 | DECIMAL                                               { $$ = "decimal"; }
2362                 | NUMERIC                                               { $$ = "numeric"; }
2363                 ;
2364
2365 char_type:  VARYING                                             { $$ = xlateSqlType("varchar"); }
2366                 | /*EMPTY*/                                             { $$ = xlateSqlType("char"); }
2367                 ;
2368
2369 interval_opts:  YEARINTERVAL                                    { $$ = lcons("year", NIL); }
2370                 | MONTHINTERVAL                                                 { $$ = NIL; }
2371                 | DAYINTERVAL                                                   { $$ = NIL; }
2372                 | HOURINTERVAL                                                  { $$ = NIL; }
2373                 | MINUTEINTERVAL                                                { $$ = NIL; }
2374                 | SECONDINTERVAL                                                { $$ = NIL; }
2375                 | YEARINTERVAL TO MONTHINTERVAL                 { $$ = NIL; }
2376                 | DAYINTERVAL TO HOURINTERVAL                   { $$ = NIL; }
2377                 | DAYINTERVAL TO MINUTEINTERVAL                 { $$ = NIL; }
2378                 | DAYINTERVAL TO SECONDINTERVAL                 { $$ = NIL; }
2379                 | HOURINTERVAL TO MINUTEINTERVAL                { $$ = NIL; }
2380                 | HOURINTERVAL TO SECONDINTERVAL                { $$ = NIL; }
2381                 | /* EMPTY */                                                   { $$ = NIL; }
2382                 ;
2383
2384 Typename:  typname opt_array_bounds
2385                                 {
2386                                         $$ = $1;
2387                                         $$->arrayBounds = $2;
2388 #if FALSE
2389                                         if (!strcasecmp($1->name, "varchar"))
2390                                                 $$->typlen = 4 + 1;
2391 #endif
2392                                 }
2393                 | txname '(' Iconst ')'
2394                                 {
2395                                         /*
2396                                          * The following implements CHAR() and VARCHAR().
2397                                          * We do it here instead of the 'typname:' production
2398                                          * because we don't want to allow arrays of VARCHAR().
2399                                          * I haven't thought about whether that will work or not.
2400                                          *                                                              - ay 6/95
2401                                          * Also implements FLOAT().
2402                                          * Check precision limits assuming IEEE floating types.
2403                                          *                                                              - thomas 1997-09-18
2404                                          */
2405                                         $$ = makeNode(TypeName);
2406                                         if (!strcasecmp($1, "float")) {
2407                                                 if ($3 < 1)
2408                                                         elog(WARN,"precision for FLOAT must be at least 1",NULL);
2409                                                 else if ($3 < 7)
2410                                                         $$->name = xlateSqlType("float4");
2411                                                 else if ($3 < 16)
2412                                                         $$->name = xlateSqlType("float8");
2413                                                 else
2414                                                         elog(WARN,"precision for FLOAT must be less than 16",NULL);
2415                                         } else if (!strcasecmp($1, "decimal")) {
2416                                                 /* DECIMAL is allowed to have more precision than specified */
2417                                                 if ($3 > 9)
2418                                                         elog(WARN,"DECIMAL precision %d exceeds implementation limit of 9",$3);
2419                                                 $$->name = xlateSqlType("integer");
2420
2421                                         } else if (!strcasecmp($1, "numeric")) {
2422                                                 /* integer holds 9.33 decimal places, so assume an even 9 for now */
2423                                                 if ($3 != 9)
2424                                                         elog(WARN,"NUMERIC precision %d must be 9",$3);
2425                                                 $$->name = xlateSqlType("integer");
2426
2427                                         } else {
2428                                                 if (!strcasecmp($1, "char"))
2429                                                         $$->name = xlateSqlType("bpchar");
2430                                                 else if (!strcasecmp($1, "varchar"))
2431                                                         $$->name = xlateSqlType("varchar");
2432                                                 else
2433                                                         yyerror("parse error");
2434                                                 if ($3 < 1)
2435                                                         elog(WARN,"length for '%s' type must be at least 1",$1);
2436                                                 else if ($3 > 4096)
2437                                                         /* we can store a char() of length up to the size
2438                                                          * of a page (8KB) - page headers and friends but
2439                                                          * just to be safe here...      - ay 6/95
2440                                                          * XXX note this hardcoded limit - thomas 1997-07-13
2441                                                          */
2442                                                         elog(WARN,"length for '%s' type cannot exceed 4096",$1);
2443
2444                                                 /* we actually implement this sort of like a varlen, so
2445                                                  * the first 4 bytes is the length. (the difference
2446                                                  * between this and "text" is that we blank-pad and
2447                                                  * truncate where necessary
2448                                                  */
2449                                                 $$->typlen = 4 + $3;
2450                                         }
2451                                 }
2452                 | txname '(' Iconst ',' Iconst ')'
2453                                 {
2454                                         $$ = makeNode(TypeName);
2455                                         if (!strcasecmp($1, "decimal")) {
2456                                                 if ($3 > 9)
2457                                                         elog(WARN,"DECIMAL precision %d exceeds implementation limit of 9",$3);
2458                                                 if ($5 != 0)
2459                                                         elog(WARN,"DECIMAL scale %d must be zero",$5);
2460                                                 $$->name = xlateSqlType("integer");
2461
2462                                         } else if (!strcasecmp($1, "numeric")) {
2463                                                 if ($3 != 9)
2464                                                         elog(WARN,"NUMERIC precision %d must be 9",$3);
2465                                                 if ($5 != 0)
2466                                                         elog(WARN,"NUMERIC scale %d must be zero",$5);
2467                                                 $$->name = xlateSqlType("integer");
2468
2469                                         } else {
2470                                                 elog(WARN,"%s(%d,%d) not implemented",$1,$3,$5);
2471                                         }
2472                                         $$->name = xlateSqlType("integer");
2473                                 }
2474                 ;
2475
2476
2477 /*****************************************************************************
2478  *
2479  *      expression grammar, still needs some cleanup
2480  *
2481  *****************************************************************************/
2482
2483 a_expr_or_null: a_expr
2484                                 { $$ = $1;}
2485                 | Pnull
2486                                 {
2487                                         A_Const *n = makeNode(A_Const);
2488                                         n->val.type = T_Null;
2489                                         $$ = (Node *)n;
2490                                 }
2491
2492 a_expr:  attr opt_indirection
2493                                 {
2494                                         $1->indirection = $2;
2495                                         $$ = (Node *)$1;
2496                                 }
2497                 | AexprConst
2498                                 {       $$ = $1;  }
2499                 | '-' a_expr %prec UMINUS
2500                                 {       $$ = makeA_Expr(OP, "-", NULL, $2); }
2501                 | a_expr '+' a_expr
2502                                 {       $$ = makeA_Expr(OP, "+", $1, $3); }
2503                 | a_expr '-' a_expr
2504                                 {       $$ = makeA_Expr(OP, "-", $1, $3); }
2505                 | a_expr '/' a_expr
2506                                 {       $$ = makeA_Expr(OP, "/", $1, $3); }
2507                 | a_expr '*' a_expr
2508                                 {       $$ = makeA_Expr(OP, "*", $1, $3); }
2509                 | a_expr '<' a_expr
2510                                 {       $$ = makeA_Expr(OP, "<", $1, $3); }
2511                 | a_expr '>' a_expr
2512                                 {       $$ = makeA_Expr(OP, ">", $1, $3); }
2513                 | a_expr '=' a_expr
2514                                 {       $$ = makeA_Expr(OP, "=", $1, $3); }
2515                 | ':' a_expr
2516                                 {       $$ = makeA_Expr(OP, ":", NULL, $2); }
2517                 | ';' a_expr
2518                                 {       $$ = makeA_Expr(OP, ";", NULL, $2); }
2519                 | '|' a_expr
2520                                 {       $$ = makeA_Expr(OP, "|", NULL, $2); }
2521                 | AexprConst TYPECAST Typename
2522                                 {
2523                                         /* AexprConst can be either A_Const or ParamNo */
2524                                         if (nodeTag($1) == T_A_Const)
2525                                                 ((A_Const *)$1)->typename = $3;
2526                                         else
2527                                                 ((ParamNo *)$1)->typename = $3;
2528                                         $$ = (Node *)$1;
2529                                 }
2530                 | CAST AexprConst AS Typename
2531                                 {
2532                                         /* AexprConst can be either A_Const or ParamNo */
2533                                         if (nodeTag($2) == T_A_Const)
2534                                                 ((A_Const *)$2)->typename = $4;
2535                                         else
2536                                                 ((ParamNo *)$2)->typename = $4;
2537                                         $$ = (Node *)$2;
2538                                 }
2539                 | '(' a_expr_or_null ')'
2540                                 {       $$ = $2; }
2541                 | a_expr Op a_expr
2542                                 {       $$ = makeA_Expr(OP, $2, $1, $3); }
2543                 | a_expr LIKE a_expr
2544                                 {       $$ = makeA_Expr(OP, "~~", $1, $3); }
2545                 | a_expr NOT LIKE a_expr
2546                                 {       $$ = makeA_Expr(OP, "!~~", $1, $4); }
2547                 | Op a_expr
2548                                 {       $$ = makeA_Expr(OP, $1, NULL, $2); }
2549                 | a_expr Op
2550                                 {       $$ = makeA_Expr(OP, $2, $1, NULL); }
2551                 | Id
2552                                 {
2553                                         /* could be a column name or a relation_name */
2554                                         Ident *n = makeNode(Ident);
2555                                         n->name = $1;
2556                                         n->indirection = NULL;
2557                                         $$ = (Node *)n;
2558                                 }
2559                 | name '(' '*' ')'
2560                                 {
2561                                         FuncCall *n = makeNode(FuncCall);
2562                                         Ident *star = makeNode(Ident);
2563
2564                                         /* cheap hack for aggregate (eg. count) */
2565                                         star->name = "oid";
2566                                         n->funcname = $1;
2567                                         n->args = lcons(star, NIL);
2568                                         $$ = (Node *)n;
2569                                 }
2570                 | name '(' ')'
2571                                 {
2572                                         FuncCall *n = makeNode(FuncCall);
2573                                         n->funcname = $1;
2574                                         n->args = NIL;
2575                                         $$ = (Node *)n;
2576                                 }
2577                 | CURRENT_DATE
2578                                 {
2579                                         A_Const *n = makeNode(A_Const);
2580                                         TypeName *t = makeNode(TypeName);
2581
2582                                         n->val.type = T_String;
2583                                         n->val.val.str = "now";
2584                                         n->typename = t;
2585
2586                                         t->name = xlateSqlType("date");
2587                                         t->setof = FALSE;
2588
2589                                         $$ = (Node *)n;
2590                                 }
2591                 | CURRENT_TIME
2592                                 {
2593                                         A_Const *n = makeNode(A_Const);
2594                                         TypeName *t = makeNode(TypeName);
2595
2596                                         n->val.type = T_String;
2597                                         n->val.val.str = "now";
2598                                         n->typename = t;
2599
2600                                         t->name = xlateSqlType("time");
2601                                         t->setof = FALSE;
2602
2603                                         $$ = (Node *)n;
2604                                 }
2605                 | CURRENT_TIME '(' AexprConst ')'
2606                                 {
2607                                         FuncCall *n = makeNode(FuncCall);
2608                                         A_Const *s = makeNode(A_Const);
2609                                         TypeName *t = makeNode(TypeName);
2610
2611                                         n->funcname = xlateSqlType("time");
2612                                         n->args = lcons(s, NIL);
2613
2614                                         s->val.type = T_String;
2615                                         s->val.val.str = "now";
2616                                         s->typename = t;
2617
2618                                         t->name = xlateSqlType("time");
2619                                         t->setof = FALSE;
2620
2621                                         elog(NOTICE,"CURRENT_TIME(p) precision not implemented",NULL);
2622
2623                                         $$ = (Node *)n;
2624                                 }
2625                 | CURRENT_TIMESTAMP
2626                                 {
2627                                         A_Const *n = makeNode(A_Const);
2628                                         TypeName *t = makeNode(TypeName);
2629
2630                                         n->val.type = T_String;
2631                                         n->val.val.str = "now";
2632                                         n->typename = t;
2633
2634                                         t->name = xlateSqlType("timestamp");
2635                                         t->setof = FALSE;
2636
2637                                         $$ = (Node *)n;
2638                                 }
2639                 | CURRENT_TIMESTAMP '(' AexprConst ')'
2640                                 {
2641                                         FuncCall *n = makeNode(FuncCall);
2642                                         A_Const *s = makeNode(A_Const);
2643                                         TypeName *t = makeNode(TypeName);
2644
2645                                         n->funcname = xlateSqlType("timestamp");
2646                                         n->args = lcons(s, NIL);
2647
2648                                         s->val.type = T_String;
2649                                         s->val.val.str = "now";
2650                                         s->typename = t;
2651
2652                                         t->name = xlateSqlType("timestamp");
2653                                         t->setof = FALSE;
2654
2655                                         elog(NOTICE,"CURRENT_TIMESTAMP(p) precision not implemented",NULL);
2656
2657                                         $$ = (Node *)n;
2658                                 }
2659                 /* We probably need to define an "exists" node,
2660                  *      since the optimizer could choose to find only one match.
2661                  * Perhaps the first implementation could just check for
2662                  *      count(*) > 0? - thomas 1997-07-19
2663                  */
2664                 | EXISTS '(' SubSelect ')'
2665                                 {
2666                                         elog(WARN,"EXISTS not yet supported",NULL);
2667                                         $$ = $3;
2668                                 }
2669                 | EXTRACT '(' extract_list ')'
2670                                 {
2671                                         FuncCall *n = makeNode(FuncCall);
2672                                         n->funcname = "date_part";
2673                                         n->args = $3;
2674                                         $$ = (Node *)n;
2675                                 }
2676                 | POSITION '(' position_list ')'
2677                                 {
2678                                         FuncCall *n = makeNode(FuncCall);
2679                                         n->funcname = "strpos";
2680                                         n->args = $3;
2681                                         $$ = (Node *)n;
2682                                 }
2683                 | SUBSTRING '(' substr_list ')'
2684                                 {
2685                                         FuncCall *n = makeNode(FuncCall);
2686                                         n->funcname = "substr";
2687                                         n->args = $3;
2688                                         $$ = (Node *)n;
2689                                 }
2690                 /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
2691                 | TRIM '(' BOTH trim_list ')'
2692                                 {
2693                                         FuncCall *n = makeNode(FuncCall);
2694                                         n->funcname = "btrim";
2695                                         n->args = $4;
2696                                         $$ = (Node *)n;
2697                                 }
2698                 | TRIM '(' LEADING trim_list ')'
2699                                 {
2700                                         FuncCall *n = makeNode(FuncCall);
2701                                         n->funcname = "ltrim";
2702                                         n->args = $4;
2703                                         $$ = (Node *)n;
2704                                 }
2705                 | TRIM '(' TRAILING trim_list ')'
2706                                 {
2707                                         FuncCall *n = makeNode(FuncCall);
2708                                         n->funcname = "rtrim";
2709                                         n->args = $4;
2710                                         $$ = (Node *)n;
2711                                 }
2712                 | TRIM '(' trim_list ')'
2713                                 {
2714                                         FuncCall *n = makeNode(FuncCall);
2715                                         n->funcname = "btrim";
2716                                         n->args = $3;
2717                                         $$ = (Node *)n;
2718                                 }
2719                 | name '(' expr_list ')'
2720                                 {
2721                                         FuncCall *n = makeNode(FuncCall);
2722                                         n->funcname = $1;
2723                                         n->args = $3;
2724                                         $$ = (Node *)n;
2725                                 }
2726                 | a_expr ISNULL
2727                                 {       $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
2728                 | a_expr IS PNULL
2729                                 {       $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
2730                 | a_expr NOTNULL
2731                                 {       $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); }
2732                 | a_expr IS NOT PNULL
2733                                 {       $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); }
2734                 | a_expr BETWEEN AexprConst AND AexprConst
2735                                 {
2736                                         $$ = makeA_Expr(AND, NULL,
2737                                                 makeA_Expr(OP, ">=", $1, $3),
2738                                                 makeA_Expr(OP, "<=", $1, $5));
2739                                 }
2740                 | a_expr NOT BETWEEN AexprConst AND AexprConst
2741                                 {
2742                                         $$ = makeA_Expr(OR, NULL,
2743                                                 makeA_Expr(OP, "<", $1, $4),
2744                                                 makeA_Expr(OP, ">", $1, $6));
2745                                 }
2746                 | a_expr IN { saved_In_Expr = $1; } '(' in_expr_nodes ')'
2747                                 {       $$ = $5; }
2748                 | a_expr NOT IN { saved_In_Expr = $1; } '(' not_in_expr_nodes ')'
2749                                 {       $$ = $6; }
2750                 | a_expr AND a_expr
2751                                 {       $$ = makeA_Expr(AND, NULL, $1, $3); }
2752                 | a_expr OR a_expr
2753                                 {       $$ = makeA_Expr(OR, NULL, $1, $3); }
2754                 | NOT a_expr
2755                                 {       $$ = makeA_Expr(NOT, NULL, NULL, $2); }
2756                 ;
2757
2758 opt_indirection:  '[' a_expr ']' opt_indirection
2759                                 {
2760                                         A_Indices *ai = makeNode(A_Indices);
2761                                         ai->lidx = NULL;
2762                                         ai->uidx = $2;
2763                                         $$ = lcons(ai, $4);
2764                                 }
2765                 | '[' a_expr ':' a_expr ']' opt_indirection
2766                                 {
2767                                         A_Indices *ai = makeNode(A_Indices);
2768                                         ai->lidx = $2;
2769                                         ai->uidx = $4;
2770                                         $$ = lcons(ai, $6);
2771                                 }
2772                 | /* EMPTY */
2773                                 {       $$ = NIL; }
2774                 ;
2775
2776 expr_list: a_expr_or_null
2777                                 { $$ = lcons($1, NIL); }
2778                 |  expr_list ',' a_expr_or_null
2779                                 { $$ = lappend($1, $3); }
2780                 |  expr_list USING a_expr
2781                                 { $$ = lappend($1, $3); }
2782                 ;
2783
2784 extract_list: DateTime FROM a_expr
2785                                 {
2786                                         A_Const *n = makeNode(A_Const);
2787                                         n->val.type = T_String;
2788                                         n->val.val.str = $1;
2789 #ifdef PARSEDEBUG
2790 printf( "string is %s\n", $1);
2791 #endif
2792                                         $$ = lappend(lcons((Node *)n,NIL), $3);
2793                                 }
2794                 | /* EMPTY */
2795                                 {       $$ = NIL; }
2796                 ;
2797
2798 position_list: position_expr IN position_expr
2799                                 {       $$ = makeList($3, $1, -1); }
2800                 | /* EMPTY */
2801                                 {       $$ = NIL; }
2802                 ;
2803
2804 position_expr:  attr opt_indirection
2805                                 {
2806                                         $1->indirection = $2;
2807                                         $$ = (Node *)$1;
2808                                 }
2809                 | AexprConst
2810                                 {       $$ = $1;  }
2811                 | '-' position_expr %prec UMINUS
2812                                 {       $$ = makeA_Expr(OP, "-", NULL, $2); }
2813                 | position_expr '+' position_expr
2814                                 {       $$ = makeA_Expr(OP, "+", $1, $3); }
2815                 | position_expr '-' position_expr
2816                                 {       $$ = makeA_Expr(OP, "-", $1, $3); }
2817                 | position_expr '/' position_expr
2818                                 {       $$ = makeA_Expr(OP, "/", $1, $3); }
2819                 | position_expr '*' position_expr
2820                                 {       $$ = makeA_Expr(OP, "*", $1, $3); }
2821                 | '|' position_expr
2822                                 {       $$ = makeA_Expr(OP, "|", NULL, $2); }
2823                 | AexprConst TYPECAST Typename
2824                                 {
2825                                         /* AexprConst can be either A_Const or ParamNo */
2826                                         if (nodeTag($1) == T_A_Const)
2827                                                 ((A_Const *)$1)->typename = $3;
2828                                         else
2829                                                 ((ParamNo *)$1)->typename = $3;
2830                                         $$ = (Node *)$1;
2831                                 }
2832                 | CAST AexprConst AS Typename
2833                                 {
2834                                         /* AexprConst can be either A_Const or ParamNo */
2835                                         if (nodeTag($2) == T_A_Const)
2836                                                 ((A_Const *)$2)->typename = $4;
2837                                         else
2838                                                 ((ParamNo *)$2)->typename = $4;
2839                                         $$ = (Node *)$2;
2840                                 }
2841                 | '(' position_expr ')'
2842                                 {       $$ = $2; }
2843                 | position_expr Op position_expr
2844                                 {       $$ = makeA_Expr(OP, $2, $1, $3); }
2845                 | Op position_expr
2846                                 {       $$ = makeA_Expr(OP, $1, NULL, $2); }
2847                 | position_expr Op
2848                                 {       $$ = makeA_Expr(OP, $2, $1, NULL); }
2849                 | Id
2850                                 {
2851                                         /* could be a column name or a relation_name */
2852                                         Ident *n = makeNode(Ident);
2853                                         n->name = $1;
2854                                         n->indirection = NULL;
2855                                         $$ = (Node *)n;
2856                                 }
2857                 | name '(' ')'
2858                                 {
2859                                         FuncCall *n = makeNode(FuncCall);
2860                                         n->funcname = $1;
2861                                         n->args = NIL;
2862                                         $$ = (Node *)n;
2863                                 }
2864                 | POSITION '(' position_list ')'
2865                                 {
2866                                         FuncCall *n = makeNode(FuncCall);
2867                                         n->funcname = "strpos";
2868                                         n->args = $3;
2869                                         $$ = (Node *)n;
2870                                 }
2871                 | SUBSTRING '(' substr_list ')'
2872                                 {
2873                                         FuncCall *n = makeNode(FuncCall);
2874                                         n->funcname = "substr";
2875                                         n->args = $3;
2876                                         $$ = (Node *)n;
2877                                 }
2878                 /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
2879                 | TRIM '(' BOTH trim_list ')'
2880                                 {
2881                                         FuncCall *n = makeNode(FuncCall);
2882                                         n->funcname = "btrim";
2883                                         n->args = $4;
2884                                         $$ = (Node *)n;
2885                                 }
2886                 | TRIM '(' LEADING trim_list ')'
2887                                 {
2888                                         FuncCall *n = makeNode(FuncCall);
2889                                         n->funcname = "ltrim";
2890                                         n->args = $4;
2891                                         $$ = (Node *)n;
2892                                 }
2893                 | TRIM '(' TRAILING trim_list ')'
2894                                 {
2895                                         FuncCall *n = makeNode(FuncCall);
2896                                         n->funcname = "rtrim";
2897                                         n->args = $4;
2898                                         $$ = (Node *)n;
2899                                 }
2900                 | TRIM '(' trim_list ')'
2901                                 {
2902                                         FuncCall *n = makeNode(FuncCall);
2903                                         n->funcname = "btrim";
2904                                         n->args = $3;
2905                                         $$ = (Node *)n;
2906                                 }
2907                 | name '(' expr_list ')'
2908                                 {
2909                                         FuncCall *n = makeNode(FuncCall);
2910                                         n->funcname = $1;
2911                                         n->args = $3;
2912                                         $$ = (Node *)n;
2913                                 }
2914                 ;
2915
2916 substr_list: expr_list substr_from substr_for
2917                                 {
2918                                         $$ = nconc(nconc($1,$2),$3);
2919                                 }
2920                 | /* EMPTY */
2921                                 {       $$ = NIL; }
2922                 ;
2923
2924 substr_from: FROM expr_list
2925                                 {       $$ = $2; }
2926                 | /* EMPTY */
2927                                 {
2928                                         A_Const *n = makeNode(A_Const);
2929                                         n->val.type = T_Integer;
2930                                         n->val.val.ival = 1;
2931                                         $$ = lcons((Node *)n,NIL);
2932                                 }
2933                 ;
2934
2935 substr_for: FOR expr_list
2936                                 {       $$ = $2; }
2937                 | /* EMPTY */
2938                                 {       $$ = NIL; }
2939                 ;
2940
2941 trim_list: a_expr FROM expr_list
2942                                 { $$ = lappend($3, $1); }
2943                 |  FROM expr_list
2944                                 { $$ = $2; }
2945                 |  expr_list
2946                                 { $$ = $1; }
2947                 ;
2948
2949 in_expr_nodes: AexprConst
2950                                 {       $$ = makeA_Expr(OP, "=", saved_In_Expr, $1); }
2951                 |  in_expr_nodes ',' AexprConst
2952                                 {       $$ = makeA_Expr(OR, NULL, $1,
2953                                                 makeA_Expr(OP, "=", saved_In_Expr, $3));
2954                                 }
2955                 ;
2956
2957 not_in_expr_nodes: AexprConst
2958                                 {       $$ = makeA_Expr(OP, "<>", saved_In_Expr, $1); }
2959                 |  not_in_expr_nodes ',' AexprConst
2960                                 {       $$ = makeA_Expr(AND, NULL, $1,
2961                                                 makeA_Expr(OP, "<>", saved_In_Expr, $3));
2962                                 }
2963                 ;
2964
2965 attr:  relation_name '.' attrs
2966                                 {
2967                                         $$ = makeNode(Attr);
2968                                         $$->relname = $1;
2969                                         $$->paramNo = NULL;
2970                                         $$->attrs = $3;
2971                                         $$->indirection = NULL;
2972                                 }
2973                 | ParamNo '.' attrs
2974                                 {
2975                                         $$ = makeNode(Attr);
2976                                         $$->relname = NULL;
2977                                         $$->paramNo = $1;
2978                                         $$->attrs = $3;
2979                                         $$->indirection = NULL;
2980                                 }
2981                 ;
2982
2983 attrs:    attr_name
2984                                 { $$ = lcons(makeString($1), NIL); }
2985                 | attrs '.' attr_name
2986                                 { $$ = lappend($1, makeString($3)); }
2987                 | attrs '.' '*'
2988                                 { $$ = lappend($1, makeString("*")); }
2989                 ;
2990
2991 DateTime:  YEARINTERVAL                                                 { $$ = "year"; }
2992                 | MONTHINTERVAL                                                 { $$ = "month"; }
2993                 | DAYINTERVAL                                                   { $$ = "day"; }
2994                 | HOURINTERVAL                                                  { $$ = "hour"; }
2995                 | MINUTEINTERVAL                                                { $$ = "minute"; }
2996                 | SECONDINTERVAL                                                { $$ = "second"; }
2997                 ;
2998
2999 /*****************************************************************************
3000  *
3001  *      target lists
3002  *
3003  *****************************************************************************/
3004
3005 res_target_list:  res_target_list ',' res_target_el
3006                                 {       $$ = lappend($1,$3);  }
3007                 | res_target_el
3008                                 {       $$ = lcons($1, NIL);  }
3009                 | '*'
3010                                 {
3011                                         ResTarget *rt = makeNode(ResTarget);
3012                                         Attr *att = makeNode(Attr);
3013                                         att->relname = "*";
3014                                         att->paramNo = NULL;
3015                                         att->attrs = NULL;
3016                                         att->indirection = NIL;
3017                                         rt->name = NULL;
3018                                         rt->indirection = NULL;
3019                                         rt->val = (Node *)att;
3020                                         $$ = lcons(rt, NIL);
3021                                 }
3022                 ;
3023
3024 res_target_el: Id opt_indirection '=' a_expr_or_null
3025                                 {
3026                                         $$ = makeNode(ResTarget);
3027                                         $$->name = $1;
3028                                         $$->indirection = $2;
3029                                         $$->val = (Node *)$4;
3030                                 }
3031                 | attr opt_indirection
3032                                 {
3033                                         $$ = makeNode(ResTarget);
3034                                         $$->name = NULL;
3035                                         $$->indirection = $2;
3036                                         $$->val = (Node *)$1;
3037                                 }
3038                 | relation_name '.' '*'
3039                                 {
3040                                         Attr *att = makeNode(Attr);
3041                                         att->relname = $1;
3042                                         att->paramNo = NULL;
3043                                         att->attrs = lcons(makeString("*"), NIL);
3044                                         att->indirection = NIL;
3045                                         $$ = makeNode(ResTarget);
3046                                         $$->name = NULL;
3047                                         $$->indirection = NULL;
3048                                         $$->val = (Node *)att;
3049                                 }
3050                 ;
3051
3052 /*
3053 ** target list for select.
3054 ** should get rid of the other but is still needed by the defunct retrieve into
3055 ** and update (uses a subset)
3056 */
3057 res_target_list2: res_target_list2 ',' res_target_el2
3058                                 {       $$ = lappend($1, $3);  }
3059                 | res_target_el2
3060                                 {       $$ = lcons($1, NIL);  }
3061                 ;
3062
3063 /* AS is not optional because shift/red conflict with unary ops */
3064 res_target_el2: a_expr_or_null AS ColId
3065                                 {
3066                                         $$ = makeNode(ResTarget);
3067                                         $$->name = $3;
3068                                         $$->indirection = NULL;
3069                                         $$->val = (Node *)$1;
3070                                 }
3071                 | a_expr_or_null
3072                                 {
3073                                         $$ = makeNode(ResTarget);
3074                                         $$->name = NULL;
3075                                         $$->indirection = NULL;
3076                                         $$->val = (Node *)$1;
3077                                 }
3078                 | relation_name '.' '*'
3079                                 {
3080                                         Attr *att = makeNode(Attr);
3081                                         att->relname = $1;
3082                                         att->paramNo = NULL;
3083                                         att->attrs = lcons(makeString("*"), NIL);
3084                                         att->indirection = NIL;
3085                                         $$ = makeNode(ResTarget);
3086                                         $$->name = NULL;
3087                                         $$->indirection = NULL;
3088                                         $$->val = (Node *)att;
3089                                 }
3090                 | '*'
3091                                 {
3092                                         Attr *att = makeNode(Attr);
3093                                         att->relname = "*";
3094                                         att->paramNo = NULL;
3095                                         att->attrs = NULL;
3096                                         att->indirection = NIL;
3097                                         $$ = makeNode(ResTarget);
3098                                         $$->name = NULL;
3099                                         $$->indirection = NULL;
3100                                         $$->val = (Node *)att;
3101                                 }
3102                 ;
3103
3104 opt_id:  Id                                                                             { $$ = $1; }
3105                 | /* EMPTY */                                                   { $$ = NULL; }
3106                 ;
3107
3108 relation_name:  SpecialRuleRelation
3109                                 {
3110                                         $$ = $1;
3111                                         strNcpy(saved_relname, $1, NAMEDATALEN-1);
3112                                 }
3113                 | ColId
3114                                 {
3115                                         /* disallow refs to magic system tables */
3116                                         if (strcmp(LogRelationName, $1) == 0
3117                                            || strcmp(VariableRelationName, $1) == 0
3118                                            || strcmp(TimeRelationName, $1) == 0
3119                                            || strcmp(MagicRelationName, $1) == 0)
3120                                                 elog(WARN,"%s cannot be accessed by users",$1);
3121                                         else
3122                                                 $$ = $1;
3123                                         strNcpy(saved_relname, $1, NAMEDATALEN-1);
3124                                 }
3125                 ;
3126
3127 database_name:                  Id                              { $$ = $1; };
3128 access_method:                  Id                              { $$ = $1; };
3129 attr_name:                              ColId                   { $$ = $1; };
3130 class:                                  Id                              { $$ = $1; };
3131 index_name:                             Id                              { $$ = $1; };
3132
3133 name:  Id                                                               { $$ = $1; }
3134                 | TIME                                                  { $$ = xlateSqlType("time"); }
3135                 ;
3136
3137 date:                                   Sconst                  { $$ = $1; };
3138 file_name:                              Sconst                  { $$ = $1; };
3139 recipe_name:                    Id                              { $$ = $1; };
3140
3141 AexprConst:  Iconst
3142                                 {
3143                                         A_Const *n = makeNode(A_Const);
3144                                         n->val.type = T_Integer;
3145                                         n->val.val.ival = $1;
3146                                         $$ = (Node *)n;
3147                                 }
3148                 | FCONST
3149                                 {
3150                                         A_Const *n = makeNode(A_Const);
3151                                         n->val.type = T_Float;
3152                                         n->val.val.dval = $1;
3153                                         $$ = (Node *)n;
3154                                 }
3155                 | Sconst
3156                                 {
3157                                         A_Const *n = makeNode(A_Const);
3158                                         n->val.type = T_String;
3159                                         n->val.val.str = $1;
3160                                         $$ = (Node *)n;
3161                                 }
3162                 | ParamNo
3163                                 {       $$ = (Node *)$1;  }
3164                 ;
3165
3166 ParamNo:  PARAM
3167                                 {
3168                                         $$ = makeNode(ParamNo);
3169                                         $$->number = $1;
3170                                 }
3171                 ;
3172
3173 NumConst:  Iconst                                               { $$ = makeInteger($1); }
3174                 |  FCONST                                               { $$ = makeFloat($1); }
3175                 ;
3176
3177 Iconst:  ICONST                                                 { $$ = $1; };
3178 Sconst:  SCONST                                                 { $$ = $1; };
3179
3180 Id:  IDENT                                                              { $$ = $1; };
3181
3182 ColId:  Id                                                              { $$ = $1; }
3183                 | DateTime                                              { $$ = $1; }
3184                 ;
3185
3186 SpecialRuleRelation:  CURRENT
3187                                 {
3188                                         if (QueryIsRule)
3189                                                 $$ = "*CURRENT*";
3190                                         else
3191                                                 elog(WARN,"CURRENT used in non-rule query",NULL);
3192                                 }
3193                 | NEW
3194                                 {
3195                                         if (QueryIsRule)
3196                                                 $$ = "*NEW*";
3197                                         else
3198                                                 elog(WARN,"NEW used in non-rule query",NULL);
3199                                 }
3200                 ;
3201
3202 Type:   P_TYPE;
3203 Pnull:  PNULL;
3204
3205
3206 %%
3207
3208 static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr)
3209 {
3210         A_Expr *a = makeNode(A_Expr);
3211         a->oper = oper;
3212         a->opname = opname;
3213         a->lexpr = lexpr;
3214         a->rexpr = rexpr;
3215         return (Node *)a;
3216 }
3217
3218 /* xlateSqlType()
3219  * Convert alternate type names to internal Postgres types.
3220  * Do not convert "float", since that is handled elsewhere
3221  *  for FLOAT(p) syntax.
3222  */
3223 static char *
3224 xlateSqlType(char *name)
3225 {
3226         if (!strcasecmp(name,"int") ||
3227                 !strcasecmp(name,"integer"))
3228                 return "int4"; /* strdup("int4") --   strdup leaks memory here */
3229         else if (!strcasecmp(name, "smallint"))
3230                 return "int2";
3231         else if (!strcasecmp(name, "real"))
3232                 return "float8";
3233         else if (!strcasecmp(name, "interval"))
3234                 return "timespan";
3235         else
3236                 return name;
3237 }
3238
3239 void parser_init(Oid *typev, int nargs)
3240 {
3241         QueryIsRule = FALSE;
3242         saved_relname[0]= '\0';
3243         saved_In_Expr = NULL;
3244
3245         param_type_init(typev, nargs);
3246 }
3247
3248 /* FlattenStringList()
3249  * Traverse list of string nodes and convert to a single string.
3250  * Used for reconstructing string form of complex expressions.
3251  *
3252  * Allocate at least one byte for terminator.
3253  */
3254 static char *
3255 FlattenStringList(List *list)
3256 {
3257         List *l;
3258         Value *v;
3259         char *s;
3260         char *sp;
3261         int nlist, len = 0;
3262
3263         nlist = length(list);
3264 #ifdef PARSEDEBUG
3265 printf( "list has %d elements\n", nlist);
3266 #endif
3267         l = list;
3268         while(l != NIL) {
3269                 v = (Value *)lfirst(l);
3270                 sp = v->val.str;
3271                 l = lnext(l);
3272 #ifdef PARSEDEBUG
3273 printf( "sp is x%8p; length of %s is %d\n", sp, sp, strlen(sp));
3274 #endif
3275                 len += strlen(sp);
3276         };
3277         len += nlist;
3278
3279         s = (char*) palloc(len+1);
3280         *s = '\0';
3281
3282         l = list;
3283         while(l != NIL) {
3284                 v = (Value *)lfirst(l);
3285                 sp = v->val.str;
3286                 l = lnext(l);
3287 #ifdef PARSEDEBUG
3288 printf( "length of %s is %d\n", sp, strlen(sp));
3289 #endif
3290                 strcat(s,sp);
3291                 if (l != NIL) strcat(s," ");
3292         };
3293         *(s+len) = '\0';
3294
3295 #ifdef PARSEDEBUG
3296 printf( "flattened string is \"%s\"\n", s);
3297 #endif
3298
3299         return(s);
3300 } /* FlattenStringList() */
3301
3302 /* makeConstantList()
3303  * Convert constant value node into string node.
3304  */
3305 static List *
3306 makeConstantList( A_Const *n)
3307 {
3308         char *defval = NULL;
3309 #ifdef PARSEDEBUG
3310 printf( "in AexprConst\n");
3311 #endif
3312         if (nodeTag(n) != T_A_Const) {
3313                 elog(WARN,"Cannot handle non-constant parameter",NULL);
3314
3315         } else if (n->val.type == T_Float) {
3316 #ifdef PARSEDEBUG
3317 printf( "AexprConst float is %f\n", n->val.val.dval);
3318 #endif
3319                 defval = (char*) palloc(20+1);
3320                 sprintf( defval, "%g", n->val.val.dval);
3321
3322         } else if (n->val.type == T_Integer) {
3323 #ifdef PARSEDEBUG
3324 printf( "AexprConst integer is %ld\n", n->val.val.ival);
3325 #endif
3326                 defval = (char*) palloc(20+1);
3327                 sprintf( defval, "%ld", n->val.val.ival);
3328
3329         } else if (n->val.type == T_String) {
3330
3331 #ifdef PARSEDEBUG
3332 printf( "AexprConst string is \"%s\"\n", n->val.val.str);
3333 #endif
3334
3335                 defval = (char*) palloc(strlen( ((A_Const *) n)->val.val.str) + 3);
3336                 strcpy( defval, "'");
3337                 strcat( defval, ((A_Const *) n)->val.val.str);
3338                 strcat( defval, "'");
3339
3340         } else {
3341                 elog(WARN,"Internal error: cannot encode node",NULL);
3342         };
3343
3344 #ifdef PARSEDEBUG
3345 printf( "AexprConst argument is \"%s\"\n", defval);
3346 #endif
3347
3348         return( lcons( makeString(defval), NIL));
3349 } /* makeConstantList() */