]> granicus.if.org Git - postgresql/blob - src/backend/parser/gram.y
I started adding the Having Clause and it works quite fine for
[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 2.8 1998/03/30 16:36:35 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 "parser/parse_type.h"
43 #include "utils/acl.h"
44 #include "utils/palloc.h"
45 #include "catalog/catname.h"
46 #include "utils/elog.h"
47 #include "access/xact.h"
48
49 static char saved_relname[NAMEDATALEN];  /* need this for complex attributes */
50 static bool QueryIsRule = FALSE;
51 static List *saved_In_Expr = NIL;
52 static Oid      *param_type_info;
53 static int      pfunc_num_args;
54 extern List *parsetree;
55
56
57 /*
58  * If you need access to certain yacc-generated variables and find that
59  * they're static by default, uncomment the next line.  (this is not a
60  * problem, yet.)
61  */
62 /*#define __YYSCLASS*/
63
64 static char *xlateSqlFunc(char *);
65 static char *xlateSqlType(char *);
66 static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
67 static Node *makeRowExpr(char *opr, List *largs, List *rargs);
68 void mapTargetColumns(List *source, List *target);
69 static List *makeConstantList( A_Const *node);
70 static char *FlattenStringList(List *list);
71 static char *fmtId(char *rawid);
72 static Node *makeIndexable(char *opname, Node *lexpr, Node *rexpr);
73 static void param_type_init(Oid *typev, int nargs);
74
75 Oid     param_type(int t); /* used in parse_expr.c */
76
77 /* old versions of flex define this as a macro */
78 #if defined(yywrap)
79 #undef yywrap
80 #endif /* yywrap */
81 %}
82
83
84 %union
85 {
86         double                          dval;
87         int                                     ival;
88         char                            chr;
89         char                            *str;
90         bool                            boolean;
91         bool*                           pboolean;       /* for pg_shadow privileges */
92         List                            *list;
93         Node                            *node;
94         Value                           *value;
95
96         Attr                            *attr;
97
98         TypeName                        *typnam;
99         DefElem                         *defelt;
100         ParamString                     *param;
101         SortGroupBy                     *sortgroupby;
102         IndexElem                       *ielem;
103         RangeVar                        *range;
104         RelExpr                         *relexp;
105         A_Indices                       *aind;
106         ResTarget                       *target;
107         ParamNo                         *paramno;
108
109         VersionStmt                     *vstmt;
110         DefineStmt                      *dstmt;
111         RuleStmt                        *rstmt;
112         InsertStmt                      *astmt;
113 }
114
115 %type <node>    stmt,
116                 AddAttrStmt, ClosePortalStmt,
117                 CopyStmt, CreateStmt, CreateAsStmt, CreateSeqStmt, DefineStmt, DestroyStmt,
118                 ExtendStmt, FetchStmt,  GrantStmt, CreateTrigStmt, DropTrigStmt,
119                 CreatePLangStmt, DropPLangStmt,
120                 IndexStmt, ListenStmt, LockStmt, OptimizableStmt,
121                 ProcedureStmt,  RecipeStmt, RemoveAggrStmt, RemoveOperStmt,
122                 RemoveFuncStmt, RemoveStmt,
123                 RenameStmt, RevokeStmt, RuleStmt, TransactionStmt, ViewStmt, LoadStmt,
124                 CreatedbStmt, DestroydbStmt, VacuumStmt, CursorStmt, SubSelect,
125                 UpdateStmt, InsertStmt, SelectStmt, NotifyStmt, DeleteStmt, ClusterStmt,
126                 ExplainStmt, VariableSetStmt, VariableShowStmt, VariableResetStmt,
127                 CreateUserStmt, AlterUserStmt, DropUserStmt
128
129 %type <str>             opt_database, location
130
131 %type <pboolean> user_createdb_clause, user_createuser_clause
132 %type <str>   user_passwd_clause
133 %type <str>   user_valid_clause
134 %type <list>  user_group_list, user_group_clause
135
136 %type <str>             join_expr, join_outer, join_spec
137 %type <boolean> TriggerActionTime, TriggerForSpec, PLangTrusted
138
139 %type <str>             TriggerEvents, TriggerFuncArg
140
141 %type <str>             relation_name, copy_file_name, copy_delimiter, def_name,
142                 database_name, access_method_clause, access_method, attr_name,
143                 class, index_name, name, func_name, file_name, recipe_name, aggr_argtype
144
145 %type <str>             opt_id, opt_portal_name,
146                 all_Op, MathOp, opt_name, opt_unique,
147                 result, OptUseOp, opt_class, SpecialRuleRelation
148
149 %type <str>             privileges, operation_commalist, grantee
150 %type <chr>             operation, TriggerOneEvent
151
152 %type <list>    stmtblock, stmtmulti,
153                 relation_name_list, OptTableElementList,
154                 OptInherit, definition,
155                 opt_with, func_args, func_args_list,
156                 oper_argtypes, OptStmtList, OptStmtBlock, OptStmtMulti,
157                 opt_column_list, columnList, opt_va_list, va_list,
158                 sort_clause, sortby_list, index_params, index_list, name_list,
159                 from_clause, from_list, opt_array_bounds, nest_array_bounds,
160                 expr_list, attrs, res_target_list, res_target_list2,
161                 def_list, opt_indirection, group_clause, groupby_list, TriggerFuncArgs
162
163 %type <node>    func_return
164 %type <boolean> set_opt
165
166 %type <boolean> TriggerForOpt, TriggerForType
167
168 %type <list>    union_clause, select_list
169 %type <list>    join_list
170 %type <sortgroupby>
171                                 join_using
172 %type <boolean> opt_union
173 %type <boolean> opt_table
174
175 %type <node>    position_expr
176 %type <list>    extract_list, position_list
177 %type <list>    substr_list, substr_from, substr_for, trim_list
178 %type <list>    opt_interval
179
180 %type <boolean> opt_inh_star, opt_binary, opt_instead, opt_with_copy,
181                                 index_opt_unique, opt_verbose, opt_analyze
182
183 %type <ival>    copy_dirn, def_type, opt_direction, remove_type,
184                                 opt_column, event
185
186 %type <ival>    fetch_how_many
187
188 %type <list>    OptSeqList
189 %type <defelt>  OptSeqElem
190
191 %type <dstmt>   def_rest
192 %type <astmt>   insert_rest
193
194 %type <node>    OptTableElement, ConstraintElem
195 %type <node>    columnDef, alter_clause
196 %type <defelt>  def_elem
197 %type <node>    def_arg, columnElem, where_clause,
198                                 a_expr, a_expr_or_null, b_expr, AexprConst,
199                                 in_expr, in_expr_nodes, not_in_expr, not_in_expr_nodes,
200                                 having_clause
201 %type <list>    row_descriptor, row_list
202 %type <node>    row_expr
203 %type <list>    OptCreateAs, CreateAsList
204 %type <node>    CreateAsElement
205 %type <value>   NumConst
206 %type <value>   IntegerOnly
207 %type <attr>    event_object, attr
208 %type <sortgroupby>             groupby
209 %type <sortgroupby>             sortby
210 %type <ielem>   index_elem, func_index
211 %type <range>   from_val
212 %type <relexp>  relation_expr
213 %type <target>  res_target_el, res_target_el2
214 %type <paramno> ParamNo
215
216 %type <typnam>  Typename, opt_type, Array, Generic, Character, Datetime, Numeric
217 %type <str>             generic, numeric, character, datetime
218 %type <str>             opt_charset, opt_collate
219 %type <str>             opt_float, opt_numeric, opt_decimal
220 %type <boolean> opt_varying, opt_timezone
221
222 %type <ival>    Iconst
223 %type <str>             Sconst
224 %type <str>             UserId, var_value, zone_value
225 %type <str>             ColId, ColLabel
226 %type <str>             TypeId
227
228 %type <node>    TableConstraint
229 %type <list>    constraint_list, constraint_expr
230 %type <list>    default_list, default_expr
231 %type <list>    ColQualList, ColQualifier
232 %type <node>    ColConstraint, ColConstraintElem
233 %type <list>    key_actions, key_action
234 %type <str>             key_match, key_reference
235
236 /*
237  * If you make any token changes, remember to:
238  *              - use "yacc -d" and update parse.h
239  *              - update the keyword table in parser/keywords.c
240  */
241
242 /* Reserved word tokens
243  * SQL92 syntax has many type-specific constructs.
244  * So, go ahead and make these types reserved words,
245  *  and call-out the syntax explicitly.
246  * This gets annoying when trying to also retain Postgres' nice
247  *  type-extensible features, but we don't really have a choice.
248  * - thomas 1997-10-11
249  */
250
251 /* Keywords (in SQL92 reserved words) */
252 %token  ACTION, ADD, ALL, ALTER, AND, ANY AS, ASC,
253                 BEGIN_TRANS, BETWEEN, BOTH, BY,
254                 CASCADE, CAST, CHAR, CHARACTER, CHECK, CLOSE, COLLATE, COLUMN, COMMIT, 
255                 CONSTRAINT, CREATE, CROSS, CURRENT, CURRENT_DATE, CURRENT_TIME, 
256                 CURRENT_TIMESTAMP, CURRENT_USER, CURSOR,
257                 DAY_P, DECIMAL, DECLARE, DEFAULT, DELETE, DESC, DISTINCT, DOUBLE, DROP,
258                 END_TRANS, EXECUTE, EXISTS, EXTRACT,
259                 FETCH, FLOAT, FOR, FOREIGN, FROM, FULL,
260                 GRANT, GROUP, HAVING, HOUR_P,
261                 IN, INNER_P, INSERT, INTERVAL, INTO, IS,
262                 JOIN, KEY, LANGUAGE, LEADING, LEFT, LIKE, LOCAL,
263                 MATCH, MINUTE_P, MONTH_P,
264                 NATIONAL, NATURAL, NCHAR, NO, NOT, NOTIFY, NULL_P, NUMERIC,
265                 ON, OPTION, OR, ORDER, OUTER_P,
266                 PARTIAL, POSITION, PRECISION, PRIMARY, PRIVILEGES, PROCEDURE, PUBLIC,
267                 REFERENCES, REVOKE, RIGHT, ROLLBACK,
268                 SECOND_P, SELECT, SET, SUBSTRING,
269                 TABLE, TIME, TIMESTAMP, TO, TRAILING, TRANSACTION, TRIM,
270                 UNION, UNIQUE, UPDATE, USING,
271                 VALUES, VARCHAR, VARYING, VIEW,
272                 WHERE, WITH, WORK, YEAR_P, ZONE
273
274 /* Keywords (in SQL3 reserved words) */
275 %token  FALSE_P, TRIGGER, TRUE_P
276
277 /* Keywords (in SQL92 non-reserved words) */
278 %token  TYPE_P
279
280 /* Keywords for Postgres support (not in SQL92 reserved words) */
281 %token  ABORT_TRANS, AFTER, AGGREGATE, ANALYZE,
282                 BACKWARD, BEFORE, BINARY, CACHE, CLUSTER, COPY, CYCLE,
283                 DATABASE, DELIMITERS, DO, EACH, EXPLAIN, EXTEND,
284                 FORWARD, FUNCTION, HANDLER,
285                 INCREMENT, INDEX, INHERITS, INSTEAD, ISNULL,
286                 LANCOMPILER, LISTEN, LOAD, LOCK_P, LOCATION, MAXVALUE, MINVALUE, MOVE,
287                 NEW, NONE, NOTHING, NOTNULL, OIDS, OPERATOR, PROCEDURAL,
288                 RECIPE, RENAME, RESET, RETURNS, ROW, RULE,
289                 SEQUENCE, SETOF, SHOW, START, STATEMENT, STDIN, STDOUT, TRUSTED, 
290                 VACUUM, VERBOSE, VERSION
291
292 /* Keywords (obsolete; retain through next version for parser - thomas 1997-12-04) */
293 %token  ARCHIVE
294
295 /*
296  * Tokens for pg_passwd support.  The CREATEDB and CREATEUSER tokens should go away
297  * when some sort of pg_privileges relation is introduced.
298  *
299  *                                    Todd A. Brandys
300  */
301 %token  USER, PASSWORD, CREATEDB, NOCREATEDB, CREATEUSER, NOCREATEUSER, VALID, UNTIL
302
303 /* Special keywords, not in the query language - see the "lex" file */
304 %token <str>    IDENT, SCONST, Op
305 %token <ival>   ICONST, PARAM
306 %token <dval>   FCONST
307
308 /* these are not real. they are here so that they get generated as #define's*/
309 %token                  OP
310
311 /* precedence */
312 %left           OR
313 %left           AND
314 %right          NOT
315 %right          '='
316 %nonassoc       '<' '>'
317 %nonassoc       LIKE
318 %nonassoc       BETWEEN
319 %nonassoc       IN
320 %nonassoc       Op                              /* multi-character ops and user-defined operators */
321 %nonassoc       NOTNULL
322 %nonassoc       ISNULL
323 %nonassoc       IS
324 %left           '+' '-'
325 %left           '*' '/'
326 %left           '|'                             /* this is the relation union op, not logical or */
327 /* Unary Operators */
328 %right          ':'
329 %left           ';'                             /* end of statement or natural log */
330 %right          UMINUS
331 %left           '.'
332 %left           '[' ']'
333 %nonassoc       TYPECAST
334 %nonassoc       REDUCE
335 %left           UNION
336 %%
337
338 stmtblock:  stmtmulti
339                                 { parsetree = $1; }
340                 | stmt
341                                 { parsetree = lcons($1,NIL); }
342                 ;
343
344 stmtmulti:  stmtmulti stmt ';'
345                                 { $$ = lappend($1, $2); }
346                 | stmtmulti stmt
347                                 { $$ = lappend($1, $2); }
348                 | stmt ';'
349                                 { $$ = lcons($1,NIL); }
350                 ;
351
352 stmt :    AddAttrStmt
353                 | AlterUserStmt
354                 | ClosePortalStmt
355                 | CopyStmt
356                 | CreateStmt
357                 | CreateAsStmt
358                 | CreateSeqStmt
359                 | CreatePLangStmt
360                 | CreateTrigStmt
361                 | CreateUserStmt
362                 | ClusterStmt
363                 | DefineStmt
364                 | DestroyStmt
365                 | DropPLangStmt
366                 | DropTrigStmt
367                 | DropUserStmt
368                 | ExtendStmt
369                 | ExplainStmt
370                 | FetchStmt
371                 | GrantStmt
372                 | IndexStmt
373                 | ListenStmt
374                 | LockStmt
375                 | ProcedureStmt
376                 | RecipeStmt
377                 | RemoveAggrStmt
378                 | RemoveOperStmt
379                 | RemoveFuncStmt
380                 | RemoveStmt
381                 | RenameStmt
382                 | RevokeStmt
383                 | OptimizableStmt
384                 | RuleStmt
385                 | TransactionStmt
386                 | ViewStmt
387                 | LoadStmt
388                 | CreatedbStmt
389                 | DestroydbStmt
390                 | VacuumStmt
391                 | VariableSetStmt
392                 | VariableShowStmt
393                 | VariableResetStmt
394                 ;
395
396 /*****************************************************************************
397  *
398  * Create a new Postgres DBMS user
399  *
400  *
401  *****************************************************************************/
402
403 CreateUserStmt:  CREATE USER UserId user_passwd_clause user_createdb_clause
404                         user_createuser_clause user_group_clause user_valid_clause
405                                 {
406                                         CreateUserStmt *n = makeNode(CreateUserStmt);
407                                         n->user = $3;
408                                         n->password = $4;
409                                         n->createdb = $5;
410                                         n->createuser = $6;
411                                         n->groupElts = $7;
412                                         n->validUntil = $8;
413                                         $$ = (Node *)n;
414                                 }
415                 ;
416
417 /*****************************************************************************
418  *
419  * Alter a postresql DBMS user
420  *
421  *
422  *****************************************************************************/
423
424 AlterUserStmt:  ALTER USER UserId user_passwd_clause user_createdb_clause
425                         user_createuser_clause user_group_clause user_valid_clause
426                                 {
427                                         AlterUserStmt *n = makeNode(AlterUserStmt);
428                                         n->user = $3;
429                                         n->password = $4;
430                                         n->createdb = $5;
431                                         n->createuser = $6;
432                                         n->groupElts = $7;
433                                         n->validUntil = $8;
434                                         $$ = (Node *)n;
435                                 }
436                 ;
437
438 /*****************************************************************************
439  *
440  * Drop a postresql DBMS user
441  *
442  *
443  *****************************************************************************/
444
445 DropUserStmt:  DROP USER UserId
446                                 {
447                                         DropUserStmt *n = makeNode(DropUserStmt);
448                                         n->user = $3;
449                                         $$ = (Node *)n;
450                                 }
451                 ;
452
453 user_passwd_clause:  WITH PASSWORD UserId               { $$ = $3; }
454                         | /*EMPTY*/                                                     { $$ = NULL; }
455                 ;
456
457 user_createdb_clause:  CREATEDB
458                                 {
459                                         bool*  b;
460                                         $$ = (b = (bool*)palloc(sizeof(bool)));
461                                         *b = true;
462                                 }
463                         | NOCREATEDB
464                                 {
465                                         bool*  b;
466                                         $$ = (b = (bool*)palloc(sizeof(bool)));
467                                         *b = false;
468                                 }
469                         | /*EMPTY*/                                                     { $$ = NULL; }
470                 ;
471
472 user_createuser_clause:  CREATEUSER
473                                 {
474                                         bool*  b;
475                                         $$ = (b = (bool*)palloc(sizeof(bool)));
476                                         *b = true;
477                                 }
478                         | NOCREATEUSER
479                                 {
480                                         bool*  b;
481                                         $$ = (b = (bool*)palloc(sizeof(bool)));
482                                         *b = false;
483                                 }
484                         | /*EMPTY*/                                                     { $$ = NULL; }
485                 ;
486
487 user_group_list:  user_group_list ',' UserId
488                                 {
489                                         $$ = lcons((void*)makeString($3), $1);
490                                 }
491                         | UserId
492                                 {
493                                         $$ = lcons((void*)makeString($1), NIL);
494                                 }
495                 ;
496
497 user_group_clause:  IN GROUP user_group_list    { $$ = $3; }
498                         | /*EMPTY*/                                                     { $$ = NULL; }
499                 ;
500
501 user_valid_clause:  VALID UNTIL SCONST                  { $$ = $3; }
502                         | /*EMPTY*/                                                     { $$ = NULL; }
503                 ;
504
505 /*****************************************************************************
506  *
507  * Set PG internal variable
508  *        SET name TO 'var_value'
509  * Include SQL92 syntax (thomas 1997-10-22):
510  *    SET TIME ZONE 'var_value'
511  *
512  *****************************************************************************/
513
514 VariableSetStmt:  SET ColId TO var_value
515                                 {
516                                         VariableSetStmt *n = makeNode(VariableSetStmt);
517                                         n->name  = $2;
518                                         n->value = $4;
519                                         $$ = (Node *) n;
520                                 }
521                 | SET ColId '=' var_value
522                                 {
523                                         VariableSetStmt *n = makeNode(VariableSetStmt);
524                                         n->name  = $2;
525                                         n->value = $4;
526                                         $$ = (Node *) n;
527                                 }
528                 | SET TIME ZONE zone_value
529                                 {
530                                         VariableSetStmt *n = makeNode(VariableSetStmt);
531                                         n->name  = "timezone";
532                                         n->value = $4;
533                                         $$ = (Node *) n;
534                                 }
535                 ;
536
537 var_value:  Sconst                      { $$ = $1; }
538                 | DEFAULT                       { $$ = NULL; }
539                 ;
540
541 zone_value:  Sconst                     { $$ = $1; }
542                 | DEFAULT                       { $$ = NULL; }
543                 | LOCAL                         { $$ = "default"; }
544                 ;
545
546 VariableShowStmt:  SHOW ColId
547                                 {
548                                         VariableShowStmt *n = makeNode(VariableShowStmt);
549                                         n->name  = $2;
550                                         $$ = (Node *) n;
551                                 }
552                 | SHOW TIME ZONE
553                                 {
554                                         VariableShowStmt *n = makeNode(VariableShowStmt);
555                                         n->name  = "timezone";
556                                         $$ = (Node *) n;
557                                 }
558                 ;
559
560 VariableResetStmt:      RESET ColId
561                                 {
562                                         VariableResetStmt *n = makeNode(VariableResetStmt);
563                                         n->name  = $2;
564                                         $$ = (Node *) n;
565                                 }
566                 | RESET TIME ZONE
567                                 {
568                                         VariableResetStmt *n = makeNode(VariableResetStmt);
569                                         n->name  = "timezone";
570                                         $$ = (Node *) n;
571                                 }
572                 ;
573
574
575 /*****************************************************************************
576  *
577  *              QUERY :
578  *                              addattr ( attr1 = type1 .. attrn = typen ) to <relname> [*]
579  *
580  *****************************************************************************/
581
582 AddAttrStmt:  ALTER TABLE relation_name opt_inh_star alter_clause
583                                 {
584                                         AddAttrStmt *n = makeNode(AddAttrStmt);
585                                         n->relname = $3;
586                                         n->inh = $4;
587                                         n->colDef = $5;
588                                         $$ = (Node *)n;
589                                 }
590                 ;
591
592 alter_clause:  ADD opt_column columnDef
593                                 {
594                                         $$ = $3;
595                                 }
596                         | ADD '(' OptTableElementList ')'
597                                 {
598                                         Node *lp = lfirst($3);
599
600                                         if (length($3) != 1)
601                                                 elog(ERROR,"ALTER TABLE/ADD() allows one column only");
602                                         $$ = lp;
603                                 }
604                         | DROP opt_column ColId
605                                 {       elog(ERROR,"ALTER TABLE/DROP COLUMN not yet implemented"); }
606                         | ALTER opt_column ColId SET DEFAULT default_expr
607                                 {       elog(ERROR,"ALTER TABLE/ALTER COLUMN/SET DEFAULT not yet implemented"); }
608                         | ALTER opt_column ColId DROP DEFAULT
609                                 {       elog(ERROR,"ALTER TABLE/ALTER COLUMN/DROP DEFAULT not yet implemented"); }
610                         | ADD ConstraintElem
611                                 {       elog(ERROR,"ALTER TABLE/ADD CONSTRAINT not yet implemented"); }
612                 ;
613
614
615 /*****************************************************************************
616  *
617  *              QUERY :
618  *                              close <optname>
619  *
620  *****************************************************************************/
621
622 ClosePortalStmt:  CLOSE opt_id
623                                 {
624                                         ClosePortalStmt *n = makeNode(ClosePortalStmt);
625                                         n->portalname = $2;
626                                         $$ = (Node *)n;
627                                 }
628                 ;
629
630
631 /*****************************************************************************
632  *
633  *              QUERY :
634  *                              COPY [BINARY] <relname> FROM/TO
635  *                              [USING DELIMITERS <delimiter>]
636  *
637  *****************************************************************************/
638
639 CopyStmt:  COPY opt_binary relation_name opt_with_copy copy_dirn copy_file_name copy_delimiter
640                                 {
641                                         CopyStmt *n = makeNode(CopyStmt);
642                                         n->binary = $2;
643                                         n->relname = $3;
644                                         n->oids = $4;
645                                         n->direction = $5;
646                                         n->filename = $6;
647                                         n->delimiter = $7;
648                                         $$ = (Node *)n;
649                                 }
650                 ;
651
652 copy_dirn:      TO
653                                 { $$ = TO; }
654                 | FROM
655                                 { $$ = FROM; }
656                 ;
657
658 /*
659  * copy_file_name NULL indicates stdio is used. Whether stdin or stdout is
660  * used depends on the direction. (It really doesn't make sense to copy from
661  * stdout. We silently correct the "typo".               - AY 9/94
662  */
663 copy_file_name:  Sconst                                                 { $$ = $1; }
664                 | STDIN                                                                 { $$ = NULL; }
665                 | STDOUT                                                                { $$ = NULL; }
666                 ;
667
668 opt_binary:  BINARY                                                             { $$ = TRUE; }
669                 | /*EMPTY*/                                                             { $$ = FALSE; }
670                 ;
671
672 opt_with_copy:  WITH OIDS                                               { $$ = TRUE; }
673                 | /*EMPTY*/                                                             { $$ = FALSE; }
674                 ;
675
676 /*
677  * the default copy delimiter is tab but the user can configure it
678  */
679 copy_delimiter:  USING DELIMITERS Sconst                { $$ = $3; }
680                 | /*EMPTY*/                                                             { $$ = "\t"; }
681                 ;
682
683
684 /*****************************************************************************
685  *
686  *              QUERY :
687  *                              CREATE relname
688  *
689  *****************************************************************************/
690
691 CreateStmt:  CREATE TABLE relation_name '(' OptTableElementList ')'
692                                 OptInherit OptArchiveType
693                                 {
694                                         CreateStmt *n = makeNode(CreateStmt);
695                                         n->relname = $3;
696                                         n->tableElts = $5;
697                                         n->inhRelnames = $7;
698                                         n->constraints = NIL;
699                                         $$ = (Node *)n;
700                                 }
701                 ;
702
703 OptTableElementList:  OptTableElementList ',' OptTableElement
704                                                                                                 { $$ = lappend($1, $3); }
705                         | OptTableElement                                       { $$ = lcons($1, NIL); }
706                         | /*EMPTY*/                                                     { $$ = NULL; }
707                 ;
708
709 OptTableElement:  columnDef                                             { $$ = $1; }
710                         | TableConstraint                                       { $$ = $1; }
711                 ;
712
713 columnDef:  ColId Typename ColQualifier
714                                 {
715                                         ColumnDef *n = makeNode(ColumnDef);
716                                         n->colname = $1;
717                                         n->typename = $2;
718                                         n->defval = NULL;
719                                         n->is_not_null = FALSE;
720                                         n->constraints = $3;
721                                         $$ = (Node *)n;
722                                 }
723                 ;
724
725 ColQualifier:  ColQualList                                              { $$ = $1; }
726                         | /*EMPTY*/                                                     { $$ = NULL; }
727                 ;
728
729 ColQualList:  ColQualList ColConstraint                 { $$ = lappend($1,$2); }
730                         | ColConstraint                                         { $$ = lcons($1, NIL); }
731                 ;
732
733 ColConstraint:
734                 CONSTRAINT name ColConstraintElem
735                                 {
736                                                 Constraint *n = (Constraint *)$3;
737                                                 n->name = fmtId($2);
738                                                 $$ = $3;
739                                 }
740                 | ColConstraintElem
741                                 { $$ = $1; }
742                 ;
743
744 ColConstraintElem:  CHECK '(' constraint_expr ')'
745                                 {
746                                         Constraint *n = makeNode(Constraint);
747                                         n->contype = CONSTR_CHECK;
748                                         n->name = NULL;
749                                         n->def = FlattenStringList($3);
750                                         n->keys = NULL;
751                                         $$ = (Node *)n;
752                                 }
753                         | DEFAULT default_expr
754                                 {
755                                         Constraint *n = makeNode(Constraint);
756                                         n->contype = CONSTR_DEFAULT;
757                                         n->name = NULL;
758                                         n->def = FlattenStringList($2);
759                                         n->keys = NULL;
760                                         $$ = (Node *)n;
761                                 }
762                         | NOT NULL_P
763                                 {
764                                         Constraint *n = makeNode(Constraint);
765                                         n->contype = CONSTR_NOTNULL;
766                                         n->name = NULL;
767                                         n->def = NULL;
768                                         n->keys = NULL;
769                                         $$ = (Node *)n;
770                                 }
771                         | UNIQUE
772                                 {
773                                         Constraint *n = makeNode(Constraint);
774                                         n->contype = CONSTR_UNIQUE;
775                                         n->name = NULL;
776                                         n->def = NULL;
777                                         n->keys = NULL;
778                                         $$ = (Node *)n;
779                                 }
780                         | PRIMARY KEY
781                                 {
782                                         Constraint *n = makeNode(Constraint);
783                                         n->contype = CONSTR_PRIMARY;
784                                         n->name = NULL;
785                                         n->def = NULL;
786                                         n->keys = NULL;
787                                         $$ = (Node *)n;
788                                 }
789                         | REFERENCES ColId opt_column_list key_match key_actions
790                                 {
791                                         elog(NOTICE,"CREATE TABLE/FOREIGN KEY clause ignored; not yet implemented");
792                                         $$ = NULL;
793                                 }
794                 ;
795
796 default_list:  default_list ',' default_expr
797                                 {
798                                         $$ = lappend($1,makeString(","));
799                                         $$ = nconc($$, $3);
800                                 }
801                         | default_expr
802                                 {
803                                         $$ = $1;
804                                 }
805                 ;
806
807 default_expr:  AexprConst
808                                 {       $$ = makeConstantList((A_Const *) $1); }
809                         | NULL_P
810                                 {       $$ = lcons( makeString("NULL"), NIL); }
811                         | '-' default_expr %prec UMINUS
812                                 {       $$ = lcons( makeString( "-"), $2); }
813                         | default_expr '+' default_expr
814                                 {       $$ = nconc( $1, lcons( makeString( "+"), $3)); }
815                         | default_expr '-' default_expr
816                                 {       $$ = nconc( $1, lcons( makeString( "-"), $3)); }
817                         | default_expr '/' default_expr
818                                 {       $$ = nconc( $1, lcons( makeString( "/"), $3)); }
819                         | default_expr '*' default_expr
820                                 {       $$ = nconc( $1, lcons( makeString( "*"), $3)); }
821                         | default_expr '=' default_expr
822                                 {       elog(ERROR,"boolean expressions not supported in DEFAULT"); }
823                         | default_expr '<' default_expr
824                                 {       elog(ERROR,"boolean expressions not supported in DEFAULT"); }
825                         | default_expr '>' default_expr
826                                 {       elog(ERROR,"boolean expressions not supported in DEFAULT"); }
827                         | ':' default_expr
828                                 {       $$ = lcons( makeString( ":"), $2); }
829                         | ';' default_expr
830                                 {       $$ = lcons( makeString( ";"), $2); }
831                         | '|' default_expr
832                                 {       $$ = lcons( makeString( "|"), $2); }
833                         | default_expr TYPECAST Typename
834                                 {
835                                         $3->name = fmtId($3->name);
836                                         $$ = nconc( lcons( makeString( "CAST"), $1), makeList( makeString("AS"), $3, -1));
837                                 }
838                         | CAST '(' default_expr AS Typename ')'
839                                 {
840                                         $5->name = fmtId($5->name);
841                                         $$ = nconc( lcons( makeString( "CAST"), $3), makeList( makeString("AS"), $5, -1));
842                                 }
843                         | '(' default_expr ')'
844                                 {       $$ = lappend( lcons( makeString( "("), $2), makeString( ")")); }
845                         | func_name '(' ')'
846                                 {
847                                         $$ = makeList( makeString($1), makeString("("), -1);
848                                         $$ = lappend( $$, makeString(")"));
849                                 }
850                         | func_name '(' default_list ')'
851                                 {
852                                         $$ = makeList( makeString($1), makeString("("), -1);
853                                         $$ = nconc( $$, $3);
854                                         $$ = lappend( $$, makeString(")"));
855                                 }
856                         | default_expr Op default_expr
857                                 {
858                                         if (!strcmp("<=", $2) || !strcmp(">=", $2))
859                                                 elog(ERROR,"boolean expressions not supported in DEFAULT");
860                                         $$ = nconc( $1, lcons( makeString( $2), $3));
861                                 }
862                         | Op default_expr
863                                 {       $$ = lcons( makeString( $1), $2); }
864                         | default_expr Op
865                                 {       $$ = lappend( $1, makeString( $2)); }
866                         /* XXX - thomas 1997-10-07 v6.2 function-specific code to be changed */
867                         | CURRENT_DATE
868                                 {       $$ = lcons( makeString( "date( 'current'::datetime + '0 sec')"), NIL); }
869                         | CURRENT_TIME
870                                 {       $$ = lcons( makeString( "'now'::time"), NIL); }
871                         | CURRENT_TIME '(' Iconst ')'
872                                 {
873                                         if ($3 != 0)
874                                                 elog(NOTICE,"CURRENT_TIME(%d) precision not implemented; zero used instead",$3);
875                                         $$ = lcons( makeString( "'now'::time"), NIL);
876                                 }
877                         | CURRENT_TIMESTAMP
878                                 {       $$ = lcons( makeString( "now()"), NIL); }
879                         | CURRENT_TIMESTAMP '(' Iconst ')'
880                                 {
881                                         if ($3 != 0)
882                                                 elog(NOTICE,"CURRENT_TIMESTAMP(%d) precision not implemented; zero used instead",$3);
883                                         $$ = lcons( makeString( "now()"), NIL);
884                                 }
885                         | CURRENT_USER
886                                 {       $$ = lcons( makeString( "CURRENT_USER"), NIL); }
887                 ;
888
889 /* ConstraintElem specifies constraint syntax which is not embedded into
890  *  a column definition. ColConstraintElem specifies the embedded form.
891  * - thomas 1997-12-03
892  */
893 TableConstraint:  CONSTRAINT name ConstraintElem
894                                 {
895                                                 Constraint *n = (Constraint *)$3;
896                                                 n->name = fmtId($2);
897                                                 $$ = $3;
898                                 }
899                 | ConstraintElem
900                                 { $$ = $1; }
901                 ;
902
903 ConstraintElem:  CHECK '(' constraint_expr ')'
904                                 {
905                                         Constraint *n = makeNode(Constraint);
906                                         n->contype = CONSTR_CHECK;
907                                         n->name = NULL;
908                                         n->def = FlattenStringList($3);
909                                         $$ = (Node *)n;
910                                 }
911                 | UNIQUE '(' columnList ')'
912                                 {
913                                         Constraint *n = makeNode(Constraint);
914                                         n->contype = CONSTR_UNIQUE;
915                                         n->name = NULL;
916                                         n->def = NULL;
917                                         n->keys = $3;
918                                         $$ = (Node *)n;
919                                 }
920                 | PRIMARY KEY '(' columnList ')'
921                                 {
922                                         Constraint *n = makeNode(Constraint);
923                                         n->contype = CONSTR_PRIMARY;
924                                         n->name = NULL;
925                                         n->def = NULL;
926                                         n->keys = $4;
927                                         $$ = (Node *)n;
928                                 }
929                 | FOREIGN KEY '(' columnList ')' REFERENCES ColId opt_column_list key_match key_actions
930                                 {       elog(NOTICE,"CREATE TABLE/FOREIGN KEY clause ignored; not yet implemented"); }
931                 ;
932
933 constraint_list:  constraint_list ',' constraint_expr
934                                 {
935                                         $$ = lappend($1,makeString(","));
936                                         $$ = nconc($$, $3);
937                                 }
938                         | constraint_expr
939                                 {
940                                         $$ = $1;
941                                 }
942                 ;
943
944 constraint_expr:  AexprConst
945                                 {       $$ = makeConstantList((A_Const *) $1); }
946                         | NULL_P
947                                 {       $$ = lcons( makeString("NULL"), NIL); }
948                         | ColId
949                                 {
950                                         $$ = lcons( makeString(fmtId($1)), NIL);
951                                 }
952                         | '-' constraint_expr %prec UMINUS
953                                 {       $$ = lcons( makeString( "-"), $2); }
954                         | constraint_expr '+' constraint_expr
955                                 {       $$ = nconc( $1, lcons( makeString( "+"), $3)); }
956                         | constraint_expr '-' constraint_expr
957                                 {       $$ = nconc( $1, lcons( makeString( "-"), $3)); }
958                         | constraint_expr '/' constraint_expr
959                                 {       $$ = nconc( $1, lcons( makeString( "/"), $3)); }
960                         | constraint_expr '*' constraint_expr
961                                 {       $$ = nconc( $1, lcons( makeString( "*"), $3)); }
962                         | constraint_expr '=' constraint_expr
963                                 {       $$ = nconc( $1, lcons( makeString( "="), $3)); }
964                         | constraint_expr '<' constraint_expr
965                                 {       $$ = nconc( $1, lcons( makeString( "<"), $3)); }
966                         | constraint_expr '>' constraint_expr
967                                 {       $$ = nconc( $1, lcons( makeString( ">"), $3)); }
968                         | ':' constraint_expr
969                                 {       $$ = lcons( makeString( ":"), $2); }
970                         | ';' constraint_expr
971                                 {       $$ = lcons( makeString( ";"), $2); }
972                         | '|' constraint_expr
973                                 {       $$ = lcons( makeString( "|"), $2); }
974                         | constraint_expr TYPECAST Typename
975                                 {
976                                         $3->name = fmtId($3->name);
977                                         $$ = nconc( lcons( makeString( "CAST"), $1), makeList( makeString("AS"), $3, -1));
978                                 }
979                         | CAST '(' constraint_expr AS Typename ')'
980                                 {
981                                         $5->name = fmtId($5->name);
982                                         $$ = nconc( lcons( makeString( "CAST"), $3), makeList( makeString("AS"), $5, -1));
983                                 }
984                         | '(' constraint_expr ')'
985                                 {       $$ = lappend( lcons( makeString( "("), $2), makeString( ")")); }
986                         | func_name '(' ')'
987                                 {
988                                         $$ = makeList( makeString($1), makeString("("), -1);
989                                         $$ = lappend( $$, makeString(")"));
990                                 }
991                         | func_name '(' constraint_list ')'
992                                 {
993                                         $$ = makeList( makeString($1), makeString("("), -1);
994                                         $$ = nconc( $$, $3);
995                                         $$ = lappend( $$, makeString(")"));
996                                 }
997                         | constraint_expr Op constraint_expr
998                                 {       $$ = nconc( $1, lcons( makeString( $2), $3)); }
999                         | constraint_expr LIKE constraint_expr
1000                                 {       $$ = nconc( $1, lcons( makeString( "like"), $3)); }
1001                         | constraint_expr AND constraint_expr
1002                                 {       $$ = nconc( $1, lcons( makeString( "AND"), $3)); }
1003                         | constraint_expr OR constraint_expr
1004                                 {       $$ = nconc( $1, lcons( makeString( "OR"), $3)); }
1005                         | NOT constraint_expr
1006                                 {       $$ = lcons( makeString( "NOT"), $2); }
1007                         | Op constraint_expr
1008                                 {       $$ = lcons( makeString( $1), $2); }
1009                         | constraint_expr Op
1010                                 {       $$ = lappend( $1, makeString( $2)); }
1011                         | constraint_expr ISNULL
1012                                 {       $$ = lappend( $1, makeString( "IS NULL")); }
1013                         | constraint_expr IS NULL_P
1014                                 {       $$ = lappend( $1, makeString( "IS NULL")); }
1015                         | constraint_expr NOTNULL
1016                                 {       $$ = lappend( $1, makeString( "IS NOT NULL")); }
1017                         | constraint_expr IS NOT NULL_P
1018                                 {       $$ = lappend( $1, makeString( "IS NOT NULL")); }
1019                         | constraint_expr IS TRUE_P
1020                                 {       $$ = lappend( $1, makeString( "IS TRUE")); }
1021                         | constraint_expr IS FALSE_P
1022                                 {       $$ = lappend( $1, makeString( "IS FALSE")); }
1023                         | constraint_expr IS NOT TRUE_P
1024                                 {       $$ = lappend( $1, makeString( "IS NOT TRUE")); }
1025                         | constraint_expr IS NOT FALSE_P
1026                                 {       $$ = lappend( $1, makeString( "IS NOT FALSE")); }
1027                 ;
1028
1029 key_match:  MATCH FULL                                  { $$ = NULL; }
1030                 | MATCH PARTIAL                                 { $$ = NULL; }
1031                 | /*EMPTY*/                                             { $$ = NULL; }
1032                 ;
1033
1034 key_actions:  key_action key_action             { $$ = NIL; }
1035                 | key_action                                    { $$ = NIL; }
1036                 | /*EMPTY*/                                             { $$ = NIL; }
1037                 ;
1038
1039 key_action:  ON DELETE key_reference    { $$ = NIL; }
1040                 | ON UPDATE key_reference               { $$ = NIL; }
1041                 ;
1042
1043 key_reference:  NO ACTION                               { $$ = NULL; }
1044                 | CASCADE                                               { $$ = NULL; }
1045                 | SET DEFAULT                                   { $$ = NULL; }
1046                 | SET NULL_P                                    { $$ = NULL; }
1047                 ;
1048
1049 OptInherit:  INHERITS '(' relation_name_list ')'                { $$ = $3; }
1050                 | /*EMPTY*/                                                                             { $$ = NIL; }
1051                 ;
1052
1053 /*
1054  *      "ARCHIVE" keyword was removed in 6.3, but we keep it for now
1055  *  so people can upgrade with old pg_dump scripts. - momjian 1997-11-20(?)
1056  */
1057 OptArchiveType:  ARCHIVE '=' NONE                                               { }
1058                 | /*EMPTY*/                                                                             { }
1059                 ;
1060
1061 CreateAsStmt:  CREATE TABLE relation_name OptCreateAs AS SubSelect
1062                                 {
1063                                         SelectStmt *n = (SelectStmt *)$6;
1064                                         if ($4 != NIL)
1065                                                 mapTargetColumns($4, n->targetList);
1066                                         n->into = $3;
1067                                         $$ = (Node *)n;
1068                                 }
1069                 ;
1070
1071 OptCreateAs:  '(' CreateAsList ')'                              { $$ = $2; }
1072                         | /*EMPTY*/                                                     { $$ = NULL; }
1073                 ;
1074
1075 CreateAsList:  CreateAsList ',' CreateAsElement { $$ = lappend($1, $3); }
1076                         | CreateAsElement                                       { $$ = lcons($1, NIL); }
1077                 ;
1078
1079 CreateAsElement:  ColId
1080                                 {
1081                                         ColumnDef *n = makeNode(ColumnDef);
1082                                         n->colname = $1;
1083                                         n->typename = NULL;
1084                                         n->defval = NULL;
1085                                         n->is_not_null = FALSE;
1086                                         n->constraints = NULL;
1087                                         $$ = (Node *)n;
1088                                 }
1089                 ;
1090
1091
1092 /*****************************************************************************
1093  *
1094  *              QUERY :
1095  *                              CREATE SEQUENCE seqname
1096  *
1097  *****************************************************************************/
1098
1099 CreateSeqStmt:  CREATE SEQUENCE relation_name OptSeqList
1100                                 {
1101                                         CreateSeqStmt *n = makeNode(CreateSeqStmt);
1102                                         n->seqname = $3;
1103                                         n->options = $4;
1104                                         $$ = (Node *)n;
1105                                 }
1106                 ;
1107
1108 OptSeqList:  OptSeqList OptSeqElem
1109                                 { $$ = lappend($1, $2); }
1110                         |       { $$ = NIL; }
1111                 ;
1112
1113 OptSeqElem:  CACHE IntegerOnly
1114                                 {
1115                                         $$ = makeNode(DefElem);
1116                                         $$->defname = "cache";
1117                                         $$->arg = (Node *)$2;
1118                                 }
1119                         | CYCLE
1120                                 {
1121                                         $$ = makeNode(DefElem);
1122                                         $$->defname = "cycle";
1123                                         $$->arg = (Node *)NULL;
1124                                 }
1125                         | INCREMENT IntegerOnly
1126                                 {
1127                                         $$ = makeNode(DefElem);
1128                                         $$->defname = "increment";
1129                                         $$->arg = (Node *)$2;
1130                                 }
1131                         | MAXVALUE IntegerOnly
1132                                 {
1133                                         $$ = makeNode(DefElem);
1134                                         $$->defname = "maxvalue";
1135                                         $$->arg = (Node *)$2;
1136                                 }
1137                         | MINVALUE IntegerOnly
1138                                 {
1139                                         $$ = makeNode(DefElem);
1140                                         $$->defname = "minvalue";
1141                                         $$->arg = (Node *)$2;
1142                                 }
1143                         | START IntegerOnly
1144                                 {
1145                                         $$ = makeNode(DefElem);
1146                                         $$->defname = "start";
1147                                         $$->arg = (Node *)$2;
1148                                 }
1149                 ;
1150
1151 IntegerOnly:  Iconst
1152                                 {
1153                                         $$ = makeInteger($1);
1154                                 }
1155                         | '-' Iconst
1156                                 {
1157                                         $$ = makeInteger($2);
1158                                         $$->val.ival = - $$->val.ival;
1159                                 }
1160                 ;
1161
1162 /*****************************************************************************
1163  *
1164  *              QUERIES :
1165  *                              CREATE PROCEDURAL LANGUAGE ...
1166  *                              DROP PROCEDURAL LANGUAGE ...
1167  *
1168  *****************************************************************************/
1169
1170 CreatePLangStmt:  CREATE PLangTrusted PROCEDURAL LANGUAGE Sconst 
1171                         HANDLER def_name LANCOMPILER Sconst
1172                         {
1173                                 CreatePLangStmt *n = makeNode(CreatePLangStmt);
1174                                 n->plname = $5;
1175                                 n->plhandler = $7;
1176                                 n->plcompiler = $9;
1177                                 n->pltrusted = $2;
1178                                 $$ = (Node *)n;
1179                         }
1180                 ;
1181
1182 PLangTrusted:           TRUSTED { $$ = TRUE; }
1183                         |       { $$ = FALSE; }
1184
1185 DropPLangStmt:  DROP PROCEDURAL LANGUAGE Sconst
1186                         {
1187                                 DropPLangStmt *n = makeNode(DropPLangStmt);
1188                                 n->plname = $4;
1189                                 $$ = (Node *)n;
1190                         }
1191                 ;
1192
1193 /*****************************************************************************
1194  *
1195  *              QUERIES :
1196  *                              CREATE TRIGGER ...
1197  *                              DROP TRIGGER ...
1198  *
1199  *****************************************************************************/
1200
1201 CreateTrigStmt:  CREATE TRIGGER name TriggerActionTime TriggerEvents ON
1202                                 relation_name TriggerForSpec EXECUTE PROCEDURE
1203                                 name '(' TriggerFuncArgs ')'
1204                                 {
1205                                         CreateTrigStmt *n = makeNode(CreateTrigStmt);
1206                                         n->trigname = $3;
1207                                         n->relname = $7;
1208                                         n->funcname = $11;
1209                                         n->args = $13;
1210                                         n->before = $4;
1211                                         n->row = $8;
1212                                         memcpy (n->actions, $5, 4);
1213                                         $$ = (Node *)n;
1214                                 }
1215                 ;
1216
1217 TriggerActionTime:  BEFORE                                              { $$ = TRUE; }
1218                         | AFTER                                                         { $$ = FALSE; }
1219                 ;
1220
1221 TriggerEvents:  TriggerOneEvent
1222                                 {
1223                                         char *e = palloc (4);
1224                                         e[0] = $1; e[1] = 0; $$ = e;
1225                                 }
1226                         | TriggerOneEvent OR TriggerOneEvent
1227                                 {
1228                                         char *e = palloc (4);
1229                                         e[0] = $1; e[1] = $3; e[2] = 0; $$ = e;
1230                                 }
1231                         | TriggerOneEvent OR TriggerOneEvent OR TriggerOneEvent
1232                                 {
1233                                         char *e = palloc (4);
1234                                         e[0] = $1; e[1] = $3; e[2] = $5; e[3] = 0;
1235                                         $$ = e;
1236                                 }
1237                 ;
1238
1239 TriggerOneEvent:  INSERT                                        { $$ = 'i'; }
1240                         | DELETE                                                { $$ = 'd'; }
1241                         | UPDATE                                                { $$ = 'u'; }
1242                 ;
1243
1244 TriggerForSpec:  FOR TriggerForOpt TriggerForType
1245                                 {
1246                                         $$ = $3;
1247                                 }
1248                 ;
1249
1250 TriggerForOpt:  EACH                                            { $$ = TRUE; }
1251                         | /*EMPTY*/                                             { $$ = FALSE; }
1252                 ;
1253
1254 TriggerForType:  ROW                                            { $$ = TRUE; }
1255                         | STATEMENT                                             { $$ = FALSE; }
1256                 ;
1257
1258 TriggerFuncArgs:  TriggerFuncArg
1259                                 { $$ = lcons($1, NIL); }
1260                         | TriggerFuncArgs ',' TriggerFuncArg
1261                                 { $$ = lappend($1, $3); }
1262                         | /*EMPTY*/
1263                                 { $$ = NIL; }
1264                 ;
1265
1266 TriggerFuncArg:  ICONST
1267                                 {
1268                                         char *s = (char *) palloc (256);
1269                                         sprintf (s, "%d", $1);
1270                                         $$ = s;
1271                                 }
1272                         | FCONST
1273                                 {
1274                                         char *s = (char *) palloc (256);
1275                                         sprintf (s, "%g", $1);
1276                                         $$ = s;
1277                                 }
1278                         | Sconst                                                {  $$ = $1; }
1279                         | IDENT                                                 {  $$ = $1; }
1280                 ;
1281
1282 DropTrigStmt:  DROP TRIGGER name ON relation_name
1283                                 {
1284                                         DropTrigStmt *n = makeNode(DropTrigStmt);
1285                                         n->trigname = $3;
1286                                         n->relname = $5;
1287                                         $$ = (Node *) n;
1288                                 }
1289                 ;
1290
1291
1292 /*****************************************************************************
1293  *
1294  *              QUERY :
1295  *                              define (type,operator,aggregate)
1296  *
1297  *****************************************************************************/
1298
1299 DefineStmt:  CREATE def_type def_rest
1300                                 {
1301                                         $3->defType = $2;
1302                                         $$ = (Node *)$3;
1303                                 }
1304                 ;
1305
1306 def_rest:  def_name definition
1307                                 {
1308                                         $$ = makeNode(DefineStmt);
1309                                         $$->defname = $1;
1310                                         $$->definition = $2;
1311                                 }
1312                 ;
1313
1314 def_type:  OPERATOR                                                     { $$ = OPERATOR; }
1315                 | TYPE_P                                                        { $$ = TYPE_P; }
1316                 | AGGREGATE                                                     { $$ = AGGREGATE; }
1317                 ;
1318
1319 def_name:  PROCEDURE                                            { $$ = "procedure"; }
1320                 | JOIN                                                          { $$ = "join"; }
1321                 | ColId                                                         { $$ = $1; }
1322                 | MathOp                                                        { $$ = $1; }
1323                 | Op                                                            { $$ = $1; }
1324                 ;
1325
1326 definition:  '(' def_list ')'                           { $$ = $2; }
1327                 ;
1328
1329 def_list:  def_elem                                                     { $$ = lcons($1, NIL); }
1330                 | def_list ',' def_elem                         { $$ = lappend($1, $3); }
1331                 ;
1332
1333 def_elem:  def_name '=' def_arg
1334                                 {
1335                                         $$ = makeNode(DefElem);
1336                                         $$->defname = $1;
1337                                         $$->arg = (Node *)$3;
1338                                 }
1339                 | def_name
1340                                 {
1341                                         $$ = makeNode(DefElem);
1342                                         $$->defname = $1;
1343                                         $$->arg = (Node *)NULL;
1344                                 }
1345                 | DEFAULT '=' def_arg
1346                                 {
1347                                         $$ = makeNode(DefElem);
1348                                         $$->defname = "default";
1349                                         $$->arg = (Node *)$3;
1350                                 }
1351                 ;
1352
1353 def_arg:  ColId                                                 {  $$ = (Node *)makeString($1); }
1354                 | all_Op                                                {  $$ = (Node *)makeString($1); }
1355                 | NumConst                                              {  $$ = (Node *)$1; /* already a Value */ }
1356                 | Sconst                                                {  $$ = (Node *)makeString($1); }
1357                 | SETOF ColId
1358                                 {
1359                                         TypeName *n = makeNode(TypeName);
1360                                         n->name = $2;
1361                                         n->setof = TRUE;
1362                                         n->arrayBounds = NULL;
1363                                         n->typmod = -1;
1364                                         $$ = (Node *)n;
1365                                 }
1366                 ;
1367
1368
1369 /*****************************************************************************
1370  *
1371  *              QUERY:
1372  *                              destroy <relname1> [, <relname2> .. <relnameN> ]
1373  *
1374  *****************************************************************************/
1375
1376 DestroyStmt:  DROP TABLE relation_name_list
1377                                 {
1378                                         DestroyStmt *n = makeNode(DestroyStmt);
1379                                         n->relNames = $3;
1380                                         n->sequence = FALSE;
1381                                         $$ = (Node *)n;
1382                                 }
1383                 | DROP SEQUENCE relation_name_list
1384                                 {
1385                                         DestroyStmt *n = makeNode(DestroyStmt);
1386                                         n->relNames = $3;
1387                                         n->sequence = TRUE;
1388                                         $$ = (Node *)n;
1389                                 }
1390                 ;
1391
1392
1393 /*****************************************************************************
1394  *
1395  *              QUERY:
1396  *                      fetch/move [forward | backward] [number | all ] [ in <portalname> ]
1397  *
1398  *****************************************************************************/
1399
1400 FetchStmt:      FETCH opt_direction fetch_how_many opt_portal_name
1401                                 {
1402                                         FetchStmt *n = makeNode(FetchStmt);
1403                                         n->direction = $2;
1404                                         n->howMany = $3;
1405                                         n->portalname = $4;
1406                                         n->ismove = false;
1407                                         $$ = (Node *)n;
1408                                 }
1409                 |       MOVE opt_direction fetch_how_many opt_portal_name
1410                                 {
1411                                         FetchStmt *n = makeNode(FetchStmt);
1412                                         n->direction = $2;
1413                                         n->howMany = $3;
1414                                         n->portalname = $4;
1415                                         n->ismove = TRUE;
1416                                         $$ = (Node *)n;
1417                                 }
1418                 ;
1419
1420 opt_direction:  FORWARD                                                 { $$ = FORWARD; }
1421                 | BACKWARD                                                              { $$ = BACKWARD; }
1422                 | /*EMPTY*/                                                             { $$ = FORWARD; /* default */ }
1423                 ;
1424
1425 fetch_how_many:  Iconst
1426                            { $$ = $1;
1427                                  if ($1 <= 0) elog(ERROR,"Please specify nonnegative count for fetch"); }
1428                 | ALL                                                   { $$ = 0; /* 0 means fetch all tuples*/ }
1429                 | /*EMPTY*/                                             { $$ = 1; /*default*/ }
1430                 ;
1431
1432 opt_portal_name:  IN name                               { $$ = $2; }
1433                 | /*EMPTY*/                                             { $$ = NULL; }
1434                 ;
1435
1436
1437 /*****************************************************************************
1438  *
1439  *              QUERY:
1440  *                              GRANT [privileges] ON [relation_name_list] TO [GROUP] grantee
1441  *
1442  *****************************************************************************/
1443
1444 GrantStmt:  GRANT privileges ON relation_name_list TO grantee opt_with_grant
1445                                 {
1446                                         $$ = (Node*)makeAclStmt($2,$4,$6,'+');
1447                                 }
1448                 ;
1449
1450 privileges:  ALL PRIVILEGES
1451                                 {
1452                                  $$ = aclmakepriv("rwaR",0);
1453                                 }
1454                 | ALL
1455                                 {
1456                                  $$ = aclmakepriv("rwaR",0);
1457                                 }
1458                 | operation_commalist
1459                                 {
1460                                  $$ = $1;
1461                                 }
1462                 ;
1463
1464 operation_commalist:  operation
1465                                 {
1466                                                 $$ = aclmakepriv("",$1);
1467                                 }
1468                 | operation_commalist ',' operation
1469                                 {
1470                                                 $$ = aclmakepriv($1,$3);
1471                                 }
1472                 ;
1473
1474 operation:  SELECT
1475                                 {
1476                                                 $$ = ACL_MODE_RD_CHR;
1477                                 }
1478                 | INSERT
1479                                 {
1480                                                 $$ = ACL_MODE_AP_CHR;
1481                                 }
1482                 | UPDATE
1483                                 {
1484                                                 $$ = ACL_MODE_WR_CHR;
1485                                 }
1486                 | DELETE
1487                                 {
1488                                                 $$ = ACL_MODE_WR_CHR;
1489                                 }
1490                 | RULE
1491                                 {
1492                                                 $$ = ACL_MODE_RU_CHR;
1493                                 }
1494                 ;
1495
1496 grantee:  PUBLIC
1497                                 {
1498                                                 $$ = aclmakeuser("A","");
1499                                 }
1500                 | GROUP ColId
1501                                 {
1502                                                 $$ = aclmakeuser("G",$2);
1503                                 }
1504                 | ColId
1505                                 {
1506                                                 $$ = aclmakeuser("U",$1);
1507                                 }
1508                 ;
1509
1510 opt_with_grant:  WITH GRANT OPTION
1511                                 {
1512                                         yyerror("WITH GRANT OPTION is not supported.  Only relation owners can set privileges");
1513                                  }
1514                 | /*EMPTY*/
1515                 ;
1516
1517
1518 /*****************************************************************************
1519  *
1520  *              QUERY:
1521  *                              REVOKE [privileges] ON [relation_name] FROM [user]
1522  *
1523  *****************************************************************************/
1524
1525 RevokeStmt:  REVOKE privileges ON relation_name_list FROM grantee
1526                                 {
1527                                         $$ = (Node*)makeAclStmt($2,$4,$6,'-');
1528                                 }
1529                 ;
1530
1531
1532 /*****************************************************************************
1533  *
1534  *              QUERY:
1535  *                              create index <indexname> on <relname>
1536  *                                using <access> "(" (<col> with <op>)+ ")" [with
1537  *                                <target_list>]
1538  *
1539  *      [where <qual>] is not supported anymore
1540  *****************************************************************************/
1541
1542 IndexStmt:      CREATE index_opt_unique INDEX index_name ON relation_name
1543                         access_method_clause '(' index_params ')' opt_with
1544                                 {
1545                                         /* should check that access_method is valid,
1546                                            etc ... but doesn't */
1547                                         IndexStmt *n = makeNode(IndexStmt);
1548                                         n->unique = $2;
1549                                         n->idxname = $4;
1550                                         n->relname = $6;
1551                                         n->accessMethod = $7;
1552                                         n->indexParams = $9;
1553                                         n->withClause = $11;
1554                                         n->whereClause = NULL;
1555                                         $$ = (Node *)n;
1556                                 }
1557                 ;
1558
1559 index_opt_unique:  UNIQUE                                               { $$ = TRUE; }
1560                 | /*EMPTY*/                                                             { $$ = FALSE; }
1561                 ;
1562
1563 access_method_clause:  USING access_method              { $$ = $2; }
1564                 | /*EMPTY*/                                                             { $$ = "btree"; }
1565                 ;
1566
1567 index_params:  index_list                                               { $$ = $1; }
1568                 | func_index                                                    { $$ = lcons($1,NIL); }
1569                 ;
1570
1571 index_list:  index_list ',' index_elem                  { $$ = lappend($1, $3); }
1572                 | index_elem                                                    { $$ = lcons($1, NIL); }
1573                 ;
1574
1575 func_index:  func_name '(' name_list ')' opt_type opt_class
1576                                 {
1577                                         $$ = makeNode(IndexElem);
1578                                         $$->name = $1;
1579                                         $$->args = $3;
1580                                         $$->class = $6;
1581                                         $$->tname = $5;
1582                                 }
1583                   ;
1584
1585 index_elem:  attr_name opt_type opt_class
1586                                 {
1587                                         $$ = makeNode(IndexElem);
1588                                         $$->name = $1;
1589                                         $$->args = NIL;
1590                                         $$->class = $3;
1591                                         $$->tname = $2;
1592                                 }
1593                 ;
1594
1595 opt_type:  ':' Typename                                                 { $$ = $2; }
1596                 | FOR Typename                                                  { $$ = $2; }
1597                 | /*EMPTY*/                                                             { $$ = NULL; }
1598                 ;
1599
1600 /* opt_class "WITH class" conflicts with preceeding opt_type
1601  *  for Typename of "TIMESTAMP WITH TIME ZONE"
1602  * So, remove "WITH class" from the syntax. OK??
1603  * - thomas 1997-10-12
1604  *              | WITH class                                                    { $$ = $2; }
1605  */
1606 opt_class:  class                                                               { $$ = $1; }
1607                 | USING class                                                   { $$ = $2; }
1608                 | /*EMPTY*/                                                             { $$ = NULL; }
1609                 ;
1610
1611
1612 /*****************************************************************************
1613  *
1614  *              QUERY:
1615  *                              extend index <indexname> [where <qual>]
1616  *
1617  *****************************************************************************/
1618
1619 ExtendStmt:  EXTEND INDEX index_name where_clause
1620                                 {
1621                                         ExtendStmt *n = makeNode(ExtendStmt);
1622                                         n->idxname = $3;
1623                                         n->whereClause = $4;
1624                                         $$ = (Node *)n;
1625                                 }
1626                 ;
1627
1628
1629 /*****************************************************************************
1630  *
1631  *              QUERY:
1632  *                              execute recipe <recipeName>
1633  *
1634  *****************************************************************************/
1635
1636 RecipeStmt:  EXECUTE RECIPE recipe_name
1637                                 {
1638                                         RecipeStmt *n;
1639                                         if (!IsTransactionBlock())
1640                                                 elog(ERROR,"EXECUTE RECIPE may only be used in begin/end transaction blocks");
1641
1642                                         n = makeNode(RecipeStmt);
1643                                         n->recipeName = $3;
1644                                         $$ = (Node *)n;
1645                                 }
1646                 ;
1647
1648
1649 /*****************************************************************************
1650  *
1651  *              QUERY:
1652  *                              define function <fname>
1653  *                                         (language = <lang>, returntype = <typename>
1654  *                                              [, arch_pct = <percentage | pre-defined>]
1655  *                                              [, disk_pct = <percentage | pre-defined>]
1656  *                                              [, byte_pct = <percentage | pre-defined>]
1657  *                                              [, perbyte_cpu = <int | pre-defined>]
1658  *                                              [, percall_cpu = <int | pre-defined>]
1659  *                                              [, iscachable])
1660  *                                              [arg is (<type-1> { , <type-n>})]
1661  *                                              as <filename or code in language as appropriate>
1662  *
1663  *****************************************************************************/
1664
1665 ProcedureStmt:  CREATE FUNCTION func_name func_args
1666                          RETURNS func_return opt_with AS Sconst LANGUAGE Sconst
1667                                 {
1668                                         ProcedureStmt *n = makeNode(ProcedureStmt);
1669                                         n->funcname = $3;
1670                                         n->defArgs = $4;
1671                                         n->returnType = $6;
1672                                         n->withClause = $7;
1673                                         n->as = $9;
1674                                         n->language = $11;
1675                                         $$ = (Node *)n;
1676                                 };
1677
1678 opt_with:  WITH definition                                              { $$ = $2; }
1679                 | /*EMPTY*/                                                             { $$ = NIL; }
1680                 ;
1681
1682 func_args:  '(' func_args_list ')'                              { $$ = $2; }
1683                 | '(' ')'                                                               { $$ = NIL; }
1684                 ;
1685
1686 func_args_list:  TypeId
1687                                 {       $$ = lcons(makeString($1),NIL); }
1688                 | func_args_list ',' TypeId
1689                                 {       $$ = lappend($1,makeString($3)); }
1690                 ;
1691
1692 func_return:  set_opt TypeId
1693                                 {
1694                                         TypeName *n = makeNode(TypeName);
1695                                         n->name = $2;
1696                                         n->setof = $1;
1697                                         n->arrayBounds = NULL;
1698                                         $$ = (Node *)n;
1699                                 }
1700                 ;
1701
1702 set_opt:  SETOF                                                                 { $$ = TRUE; }
1703                 | /*EMPTY*/                                                             { $$ = FALSE; }
1704                 ;
1705
1706 /*****************************************************************************
1707  *
1708  *              QUERY:
1709  *
1710  *              remove function <funcname>
1711  *                              (REMOVE FUNCTION "funcname" (arg1, arg2, ...))
1712  *              remove aggregate <aggname>
1713  *                              (REMOVE AGGREGATE "aggname" "aggtype")
1714  *              remove operator <opname>
1715  *                              (REMOVE OPERATOR "opname" (leftoperand_typ rightoperand_typ))
1716  *              remove type <typename>
1717  *                              (REMOVE TYPE "typename")
1718  *              remove rule <rulename>
1719  *                              (REMOVE RULE "rulename")
1720  *
1721  *****************************************************************************/
1722
1723 RemoveStmt:  DROP remove_type name
1724                                 {
1725                                         RemoveStmt *n = makeNode(RemoveStmt);
1726                                         n->removeType = $2;
1727                                         n->name = $3;
1728                                         $$ = (Node *)n;
1729                                 }
1730                 ;
1731
1732 remove_type:  TYPE_P                                                    {  $$ = TYPE_P; }
1733                 | INDEX                                                                 {  $$ = INDEX; }
1734                 | RULE                                                                  {  $$ = RULE; }
1735                 | VIEW                                                                  {  $$ = VIEW; }
1736                 ;
1737
1738
1739 RemoveAggrStmt:  DROP AGGREGATE name aggr_argtype
1740                                 {
1741                                                 RemoveAggrStmt *n = makeNode(RemoveAggrStmt);
1742                                                 n->aggname = $3;
1743                                                 n->aggtype = $4;
1744                                                 $$ = (Node *)n;
1745                                 }
1746                 ;
1747
1748 aggr_argtype:  name                                                             { $$ = $1; }
1749                 | '*'                                                                   { $$ = NULL; }
1750                 ;
1751
1752
1753 RemoveFuncStmt:  DROP FUNCTION func_name func_args
1754                                 {
1755                                         RemoveFuncStmt *n = makeNode(RemoveFuncStmt);
1756                                         n->funcname = $3;
1757                                         n->args = $4;
1758                                         $$ = (Node *)n;
1759                                 }
1760                 ;
1761
1762
1763 RemoveOperStmt:  DROP OPERATOR all_Op '(' oper_argtypes ')'
1764                                 {
1765                                         RemoveOperStmt *n = makeNode(RemoveOperStmt);
1766                                         n->opname = $3;
1767                                         n->args = $5;
1768                                         $$ = (Node *)n;
1769                                 }
1770                 ;
1771
1772 all_Op:  Op | MathOp;
1773
1774 MathOp: '+'                             { $$ = "+"; }
1775                 | '-'                   { $$ = "-"; }
1776                 | '*'                   { $$ = "*"; }
1777                 | '/'                   { $$ = "/"; }
1778                 | '<'                   { $$ = "<"; }
1779                 | '>'                   { $$ = ">"; }
1780                 | '='                   { $$ = "="; }
1781                 ;
1782
1783 oper_argtypes:  name
1784                                 {
1785                                    elog(ERROR,"parser: argument type missing (use NONE for unary operators)");
1786                                 }
1787                 | name ',' name
1788                                 { $$ = makeList(makeString($1), makeString($3), -1); }
1789                 | NONE ',' name                 /* left unary */
1790                                 { $$ = makeList(NULL, makeString($3), -1); }
1791                 | name ',' NONE                 /* right unary */
1792                                 { $$ = makeList(makeString($1), NULL, -1); }
1793                 ;
1794
1795
1796 /*****************************************************************************
1797  *
1798  *              QUERY:
1799  *                              rename <attrname1> in <relname> [*] to <attrname2>
1800  *                              rename <relname1> to <relname2>
1801  *
1802  *****************************************************************************/
1803
1804 RenameStmt:  ALTER TABLE relation_name opt_inh_star
1805                                   RENAME opt_column opt_name TO name
1806                                 {
1807                                         RenameStmt *n = makeNode(RenameStmt);
1808                                         n->relname = $3;
1809                                         n->inh = $4;
1810                                         n->column = $7;
1811                                         n->newname = $9;
1812                                         $$ = (Node *)n;
1813                                 }
1814                 ;
1815
1816 opt_name:  name                                                 { $$ = $1; }
1817                 | /*EMPTY*/                                             { $$ = NULL; }
1818                 ;
1819
1820 opt_column:  COLUMN                                             { $$ = COLUMN; }
1821                 | /*EMPTY*/                                             { $$ = 0; }
1822                 ;
1823
1824
1825 /*****************************************************************************
1826  *
1827  *              QUERY:  Define Rewrite Rule , Define Tuple Rule
1828  *                              Define Rule <old rules >
1829  *
1830  *              only rewrite rule is supported -- ay 9/94
1831  *
1832  *****************************************************************************/
1833
1834 RuleStmt:  CREATE RULE name AS
1835                    { QueryIsRule=TRUE; }
1836                    ON event TO event_object where_clause
1837                    DO opt_instead OptStmtList
1838                                 {
1839                                         RuleStmt *n = makeNode(RuleStmt);
1840                                         n->rulename = $3;
1841                                         n->event = $7;
1842                                         n->object = $9;
1843                                         n->whereClause = $10;
1844                                         n->instead = $12;
1845                                         n->actions = $13;
1846                                         $$ = (Node *)n;
1847                                 }
1848                 ;
1849
1850 OptStmtList:  NOTHING                                   { $$ = NIL; }
1851                 | OptimizableStmt                               { $$ = lcons($1, NIL); }
1852                 | '[' OptStmtBlock ']'                  { $$ = $2; }
1853                 ;
1854
1855 OptStmtBlock:  OptStmtMulti
1856                                 {  $$ = $1; }
1857                 | OptimizableStmt
1858                                 { $$ = lcons($1, NIL); }
1859                 ;
1860
1861 OptStmtMulti:  OptStmtMulti OptimizableStmt ';'
1862                                 {  $$ = lappend($1, $2); }
1863                 | OptStmtMulti OptimizableStmt
1864                                 {  $$ = lappend($1, $2); }
1865                 | OptimizableStmt ';'
1866                                 { $$ = lcons($1, NIL); }
1867                 ;
1868
1869 event_object:  relation_name '.' attr_name
1870                                 {
1871                                         $$ = makeNode(Attr);
1872                                         $$->relname = $1;
1873                                         $$->paramNo = NULL;
1874                                         $$->attrs = lcons(makeString($3), NIL);
1875                                         $$->indirection = NIL;
1876                                 }
1877                 | relation_name
1878                                 {
1879                                         $$ = makeNode(Attr);
1880                                         $$->relname = $1;
1881                                         $$->paramNo = NULL;
1882                                         $$->attrs = NIL;
1883                                         $$->indirection = NIL;
1884                                 }
1885                 ;
1886
1887 /* change me to select, update, etc. some day */
1888 event:  SELECT                                                  { $$ = CMD_SELECT; }
1889                 | UPDATE                                                { $$ = CMD_UPDATE; }
1890                 | DELETE                                                { $$ = CMD_DELETE; }
1891                 | INSERT                                                { $$ = CMD_INSERT; }
1892                  ;
1893
1894 opt_instead:  INSTEAD                                   { $$ = TRUE; }
1895                 | /*EMPTY*/                                             { $$ = FALSE; }
1896                 ;
1897
1898
1899 /*****************************************************************************
1900  *
1901  *              QUERY:
1902  *                              NOTIFY <relation_name>  can appear both in rule bodies and
1903  *                              as a query-level command
1904  *
1905  *****************************************************************************/
1906
1907 NotifyStmt:  NOTIFY relation_name
1908                                 {
1909                                         NotifyStmt *n = makeNode(NotifyStmt);
1910                                         n->relname = $2;
1911                                         $$ = (Node *)n;
1912                                 }
1913                 ;
1914
1915 ListenStmt:  LISTEN relation_name
1916                                 {
1917                                         ListenStmt *n = makeNode(ListenStmt);
1918                                         n->relname = $2;
1919                                         $$ = (Node *)n;
1920                                 }
1921 ;
1922
1923
1924 /*****************************************************************************
1925  *
1926  *              Transactions:
1927  *
1928  *              abort transaction
1929  *                              (ABORT)
1930  *              begin transaction
1931  *                              (BEGIN)
1932  *              end transaction
1933  *                              (END)
1934  *
1935  *****************************************************************************/
1936
1937 TransactionStmt:  ABORT_TRANS TRANSACTION
1938                                 {
1939                                         TransactionStmt *n = makeNode(TransactionStmt);
1940                                         n->command = ABORT_TRANS;
1941                                         $$ = (Node *)n;
1942                                 }
1943                 | BEGIN_TRANS TRANSACTION
1944                                 {
1945                                         TransactionStmt *n = makeNode(TransactionStmt);
1946                                         n->command = BEGIN_TRANS;
1947                                         $$ = (Node *)n;
1948                                 }
1949                 | BEGIN_TRANS WORK
1950                                 {
1951                                         TransactionStmt *n = makeNode(TransactionStmt);
1952                                         n->command = BEGIN_TRANS;
1953                                         $$ = (Node *)n;
1954                                 }
1955                 | COMMIT WORK
1956                                 {
1957                                         TransactionStmt *n = makeNode(TransactionStmt);
1958                                         n->command = END_TRANS;
1959                                         $$ = (Node *)n;
1960                                 }
1961                 | END_TRANS TRANSACTION
1962                                 {
1963                                         TransactionStmt *n = makeNode(TransactionStmt);
1964                                         n->command = END_TRANS;
1965                                         $$ = (Node *)n;
1966                                 }
1967                 | ROLLBACK WORK
1968                                 {
1969                                         TransactionStmt *n = makeNode(TransactionStmt);
1970                                         n->command = ABORT_TRANS;
1971                                         $$ = (Node *)n;
1972                                 }
1973
1974                 | ABORT_TRANS
1975                                 {
1976                                         TransactionStmt *n = makeNode(TransactionStmt);
1977                                         n->command = ABORT_TRANS;
1978                                         $$ = (Node *)n;
1979                                 }
1980                 | BEGIN_TRANS
1981                                 {
1982                                         TransactionStmt *n = makeNode(TransactionStmt);
1983                                         n->command = BEGIN_TRANS;
1984                                         $$ = (Node *)n;
1985                                 }
1986                 | COMMIT
1987                                 {
1988                                         TransactionStmt *n = makeNode(TransactionStmt);
1989                                         n->command = END_TRANS;
1990                                         $$ = (Node *)n;
1991                                 }
1992
1993                 | END_TRANS
1994                                 {
1995                                         TransactionStmt *n = makeNode(TransactionStmt);
1996                                         n->command = END_TRANS;
1997                                         $$ = (Node *)n;
1998                                 }
1999                 | ROLLBACK
2000                                 {
2001                                         TransactionStmt *n = makeNode(TransactionStmt);
2002                                         n->command = ABORT_TRANS;
2003                                         $$ = (Node *)n;
2004                                 }
2005                 ;
2006
2007
2008 /*****************************************************************************
2009  *
2010  *              QUERY:
2011  *                              define view <viewname> '('target-list ')' [where <quals> ]
2012  *
2013  *****************************************************************************/
2014
2015 ViewStmt:  CREATE VIEW name AS SelectStmt
2016                                 {
2017                                         ViewStmt *n = makeNode(ViewStmt);
2018                                         n->viewname = $3;
2019                                         n->query = (Query *)$5;
2020                                         if (((SelectStmt *)n->query)->sortClause != NULL)
2021                                                 elog(ERROR,"Order by and Distinct on views is not implemented.");
2022                                         if (((SelectStmt *)n->query)->unionClause != NULL)
2023                                                 elog(ERROR,"Views on unions not implemented.");
2024                                         $$ = (Node *)n;
2025                                 }
2026                 ;
2027
2028
2029 /*****************************************************************************
2030  *
2031  *              QUERY:
2032  *                              load "filename"
2033  *
2034  *****************************************************************************/
2035
2036 LoadStmt:  LOAD file_name
2037                                 {
2038                                         LoadStmt *n = makeNode(LoadStmt);
2039                                         n->filename = $2;
2040                                         $$ = (Node *)n;
2041                                 }
2042                 ;
2043
2044
2045 /*****************************************************************************
2046  *
2047  *              QUERY:
2048  *                              createdb dbname
2049  *
2050  *****************************************************************************/
2051
2052 CreatedbStmt:  CREATE DATABASE database_name opt_database
2053                                 {
2054                                         CreatedbStmt *n = makeNode(CreatedbStmt);
2055                                         n->dbname = $3;
2056                                         n->dbpath = $4;
2057                                         $$ = (Node *)n;
2058                                 }
2059                 ;
2060
2061 opt_database:  WITH LOCATION '=' location               { $$ = $4; }
2062                 | /*EMPTY*/                                                             { $$ = NULL; }
2063                 ;
2064
2065 location:  Sconst                                                               { $$ = $1; }
2066                 | DEFAULT                                                               { $$ = NULL; }
2067                 | /*EMPTY*/                                                             { $$ = NULL; }
2068                 ;
2069
2070 /*****************************************************************************
2071  *
2072  *              QUERY:
2073  *                              destroydb dbname
2074  *
2075  *****************************************************************************/
2076
2077 DestroydbStmt:  DROP DATABASE database_name
2078                                 {
2079                                         DestroydbStmt *n = makeNode(DestroydbStmt);
2080                                         n->dbname = $3;
2081                                         $$ = (Node *)n;
2082                                 }
2083                 ;
2084
2085
2086 /*****************************************************************************
2087  *
2088  *              QUERY:
2089  *                              cluster <index_name> on <relation_name>
2090  *
2091  *****************************************************************************/
2092
2093 ClusterStmt:  CLUSTER index_name ON relation_name
2094                                 {
2095                                    ClusterStmt *n = makeNode(ClusterStmt);
2096                                    n->relname = $4;
2097                                    n->indexname = $2;
2098                                    $$ = (Node*)n;
2099                                 }
2100                 ;
2101
2102
2103 /*****************************************************************************
2104  *
2105  *              QUERY:
2106  *                              vacuum
2107  *
2108  *****************************************************************************/
2109
2110 VacuumStmt:  VACUUM opt_verbose opt_analyze
2111                                 {
2112                                         VacuumStmt *n = makeNode(VacuumStmt);
2113                                         n->verbose = $2;
2114                                         n->analyze = $3;
2115                                         n->vacrel = NULL;
2116                                         n->va_spec = NIL;
2117                                         $$ = (Node *)n;
2118                                 }
2119                 | VACUUM opt_verbose opt_analyze relation_name opt_va_list
2120                                 {
2121                                         VacuumStmt *n = makeNode(VacuumStmt);
2122                                         n->verbose = $2;
2123                                         n->analyze = $3;
2124                                         n->vacrel = $4;
2125                                         n->va_spec = $5;
2126                                         if ( $5 != NIL && !$4 )
2127                                                 elog(ERROR,"parser: syntax error at or near \"(\"");
2128                                         $$ = (Node *)n;
2129                                 }
2130                 ;
2131
2132 opt_verbose:  VERBOSE                                                   { $$ = TRUE; }
2133                 | /*EMPTY*/                                                             { $$ = FALSE; }
2134                 ;
2135
2136 opt_analyze:  ANALYZE                                                   { $$ = TRUE; }
2137                 | /*EMPTY*/                                                             { $$ = FALSE; }
2138                 ;
2139
2140 opt_va_list:  '(' va_list ')'                                   { $$ = $2; }
2141                 | /*EMPTY*/                                                             { $$ = NIL; }
2142                 ;
2143
2144 va_list:  name
2145                                 { $$=lcons($1,NIL); }
2146                 | va_list ',' name
2147                                 { $$=lappend($1,$3); }
2148                 ;
2149
2150
2151 /*****************************************************************************
2152  *
2153  *              QUERY:
2154  *                              EXPLAIN query
2155  *
2156  *****************************************************************************/
2157
2158 ExplainStmt:  EXPLAIN opt_verbose OptimizableStmt
2159                                 {
2160                                         ExplainStmt *n = makeNode(ExplainStmt);
2161                                         n->verbose = $2;
2162                                         n->query = (Query*)$3;
2163                                         $$ = (Node *)n;
2164                                 }
2165                 ;
2166
2167
2168 /*****************************************************************************
2169  *                                                                                                                                                       *
2170  *              Optimizable Stmts:                                                                                                       *
2171  *                                                                                                                                                       *
2172  *              one of the five queries processed by the planner                                         *
2173  *                                                                                                                                                       *
2174  *              [ultimately] produces query-trees as specified                                           *
2175  *              in the query-spec document in ~postgres/ref                                                      *
2176  *                                                                                                                                                       *
2177  *****************************************************************************/
2178
2179 OptimizableStmt:  SelectStmt
2180                 | CursorStmt
2181                 | UpdateStmt
2182                 | InsertStmt
2183                 | NotifyStmt
2184                 | DeleteStmt                                    /* by default all are $$=$1 */
2185                 ;
2186
2187
2188 /*****************************************************************************
2189  *
2190  *              QUERY:
2191  *                              INSERT STATEMENTS
2192  *
2193  *****************************************************************************/
2194
2195 InsertStmt:  INSERT INTO relation_name opt_column_list insert_rest
2196                                 {
2197                                         $5->relname = $3;
2198                                         $5->cols = $4;
2199                                         $$ = (Node *)$5;
2200                                 }
2201                 ;
2202
2203 insert_rest:  VALUES '(' res_target_list2 ')'
2204                                 {
2205                                         $$ = makeNode(InsertStmt);
2206                                         $$->unique = NULL;
2207                                         $$->targetList = $3;
2208                                         $$->fromClause = NIL;
2209                                         $$->whereClause = NULL;
2210                                         $$->groupClause = NIL;
2211                                         $$->havingClause = NULL;
2212                                         $$->unionClause = NIL;
2213                                 }
2214                 | SELECT opt_unique res_target_list2
2215                          from_clause where_clause
2216                          group_clause having_clause
2217                          union_clause
2218                                 {
2219                                         $$ = makeNode(InsertStmt);
2220                                         $$->unique = $2;
2221                                         $$->targetList = $3;
2222                                         $$->fromClause = $4;
2223                                         $$->whereClause = $5;
2224                                         $$->groupClause = $6;
2225                                         $$->havingClause = $7;
2226                                         $$->unionClause = $8;
2227                                 }
2228                 ;
2229
2230 opt_column_list:  '(' columnList ')'                    { $$ = $2; }
2231                 | /*EMPTY*/                                                             { $$ = NIL; }
2232                 ;
2233
2234 columnList:
2235                   columnList ',' columnElem
2236                                 { $$ = lappend($1, $3); }
2237                 | columnElem
2238                                 { $$ = lcons($1, NIL); }
2239                 ;
2240
2241 columnElem:  ColId opt_indirection
2242                                 {
2243                                         Ident *id = makeNode(Ident);
2244                                         id->name = $1;
2245                                         id->indirection = $2;
2246                                         $$ = (Node *)id;
2247                                 }
2248                 ;
2249
2250
2251 /*****************************************************************************
2252  *
2253  *              QUERY:
2254  *                              DELETE STATEMENTS
2255  *
2256  *****************************************************************************/
2257
2258 DeleteStmt:  DELETE FROM relation_name
2259                          where_clause
2260                                 {
2261                                         DeleteStmt *n = makeNode(DeleteStmt);
2262                                         n->relname = $3;
2263                                         n->whereClause = $4;
2264                                         $$ = (Node *)n;
2265                                 }
2266                 ;
2267
2268 /*
2269  *      Total hack to just lock a table inside a transaction.
2270  *      Is it worth making this a separate command, with
2271  *      its own node type and file.  I don't think so. bjm 1998/1/22
2272  */
2273 LockStmt:  LOCK_P opt_table relation_name
2274                                 {
2275                                         DeleteStmt *n = makeNode(DeleteStmt);
2276                                         A_Const *c = makeNode(A_Const);
2277
2278                                         c->val.type = T_String;
2279                                         c->val.val.str = "f";
2280                                         c->typename = makeNode(TypeName);
2281                                         c->typename->name = xlateSqlType("bool");
2282                                         c->typename->typmod = -1;
2283
2284                                         n->relname = $3;
2285                                         n->whereClause = (Node *)c;
2286                                         $$ = (Node *)n;
2287                                 }
2288                 ;
2289
2290
2291 /*****************************************************************************
2292  *
2293  *              QUERY:
2294  *                              UpdateStmt (UPDATE)
2295  *
2296  *****************************************************************************/
2297
2298 UpdateStmt:  UPDATE relation_name
2299                           SET res_target_list
2300                           from_clause
2301                           where_clause
2302                                 {
2303                                         UpdateStmt *n = makeNode(UpdateStmt);
2304                                         n->relname = $2;
2305                                         n->targetList = $4;
2306                                         n->fromClause = $5;
2307                                         n->whereClause = $6;
2308                                         $$ = (Node *)n;
2309                                 }
2310                 ;
2311
2312
2313 /*****************************************************************************
2314  *
2315  *              QUERY:
2316  *                              CURSOR STATEMENTS
2317  *
2318  *****************************************************************************/
2319 CursorStmt:  DECLARE name opt_binary CURSOR FOR
2320                          SELECT opt_unique res_target_list2
2321                          from_clause where_clause
2322                          group_clause having_clause
2323                          union_clause sort_clause
2324                                 {
2325                                         SelectStmt *n = makeNode(SelectStmt);
2326
2327                                         /* from PORTAL name */
2328                                         /*
2329                                          *      15 august 1991 -- since 3.0 postgres does locking
2330                                          *      right, we discovered that portals were violating
2331                                          *      locking protocol.  portal locks cannot span xacts.
2332                                          *      as a short-term fix, we installed the check here.
2333                                          *                                                      -- mao
2334                                          */
2335                                         if (!IsTransactionBlock())
2336                                                 elog(ERROR,"Named portals may only be used in begin/end transaction blocks");
2337
2338                                         n->portalname = $2;
2339                                         n->binary = $3;
2340                                         n->unique = $7;
2341                                         n->targetList = $8;
2342                                         n->fromClause = $9;
2343                                         n->whereClause = $10;
2344                                         n->groupClause = $11;
2345                                         n->havingClause = $12;
2346                                         n->unionClause = $13;
2347                                         n->sortClause = $14;
2348                                         $$ = (Node *)n;
2349                                 }
2350                 ;
2351
2352
2353 /*****************************************************************************
2354  *
2355  *              QUERY:
2356  *                              SELECT STATEMENTS
2357  *
2358  *****************************************************************************/
2359
2360 SelectStmt:  SELECT opt_unique res_target_list2
2361                          result from_clause where_clause
2362                          group_clause having_clause
2363                          union_clause sort_clause
2364                                 {
2365                                         SelectStmt *n = makeNode(SelectStmt);
2366                                         n->unique = $2;
2367                                         n->targetList = $3;
2368                                         n->into = $4;
2369                                         n->fromClause = $5;
2370                                         n->whereClause = $6;
2371                                         n->groupClause = $7;
2372                                         n->havingClause = $8;
2373                                         n->unionClause = $9;
2374                                         n->sortClause = $10;
2375                                         $$ = (Node *)n;
2376                                 }
2377                 ;
2378
2379 union_clause:  UNION opt_union select_list
2380                                 {
2381                                         SelectStmt *n = (SelectStmt *)lfirst($3);
2382                                         n->unionall = $2;
2383                                         $$ = $3;
2384                                 }
2385                 | /*EMPTY*/
2386                                 { $$ = NIL; }
2387                 ;
2388
2389 select_list:  select_list UNION opt_union SubSelect
2390                                 {
2391                                         SelectStmt *n = (SelectStmt *)$4;
2392                                         n->unionall = $3;
2393                                         $$ = lappend($1, $4);
2394                                 }
2395                 | SubSelect
2396                                 { $$ = lcons($1, NIL); }
2397                 ;
2398
2399 SubSelect:      SELECT opt_unique res_target_list2
2400                          from_clause where_clause
2401                          group_clause having_clause
2402                                 {
2403                                         SelectStmt *n = makeNode(SelectStmt);
2404                                         n->unique = $2;
2405                                         n->unionall = FALSE;
2406                                         n->targetList = $3;
2407                                         n->fromClause = $4;
2408                                         n->whereClause = $5;
2409                                         n->groupClause = $6;
2410                                         n->havingClause = $7;
2411                                         $$ = (Node *)n;
2412                                 }
2413                 ;
2414
2415 result:  INTO opt_table relation_name                   { $$= $3; }
2416                 | /*EMPTY*/                                                             { $$ = NULL; }
2417                 ;
2418
2419 opt_table:  TABLE                                                               { $$ = TRUE; }
2420                 | /*EMPTY*/                                                             { $$ = FALSE; }
2421                 ;
2422
2423 opt_union:  ALL                                                                 { $$ = TRUE; }
2424                 | /*EMPTY*/                                                             { $$ = FALSE; }
2425                 ;
2426
2427 opt_unique:  DISTINCT                                                   { $$ = "*"; }
2428                 | DISTINCT ON ColId                                             { $$ = $3; }
2429                 | ALL                                                                   { $$ = NULL; }
2430                 | /*EMPTY*/                                                             { $$ = NULL; }
2431                 ;
2432
2433 sort_clause:  ORDER BY sortby_list                              { $$ = $3; }
2434                 | /*EMPTY*/                                                             { $$ = NIL; }
2435                 ;
2436
2437 sortby_list:  sortby                                                    { $$ = lcons($1, NIL); }
2438                 | sortby_list ',' sortby                                { $$ = lappend($1, $3); }
2439                 ;
2440
2441 sortby:  ColId OptUseOp
2442                                 {
2443                                         $$ = makeNode(SortGroupBy);
2444                                         $$->resno = 0;
2445                                         $$->range = NULL;
2446                                         $$->name = $1;
2447                                         $$->useOp = $2;
2448                                 }
2449                 | ColId '.' ColId OptUseOp
2450                                 {
2451                                         $$ = makeNode(SortGroupBy);
2452                                         $$->resno = 0;
2453                                         $$->range = $1;
2454                                         $$->name = $3;
2455                                         $$->useOp = $4;
2456                                 }
2457                 | Iconst OptUseOp
2458                                 {
2459                                         $$ = makeNode(SortGroupBy);
2460                                         $$->resno = $1;
2461                                         $$->range = NULL;
2462                                         $$->name = NULL;
2463                                         $$->useOp = $2;
2464                                 }
2465                 ;
2466
2467 OptUseOp:  USING Op                                                             { $$ = $2; }
2468                 | USING '<'                                                             { $$ = "<"; }
2469                 | USING '>'                                                             { $$ = ">"; }
2470                 | ASC                                                                   { $$ = "<"; }
2471                 | DESC                                                                  { $$ = ">"; }
2472                 | /*EMPTY*/                                                             { $$ = "<"; /*default*/ }
2473                 ;
2474
2475 /*
2476  *      jimmy bell-style recursive queries aren't supported in the
2477  *      current system.
2478  *
2479  *      ...however, recursive addattr and rename supported.  make special
2480  *      cases for these.
2481  */
2482 opt_inh_star:  '*'                                                              { $$ = TRUE; }
2483                 | /*EMPTY*/                                                             { $$ = FALSE; }
2484                 ;
2485
2486 relation_name_list:  name_list;
2487
2488 name_list:  name
2489                                 {       $$ = lcons(makeString($1),NIL); }
2490                 | name_list ',' name
2491                                 {       $$ = lappend($1,makeString($3)); }
2492                 ;
2493
2494 group_clause:  GROUP BY groupby_list                    { $$ = $3; }
2495                 | /*EMPTY*/                                                             { $$ = NIL; }
2496                 ;
2497
2498 groupby_list:  groupby                                                  { $$ = lcons($1, NIL); }
2499                 | groupby_list ',' groupby                              { $$ = lappend($1, $3); }
2500                 ;
2501
2502 groupby:  ColId
2503                                 {
2504                                         $$ = makeNode(SortGroupBy);
2505                                         $$->resno = 0;
2506                                         $$->range = NULL;
2507                                         $$->name = $1;
2508                                         $$->useOp = NULL;
2509                                 }
2510                 | ColId '.' ColId
2511                                 {
2512                                         $$ = makeNode(SortGroupBy);
2513                                         $$->resno = 0;
2514                                         $$->range = $1;
2515                                         $$->name = $3;
2516                                         $$->useOp = NULL;
2517                                 }
2518                 | Iconst
2519                                 {
2520                                         $$ = makeNode(SortGroupBy);
2521                                         $$->resno = $1;
2522                                         $$->range = NULL;
2523                                         $$->name = NULL;
2524                                         $$->useOp = NULL;
2525                                 }
2526                 ;
2527
2528 having_clause:  HAVING a_expr
2529                                 {
2530                                         /***S*H***/ /* elog(NOTICE, "HAVING not yet supported; ignore clause");*/
2531                                         $$ = $2;
2532                                 }
2533                 | /*EMPTY*/                                                             { $$ = NULL; }
2534                 ;
2535
2536
2537 /*****************************************************************************
2538  *
2539  *      clauses common to all Optimizable Stmts:
2540  *              from_clause             -
2541  *              where_clause    -
2542  *
2543  *****************************************************************************/
2544
2545 from_clause:  FROM '(' relation_expr join_expr JOIN relation_expr join_spec ')'
2546                                 {
2547                                         $$ = NIL;
2548                                         elog(ERROR,"JOIN not yet implemented");
2549                                 }
2550                 | FROM from_list                                                { $$ = $2; }
2551                 | /*EMPTY*/                                                             { $$ = NIL; }
2552                 ;
2553
2554 from_list:      from_list ',' from_val
2555                                 { $$ = lappend($1, $3); }
2556                 | from_val CROSS JOIN from_val
2557                                 { elog(ERROR,"CROSS JOIN not yet implemented"); }
2558                 | from_val
2559                                 { $$ = lcons($1, NIL); }
2560                 ;
2561
2562 from_val:  relation_expr AS ColLabel
2563                                 {
2564                                         $$ = makeNode(RangeVar);
2565                                         $$->relExpr = $1;
2566                                         $$->name = $3;
2567                                 }
2568                 | relation_expr ColId
2569                                 {
2570                                         $$ = makeNode(RangeVar);
2571                                         $$->relExpr = $1;
2572                                         $$->name = $2;
2573                                 }
2574                 | relation_expr
2575                                 {
2576                                         $$ = makeNode(RangeVar);
2577                                         $$->relExpr = $1;
2578                                         $$->name = NULL;
2579                                 }
2580                 ;
2581
2582 join_expr:  NATURAL join_expr                                   { $$ = NULL; }
2583                 | FULL join_outer
2584                                 { elog(ERROR,"FULL OUTER JOIN not yet implemented"); }
2585                 | LEFT join_outer
2586                                 { elog(ERROR,"LEFT OUTER JOIN not yet implemented"); }
2587                 | RIGHT join_outer
2588                                 { elog(ERROR,"RIGHT OUTER JOIN not yet implemented"); }
2589                 | OUTER_P
2590                                 { elog(ERROR,"OUTER JOIN not yet implemented"); }
2591                 | INNER_P
2592                                 { elog(ERROR,"INNER JOIN not yet implemented"); }
2593                 | UNION
2594                                 { elog(ERROR,"UNION JOIN not yet implemented"); }
2595                 | /*EMPTY*/
2596                                 { elog(ERROR,"INNER JOIN not yet implemented"); }
2597                 ;
2598
2599 join_outer:  OUTER_P                                                    { $$ = NULL; }
2600                 | /*EMPTY*/                                                             { $$ = NULL;  /* no qualifiers */ }
2601                 ;
2602
2603 join_spec:      ON '(' a_expr ')'                                       { $$ = NULL; }
2604                 | USING '(' join_list ')'                               { $$ = NULL; }
2605                 | /*EMPTY*/                                                             { $$ = NULL;  /* no qualifiers */ }
2606                 ;
2607
2608 join_list:  join_using                                                  { $$ = lcons($1, NIL); }
2609                 | join_list ',' join_using                              { $$ = lappend($1, $3); }
2610                 ;
2611
2612 join_using:  ColId
2613                                 {
2614                                         $$ = makeNode(SortGroupBy);
2615                                         $$->resno = 0;
2616                                         $$->range = NULL;
2617                                         $$->name = $1;
2618                                         $$->useOp = NULL;
2619                                 }
2620                 | ColId '.' ColId
2621                                 {
2622                                         $$ = makeNode(SortGroupBy);
2623                                         $$->resno = 0;
2624                                         $$->range = $1;
2625                                         $$->name = $3;
2626                                         $$->useOp = NULL;
2627                                 }
2628                 | Iconst
2629                                 {
2630                                         $$ = makeNode(SortGroupBy);
2631                                         $$->resno = $1;
2632                                         $$->range = NULL;
2633                                         $$->name = NULL;
2634                                         $$->useOp = NULL;
2635                                 }
2636                 ;
2637
2638 where_clause:  WHERE a_expr                                             { $$ = $2; }
2639                 | /*EMPTY*/                                                             { $$ = NULL;  /* no qualifiers */ }
2640                 ;
2641
2642 relation_expr:  relation_name
2643                                 {
2644                                         /* normal relations */
2645                                         $$ = makeNode(RelExpr);
2646                                         $$->relname = $1;
2647                                         $$->inh = FALSE;
2648                                 }
2649                 | relation_name '*'                               %prec '='
2650                                 {
2651                                         /* inheritance query */
2652                                         $$ = makeNode(RelExpr);
2653                                         $$->relname = $1;
2654                                         $$->inh = TRUE;
2655                                 }
2656
2657 opt_array_bounds:  '[' ']' nest_array_bounds
2658                                 {  $$ = lcons(makeInteger(-1), $3); }
2659                 | '[' Iconst ']' nest_array_bounds
2660                                 {  $$ = lcons(makeInteger($2), $4); }
2661                 | /* EMPTY */
2662                                 {  $$ = NIL; }
2663                 ;
2664
2665 nest_array_bounds:      '[' ']' nest_array_bounds
2666                                 {  $$ = lcons(makeInteger(-1), $3); }
2667                 | '[' Iconst ']' nest_array_bounds
2668                                 {  $$ = lcons(makeInteger($2), $4); }
2669                 | /*EMPTY*/
2670                                 {  $$ = NIL; }
2671                 ;
2672
2673
2674 /*****************************************************************************
2675  *
2676  *      Type syntax
2677  *              SQL92 introduces a large amount of type-specific syntax.
2678  *              Define individual clauses to handle these cases, and use
2679  *               the generic case to handle regular type-extensible Postgres syntax.
2680  *              - thomas 1997-10-10
2681  *
2682  *****************************************************************************/
2683
2684 Typename:  Array opt_array_bounds
2685                                 {
2686                                         $$ = $1;
2687                                         $$->arrayBounds = $2;
2688
2689                                         /* Is this the name of a complex type? If so, implement
2690                                          * it as a set.
2691                                          */
2692                                         if (!strcmp(saved_relname, $$->name))
2693                                                 /* This attr is the same type as the relation
2694                                                  * being defined. The classic example: create
2695                                                  * emp(name=text,mgr=emp)
2696                                                  */
2697                                                 $$->setof = TRUE;
2698                                         else if (typeTypeRelid(typenameType($$->name)) != InvalidOid)
2699                                                  /* (Eventually add in here that the set can only
2700                                                   * contain one element.)
2701                                                   */
2702                                                 $$->setof = TRUE;
2703                                         else
2704                                                 $$->setof = FALSE;
2705                                 }
2706                 | Character
2707                 | SETOF Array
2708                                 {
2709                                         $$ = $2;
2710                                         $$->setof = TRUE;
2711                                 }
2712                 ;
2713
2714 Array:  Generic
2715                 | Datetime
2716                 | Numeric
2717                 ;
2718
2719 Generic:  generic
2720                                 {
2721                                         $$ = makeNode(TypeName);
2722                                         $$->name = xlateSqlType($1);
2723                                         $$->typmod = -1;
2724                                 }
2725                 ;
2726
2727 generic:  IDENT                                                                 { $$ = $1; }
2728                 | TYPE_P                                                                { $$ = xlateSqlType("type"); }
2729                 ;
2730
2731 /* SQL92 numeric data types
2732  * Check FLOAT() precision limits assuming IEEE floating types.
2733  * Provide rudimentary DECIMAL() and NUMERIC() implementations
2734  *  by checking parameters and making sure they match what is possible with INTEGER.
2735  * - thomas 1997-09-18
2736  */
2737 Numeric:  FLOAT opt_float
2738                                 {
2739                                         $$ = makeNode(TypeName);
2740                                         $$->name = xlateSqlType($2);
2741                                         $$->typmod = -1;
2742                                 }
2743                 | DOUBLE PRECISION
2744                                 {
2745                                         $$ = makeNode(TypeName);
2746                                         $$->name = xlateSqlType("float");
2747                                 }
2748                 | DECIMAL opt_decimal
2749                                 {
2750                                         $$ = makeNode(TypeName);
2751                                         $$->name = xlateSqlType("integer");
2752                                         $$->typmod = -1;
2753                                 }
2754                 | NUMERIC opt_numeric
2755                                 {
2756                                         $$ = makeNode(TypeName);
2757                                         $$->name = xlateSqlType("integer");
2758                                         $$->typmod = -1;
2759                                 }
2760                 ;
2761
2762 numeric:  FLOAT
2763                                 {       $$ = xlateSqlType("float8"); }
2764                 | DOUBLE PRECISION
2765                                 {       $$ = xlateSqlType("float8"); }
2766                 | DECIMAL
2767                                 {       $$ = xlateSqlType("decimal"); }
2768                 | NUMERIC
2769                                 {       $$ = xlateSqlType("numeric"); }
2770                 ;
2771
2772 opt_float:  '(' Iconst ')'
2773                                 {
2774                                         if ($2 < 1)
2775                                                 elog(ERROR,"precision for FLOAT must be at least 1");
2776                                         else if ($2 < 7)
2777                                                 $$ = xlateSqlType("float4");
2778                                         else if ($2 < 16)
2779                                                 $$ = xlateSqlType("float8");
2780                                         else
2781                                                 elog(ERROR,"precision for FLOAT must be less than 16");
2782                                 }
2783                 | /*EMPTY*/
2784                                 {
2785                                         $$ = xlateSqlType("float8");
2786                                 }
2787                 ;
2788
2789 opt_numeric:  '(' Iconst ',' Iconst ')'
2790                                 {
2791                                         if ($2 != 9)
2792                                                 elog(ERROR,"NUMERIC precision %d must be 9",$2);
2793                                         if ($4 != 0)
2794                                                 elog(ERROR,"NUMERIC scale %d must be zero",$4);
2795                                 }
2796                 | '(' Iconst ')'
2797                                 {
2798                                         if ($2 != 9)
2799                                                 elog(ERROR,"NUMERIC precision %d must be 9",$2);
2800                                 }
2801                 | /*EMPTY*/
2802                                 {
2803                                         $$ = NULL;
2804                                 }
2805                 ;
2806
2807 opt_decimal:  '(' Iconst ',' Iconst ')'
2808                                 {
2809                                         if ($2 > 9)
2810                                                 elog(ERROR,"DECIMAL precision %d exceeds implementation limit of 9",$2);
2811                                         if ($4 != 0)
2812                                                 elog(ERROR,"DECIMAL scale %d must be zero",$4);
2813                                         $$ = NULL;
2814                                 }
2815                 | '(' Iconst ')'
2816                                 {
2817                                         if ($2 > 9)
2818                                                 elog(ERROR,"DECIMAL precision %d exceeds implementation limit of 9",$2);
2819                                         $$ = NULL;
2820                                 }
2821                 | /*EMPTY*/
2822                                 {
2823                                         $$ = NULL;
2824                                 }
2825                 ;
2826
2827 /* SQL92 character data types
2828  * The following implements CHAR() and VARCHAR().
2829  * We do it here instead of the 'Generic' production
2830  * because we don't want to allow arrays of VARCHAR().
2831  * I haven't thought about whether that will work or not.
2832  *                                                              - ay 6/95
2833  */
2834 Character:  character '(' Iconst ')'
2835                                 {
2836                                         $$ = makeNode(TypeName);
2837                                         if (!strcasecmp($1, "char"))
2838                                                 $$->name = xlateSqlType("bpchar");
2839                                         else if (!strcasecmp($1, "varchar"))
2840                                                 $$->name = xlateSqlType("varchar");
2841                                         else
2842                                                 yyerror("parse error");
2843                                         if ($3 < 1)
2844                                                 elog(ERROR,"length for '%s' type must be at least 1",$1);
2845                                         else if ($3 > 4096)
2846                                                 /* we can store a char() of length up to the size
2847                                                  * of a page (8KB) - page headers and friends but
2848                                                  * just to be safe here...      - ay 6/95
2849                                                  * XXX note this hardcoded limit - thomas 1997-07-13
2850                                                  */
2851                                                 elog(ERROR,"length for type '%s' cannot exceed 4096",$1);
2852
2853                                         /* we actually implement this sort of like a varlen, so
2854                                          * the first 4 bytes is the length. (the difference
2855                                          * between this and "text" is that we blank-pad and
2856                                          * truncate where necessary
2857                                          */
2858                                         $$->typmod = VARHDRSZ + $3;
2859                                 }
2860                 | character
2861                                 {
2862                                         $$ = makeNode(TypeName);
2863                                         $$->name = xlateSqlType($1);
2864                                         $$->typmod = -1;
2865                                 }
2866                 ;
2867
2868 character:  CHARACTER opt_varying opt_charset opt_collate
2869                                 {
2870                                         char *type, *c;
2871                                         if (($3 == NULL) || (strcasecmp($3, "sql_text") == 0)) {
2872                                                 if ($2) type = xlateSqlType("varchar");
2873                                                 else type = xlateSqlType("char");
2874                                         } else {
2875                                                 if ($2) {
2876                                                         c = palloc(strlen("var") + strlen($3) + 1);
2877                                                         strcpy(c, "var");
2878                                                         strcat(c, $3);
2879                                                         type = xlateSqlType(c);
2880                                                 } else {
2881                                                         type = xlateSqlType($3);
2882                                                 }
2883                                         };
2884                                         if ($4 != NULL)
2885                                         elog(ERROR,"COLLATE %s not yet implemented",$4);
2886                                         $$ = type;
2887                                 }
2888                 | CHAR opt_varying                                              { $$ = xlateSqlType($2? "varchar": "char"); }
2889                 | VARCHAR                                                               { $$ = xlateSqlType("varchar"); }
2890                 | NATIONAL CHARACTER opt_varying                { $$ = xlateSqlType($3? "varchar": "char"); }
2891                 | NCHAR opt_varying                                             { $$ = xlateSqlType($2? "varchar": "char"); }
2892                 ;
2893
2894 opt_varying:  VARYING                                                   { $$ = TRUE; }
2895                 | /*EMPTY*/                                                             { $$ = FALSE; }
2896                 ;
2897
2898 opt_charset:  CHARACTER SET ColId                               { $$ = $3; }
2899                 | /*EMPTY*/                                                             { $$ = NULL; }
2900                 ;
2901
2902 opt_collate:  COLLATE ColId                                             { $$ = $2; }
2903                 | /*EMPTY*/                                                             { $$ = NULL; }
2904                 ;
2905
2906 Datetime:  datetime
2907                                 {
2908                                         $$ = makeNode(TypeName);
2909                                         $$->name = xlateSqlType($1);
2910                                         $$->typmod = -1;
2911                                 }
2912                 | TIMESTAMP opt_timezone
2913                                 {
2914                                         $$ = makeNode(TypeName);
2915                                         $$->name = xlateSqlType("timestamp");
2916                                         $$->timezone = $2;
2917                                         $$->typmod = -1;
2918                                 }
2919                 | TIME
2920                                 {
2921                                         $$ = makeNode(TypeName);
2922                                         $$->name = xlateSqlType("time");
2923                                         $$->typmod = -1;
2924                                 }
2925                 | INTERVAL opt_interval
2926                                 {
2927                                         $$ = makeNode(TypeName);
2928                                         $$->name = xlateSqlType("interval");
2929                                         $$->typmod = -1;
2930                                 }
2931                 ;
2932
2933 datetime:  YEAR_P                                                               { $$ = "year"; }
2934                 | MONTH_P                                                               { $$ = "month"; }
2935                 | DAY_P                                                                 { $$ = "day"; }
2936                 | HOUR_P                                                                { $$ = "hour"; }
2937                 | MINUTE_P                                                              { $$ = "minute"; }
2938                 | SECOND_P                                                              { $$ = "second"; }
2939                 ;
2940
2941 opt_timezone:  WITH TIME ZONE                                   { $$ = TRUE; }
2942                 | /*EMPTY*/                                                             { $$ = FALSE; }
2943                 ;
2944
2945 opt_interval:  datetime                                                 { $$ = lcons($1, NIL); }
2946                 | YEAR_P TO MONTH_P                                             { $$ = NIL; }
2947                 | DAY_P TO HOUR_P                                               { $$ = NIL; }
2948                 | DAY_P TO MINUTE_P                                             { $$ = NIL; }
2949                 | DAY_P TO SECOND_P                                             { $$ = NIL; }
2950                 | HOUR_P TO MINUTE_P                                    { $$ = NIL; }
2951                 | HOUR_P TO SECOND_P                                    { $$ = NIL; }
2952                 | /*EMPTY*/                                                             { $$ = NIL; }
2953                 ;
2954
2955
2956 /*****************************************************************************
2957  *
2958  *      expression grammar, still needs some cleanup
2959  *
2960  *****************************************************************************/
2961
2962 a_expr_or_null:  a_expr
2963                                 { $$ = $1; }
2964                 | NULL_P
2965                                 {
2966                                         A_Const *n = makeNode(A_Const);
2967                                         n->val.type = T_Null;
2968                                         $$ = (Node *)n;
2969                                 }
2970                 ;
2971
2972 /* Expressions using row descriptors
2973  * Define row_descriptor to allow yacc to break the reduce/reduce conflict
2974  *  with singleton expressions.
2975  */
2976 row_expr: '(' row_descriptor ')' IN '(' SubSelect ')'
2977                                 {
2978                                         SubLink *n = makeNode(SubLink);
2979                                         n->lefthand = $2;
2980                                         n->oper = lcons("=",NIL);
2981                                         n->useor = false;
2982                                         n->subLinkType = ANY_SUBLINK;
2983                                         n->subselect = $6;
2984                                         $$ = (Node *)n;
2985                                 }
2986                 | '(' row_descriptor ')' NOT IN '(' SubSelect ')'
2987                                 {
2988                                         SubLink *n = makeNode(SubLink);
2989                                         n->lefthand = $2;
2990                                         n->oper = lcons("<>",NIL);
2991                                         n->useor = true;
2992                                         n->subLinkType = ALL_SUBLINK;
2993                                         n->subselect = $7;
2994                                         $$ = (Node *)n;
2995                                 }
2996                 | '(' row_descriptor ')' Op '(' SubSelect ')'
2997                                 {
2998                                         SubLink *n = makeNode(SubLink);
2999                                         n->lefthand = $2;
3000                                         n->oper = lcons($4, NIL);
3001                                         if (strcmp($4,"<>") == 0)
3002                                                 n->useor = true;
3003                                         else
3004                                                 n->useor = false;
3005                                         n->subLinkType = EXPR_SUBLINK;
3006                                         n->subselect = $6;
3007                                         $$ = (Node *)n;
3008                                 }
3009                 | '(' row_descriptor ')' '+' '(' SubSelect ')'
3010                                 {
3011                                         SubLink *n = makeNode(SubLink);
3012                                         n->lefthand = $2;
3013                                         n->oper = lcons("+", NIL);
3014                                         n->useor = false;
3015                                         n->subLinkType = EXPR_SUBLINK;
3016                                         n->subselect = $6;
3017                                         $$ = (Node *)n;
3018                                 }
3019                 | '(' row_descriptor ')' '-' '(' SubSelect ')'
3020                                 {
3021                                         SubLink *n = makeNode(SubLink);
3022                                         n->lefthand = $2;
3023                                         n->oper = lcons("-", NIL);
3024                                         n->useor = false;
3025                                         n->subLinkType = EXPR_SUBLINK;
3026                                         n->subselect = $6;
3027                                         $$ = (Node *)n;
3028                                 }
3029                 | '(' row_descriptor ')' '/' '(' SubSelect ')'
3030                                 {
3031                                         SubLink *n = makeNode(SubLink);
3032                                         n->lefthand = $2;
3033                                         n->oper = lcons("/", NIL);
3034                                         n->useor = false;
3035                                         n->subLinkType = EXPR_SUBLINK;
3036                                         n->subselect = $6;
3037                                         $$ = (Node *)n;
3038                                 }
3039                 | '(' row_descriptor ')' '*' '(' SubSelect ')'
3040                                 {
3041                                         SubLink *n = makeNode(SubLink);
3042                                         n->lefthand = $2;
3043                                         n->oper = lcons("*", NIL);
3044                                         n->useor = false;
3045                                         n->subLinkType = EXPR_SUBLINK;
3046                                         n->subselect = $6;
3047                                         $$ = (Node *)n;
3048                                 }
3049                 | '(' row_descriptor ')' '<' '(' SubSelect ')'
3050                                 {
3051                                         SubLink *n = makeNode(SubLink);
3052                                         n->lefthand = $2;
3053                                         n->oper = lcons("<", NIL);
3054                                         n->useor = false;
3055                                         n->subLinkType = EXPR_SUBLINK;
3056                                         n->subselect = $6;
3057                                         $$ = (Node *)n;
3058                                 }
3059                 | '(' row_descriptor ')' '>' '(' SubSelect ')'
3060                                 {
3061                                         SubLink *n = makeNode(SubLink);
3062                                         n->lefthand = $2;
3063                                         n->oper = lcons(">", NIL);
3064                                         n->useor = false;
3065                                         n->subLinkType = EXPR_SUBLINK;
3066                                         n->subselect = $6;
3067                                         $$ = (Node *)n;
3068                                 }
3069                 | '(' row_descriptor ')' '=' '(' SubSelect ')'
3070                                 {
3071                                         SubLink *n = makeNode(SubLink);
3072                                         n->lefthand = $2;
3073                                         n->oper = lcons("=", NIL);
3074                                         n->useor = false;
3075                                         n->subLinkType = EXPR_SUBLINK;
3076                                         n->subselect = $6;
3077                                         $$ = (Node *)n;
3078                                 }
3079                 | '(' row_descriptor ')' Op ANY '(' SubSelect ')'
3080                                 {
3081                                         SubLink *n = makeNode(SubLink);
3082                                         n->lefthand = $2;
3083                                         n->oper = lcons($4,NIL);
3084                                         if (strcmp($4,"<>") == 0)
3085                                                 n->useor = true;
3086                                         else
3087                                                 n->useor = false;
3088                                         n->subLinkType = ANY_SUBLINK;
3089                                         n->subselect = $7;
3090                                         $$ = (Node *)n;
3091                                 }
3092                 | '(' row_descriptor ')' '+' ANY '(' SubSelect ')'
3093                                 {
3094                                         SubLink *n = makeNode(SubLink);
3095                                         n->lefthand = $2;
3096                                         n->oper = lcons("+",NIL);
3097                                         n->useor = false;
3098                                         n->subLinkType = ANY_SUBLINK;
3099                                         n->subselect = $7;
3100                                         $$ = (Node *)n;
3101                                 }
3102                 | '(' row_descriptor ')' '-' ANY '(' SubSelect ')'
3103                                 {
3104                                         SubLink *n = makeNode(SubLink);
3105                                         n->lefthand = $2;
3106                                         n->oper = lcons("-",NIL);
3107                                         n->useor = false;
3108                                         n->subLinkType = ANY_SUBLINK;
3109                                         n->subselect = $7;
3110                                         $$ = (Node *)n;
3111                                 }
3112                 | '(' row_descriptor ')' '/' ANY '(' SubSelect ')'
3113                                 {
3114                                         SubLink *n = makeNode(SubLink);
3115                                         n->lefthand = $2;
3116                                         n->oper = lcons("/",NIL);
3117                                         n->useor = false;
3118                                         n->subLinkType = ANY_SUBLINK;
3119                                         n->subselect = $7;
3120                                         $$ = (Node *)n;
3121                                 }
3122                 | '(' row_descriptor ')' '*' ANY '(' SubSelect ')'
3123                                 {
3124                                         SubLink *n = makeNode(SubLink);
3125                                         n->lefthand = $2;
3126                                         n->oper = lcons("*",NIL);
3127                                         n->useor = false;
3128                                         n->subLinkType = ANY_SUBLINK;
3129                                         n->subselect = $7;
3130                                         $$ = (Node *)n;
3131                                 }
3132                 | '(' row_descriptor ')' '<' ANY '(' SubSelect ')'
3133                                 {
3134                                         SubLink *n = makeNode(SubLink);
3135                                         n->lefthand = $2;
3136                                         n->oper = lcons("<",NIL);
3137                                         n->useor = false;
3138                                         n->subLinkType = ANY_SUBLINK;
3139                                         n->subselect = $7;
3140                                         $$ = (Node *)n;
3141                                 }
3142                 | '(' row_descriptor ')' '>' ANY '(' SubSelect ')'
3143                                 {
3144                                         SubLink *n = makeNode(SubLink);
3145                                         n->lefthand = $2;
3146                                         n->oper = lcons(">",NIL);
3147                                         n->useor = false;
3148                                         n->subLinkType = ANY_SUBLINK;
3149                                         n->subselect = $7;
3150                                         $$ = (Node *)n;
3151                                 }
3152                 | '(' row_descriptor ')' '=' ANY '(' SubSelect ')'
3153                                 {
3154                                         SubLink *n = makeNode(SubLink);
3155                                         n->lefthand = $2;
3156                                         n->oper = lcons("=",NIL);
3157                                         n->useor = false;
3158                                         n->subLinkType = ANY_SUBLINK;
3159                                         n->subselect = $7;
3160                                         $$ = (Node *)n;
3161                                 }
3162                 | '(' row_descriptor ')' Op ALL '(' SubSelect ')'
3163                                 {
3164                                         SubLink *n = makeNode(SubLink);
3165                                         n->lefthand = $2;
3166                                         n->oper = lcons($4,NIL);
3167                                         if (strcmp($4,"<>") == 0)
3168                                                 n->useor = true;
3169                                         else
3170                                                 n->useor = false;
3171                                         n->subLinkType = ALL_SUBLINK;
3172                                         n->subselect = $7;
3173                                         $$ = (Node *)n;
3174                                 }
3175                 | '(' row_descriptor ')' '+' ALL '(' SubSelect ')'
3176                                 {
3177                                         SubLink *n = makeNode(SubLink);
3178                                         n->lefthand = $2;
3179                                         n->oper = lcons("+",NIL);
3180                                         n->useor = false;
3181                                         n->subLinkType = ALL_SUBLINK;
3182                                         n->subselect = $7;
3183                                         $$ = (Node *)n;
3184                                 }
3185                 | '(' row_descriptor ')' '-' ALL '(' SubSelect ')'
3186                                 {
3187                                         SubLink *n = makeNode(SubLink);
3188                                         n->lefthand = $2;
3189                                         n->oper = lcons("-",NIL);
3190                                         n->useor = false;
3191                                         n->subLinkType = ALL_SUBLINK;
3192                                         n->subselect = $7;
3193                                         $$ = (Node *)n;
3194                                 }
3195                 | '(' row_descriptor ')' '/' ALL '(' SubSelect ')'
3196                                 {
3197                                         SubLink *n = makeNode(SubLink);
3198                                         n->lefthand = $2;
3199                                         n->oper = lcons("/",NIL);
3200                                         n->useor = false;
3201                                         n->subLinkType = ALL_SUBLINK;
3202                                         n->subselect = $7;
3203                                         $$ = (Node *)n;
3204                                 }
3205                 | '(' row_descriptor ')' '*' ALL '(' SubSelect ')'
3206                                 {
3207                                         SubLink *n = makeNode(SubLink);
3208                                         n->lefthand = $2;
3209                                         n->oper = lcons("*",NIL);
3210                                         n->useor = false;
3211                                         n->subLinkType = ALL_SUBLINK;
3212                                         n->subselect = $7;
3213                                         $$ = (Node *)n;
3214                                 }
3215                 | '(' row_descriptor ')' '<' ALL '(' SubSelect ')'
3216                                 {
3217                                         SubLink *n = makeNode(SubLink);
3218                                         n->lefthand = $2;
3219                                         n->oper = lcons("<",NIL);
3220                                         n->useor = false;
3221                                         n->subLinkType = ALL_SUBLINK;
3222                                         n->subselect = $7;
3223                                         $$ = (Node *)n;
3224                                 }
3225                 | '(' row_descriptor ')' '>' ALL '(' SubSelect ')'
3226                                 {
3227                                         SubLink *n = makeNode(SubLink);
3228                                         n->lefthand = $2;
3229                                         n->oper = lcons(">",NIL);
3230                                         n->useor = false;
3231                                         n->subLinkType = ALL_SUBLINK;
3232                                         n->subselect = $7;
3233                                         $$ = (Node *)n;
3234                                 }
3235                 | '(' row_descriptor ')' '=' ALL '(' SubSelect ')'
3236                                 {
3237                                         SubLink *n = makeNode(SubLink);
3238                                         n->lefthand = $2;
3239                                         n->oper = lcons("=",NIL);
3240                                         n->useor = false;
3241                                         n->subLinkType = ALL_SUBLINK;
3242                                         n->subselect = $7;
3243                                         $$ = (Node *)n;
3244                                 }
3245                 | '(' row_descriptor ')' Op '(' row_descriptor ')'
3246                                 {
3247                                         $$ = makeRowExpr($4, $2, $6);
3248                                 }
3249                 | '(' row_descriptor ')' '+' '(' row_descriptor ')'
3250                                 {
3251                                         $$ = makeRowExpr("+", $2, $6);
3252                                 }
3253                 | '(' row_descriptor ')' '-' '(' row_descriptor ')'
3254                                 {
3255                                         $$ = makeRowExpr("-", $2, $6);
3256                                 }
3257                 | '(' row_descriptor ')' '/' '(' row_descriptor ')'
3258                                 {
3259                                         $$ = makeRowExpr("/", $2, $6);
3260                                 }
3261                 | '(' row_descriptor ')' '*' '(' row_descriptor ')'
3262                                 {
3263                                         $$ = makeRowExpr("*", $2, $6);
3264                                 }
3265                 | '(' row_descriptor ')' '<' '(' row_descriptor ')'
3266                                 {
3267                                         $$ = makeRowExpr("<", $2, $6);
3268                                 }
3269                 | '(' row_descriptor ')' '>' '(' row_descriptor ')'
3270                                 {
3271                                         $$ = makeRowExpr(">", $2, $6);
3272                                 }
3273                 | '(' row_descriptor ')' '=' '(' row_descriptor ')'
3274                                 {
3275                                         $$ = makeRowExpr("=", $2, $6);
3276                                 }
3277                 ;
3278
3279 row_descriptor:  row_list ',' a_expr
3280                                 {
3281                                         $$ = lappend($1, $3);
3282                                 }
3283                 ;
3284
3285 row_list:  row_list ',' a_expr
3286                                 {
3287                                         $$ = lappend($1, $3);
3288                                 }
3289                 | a_expr
3290                                 {
3291                                         $$ = lcons($1, NIL);
3292                                 }
3293                 ;
3294
3295 /*
3296  * This is the heart of the expression syntax.
3297  * Note that the BETWEEN clause looks similar to a boolean expression
3298  *  and so we must define b_expr which is almost the same as a_expr
3299  *  but without the boolean expressions.
3300  * All operations are allowed in a BETWEEN clause if surrounded by parens.
3301  */
3302
3303 a_expr:  attr opt_indirection
3304                                 {
3305                                         $1->indirection = $2;
3306                                         $$ = (Node *)$1;
3307                                 }
3308                 | row_expr
3309                                 {       $$ = $1;  }
3310                 | AexprConst
3311                                 {       $$ = $1;  }
3312                 | ColId
3313                                 {
3314                                         /* could be a column name or a relation_name */
3315                                         Ident *n = makeNode(Ident);
3316                                         n->name = $1;
3317                                         n->indirection = NULL;
3318                                         $$ = (Node *)n;
3319                                 }
3320                 | '-' a_expr %prec UMINUS
3321                                 {       $$ = makeA_Expr(OP, "-", NULL, $2); }
3322                 | a_expr '+' a_expr
3323                                 {       $$ = makeA_Expr(OP, "+", $1, $3); }
3324                 | a_expr '-' a_expr
3325                                 {       $$ = makeA_Expr(OP, "-", $1, $3); }
3326                 | a_expr '/' a_expr
3327                                 {       $$ = makeA_Expr(OP, "/", $1, $3); }
3328                 | a_expr '*' a_expr
3329                                 {       $$ = makeA_Expr(OP, "*", $1, $3); }
3330                 | a_expr '<' a_expr
3331                                 {       $$ = makeA_Expr(OP, "<", $1, $3); }
3332                 | a_expr '>' a_expr
3333                                 {       $$ = makeA_Expr(OP, ">", $1, $3); }
3334                 | a_expr '=' a_expr
3335                                 {       $$ = makeA_Expr(OP, "=", $1, $3); }
3336                 | ':' a_expr
3337                                 {       $$ = makeA_Expr(OP, ":", NULL, $2); }
3338                 | ';' a_expr
3339                                 {       $$ = makeA_Expr(OP, ";", NULL, $2); }
3340                 | '|' a_expr
3341                                 {       $$ = makeA_Expr(OP, "|", NULL, $2); }
3342                 | a_expr TYPECAST Typename
3343                                 {
3344                                         $$ = (Node *)$1;
3345                                         /* AexprConst can be either A_Const or ParamNo */
3346                                         if (nodeTag($1) == T_A_Const) {
3347                                                 ((A_Const *)$1)->typename = $3;
3348                                         } else if (nodeTag($1) == T_Param) {
3349                                                 ((ParamNo *)$1)->typename = $3;
3350                                         /* otherwise, try to transform to a function call */
3351                                         } else {
3352                                                 FuncCall *n = makeNode(FuncCall);
3353                                                 n->funcname = $3->name;
3354                                                 n->args = lcons($1,NIL);
3355                                                 $$ = (Node *)n;
3356                                         }
3357                                 }
3358                 | CAST '(' a_expr AS Typename ')'
3359                                 {
3360                                         $$ = (Node *)$3;
3361                                         /* AexprConst can be either A_Const or ParamNo */
3362                                         if (nodeTag($3) == T_A_Const) {
3363                                                 ((A_Const *)$3)->typename = $5;
3364                                         } else if (nodeTag($5) == T_Param) {
3365                                                 ((ParamNo *)$3)->typename = $5;
3366                                         /* otherwise, try to transform to a function call */
3367                                         } else {
3368                                                 FuncCall *n = makeNode(FuncCall);
3369                                                 n->funcname = $5->name;
3370                                                 n->args = lcons($3,NIL);
3371                                                 $$ = (Node *)n;
3372                                         }
3373                                 }
3374                 | '(' a_expr_or_null ')'
3375                                 {       $$ = $2; }
3376                 | a_expr Op a_expr
3377                                 {       $$ = makeIndexable($2,$1,$3);   }
3378                 | a_expr LIKE a_expr
3379                                 {       $$ = makeIndexable("~~", $1, $3); }
3380                 | a_expr NOT LIKE a_expr
3381                                 {       $$ = makeA_Expr(OP, "!~~", $1, $4); }
3382                 | Op a_expr
3383                                 {       $$ = makeA_Expr(OP, $1, NULL, $2); }
3384                 | a_expr Op
3385                                 {       $$ = makeA_Expr(OP, $2, $1, NULL); }
3386                 | func_name '(' '*' ')'
3387                                 {
3388                                         /* cheap hack for aggregate (eg. count) */
3389                                         FuncCall *n = makeNode(FuncCall);
3390                                         A_Const *star = makeNode(A_Const);
3391
3392                                         star->val.type = T_String;
3393                                         star->val.val.str = "";
3394                                         n->funcname = $1;
3395                                         n->args = lcons(star, NIL);
3396                                         $$ = (Node *)n;
3397                                 }
3398                 | func_name '(' ')'
3399                                 {
3400                                         FuncCall *n = makeNode(FuncCall);
3401                                         n->funcname = $1;
3402                                         n->args = NIL;
3403                                         $$ = (Node *)n;
3404                                 }
3405                 | func_name '(' expr_list ')'
3406                                 {
3407                                         FuncCall *n = makeNode(FuncCall);
3408                                         n->funcname = $1;
3409                                         n->args = $3;
3410                                         $$ = (Node *)n;
3411                                 }
3412                 | CURRENT_DATE
3413                                 {
3414                                         A_Const *n = makeNode(A_Const);
3415                                         TypeName *t = makeNode(TypeName);
3416
3417                                         n->val.type = T_String;
3418                                         n->val.val.str = "now";
3419                                         n->typename = t;
3420
3421                                         t->name = xlateSqlType("date");
3422                                         t->setof = FALSE;
3423                                         t->typmod = -1;
3424  
3425                                         $$ = (Node *)n;
3426                                 }
3427                 | CURRENT_TIME
3428                                 {
3429                                         A_Const *n = makeNode(A_Const);
3430                                         TypeName *t = makeNode(TypeName);
3431
3432                                         n->val.type = T_String;
3433                                         n->val.val.str = "now";
3434                                         n->typename = t;
3435
3436                                         t->name = xlateSqlType("time");
3437                                         t->setof = FALSE;
3438                                         t->typmod = -1;
3439
3440                                         $$ = (Node *)n;
3441                                 }
3442                 | CURRENT_TIME '(' Iconst ')'
3443                                 {
3444                                         FuncCall *n = makeNode(FuncCall);
3445                                         A_Const *s = makeNode(A_Const);
3446                                         TypeName *t = makeNode(TypeName);
3447
3448                                         n->funcname = xlateSqlType("time");
3449                                         n->args = lcons(s, NIL);
3450
3451                                         s->val.type = T_String;
3452                                         s->val.val.str = "now";
3453                                         s->typename = t;
3454
3455                                         t->name = xlateSqlType("time");
3456                                         t->setof = FALSE;
3457                                         t->typmod = -1;
3458
3459                                         if ($3 != 0)
3460                                                 elog(NOTICE,"CURRENT_TIME(%d) precision not implemented; zero used instead",$3);
3461
3462                                         $$ = (Node *)n;
3463                                 }
3464                 | CURRENT_TIMESTAMP
3465                                 {
3466                                         A_Const *n = makeNode(A_Const);
3467                                         TypeName *t = makeNode(TypeName);
3468
3469                                         n->val.type = T_String;
3470                                         n->val.val.str = "now";
3471                                         n->typename = t;
3472
3473                                         t->name = xlateSqlType("timestamp");
3474                                         t->setof = FALSE;
3475                                         t->typmod = -1;
3476
3477                                         $$ = (Node *)n;
3478                                 }
3479                 | CURRENT_TIMESTAMP '(' Iconst ')'
3480                                 {
3481                                         FuncCall *n = makeNode(FuncCall);
3482                                         A_Const *s = makeNode(A_Const);
3483                                         TypeName *t = makeNode(TypeName);
3484
3485                                         n->funcname = xlateSqlType("timestamp");
3486                                         n->args = lcons(s, NIL);
3487
3488                                         s->val.type = T_String;
3489                                         s->val.val.str = "now";
3490                                         s->typename = t;
3491
3492                                         t->name = xlateSqlType("timestamp");
3493                                         t->setof = FALSE;
3494                                         t->typmod = -1;
3495
3496                                         if ($3 != 0)
3497                                                 elog(NOTICE,"CURRENT_TIMESTAMP(%d) precision not implemented; zero used instead",$3);
3498
3499                                         $$ = (Node *)n;
3500                                 }
3501                 | CURRENT_USER
3502                                 {
3503                                         FuncCall *n = makeNode(FuncCall);
3504                                         n->funcname = "getpgusername";
3505                                         n->args = NIL;
3506                                         $$ = (Node *)n;
3507                                 }
3508                 | EXISTS '(' SubSelect ')'
3509                                 {
3510                                         SubLink *n = makeNode(SubLink);
3511                                         n->lefthand = NIL;
3512                                         n->useor = false;
3513                                         n->oper = NIL;
3514                                         n->subLinkType = EXISTS_SUBLINK;
3515                                         n->subselect = $3;
3516                                         $$ = (Node *)n;
3517                                 }
3518                 | EXTRACT '(' extract_list ')'
3519                                 {
3520                                         FuncCall *n = makeNode(FuncCall);
3521                                         n->funcname = "date_part";
3522                                         n->args = $3;
3523                                         $$ = (Node *)n;
3524                                 }
3525                 | POSITION '(' position_list ')'
3526                                 {
3527                                         FuncCall *n = makeNode(FuncCall);
3528                                         n->funcname = "strpos";
3529                                         n->args = $3;
3530                                         $$ = (Node *)n;
3531                                 }
3532                 | SUBSTRING '(' substr_list ')'
3533                                 {
3534                                         FuncCall *n = makeNode(FuncCall);
3535                                         n->funcname = "substr";
3536                                         n->args = $3;
3537                                         $$ = (Node *)n;
3538                                 }
3539                 /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
3540                 | TRIM '(' BOTH trim_list ')'
3541                                 {
3542                                         FuncCall *n = makeNode(FuncCall);
3543                                         n->funcname = "btrim";
3544                                         n->args = $4;
3545                                         $$ = (Node *)n;
3546                                 }
3547                 | TRIM '(' LEADING trim_list ')'
3548                                 {
3549                                         FuncCall *n = makeNode(FuncCall);
3550                                         n->funcname = "ltrim";
3551                                         n->args = $4;
3552                                         $$ = (Node *)n;
3553                                 }
3554                 | TRIM '(' TRAILING trim_list ')'
3555                                 {
3556                                         FuncCall *n = makeNode(FuncCall);
3557                                         n->funcname = "rtrim";
3558                                         n->args = $4;
3559                                         $$ = (Node *)n;
3560                                 }
3561                 | TRIM '(' trim_list ')'
3562                                 {
3563                                         FuncCall *n = makeNode(FuncCall);
3564                                         n->funcname = "btrim";
3565                                         n->args = $3;
3566                                         $$ = (Node *)n;
3567                                 }
3568                 | a_expr ISNULL
3569                                 {       $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
3570                 | a_expr IS NULL_P
3571                                 {       $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
3572                 | a_expr NOTNULL
3573                                 {       $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); }
3574                 | a_expr IS NOT NULL_P
3575                                 {       $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); }
3576                 /* IS TRUE, IS FALSE, etc used to be function calls
3577                  *  but let's make them expressions to allow the optimizer
3578                  *  a chance to eliminate them if a_expr is a constant string.
3579                  * - thomas 1997-12-22
3580                  */
3581                 | a_expr IS TRUE_P
3582                                 {
3583                                         A_Const *n = makeNode(A_Const);
3584                                         n->val.type = T_String;
3585                                         n->val.val.str = "t";
3586                                         n->typename = makeNode(TypeName);
3587                                         n->typename->name = xlateSqlType("bool");
3588                                         n->typename->typmod = -1;
3589                                         $$ = makeA_Expr(OP, "=", $1,(Node *)n);
3590                                 }
3591                 | a_expr IS NOT FALSE_P
3592                                 {
3593                                         A_Const *n = makeNode(A_Const);
3594                                         n->val.type = T_String;
3595                                         n->val.val.str = "t";
3596                                         n->typename = makeNode(TypeName);
3597                                         n->typename->name = xlateSqlType("bool");
3598                                         n->typename->typmod = -1;
3599                                         $$ = makeA_Expr(OP, "=", $1,(Node *)n);
3600                                 }
3601                 | a_expr IS FALSE_P
3602                                 {
3603                                         A_Const *n = makeNode(A_Const);
3604                                         n->val.type = T_String;
3605                                         n->val.val.str = "f";
3606                                         n->typename = makeNode(TypeName);
3607                                         n->typename->name = xlateSqlType("bool");
3608                                         n->typename->typmod = -1;
3609                                         $$ = makeA_Expr(OP, "=", $1,(Node *)n);
3610                                 }
3611                 | a_expr IS NOT TRUE_P
3612                                 {
3613                                         A_Const *n = makeNode(A_Const);
3614                                         n->val.type = T_String;
3615                                         n->val.val.str = "f";
3616                                         n->typename = makeNode(TypeName);
3617                                         n->typename->name = xlateSqlType("bool");
3618                                         n->typename->typmod = -1;
3619                                         $$ = makeA_Expr(OP, "=", $1,(Node *)n);
3620                                 }
3621                 | a_expr BETWEEN b_expr AND b_expr
3622                                 {
3623                                         $$ = makeA_Expr(AND, NULL,
3624                                                 makeA_Expr(OP, ">=", $1, $3),
3625                                                 makeA_Expr(OP, "<=", $1, $5));
3626                                 }
3627                 | a_expr NOT BETWEEN b_expr AND b_expr
3628                                 {
3629                                         $$ = makeA_Expr(OR, NULL,
3630                                                 makeA_Expr(OP, "<", $1, $4),
3631                                                 makeA_Expr(OP, ">", $1, $6));
3632                                 }
3633                 | a_expr IN { saved_In_Expr = lcons($1,saved_In_Expr); } '(' in_expr ')'
3634                                 {
3635                                         saved_In_Expr = lnext(saved_In_Expr);
3636                                         if (nodeTag($5) == T_SubLink)
3637                                         {
3638                                                         SubLink *n = (SubLink *)$5;
3639                                                         n->lefthand = lcons($1, NIL);
3640                                                         n->oper = lcons("=",NIL);
3641                                                         n->useor = false;
3642                                                         n->subLinkType = ANY_SUBLINK;
3643                                                         $$ = (Node *)n;
3644                                         }
3645                                         else    $$ = $5;
3646                                 }
3647                 | a_expr NOT IN { saved_In_Expr = lcons($1,saved_In_Expr); } '(' not_in_expr ')'
3648                                 {
3649                                         saved_In_Expr = lnext(saved_In_Expr);
3650                                         if (nodeTag($6) == T_SubLink)
3651                                         {
3652                                                         SubLink *n = (SubLink *)$6;
3653                                                         n->lefthand = lcons($1, NIL);
3654                                                         n->oper = lcons("<>",NIL);
3655                                                         n->useor = false;
3656                                                         n->subLinkType = ALL_SUBLINK;
3657                                                         $$ = (Node *)n;
3658                                         }
3659                                         else    $$ = $6;
3660                                 }
3661                 | a_expr Op '(' SubSelect ')'
3662                                 {
3663                                         SubLink *n = makeNode(SubLink);
3664                                         n->lefthand = lcons($1, NULL);
3665                                         n->oper = lcons($2,NIL);
3666                                         n->useor = false;
3667                                         n->subLinkType = EXPR_SUBLINK;
3668                                         n->subselect = $4;
3669                                         $$ = (Node *)n;
3670                                 }
3671                 | a_expr '+' '(' SubSelect ')'
3672                                 {
3673                                         SubLink *n = makeNode(SubLink);
3674                                         n->lefthand = lcons($1, NULL);
3675                                         n->oper = lcons("+",NIL);
3676                                         n->useor = false;
3677                                         n->subLinkType = EXPR_SUBLINK;
3678                                         n->subselect = $4;
3679                                         $$ = (Node *)n;
3680                                 }
3681                 | a_expr '-' '(' SubSelect ')'
3682                                 {
3683                                         SubLink *n = makeNode(SubLink);
3684                                         n->lefthand = lcons($1, NULL);
3685                                         n->oper = lcons("-",NIL);
3686                                         n->useor = false;
3687                                         n->subLinkType = EXPR_SUBLINK;
3688                                         n->subselect = $4;
3689                                         $$ = (Node *)n;
3690                                 }
3691                 | a_expr '/' '(' SubSelect ')'
3692                                 {
3693                                         SubLink *n = makeNode(SubLink);
3694                                         n->lefthand = lcons($1, NULL);
3695                                         n->oper = lcons("/",NIL);
3696                                         n->useor = false;
3697                                         n->subLinkType = EXPR_SUBLINK;
3698                                         n->subselect = $4;
3699                                         $$ = (Node *)n;
3700                                 }
3701                 | a_expr '*' '(' SubSelect ')'
3702                                 {
3703                                         SubLink *n = makeNode(SubLink);
3704                                         n->lefthand = lcons($1, NULL);
3705                                         n->oper = lcons("*",NIL);
3706                                         n->useor = false;
3707                                         n->subLinkType = EXPR_SUBLINK;
3708                                         n->subselect = $4;
3709                                         $$ = (Node *)n;
3710                                 }
3711                 | a_expr '<' '(' SubSelect ')'
3712                                 {
3713                                         SubLink *n = makeNode(SubLink);
3714                                         n->lefthand = lcons($1, NULL);
3715                                         n->oper = lcons("<",NIL);
3716                                         n->useor = false;
3717                                         n->subLinkType = EXPR_SUBLINK;
3718                                         n->subselect = $4;
3719                                         $$ = (Node *)n;
3720                                 }
3721                 | a_expr '>' '(' SubSelect ')'
3722                                 {
3723                                         SubLink *n = makeNode(SubLink);
3724                                         n->lefthand = lcons($1, NULL);
3725                                         n->oper = lcons(">",NIL);
3726                                         n->useor = false;
3727                                         n->subLinkType = EXPR_SUBLINK;
3728                                         n->subselect = $4;
3729                                         $$ = (Node *)n;
3730                                 }
3731                 | a_expr '=' '(' SubSelect ')'
3732                                 {
3733                                         SubLink *n = makeNode(SubLink);
3734                                         n->lefthand = lcons($1, NULL);
3735                                         n->oper = lcons("=",NIL);
3736                                         n->useor = false;
3737                                         n->subLinkType = EXPR_SUBLINK;
3738                                         n->subselect = $4;
3739                                         $$ = (Node *)n;
3740                                 }
3741                 | a_expr Op ANY '(' SubSelect ')'
3742                                 {
3743                                         SubLink *n = makeNode(SubLink);
3744                                         n->lefthand = lcons($1,NIL);
3745                                         n->oper = lcons($2,NIL);
3746                                         n->useor = false;
3747                                         n->subLinkType = ANY_SUBLINK;
3748                                         n->subselect = $5;
3749                                         $$ = (Node *)n;
3750                                 }
3751                 | a_expr '+' ANY '(' SubSelect ')'
3752                                 {
3753                                         SubLink *n = makeNode(SubLink);
3754                                         n->lefthand = lcons($1,NIL);
3755                                         n->oper = lcons("+",NIL);
3756                                         n->useor = false;
3757                                         n->subLinkType = ANY_SUBLINK;
3758                                         n->subselect = $5;
3759                                         $$ = (Node *)n;
3760                                 }
3761                 | a_expr '-' ANY '(' SubSelect ')'
3762                                 {
3763                                         SubLink *n = makeNode(SubLink);
3764                                         n->lefthand = lcons($1,NIL);
3765                                         n->oper = lcons("-",NIL);
3766                                         n->useor = false;
3767                                         n->subLinkType = ANY_SUBLINK;
3768                                         n->subselect = $5;
3769                                         $$ = (Node *)n;
3770                                 }
3771                 | a_expr '/' ANY '(' SubSelect ')'
3772                                 {
3773                                         SubLink *n = makeNode(SubLink);
3774                                         n->lefthand = lcons($1,NIL);
3775                                         n->oper = lcons("/",NIL);
3776                                         n->useor = false;
3777                                         n->subLinkType = ANY_SUBLINK;
3778                                         n->subselect = $5;
3779                                         $$ = (Node *)n;
3780                                 }
3781                 | a_expr '*' ANY '(' SubSelect ')'
3782                                 {
3783                                         SubLink *n = makeNode(SubLink);
3784                                         n->lefthand = lcons($1,NIL);
3785                                         n->oper = lcons("*",NIL);
3786                                         n->useor = false;
3787                                         n->subLinkType = ANY_SUBLINK;
3788                                         n->subselect = $5;
3789                                         $$ = (Node *)n;
3790                                 }
3791                 | a_expr '<' ANY '(' SubSelect ')'
3792                                 {
3793                                         SubLink *n = makeNode(SubLink);
3794                                         n->lefthand = lcons($1,NIL);
3795                                         n->oper = lcons("<",NIL);
3796                                         n->useor = false;
3797                                         n->subLinkType = ANY_SUBLINK;
3798                                         n->subselect = $5;
3799                                         $$ = (Node *)n;
3800                                 }
3801                 | a_expr '>' ANY '(' SubSelect ')'
3802                                 {
3803                                         SubLink *n = makeNode(SubLink);
3804                                         n->lefthand = lcons($1,NIL);
3805                                         n->oper = lcons(">",NIL);
3806                                         n->useor = false;
3807                                         n->subLinkType = ANY_SUBLINK;
3808                                         n->subselect = $5;
3809                                         $$ = (Node *)n;
3810                                 }
3811                 | a_expr '=' ANY '(' SubSelect ')'
3812                                 {
3813                                         SubLink *n = makeNode(SubLink);
3814                                         n->lefthand = lcons($1,NIL);
3815                                         n->oper = lcons("=",NIL);
3816                                         n->useor = false;
3817                                         n->subLinkType = ANY_SUBLINK;
3818                                         n->subselect = $5;
3819                                         $$ = (Node *)n;
3820                                 }
3821                 | a_expr Op ALL '(' SubSelect ')'
3822                                 {
3823                                         SubLink *n = makeNode(SubLink);
3824                                         n->lefthand = lcons($1, NULL);
3825                                         n->oper = lcons($2,NIL);
3826                                         n->useor = false;
3827                                         n->subLinkType = ALL_SUBLINK;
3828                                         n->subselect = $5;
3829                                         $$ = (Node *)n;
3830                                 }
3831                 | a_expr '+' ALL '(' SubSelect ')'
3832                                 {
3833                                         SubLink *n = makeNode(SubLink);
3834                                         n->lefthand = lcons($1, NULL);
3835                                         n->oper = lcons("+",NIL);
3836                                         n->useor = false;
3837                                         n->subLinkType = ALL_SUBLINK;
3838                                         n->subselect = $5;
3839                                         $$ = (Node *)n;
3840                                 }
3841                 | a_expr '-' ALL '(' SubSelect ')'
3842                                 {
3843                                         SubLink *n = makeNode(SubLink);
3844                                         n->lefthand = lcons($1, NULL);
3845                                         n->oper = lcons("-",NIL);
3846                                         n->useor = false;
3847                                         n->subLinkType = ALL_SUBLINK;
3848                                         n->subselect = $5;
3849                                         $$ = (Node *)n;
3850                                 }
3851                 | a_expr '/' ALL '(' SubSelect ')'
3852                                 {
3853                                         SubLink *n = makeNode(SubLink);
3854                                         n->lefthand = lcons($1, NULL);
3855                                         n->oper = lcons("/",NIL);
3856                                         n->useor = false;
3857                                         n->subLinkType = ALL_SUBLINK;
3858                                         n->subselect = $5;
3859                                         $$ = (Node *)n;
3860                                 }
3861                 | a_expr '*' ALL '(' SubSelect ')'
3862                                 {
3863                                         SubLink *n = makeNode(SubLink);
3864                                         n->lefthand = lcons($1, NULL);
3865                                         n->oper = lcons("*",NIL);
3866                                         n->useor = false;
3867                                         n->subLinkType = ALL_SUBLINK;
3868                                         n->subselect = $5;
3869                                         $$ = (Node *)n;
3870                                 }
3871                 | a_expr '<' ALL '(' SubSelect ')'
3872                                 {
3873                                         SubLink *n = makeNode(SubLink);
3874                                         n->lefthand = lcons($1, NULL);
3875                                         n->oper = lcons("<",NIL);
3876                                         n->useor = false;
3877                                         n->subLinkType = ALL_SUBLINK;
3878                                         n->subselect = $5;
3879                                         $$ = (Node *)n;
3880                                 }
3881                 | a_expr '>' ALL '(' SubSelect ')'
3882                                 {
3883                                         SubLink *n = makeNode(SubLink);
3884                                         n->lefthand = lcons($1, NULL);
3885                                         n->oper = lcons(">",NIL);
3886                                         n->useor = false;
3887                                         n->subLinkType = ALL_SUBLINK;
3888                                         n->subselect = $5;
3889                                         $$ = (Node *)n;
3890                                 }
3891                 | a_expr '=' ALL '(' SubSelect ')'
3892                                 {
3893                                         SubLink *n = makeNode(SubLink);
3894                                         n->lefthand = lcons($1, NULL);
3895                                         n->oper = lcons("=",NIL);
3896                                         n->useor = false;
3897                                         n->subLinkType = ALL_SUBLINK;
3898                                         n->subselect = $5;
3899                                         $$ = (Node *)n;
3900                                 }
3901                 | a_expr AND a_expr
3902                                 {       $$ = makeA_Expr(AND, NULL, $1, $3); }
3903                 | a_expr OR a_expr
3904                                 {       $$ = makeA_Expr(OR, NULL, $1, $3); }
3905                 | NOT a_expr
3906                                 {       $$ = makeA_Expr(NOT, NULL, NULL, $2); }
3907                 ;
3908
3909 /*
3910  * b_expr is a subset of the complete expression syntax
3911  *  defined by a_expr. b_expr is used in BETWEEN clauses
3912  *  to eliminate parser ambiguities stemming from the AND keyword.
3913  */
3914
3915 b_expr:  attr opt_indirection
3916                                 {
3917                                         $1->indirection = $2;
3918                                         $$ = (Node *)$1;
3919                                 }
3920                 | AexprConst
3921                                 {       $$ = $1;  }
3922                 | ColId
3923                                 {
3924                                         /* could be a column name or a relation_name */
3925                                         Ident *n = makeNode(Ident);
3926                                         n->name = $1;
3927                                         n->indirection = NULL;
3928                                         $$ = (Node *)n;
3929                                 }
3930                 | '-' b_expr %prec UMINUS
3931                                 {       $$ = makeA_Expr(OP, "-", NULL, $2); }
3932                 | b_expr '+' b_expr
3933                                 {       $$ = makeA_Expr(OP, "+", $1, $3); }
3934                 | b_expr '-' b_expr
3935                                 {       $$ = makeA_Expr(OP, "-", $1, $3); }
3936                 | b_expr '/' b_expr
3937                                 {       $$ = makeA_Expr(OP, "/", $1, $3); }
3938                 | b_expr '*' b_expr
3939                                 {       $$ = makeA_Expr(OP, "*", $1, $3); }
3940                 | ':' b_expr
3941                                 {       $$ = makeA_Expr(OP, ":", NULL, $2); }
3942                 | ';' b_expr
3943                                 {       $$ = makeA_Expr(OP, ";", NULL, $2); }
3944                 | '|' b_expr
3945                                 {       $$ = makeA_Expr(OP, "|", NULL, $2); }
3946                 | b_expr TYPECAST Typename
3947                                 {
3948                                         $$ = (Node *)$1;
3949                                         /* AexprConst can be either A_Const or ParamNo */
3950                                         if (nodeTag($1) == T_A_Const) {
3951                                                 ((A_Const *)$1)->typename = $3;
3952                                         } else if (nodeTag($1) == T_Param) {
3953                                                 ((ParamNo *)$1)->typename = $3;
3954                                         /* otherwise, try to transform to a function call */
3955                                         } else {
3956                                                 FuncCall *n = makeNode(FuncCall);
3957                                                 n->funcname = $3->name;
3958                                                 n->args = lcons($1,NIL);
3959                                                 $$ = (Node *)n;
3960                                         }
3961                                 }
3962                 | CAST '(' b_expr AS Typename ')'
3963                                 {
3964                                         $$ = (Node *)$3;
3965                                         /* AexprConst can be either A_Const or ParamNo */
3966                                         if (nodeTag($3) == T_A_Const) {
3967                                                 ((A_Const *)$3)->typename = $5;
3968                                         } else if (nodeTag($3) == T_Param) {
3969                                                 ((ParamNo *)$3)->typename = $5;
3970                                         /* otherwise, try to transform to a function call */
3971                                         } else {
3972                                                 FuncCall *n = makeNode(FuncCall);
3973                                                 n->funcname = $5->name;
3974                                                 n->args = lcons($3,NIL);
3975                                                 $$ = (Node *)n;
3976                                         }
3977                                 }
3978                 | '(' a_expr ')'
3979                                 {       $$ = $2; }
3980                 | b_expr Op b_expr
3981                                 {       $$ = makeIndexable($2,$1,$3);   }
3982                 | Op b_expr
3983                                 {       $$ = makeA_Expr(OP, $1, NULL, $2); }
3984                 | b_expr Op
3985                                 {       $$ = makeA_Expr(OP, $2, $1, NULL); }
3986                 | func_name '(' ')'
3987                                 {
3988                                         FuncCall *n = makeNode(FuncCall);
3989                                         n->funcname = $1;
3990                                         n->args = NIL;
3991                                         $$ = (Node *)n;
3992                                 }
3993                 | func_name '(' expr_list ')'
3994                                 {
3995                                         FuncCall *n = makeNode(FuncCall);
3996                                         n->funcname = $1;
3997                                         n->args = $3;
3998                                         $$ = (Node *)n;
3999                                 }
4000                 | CURRENT_DATE
4001                                 {
4002                                         A_Const *n = makeNode(A_Const);
4003                                         TypeName *t = makeNode(TypeName);
4004
4005                                         n->val.type = T_String;
4006                                         n->val.val.str = "now";
4007                                         n->typename = t;
4008
4009                                         t->name = xlateSqlType("date");
4010                                         t->setof = FALSE;
4011                                         t->typmod = -1;
4012
4013                                         $$ = (Node *)n;
4014                                 }
4015                 | CURRENT_TIME
4016                                 {
4017                                         A_Const *n = makeNode(A_Const);
4018                                         TypeName *t = makeNode(TypeName);
4019
4020                                         n->val.type = T_String;
4021                                         n->val.val.str = "now";
4022                                         n->typename = t;
4023
4024                                         t->name = xlateSqlType("time");
4025                                         t->setof = FALSE;
4026                                         t->typmod = -1;
4027
4028                                         $$ = (Node *)n;
4029                                 }
4030                 | CURRENT_TIME '(' Iconst ')'
4031                                 {
4032                                         FuncCall *n = makeNode(FuncCall);
4033                                         A_Const *s = makeNode(A_Const);
4034                                         TypeName *t = makeNode(TypeName);
4035
4036                                         n->funcname = xlateSqlType("time");
4037                                         n->args = lcons(s, NIL);
4038
4039                                         s->val.type = T_String;
4040                                         s->val.val.str = "now";
4041                                         s->typename = t;
4042
4043                                         t->name = xlateSqlType("time");
4044                                         t->setof = FALSE;
4045                                         t->typmod = -1;
4046
4047                                         if ($3 != 0)
4048                                                 elog(NOTICE,"CURRENT_TIME(%d) precision not implemented; zero used instead",$3);
4049
4050                                         $$ = (Node *)n;
4051                                 }
4052                 | CURRENT_TIMESTAMP
4053                                 {
4054                                         A_Const *n = makeNode(A_Const);
4055                                         TypeName *t = makeNode(TypeName);
4056
4057                                         n->val.type = T_String;
4058                                         n->val.val.str = "now";
4059                                         n->typename = t;
4060
4061                                         t->name = xlateSqlType("timestamp");
4062                                         t->setof = FALSE;
4063                                         t->typmod = -1;
4064
4065                                         $$ = (Node *)n;
4066                                 }
4067                 | CURRENT_TIMESTAMP '(' Iconst ')'
4068                                 {
4069                                         FuncCall *n = makeNode(FuncCall);
4070                                         A_Const *s = makeNode(A_Const);
4071                                         TypeName *t = makeNode(TypeName);
4072
4073                                         n->funcname = xlateSqlType("timestamp");
4074                                         n->args = lcons(s, NIL);
4075
4076                                         s->val.type = T_String;
4077                                         s->val.val.str = "now";
4078                                         s->typename = t;
4079
4080                                         t->name = xlateSqlType("timestamp");
4081                                         t->setof = FALSE;
4082                                         t->typmod = -1;
4083
4084                                         if ($3 != 0)
4085                                                 elog(NOTICE,"CURRENT_TIMESTAMP(%d) precision not implemented; zero used instead",$3);
4086
4087                                         $$ = (Node *)n;
4088                                 }
4089                 | CURRENT_USER
4090                                 {
4091                                         FuncCall *n = makeNode(FuncCall);
4092                                         n->funcname = "getpgusername";
4093                                         n->args = NIL;
4094                                         $$ = (Node *)n;
4095                                 }
4096                 | POSITION '(' position_list ')'
4097                                 {
4098                                         FuncCall *n = makeNode(FuncCall);
4099                                         n->funcname = "strpos";
4100                                         n->args = $3;
4101                                         $$ = (Node *)n;
4102                                 }
4103                 | SUBSTRING '(' substr_list ')'
4104                                 {
4105                                         FuncCall *n = makeNode(FuncCall);
4106                                         n->funcname = "substr";
4107                                         n->args = $3;
4108                                         $$ = (Node *)n;
4109                                 }
4110                 /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
4111                 | TRIM '(' BOTH trim_list ')'
4112                                 {
4113                                         FuncCall *n = makeNode(FuncCall);
4114                                         n->funcname = "btrim";
4115                                         n->args = $4;
4116                                         $$ = (Node *)n;
4117                                 }
4118                 | TRIM '(' LEADING trim_list ')'
4119                                 {
4120                                         FuncCall *n = makeNode(FuncCall);
4121                                         n->funcname = "ltrim";
4122                                         n->args = $4;
4123                                         $$ = (Node *)n;
4124                                 }
4125                 | TRIM '(' TRAILING trim_list ')'
4126                                 {
4127                                         FuncCall *n = makeNode(FuncCall);
4128                                         n->funcname = "rtrim";
4129                                         n->args = $4;
4130                                         $$ = (Node *)n;
4131                                 }
4132                 | TRIM '(' trim_list ')'
4133                                 {
4134                                         FuncCall *n = makeNode(FuncCall);
4135                                         n->funcname = "btrim";
4136                                         n->args = $3;
4137                                         $$ = (Node *)n;
4138                                 }
4139                 ;
4140
4141 opt_indirection:  '[' a_expr ']' opt_indirection
4142                                 {
4143                                         A_Indices *ai = makeNode(A_Indices);
4144                                         ai->lidx = NULL;
4145                                         ai->uidx = $2;
4146                                         $$ = lcons(ai, $4);
4147                                 }
4148                 | '[' a_expr ':' a_expr ']' opt_indirection
4149                                 {
4150                                         A_Indices *ai = makeNode(A_Indices);
4151                                         ai->lidx = $2;
4152                                         ai->uidx = $4;
4153                                         $$ = lcons(ai, $6);
4154                                 }
4155                 | /* EMPTY */
4156                                 {       $$ = NIL; }
4157                 ;
4158
4159 expr_list:  a_expr_or_null
4160                                 { $$ = lcons($1, NIL); }
4161                 | expr_list ',' a_expr_or_null
4162                                 { $$ = lappend($1, $3); }
4163                 | expr_list USING a_expr
4164                                 { $$ = lappend($1, $3); }
4165                 ;
4166
4167 extract_list:  datetime FROM a_expr
4168                                 {
4169                                         A_Const *n = makeNode(A_Const);
4170                                         n->val.type = T_String;
4171                                         n->val.val.str = $1;
4172                                         $$ = lappend(lcons((Node *)n,NIL), $3);
4173                                 }
4174                 | /* EMPTY */
4175                                 {       $$ = NIL; }
4176                 ;
4177
4178 position_list:  position_expr IN position_expr
4179                                 {       $$ = makeList($3, $1, -1); }
4180                 | /* EMPTY */
4181                                 {       $$ = NIL; }
4182                 ;
4183
4184 position_expr:  attr opt_indirection
4185                                 {
4186                                         $1->indirection = $2;
4187                                         $$ = (Node *)$1;
4188                                 }
4189                 | AexprConst
4190                                 {       $$ = $1;  }
4191                 | '-' position_expr %prec UMINUS
4192                                 {       $$ = makeA_Expr(OP, "-", NULL, $2); }
4193                 | position_expr '+' position_expr
4194                                 {       $$ = makeA_Expr(OP, "+", $1, $3); }
4195                 | position_expr '-' position_expr
4196                                 {       $$ = makeA_Expr(OP, "-", $1, $3); }
4197                 | position_expr '/' position_expr
4198                                 {       $$ = makeA_Expr(OP, "/", $1, $3); }
4199                 | position_expr '*' position_expr
4200                                 {       $$ = makeA_Expr(OP, "*", $1, $3); }
4201                 | '|' position_expr
4202                                 {       $$ = makeA_Expr(OP, "|", NULL, $2); }
4203                 | position_expr TYPECAST Typename
4204                                 {
4205                                         $$ = (Node *)$1;
4206                                         /* AexprConst can be either A_Const or ParamNo */
4207                                         if (nodeTag($1) == T_A_Const) {
4208                                                 ((A_Const *)$1)->typename = $3;
4209                                         } else if (nodeTag($1) == T_Param) {
4210                                                 ((ParamNo *)$1)->typename = $3;
4211                                         /* otherwise, try to transform to a function call */
4212                                         } else {
4213                                                 FuncCall *n = makeNode(FuncCall);
4214                                                 n->funcname = $3->name;
4215                                                 n->args = lcons($1,NIL);
4216                                                 $$ = (Node *)n;
4217                                         }
4218                                 }
4219                 | CAST '(' position_expr AS Typename ')'
4220                                 {
4221                                         $$ = (Node *)$3;
4222                                         /* AexprConst can be either A_Const or ParamNo */
4223                                         if (nodeTag($3) == T_A_Const) {
4224                                                 ((A_Const *)$3)->typename = $5;
4225                                         } else if (nodeTag($3) == T_Param) {
4226                                                 ((ParamNo *)$3)->typename = $5;
4227                                         /* otherwise, try to transform to a function call */
4228                                         } else {
4229                                                 FuncCall *n = makeNode(FuncCall);
4230                                                 n->funcname = $5->name;
4231                                                 n->args = lcons($3,NIL);
4232                                                 $$ = (Node *)n;
4233                                         }
4234                                 }
4235                 | '(' position_expr ')'
4236                                 {       $$ = $2; }
4237                 | position_expr Op position_expr
4238                                 {       $$ = makeA_Expr(OP, $2, $1, $3); }
4239                 | Op position_expr
4240                                 {       $$ = makeA_Expr(OP, $1, NULL, $2); }
4241                 | position_expr Op
4242                                 {       $$ = makeA_Expr(OP, $2, $1, NULL); }
4243                 | ColId
4244                                 {
4245                                         /* could be a column name or a relation_name */
4246                                         Ident *n = makeNode(Ident);
4247                                         n->name = $1;
4248                                         n->indirection = NULL;
4249                                         $$ = (Node *)n;
4250                                 }
4251                 | func_name '(' ')'
4252                                 {
4253                                         FuncCall *n = makeNode(FuncCall);
4254                                         n->funcname = $1;
4255                                         n->args = NIL;
4256                                         $$ = (Node *)n;
4257                                 }
4258                 | func_name '(' expr_list ')'
4259                                 {
4260                                         FuncCall *n = makeNode(FuncCall);
4261                                         n->funcname = $1;
4262                                         n->args = $3;
4263                                         $$ = (Node *)n;
4264                                 }
4265                 | POSITION '(' position_list ')'
4266                                 {
4267                                         FuncCall *n = makeNode(FuncCall);
4268                                         n->funcname = "strpos";
4269                                         n->args = $3;
4270                                         $$ = (Node *)n;
4271                                 }
4272                 | SUBSTRING '(' substr_list ')'
4273                                 {
4274                                         FuncCall *n = makeNode(FuncCall);
4275                                         n->funcname = "substr";
4276                                         n->args = $3;
4277                                         $$ = (Node *)n;
4278                                 }
4279                 /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
4280                 | TRIM '(' BOTH trim_list ')'
4281                                 {
4282                                         FuncCall *n = makeNode(FuncCall);
4283                                         n->funcname = "btrim";
4284                                         n->args = $4;
4285                                         $$ = (Node *)n;
4286                                 }
4287                 | TRIM '(' LEADING trim_list ')'
4288                                 {
4289                                         FuncCall *n = makeNode(FuncCall);
4290                                         n->funcname = "ltrim";
4291                                         n->args = $4;
4292                                         $$ = (Node *)n;
4293                                 }
4294                 | TRIM '(' TRAILING trim_list ')'
4295                                 {
4296                                         FuncCall *n = makeNode(FuncCall);
4297                                         n->funcname = "rtrim";
4298                                         n->args = $4;
4299                                         $$ = (Node *)n;
4300                                 }
4301                 | TRIM '(' trim_list ')'
4302                                 {
4303                                         FuncCall *n = makeNode(FuncCall);
4304                                         n->funcname = "btrim";
4305                                         n->args = $3;
4306                                         $$ = (Node *)n;
4307                                 }
4308                 ;
4309
4310 substr_list:  expr_list substr_from substr_for
4311                                 {
4312                                         $$ = nconc(nconc($1,$2),$3);
4313                                 }
4314                 | /* EMPTY */
4315                                 {       $$ = NIL; }
4316                 ;
4317
4318 substr_from:  FROM expr_list
4319                                 {       $$ = $2; }
4320                 | /* EMPTY */
4321                                 {
4322                                         A_Const *n = makeNode(A_Const);
4323                                         n->val.type = T_Integer;
4324                                         n->val.val.ival = 1;
4325                                         $$ = lcons((Node *)n,NIL);
4326                                 }
4327                 ;
4328
4329 substr_for:  FOR expr_list
4330                                 {       $$ = $2; }
4331                 | /* EMPTY */
4332                                 {       $$ = NIL; }
4333                 ;
4334
4335 trim_list:  a_expr FROM expr_list
4336                                 { $$ = lappend($3, $1); }
4337                 | FROM expr_list
4338                                 { $$ = $2; }
4339                 | expr_list
4340                                 { $$ = $1; }
4341                 ;
4342
4343 in_expr:  SubSelect
4344                                 {
4345                                         SubLink *n = makeNode(SubLink);
4346                                         n->subselect = $1;
4347                                         $$ = (Node *)n;
4348                                 }
4349                 | in_expr_nodes
4350                                 {       $$ = $1; }
4351                 ;
4352
4353 in_expr_nodes:  AexprConst
4354                                 {       $$ = makeA_Expr(OP, "=", lfirst(saved_In_Expr), $1); }
4355                 | in_expr_nodes ',' AexprConst
4356                                 {       $$ = makeA_Expr(OR, NULL, $1,
4357                                                 makeA_Expr(OP, "=", lfirst(saved_In_Expr), $3));
4358                                 }
4359                 ;
4360
4361 not_in_expr:  SubSelect
4362                                 {
4363                                         SubLink *n = makeNode(SubLink);
4364                                         n->subselect = $1;
4365                                         $$ = (Node *)n;
4366                                 }
4367                 | not_in_expr_nodes
4368                                 {       $$ = $1; }
4369                 ;
4370
4371 not_in_expr_nodes:  AexprConst
4372                                 {       $$ = makeA_Expr(OP, "<>", lfirst(saved_In_Expr), $1); }
4373                 | not_in_expr_nodes ',' AexprConst
4374                                 {       $$ = makeA_Expr(AND, NULL, $1,
4375                                                 makeA_Expr(OP, "<>", lfirst(saved_In_Expr), $3));
4376                                 }
4377                 ;
4378
4379 attr:  relation_name '.' attrs
4380                                 {
4381                                         $$ = makeNode(Attr);
4382                                         $$->relname = $1;
4383                                         $$->paramNo = NULL;
4384                                         $$->attrs = $3;
4385                                         $$->indirection = NULL;
4386                                 }
4387                 | ParamNo '.' attrs
4388                                 {
4389                                         $$ = makeNode(Attr);
4390                                         $$->relname = NULL;
4391                                         $$->paramNo = $1;
4392                                         $$->attrs = $3;
4393                                         $$->indirection = NULL;
4394                                 }
4395                 ;
4396
4397 attrs:    attr_name
4398                                 { $$ = lcons(makeString($1), NIL); }
4399                 | attrs '.' attr_name
4400                                 { $$ = lappend($1, makeString($3)); }
4401                 | attrs '.' '*'
4402                                 { $$ = lappend($1, makeString("*")); }
4403                 ;
4404
4405
4406 /*****************************************************************************
4407  *
4408  *      target lists
4409  *
4410  *****************************************************************************/
4411
4412 res_target_list:  res_target_list ',' res_target_el
4413                                 {       $$ = lappend($1,$3);  }
4414                 | res_target_el
4415                                 {       $$ = lcons($1, NIL);  }
4416                 | '*'
4417                                 {
4418                                         ResTarget *rt = makeNode(ResTarget);
4419                                         Attr *att = makeNode(Attr);
4420                                         att->relname = "*";
4421                                         att->paramNo = NULL;
4422                                         att->attrs = NULL;
4423                                         att->indirection = NIL;
4424                                         rt->name = NULL;
4425                                         rt->indirection = NULL;
4426                                         rt->val = (Node *)att;
4427                                         $$ = lcons(rt, NIL);
4428                                 }
4429                 ;
4430
4431 res_target_el:  ColId opt_indirection '=' a_expr_or_null
4432                                 {
4433                                         $$ = makeNode(ResTarget);
4434                                         $$->name = $1;
4435                                         $$->indirection = $2;
4436                                         $$->val = (Node *)$4;
4437                                 }
4438                 | attr opt_indirection
4439                                 {
4440                                         $$ = makeNode(ResTarget);
4441                                         $$->name = NULL;
4442                                         $$->indirection = $2;
4443                                         $$->val = (Node *)$1;
4444                                 }
4445                 | relation_name '.' '*'
4446                                 {
4447                                         Attr *att = makeNode(Attr);
4448                                         att->relname = $1;
4449                                         att->paramNo = NULL;
4450                                         att->attrs = lcons(makeString("*"), NIL);
4451                                         att->indirection = NIL;
4452                                         $$ = makeNode(ResTarget);
4453                                         $$->name = NULL;
4454                                         $$->indirection = NULL;
4455                                         $$->val = (Node *)att;
4456                                 }
4457                 ;
4458
4459 /*
4460 ** target list for select.
4461 ** should get rid of the other but is still needed by the defunct select into
4462 ** and update (uses a subset)
4463 */
4464 res_target_list2:  res_target_list2 ',' res_target_el2
4465                                 {       $$ = lappend($1, $3);  }
4466                 | res_target_el2
4467                                 {       $$ = lcons($1, NIL);  }
4468                 ;
4469
4470 /* AS is not optional because shift/red conflict with unary ops */
4471 res_target_el2:  a_expr_or_null AS ColLabel
4472                                 {
4473                                         $$ = makeNode(ResTarget);
4474                                         $$->name = $3;
4475                                         $$->indirection = NULL;
4476                                         $$->val = (Node *)$1;
4477                                 }
4478                 | a_expr_or_null
4479                                 {
4480                                         $$ = makeNode(ResTarget);
4481                                         $$->name = NULL;
4482                                         $$->indirection = NULL;
4483                                         $$->val = (Node *)$1;
4484                                 }
4485                 | relation_name '.' '*'
4486                                 {
4487                                         Attr *att = makeNode(Attr);
4488                                         att->relname = $1;
4489                                         att->paramNo = NULL;
4490                                         att->attrs = lcons(makeString("*"), NIL);
4491                                         att->indirection = NIL;
4492                                         $$ = makeNode(ResTarget);
4493                                         $$->name = NULL;
4494                                         $$->indirection = NULL;
4495                                         $$->val = (Node *)att;
4496                                 }
4497                 | '*'
4498                                 {
4499                                         Attr *att = makeNode(Attr);
4500                                         att->relname = "*";
4501                                         att->paramNo = NULL;
4502                                         att->attrs = NULL;
4503                                         att->indirection = NIL;
4504                                         $$ = makeNode(ResTarget);
4505                                         $$->name = NULL;
4506                                         $$->indirection = NULL;
4507                                         $$->val = (Node *)att;
4508                                 }
4509                 ;
4510
4511 opt_id:  ColId                                                                  { $$ = $1; }
4512                 | /* EMPTY */                                                   { $$ = NULL; }
4513                 ;
4514
4515 relation_name:  SpecialRuleRelation
4516                                 {
4517                                         $$ = $1;
4518                                         StrNCpy(saved_relname, $1, NAMEDATALEN);
4519                                 }
4520                 | ColId
4521                                 {
4522                                         /* disallow refs to variable system tables */
4523                                         if (strcmp(LogRelationName, $1) == 0
4524                                            || strcmp(VariableRelationName, $1) == 0)
4525                                                 elog(ERROR,"%s cannot be accessed by users",$1);
4526                                         else
4527                                                 $$ = $1;
4528                                         StrNCpy(saved_relname, $1, NAMEDATALEN);
4529                                 }
4530                 ;
4531
4532 database_name:                  ColId                   { $$ = $1; };
4533 access_method:                  IDENT                   { $$ = $1; };
4534 attr_name:                              ColId                   { $$ = $1; };
4535 class:                                  IDENT                   { $$ = $1; };
4536 index_name:                             ColId                   { $$ = $1; };
4537
4538 /* Functions
4539  * Include date/time keywords as SQL92 extension.
4540  * Include TYPE as a SQL92 unreserved keyword. - thomas 1997-10-05
4541  */
4542 name:                                   ColId                   { $$ = $1; };
4543 func_name:                              ColId                   { $$ = xlateSqlFunc($1); };
4544
4545 file_name:                              Sconst                  { $$ = $1; };
4546 recipe_name:                    IDENT                   { $$ = $1; };
4547
4548 /* Constants
4549  * Include TRUE/FALSE for SQL3 support. - thomas 1997-10-24
4550  */
4551 AexprConst:  Iconst
4552                                 {
4553                                         A_Const *n = makeNode(A_Const);
4554                                         n->val.type = T_Integer;
4555                                         n->val.val.ival = $1;
4556                                         $$ = (Node *)n;
4557                                 }
4558                 | FCONST
4559                                 {
4560                                         A_Const *n = makeNode(A_Const);
4561                                         n->val.type = T_Float;
4562                                         n->val.val.dval = $1;
4563                                         $$ = (Node *)n;
4564                                 }
4565                 | Sconst
4566                                 {
4567                                         A_Const *n = makeNode(A_Const);
4568                                         n->val.type = T_String;
4569                                         n->val.val.str = $1;
4570                                         $$ = (Node *)n;
4571                                 }
4572                 | Typename Sconst
4573                                 {
4574                                         A_Const *n = makeNode(A_Const);
4575                                         n->typename = $1;
4576                                         n->val.type = T_String;
4577                                         n->val.val.str = $2;
4578                                         $$ = (Node *)n;
4579                                 }
4580                 | ParamNo
4581                                 {       $$ = (Node *)$1;  }
4582                 | TRUE_P
4583                                 {
4584                                         A_Const *n = makeNode(A_Const);
4585                                         n->val.type = T_String;
4586                                         n->val.val.str = "t";
4587                                         n->typename = makeNode(TypeName);
4588                                         n->typename->name = xlateSqlType("bool");
4589                                         n->typename->typmod = -1;
4590                                         $$ = (Node *)n;
4591                                 }
4592                 | FALSE_P
4593                                 {
4594                                         A_Const *n = makeNode(A_Const);
4595                                         n->val.type = T_String;
4596                                         n->val.val.str = "f";
4597                                         n->typename = makeNode(TypeName);
4598                                         n->typename->name = xlateSqlType("bool");
4599                                         n->typename->typmod = -1;
4600                                         $$ = (Node *)n;
4601                                 }
4602                 ;
4603
4604 ParamNo:  PARAM
4605                                 {
4606                                         $$ = makeNode(ParamNo);
4607                                         $$->number = $1;
4608                                 }
4609                 ;
4610
4611 NumConst:  Iconst                                               { $$ = makeInteger($1); }
4612                 | FCONST                                                { $$ = makeFloat($1); }
4613                 ;
4614
4615 Iconst:  ICONST                                                 { $$ = $1; };
4616 Sconst:  SCONST                                                 { $$ = $1; };
4617 UserId:  IDENT                                                  { $$ = $1; };
4618
4619 /* Column and type identifier
4620  * Does not include explicit datetime types
4621  *  since these must be decoupled in Typename syntax.
4622  * Use ColId for most identifiers. - thomas 1997-10-21
4623  */
4624 TypeId:  ColId
4625                         {       $$ = xlateSqlType($1); }
4626                 | numeric
4627                         {       $$ = xlateSqlType($1); }
4628                 | character
4629                         {       $$ = xlateSqlType($1); }
4630                 ;
4631 /* Column identifier
4632  * Include date/time keywords as SQL92 extension.
4633  * Include TYPE as a SQL92 unreserved keyword. - thomas 1997-10-05
4634  * Add other keywords. Note that as the syntax expands,
4635  *  some of these keywords will have to be removed from this
4636  *  list due to shift/reduce conflicts in yacc. If so, move
4637  *  down to the ColLabel entity. - thomas 1997-11-06
4638  */
4639 ColId:  IDENT                                                   { $$ = $1; }
4640                 | datetime                                              { $$ = $1; }
4641                 | ACTION                                                { $$ = "action"; }
4642                 | CACHE                                                 { $$ = "cache"; }
4643                 | CYCLE                                                 { $$ = "cycle"; }
4644                 | DATABASE                                              { $$ = "database"; }
4645                 | DELIMITERS                                    { $$ = "delimiters"; }
4646                 | DOUBLE                                                { $$ = "double"; }
4647                 | EACH                                                  { $$ = "each"; }
4648                 | FUNCTION                                              { $$ = "function"; }
4649                 | INCREMENT                                             { $$ = "increment"; }
4650                 | INDEX                                                 { $$ = "index"; }
4651                 | KEY                                                   { $$ = "key"; }
4652                 | LANGUAGE                                              { $$ = "language"; }
4653                 | LOCATION                                              { $$ = "location"; }
4654                 | MATCH                                                 { $$ = "match"; }
4655                 | MAXVALUE                                              { $$ = "maxvalue"; }
4656                 | MINVALUE                                              { $$ = "minvalue"; }
4657                 | OPERATOR                                              { $$ = "operator"; }
4658                 | OPTION                                                { $$ = "option"; }
4659                 | PASSWORD                                              { $$ = "password"; }
4660                 | PRIVILEGES                                    { $$ = "privileges"; }
4661                 | RECIPE                                                { $$ = "recipe"; }
4662                 | ROW                                                   { $$ = "row"; }
4663                 | STATEMENT                                             { $$ = "statement"; }
4664                 | TIME                                                  { $$ = "time"; }
4665                 | TRIGGER                                               { $$ = "trigger"; }
4666                 | TYPE_P                                                { $$ = "type"; }
4667                 | USER                                                  { $$ = "user"; }
4668                 | VALID                                                 { $$ = "valid"; }
4669                 | VERSION                                               { $$ = "version"; }
4670                 | ZONE                                                  { $$ = "zone"; }
4671                 ;
4672
4673 /* Column label
4674  * Allowed labels in "AS" clauses.
4675  * Include TRUE/FALSE SQL3 reserved words for Postgres backward
4676  *  compatibility. Cannot allow this for column names since the
4677  *  syntax would not distinguish between the constant value and
4678  *  a column name. - thomas 1997-10-24
4679  * Add other keywords to this list. Note that they appear here
4680  *  rather than in ColId if there was a shift/reduce conflict
4681  *  when used as a full identifier. - thomas 1997-11-06
4682  */
4683 ColLabel:  ColId                                                { $$ = $1; }
4684                 | ARCHIVE                                               { $$ = "archive"; }
4685                 | CLUSTER                                               { $$ = "cluster"; }
4686                 | CONSTRAINT                                    { $$ = "constraint"; }
4687                 | CROSS                                                 { $$ = "cross"; }
4688                 | FOREIGN                                               { $$ = "foreign"; }
4689                 | GROUP                                                 { $$ = "group"; }
4690                 | LOAD                                                  { $$ = "load"; }
4691                 | ORDER                                                 { $$ = "order"; }
4692                 | POSITION                                              { $$ = "position"; }
4693                 | PRECISION                                             { $$ = "precision"; }
4694                 | TABLE                                                 { $$ = "table"; }
4695                 | TRANSACTION                                   { $$ = "transaction"; }
4696                 | TRUE_P                                                { $$ = "true"; }
4697                 | FALSE_P                                               { $$ = "false"; }
4698                 ;
4699
4700 SpecialRuleRelation:  CURRENT
4701                                 {
4702                                         if (QueryIsRule)
4703                                                 $$ = "*CURRENT*";
4704                                         else
4705                                                 elog(ERROR,"CURRENT used in non-rule query");
4706                                 }
4707                 | NEW
4708                                 {
4709                                         if (QueryIsRule)
4710                                                 $$ = "*NEW*";
4711                                         else
4712                                                 elog(ERROR,"NEW used in non-rule query");
4713                                 }
4714                 ;
4715
4716 %%
4717
4718 static Node *
4719 makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr)
4720 {
4721         A_Expr *a = makeNode(A_Expr);
4722         a->oper = oper;
4723         a->opname = opname;
4724         a->lexpr = lexpr;
4725         a->rexpr = rexpr;
4726         return (Node *)a;
4727 }
4728
4729 /* makeRowExpr()
4730  * Generate separate operator nodes for a single row descriptor expression.
4731  * Perhaps this should go deeper in the parser someday... - thomas 1997-12-22
4732  */
4733 static Node *
4734 makeRowExpr(char *opr, List *largs, List *rargs)
4735 {
4736         Node *expr = NULL;
4737         Node *larg, *rarg;
4738
4739         if (length(largs) != length(rargs))
4740                 elog(ERROR,"Unequal number of entries in row expression");
4741
4742         if (lnext(largs) != NIL)
4743                 expr = makeRowExpr(opr,lnext(largs),lnext(rargs));
4744
4745         larg = lfirst(largs);
4746         rarg = lfirst(rargs);
4747
4748         if ((strcmp(opr, "=") == 0)
4749          || (strcmp(opr, "<") == 0)
4750          || (strcmp(opr, "<=") == 0)
4751          || (strcmp(opr, ">") == 0)
4752          || (strcmp(opr, ">=") == 0))
4753         {
4754                 if (expr == NULL)
4755                         expr = makeA_Expr(OP, opr, larg, rarg);
4756                 else
4757                         expr = makeA_Expr(AND, NULL, expr, makeA_Expr(OP, opr, larg, rarg));
4758         }
4759         else if (strcmp(opr, "<>") == 0)
4760         {
4761                 if (expr == NULL)
4762                         expr = makeA_Expr(OP, opr, larg, rarg);
4763                 else
4764                         expr = makeA_Expr(OR, NULL, expr, makeA_Expr(OP, opr, larg, rarg));
4765         }
4766         else
4767         {
4768                 elog(ERROR,"Operator '%s' not implemented for row expressions",opr);
4769         }
4770
4771 #if FALSE
4772         while ((largs != NIL) && (rargs != NIL))
4773         {
4774                 larg = lfirst(largs);
4775                 rarg = lfirst(rargs);
4776
4777                 if (expr == NULL)
4778                         expr = makeA_Expr(OP, opr, larg, rarg);
4779                 else
4780                         expr = makeA_Expr(AND, NULL, expr, makeA_Expr(OP, opr, larg, rarg));
4781
4782                 largs = lnext(largs);
4783                 rargs = lnext(rargs);
4784         }
4785         pprint(expr);
4786 #endif
4787
4788         return expr;
4789 }
4790
4791 void
4792 mapTargetColumns(List *src, List *dst)
4793 {
4794         ColumnDef *s;
4795         ResTarget *d;
4796
4797         if (length(src) != length(dst))
4798                 elog(ERROR,"CREATE TABLE/AS SELECT has mismatched column count");
4799
4800         while ((src != NIL) && (dst != NIL))
4801         {
4802                 s = (ColumnDef *)lfirst(src);
4803                 d = (ResTarget *)lfirst(dst);
4804
4805                 d->name = s->colname;
4806
4807                 src = lnext(src);
4808                 dst = lnext(dst);
4809         }
4810
4811         return;
4812 } /* mapTargetColumns() */
4813
4814 static Node *makeIndexable(char *opname, Node *lexpr, Node *rexpr)
4815 {
4816         Node *result = NULL;
4817
4818         /* we do this so indexes can be used */
4819         if (strcmp(opname,"~") == 0 ||
4820                 strcmp(opname,"~*") == 0)
4821         {
4822                 if (nodeTag(rexpr) == T_A_Const &&
4823                    ((A_Const *)rexpr)->val.type == T_String &&
4824                    ((A_Const *)rexpr)->val.val.str[0] == '^')
4825                 {
4826                         A_Const *n = (A_Const *)rexpr;
4827                         char *match_least = palloc(strlen(n->val.val.str)+2);
4828                         char *match_most = palloc(strlen(n->val.val.str)+2);
4829                         int pos, match_pos=0;
4830
4831                         /* skip leading ^ */
4832                         for (pos = 1; n->val.val.str[pos]; pos++)
4833                         {
4834                                 if (n->val.val.str[pos] == '.' ||
4835                                         n->val.val.str[pos] == '?' ||
4836                                         n->val.val.str[pos] == '*' ||
4837                                         n->val.val.str[pos] == '[' ||
4838                                         n->val.val.str[pos] == '$' ||
4839                                         (strcmp(opname,"~*") == 0 && isalpha(n->val.val.str[pos])))
4840                                 break;
4841                         if (n->val.val.str[pos] == '\\')
4842                                         pos++;
4843                                 match_least[match_pos] = n->val.val.str[pos];
4844                                 match_most[match_pos++] = n->val.val.str[pos];
4845                         }
4846
4847                         if (match_pos != 0)
4848                         {
4849                                 A_Const *least = makeNode(A_Const);
4850                                 A_Const *most = makeNode(A_Const);
4851                                 
4852                                 /* make strings to be used in index use */
4853                                 match_least[match_pos] = '\0';
4854                                 match_most[match_pos] = '\377';
4855                                 match_most[match_pos+1] = '\0';
4856                                 least->val.type = T_String;
4857                                 least->val.val.str = match_least;
4858                                 most->val.type = T_String;
4859                                 most->val.val.str = match_most;
4860                                 result = makeA_Expr(AND, NULL,
4861                                                 makeA_Expr(OP, "~", lexpr, rexpr),
4862                                                 makeA_Expr(AND, NULL,
4863                                                         makeA_Expr(OP, ">=", lexpr, (Node *)least),
4864                                                         makeA_Expr(OP, "<=", lexpr, (Node *)most)));
4865                         }
4866                 }
4867         }
4868         else if (strcmp(opname,"~~") == 0)
4869         {
4870                 if (nodeTag(rexpr) == T_A_Const &&
4871                    ((A_Const *)rexpr)->val.type == T_String)
4872                 {
4873                         A_Const *n = (A_Const *)rexpr;
4874                         char *match_least = palloc(strlen(n->val.val.str)+2);
4875                         char *match_most = palloc(strlen(n->val.val.str)+2);
4876                         int pos, match_pos=0;
4877         
4878                         for (pos = 0; n->val.val.str[pos]; pos++)
4879                         {
4880                                 if (n->val.val.str[pos] == '%' &&
4881                                          n->val.val.str[pos+1] != '%')
4882                                         break;
4883                                 if(n->val.val.str[pos] == '_')
4884                                         break;
4885                                 if (n->val.val.str[pos] == '\\' ||
4886                                         n->val.val.str[pos] == '%')
4887                                         pos++;
4888                                 if (n->val.val.str[pos] == '\0')
4889                                         break;
4890                                 match_least[match_pos] = n->val.val.str[pos];
4891                                 match_most[match_pos++] = n->val.val.str[pos];
4892                         }
4893         
4894                         if (match_pos != 0)
4895                         {
4896                                 A_Const *least = makeNode(A_Const);
4897                                 A_Const *most = makeNode(A_Const);
4898                                 
4899                                 /* make strings to be used in index use */
4900                                 match_least[match_pos] = '\0';
4901                                 match_most[match_pos] = '\377';
4902                                 match_most[match_pos+1] = '\0';
4903                                 least->val.type = T_String;
4904                                 least->val.val.str = match_least;
4905                                 most->val.type = T_String;
4906                                 most->val.val.str = match_most;
4907                                 result = makeA_Expr(AND, NULL,
4908                                                 makeA_Expr(OP, "~~", lexpr, rexpr),
4909                                                 makeA_Expr(AND, NULL,
4910                                                         makeA_Expr(OP, ">=", lexpr, (Node *)least),
4911                                                         makeA_Expr(OP, "<=", lexpr, (Node *)most)));
4912                         }
4913                 }
4914         }
4915         
4916         if (result == NULL)
4917                 result = makeA_Expr(OP, opname, lexpr, rexpr);
4918         return result;
4919 } /* makeIndexable() */
4920
4921
4922 /* xlateSqlFunc()
4923  * Convert alternate type names to internal Postgres types.
4924  * Do not convert "float", since that is handled elsewhere
4925  *  for FLOAT(p) syntax.
4926  */
4927 static char *
4928 xlateSqlFunc(char *name)
4929 {
4930         if (!strcasecmp(name,"character_length")
4931          || !strcasecmp(name,"char_length"))
4932                 return "length";
4933         else
4934                 return name;
4935 } /* xlateSqlFunc() */
4936
4937 /* xlateSqlType()
4938  * Convert alternate type names to internal Postgres types.
4939  */
4940 static char *
4941 xlateSqlType(char *name)
4942 {
4943         if (!strcasecmp(name,"int")
4944          || !strcasecmp(name,"integer"))
4945                 return "int4";
4946         else if (!strcasecmp(name, "smallint"))
4947                 return "int2";
4948         else if (!strcasecmp(name, "real")
4949          || !strcasecmp(name, "float"))
4950                 return "float8";
4951         else if (!strcasecmp(name, "interval"))
4952                 return "timespan";
4953         else if (!strcasecmp(name, "boolean"))
4954                 return "bool";
4955         else
4956                 return name;
4957 } /* xlateSqlType() */
4958
4959
4960 void parser_init(Oid *typev, int nargs)
4961 {
4962         QueryIsRule = FALSE;
4963         saved_relname[0]= '\0';
4964         saved_In_Expr = NULL;
4965
4966         param_type_init(typev, nargs);
4967 }
4968
4969
4970 /* FlattenStringList()
4971  * Traverse list of string nodes and convert to a single string.
4972  * Used for reconstructing string form of complex expressions.
4973  *
4974  * Allocate at least one byte for terminator.
4975  */
4976 static char *
4977 FlattenStringList(List *list)
4978 {
4979         List *l;
4980         Value *v;
4981         char *s;
4982         char *sp;
4983         int nlist, len = 0;
4984
4985         nlist = length(list);
4986         l = list;
4987         while(l != NIL) {
4988                 v = (Value *)lfirst(l);
4989                 sp = v->val.str;
4990                 l = lnext(l);
4991                 len += strlen(sp);
4992         };
4993         len += nlist;
4994
4995         s = (char*) palloc(len+1);
4996         *s = '\0';
4997
4998         l = list;
4999         while(l != NIL) {
5000                 v = (Value *)lfirst(l);
5001                 sp = v->val.str;
5002                 l = lnext(l);
5003                 strcat(s,sp);
5004                 if (l != NIL) strcat(s," ");
5005         };
5006         *(s+len) = '\0';
5007
5008 #ifdef PARSEDEBUG
5009 printf( "flattened string is \"%s\"\n", s);
5010 #endif
5011
5012         return(s);
5013 } /* FlattenStringList() */
5014
5015
5016 /* makeConstantList()
5017  * Convert constant value node into string node.
5018  */
5019 static List *
5020 makeConstantList( A_Const *n)
5021 {
5022         char *defval = NULL;
5023         if (nodeTag(n) != T_A_Const) {
5024                 elog(ERROR,"Cannot handle non-constant parameter");
5025
5026         } else if (n->val.type == T_Float) {
5027                 defval = (char*) palloc(20+1);
5028                 sprintf( defval, "%g", n->val.val.dval);
5029
5030         } else if (n->val.type == T_Integer) {
5031                 defval = (char*) palloc(20+1);
5032                 sprintf( defval, "%ld", n->val.val.ival);
5033
5034         } else if (n->val.type == T_String) {
5035                 defval = (char*) palloc(strlen( ((A_Const *) n)->val.val.str) + 3);
5036                 strcpy( defval, "'");
5037                 strcat( defval, ((A_Const *) n)->val.val.str);
5038                 strcat( defval, "'");
5039
5040         } else {
5041                 elog(ERROR,"Internal error in makeConstantList(): cannot encode node");
5042         };
5043
5044 #ifdef PARSEDEBUG
5045 printf( "AexprConst argument is \"%s\"\n", defval);
5046 #endif
5047
5048         return( lcons( makeString(defval), NIL));
5049 } /* makeConstantList() */
5050
5051
5052 /* fmtId()
5053  * Check input string for non-lowercase/non-numeric characters.
5054  * Returns either input string or input surrounded by double quotes.
5055  */
5056 static char *
5057 fmtId(char *rawid)
5058 {
5059         static char *cp;
5060
5061         for (cp = rawid; *cp != '\0'; cp++)
5062                 if (! (islower(*cp) || isdigit(*cp) || (*cp == '_'))) break;
5063
5064         if (*cp != '\0') {
5065                 cp = palloc(strlen(rawid)+1);
5066                 strcpy(cp,"\"");
5067                 strcat(cp,rawid);
5068                 strcat(cp,"\"");
5069         } else {
5070                 cp = rawid;
5071         };
5072
5073 #ifdef PARSEDEBUG
5074 printf("fmtId- %sconvert %s to %s\n", ((cp == rawid)? "do not ": ""), rawid, cp);
5075 #endif
5076
5077         return(cp);
5078 }
5079
5080 /*
5081  * param_type_init()
5082  *
5083  * keep enough information around fill out the type of param nodes
5084  * used in postquel functions
5085  */
5086 static void
5087 param_type_init(Oid *typev, int nargs)
5088 {
5089         pfunc_num_args = nargs;
5090         param_type_info = typev;
5091 }
5092
5093 Oid param_type(int t)
5094 {
5095         if ((t > pfunc_num_args) || (t == 0))
5096                 return InvalidOid;
5097         return param_type_info[t - 1];
5098 }