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