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