]> granicus.if.org Git - postgresql/blob - src/backend/parser/gram.y
Cleanup up code.
[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.10 1998/04/13 21:07:15 momjian Exp $
14  *
15  * HISTORY
16  *        AUTHOR                        DATE                    MAJOR EVENT
17  *        Andrew Yu                     Sept, 1994              POSTQUEL to SQL conversion
18  *        Andrew Yu                     Oct, 1994               lispy code conversion
19  *
20  * NOTES
21  *        CAPITALS are used to represent terminal symbols.
22  *        non-capitals are used to represent non-terminals.
23  *        SQL92-specific syntax is separated from plain SQL/Postgres syntax
24  *        to help isolate the non-extensible portions of the parser.
25  *
26  *        if you use list, make sure the datum is a node so that the printing
27  *        routines work
28  *
29  * WARNING
30  *        sometimes we assign constants to makeStrings. Make sure we don't free
31  *        those.
32  *
33  *-------------------------------------------------------------------------
34  */
35 #include <string.h>
36 #include <ctype.h>
37
38 #include "postgres.h"
39 #include "nodes/parsenodes.h"
40 #include "nodes/print.h"
41 #include "parser/gramparse.h"
42 #include "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                                         $$ = $2;
2546                                 }
2547                 | /*EMPTY*/                                                             { $$ = NULL; }
2548                 ;
2549
2550
2551 /*****************************************************************************
2552  *
2553  *      clauses common to all Optimizable Stmts:
2554  *              from_clause             -
2555  *              where_clause    -
2556  *
2557  *****************************************************************************/
2558
2559 from_clause:  FROM '(' relation_expr join_expr JOIN relation_expr join_spec ')'
2560                                 {
2561                                         $$ = NIL;
2562                                         elog(ERROR,"JOIN not yet implemented");
2563                                 }
2564                 | FROM from_list                                                { $$ = $2; }
2565                 | /*EMPTY*/                                                             { $$ = NIL; }
2566                 ;
2567
2568 from_list:      from_list ',' from_val
2569                                 { $$ = lappend($1, $3); }
2570                 | from_val CROSS JOIN from_val
2571                                 { elog(ERROR,"CROSS JOIN not yet implemented"); }
2572                 | from_val
2573                                 { $$ = lcons($1, NIL); }
2574                 ;
2575
2576 from_val:  relation_expr AS ColLabel
2577                                 {
2578                                         $$ = makeNode(RangeVar);
2579                                         $$->relExpr = $1;
2580                                         $$->name = $3;
2581                                 }
2582                 | relation_expr ColId
2583                                 {
2584                                         $$ = makeNode(RangeVar);
2585                                         $$->relExpr = $1;
2586                                         $$->name = $2;
2587                                 }
2588                 | relation_expr
2589                                 {
2590                                         $$ = makeNode(RangeVar);
2591                                         $$->relExpr = $1;
2592                                         $$->name = NULL;
2593                                 }
2594                 ;
2595
2596 join_expr:  NATURAL join_expr                                   { $$ = NULL; }
2597                 | FULL join_outer
2598                                 { elog(ERROR,"FULL OUTER JOIN not yet implemented"); }
2599                 | LEFT join_outer
2600                                 { elog(ERROR,"LEFT OUTER JOIN not yet implemented"); }
2601                 | RIGHT join_outer
2602                                 { elog(ERROR,"RIGHT OUTER JOIN not yet implemented"); }
2603                 | OUTER_P
2604                                 { elog(ERROR,"OUTER JOIN not yet implemented"); }
2605                 | INNER_P
2606                                 { elog(ERROR,"INNER JOIN not yet implemented"); }
2607                 | UNION
2608                                 { elog(ERROR,"UNION JOIN not yet implemented"); }
2609                 | /*EMPTY*/
2610                                 { elog(ERROR,"INNER JOIN not yet implemented"); }
2611                 ;
2612
2613 join_outer:  OUTER_P                                                    { $$ = NULL; }
2614                 | /*EMPTY*/                                                             { $$ = NULL;  /* no qualifiers */ }
2615                 ;
2616
2617 join_spec:      ON '(' a_expr ')'                                       { $$ = NULL; }
2618                 | USING '(' join_list ')'                               { $$ = NULL; }
2619                 | /*EMPTY*/                                                             { $$ = NULL;  /* no qualifiers */ }
2620                 ;
2621
2622 join_list:  join_using                                                  { $$ = lcons($1, NIL); }
2623                 | join_list ',' join_using                              { $$ = lappend($1, $3); }
2624                 ;
2625
2626 join_using:  ColId
2627                                 {
2628                                         $$ = makeNode(SortGroupBy);
2629                                         $$->resno = 0;
2630                                         $$->range = NULL;
2631                                         $$->name = $1;
2632                                         $$->useOp = NULL;
2633                                 }
2634                 | ColId '.' ColId
2635                                 {
2636                                         $$ = makeNode(SortGroupBy);
2637                                         $$->resno = 0;
2638                                         $$->range = $1;
2639                                         $$->name = $3;
2640                                         $$->useOp = NULL;
2641                                 }
2642                 | Iconst
2643                                 {
2644                                         $$ = makeNode(SortGroupBy);
2645                                         $$->resno = $1;
2646                                         $$->range = NULL;
2647                                         $$->name = NULL;
2648                                         $$->useOp = NULL;
2649                                 }
2650                 ;
2651
2652 where_clause:  WHERE a_expr                                             { $$ = $2; }
2653                 | /*EMPTY*/                                                             { $$ = NULL;  /* no qualifiers */ }
2654                 ;
2655
2656 relation_expr:  relation_name
2657                                 {
2658                                         /* normal relations */
2659                                         $$ = makeNode(RelExpr);
2660                                         $$->relname = $1;
2661                                         $$->inh = FALSE;
2662                                 }
2663                 | relation_name '*'                               %prec '='
2664                                 {
2665                                         /* inheritance query */
2666                                         $$ = makeNode(RelExpr);
2667                                         $$->relname = $1;
2668                                         $$->inh = TRUE;
2669                                 }
2670
2671 opt_array_bounds:  '[' ']' nest_array_bounds
2672                                 {  $$ = lcons(makeInteger(-1), $3); }
2673                 | '[' Iconst ']' nest_array_bounds
2674                                 {  $$ = lcons(makeInteger($2), $4); }
2675                 | /* EMPTY */
2676                                 {  $$ = NIL; }
2677                 ;
2678
2679 nest_array_bounds:      '[' ']' nest_array_bounds
2680                                 {  $$ = lcons(makeInteger(-1), $3); }
2681                 | '[' Iconst ']' nest_array_bounds
2682                                 {  $$ = lcons(makeInteger($2), $4); }
2683                 | /*EMPTY*/
2684                                 {  $$ = NIL; }
2685                 ;
2686
2687
2688 /*****************************************************************************
2689  *
2690  *      Type syntax
2691  *              SQL92 introduces a large amount of type-specific syntax.
2692  *              Define individual clauses to handle these cases, and use
2693  *               the generic case to handle regular type-extensible Postgres syntax.
2694  *              - thomas 1997-10-10
2695  *
2696  *****************************************************************************/
2697
2698 Typename:  Array opt_array_bounds
2699                                 {
2700                                         $$ = $1;
2701                                         $$->arrayBounds = $2;
2702
2703                                         /* Is this the name of a complex type? If so, implement
2704                                          * it as a set.
2705                                          */
2706                                         if (!strcmp(saved_relname, $$->name))
2707                                                 /* This attr is the same type as the relation
2708                                                  * being defined. The classic example: create
2709                                                  * emp(name=text,mgr=emp)
2710                                                  */
2711                                                 $$->setof = TRUE;
2712                                         else if (typeTypeRelid(typenameType($$->name)) != InvalidOid)
2713                                                  /* (Eventually add in here that the set can only
2714                                                   * contain one element.)
2715                                                   */
2716                                                 $$->setof = TRUE;
2717                                         else
2718                                                 $$->setof = FALSE;
2719                                 }
2720                 | Character
2721                 | SETOF Array
2722                                 {
2723                                         $$ = $2;
2724                                         $$->setof = TRUE;
2725                                 }
2726                 ;
2727
2728 Array:  Generic
2729                 | Datetime
2730                 | Numeric
2731                 ;
2732
2733 Generic:  generic
2734                                 {
2735                                         $$ = makeNode(TypeName);
2736                                         $$->name = xlateSqlType($1);
2737                                         $$->typmod = -1;
2738                                 }
2739                 ;
2740
2741 generic:  IDENT                                                                 { $$ = $1; }
2742                 | TYPE_P                                                                { $$ = xlateSqlType("type"); }
2743                 ;
2744
2745 /* SQL92 numeric data types
2746  * Check FLOAT() precision limits assuming IEEE floating types.
2747  * Provide rudimentary DECIMAL() and NUMERIC() implementations
2748  *  by checking parameters and making sure they match what is possible with INTEGER.
2749  * - thomas 1997-09-18
2750  */
2751 Numeric:  FLOAT opt_float
2752                                 {
2753                                         $$ = makeNode(TypeName);
2754                                         $$->name = xlateSqlType($2);
2755                                         $$->typmod = -1;
2756                                 }
2757                 | DOUBLE PRECISION
2758                                 {
2759                                         $$ = makeNode(TypeName);
2760                                         $$->name = xlateSqlType("float");
2761                                 }
2762                 | DECIMAL opt_decimal
2763                                 {
2764                                         $$ = makeNode(TypeName);
2765                                         $$->name = xlateSqlType("integer");
2766                                         $$->typmod = -1;
2767                                 }
2768                 | NUMERIC opt_numeric
2769                                 {
2770                                         $$ = makeNode(TypeName);
2771                                         $$->name = xlateSqlType("integer");
2772                                         $$->typmod = -1;
2773                                 }
2774                 ;
2775
2776 numeric:  FLOAT
2777                                 {       $$ = xlateSqlType("float8"); }
2778                 | DOUBLE PRECISION
2779                                 {       $$ = xlateSqlType("float8"); }
2780                 | DECIMAL
2781                                 {       $$ = xlateSqlType("decimal"); }
2782                 | NUMERIC
2783                                 {       $$ = xlateSqlType("numeric"); }
2784                 ;
2785
2786 opt_float:  '(' Iconst ')'
2787                                 {
2788                                         if ($2 < 1)
2789                                                 elog(ERROR,"precision for FLOAT must be at least 1");
2790                                         else if ($2 < 7)
2791                                                 $$ = xlateSqlType("float4");
2792                                         else if ($2 < 16)
2793                                                 $$ = xlateSqlType("float8");
2794                                         else
2795                                                 elog(ERROR,"precision for FLOAT must be less than 16");
2796                                 }
2797                 | /*EMPTY*/
2798                                 {
2799                                         $$ = xlateSqlType("float8");
2800                                 }
2801                 ;
2802
2803 opt_numeric:  '(' Iconst ',' Iconst ')'
2804                                 {
2805                                         if ($2 != 9)
2806                                                 elog(ERROR,"NUMERIC precision %d must be 9",$2);
2807                                         if ($4 != 0)
2808                                                 elog(ERROR,"NUMERIC scale %d must be zero",$4);
2809                                 }
2810                 | '(' Iconst ')'
2811                                 {
2812                                         if ($2 != 9)
2813                                                 elog(ERROR,"NUMERIC precision %d must be 9",$2);
2814                                 }
2815                 | /*EMPTY*/
2816                                 {
2817                                         $$ = NULL;
2818                                 }
2819                 ;
2820
2821 opt_decimal:  '(' Iconst ',' Iconst ')'
2822                                 {
2823                                         if ($2 > 9)
2824                                                 elog(ERROR,"DECIMAL precision %d exceeds implementation limit of 9",$2);
2825                                         if ($4 != 0)
2826                                                 elog(ERROR,"DECIMAL scale %d must be zero",$4);
2827                                         $$ = NULL;
2828                                 }
2829                 | '(' Iconst ')'
2830                                 {
2831                                         if ($2 > 9)
2832                                                 elog(ERROR,"DECIMAL precision %d exceeds implementation limit of 9",$2);
2833                                         $$ = NULL;
2834                                 }
2835                 | /*EMPTY*/
2836                                 {
2837                                         $$ = NULL;
2838                                 }
2839                 ;
2840
2841 /* SQL92 character data types
2842  * The following implements CHAR() and VARCHAR().
2843  * We do it here instead of the 'Generic' production
2844  * because we don't want to allow arrays of VARCHAR().
2845  * I haven't thought about whether that will work or not.
2846  *                                                              - ay 6/95
2847  */
2848 Character:  character '(' Iconst ')'
2849                                 {
2850                                         $$ = makeNode(TypeName);
2851                                         if (!strcasecmp($1, "char"))
2852                                                 $$->name = xlateSqlType("bpchar");
2853                                         else if (!strcasecmp($1, "varchar"))
2854                                                 $$->name = xlateSqlType("varchar");
2855                                         else
2856                                                 yyerror("parse error");
2857                                         if ($3 < 1)
2858                                                 elog(ERROR,"length for '%s' type must be at least 1",$1);
2859                                         else if ($3 > 4096)
2860                                                 /* we can store a char() of length up to the size
2861                                                  * of a page (8KB) - page headers and friends but
2862                                                  * just to be safe here...      - ay 6/95
2863                                                  * XXX note this hardcoded limit - thomas 1997-07-13
2864                                                  */
2865                                                 elog(ERROR,"length for type '%s' cannot exceed 4096",$1);
2866
2867                                         /* we actually implement this sort of like a varlen, so
2868                                          * the first 4 bytes is the length. (the difference
2869                                          * between this and "text" is that we blank-pad and
2870                                          * truncate where necessary
2871                                          */
2872                                         $$->typmod = VARHDRSZ + $3;
2873                                 }
2874                 | character
2875                                 {
2876                                         $$ = makeNode(TypeName);
2877                                         $$->name = xlateSqlType($1);
2878                                         $$->typmod = -1;
2879                                 }
2880                 ;
2881
2882 character:  CHARACTER opt_varying opt_charset opt_collate
2883                                 {
2884                                         char *type, *c;
2885                                         if (($3 == NULL) || (strcasecmp($3, "sql_text") == 0)) {
2886                                                 if ($2) type = xlateSqlType("varchar");
2887                                                 else type = xlateSqlType("char");
2888                                         } else {
2889                                                 if ($2) {
2890                                                         c = palloc(strlen("var") + strlen($3) + 1);
2891                                                         strcpy(c, "var");
2892                                                         strcat(c, $3);
2893                                                         type = xlateSqlType(c);
2894                                                 } else {
2895                                                         type = xlateSqlType($3);
2896                                                 }
2897                                         };
2898                                         if ($4 != NULL)
2899                                         elog(ERROR,"COLLATE %s not yet implemented",$4);
2900                                         $$ = type;
2901                                 }
2902                 | CHAR opt_varying                                              { $$ = xlateSqlType($2? "varchar": "char"); }
2903                 | VARCHAR                                                               { $$ = xlateSqlType("varchar"); }
2904                 | NATIONAL CHARACTER opt_varying                { $$ = xlateSqlType($3? "varchar": "char"); }
2905                 | NCHAR opt_varying                                             { $$ = xlateSqlType($2? "varchar": "char"); }
2906                 ;
2907
2908 opt_varying:  VARYING                                                   { $$ = TRUE; }
2909                 | /*EMPTY*/                                                             { $$ = FALSE; }
2910                 ;
2911
2912 opt_charset:  CHARACTER SET ColId                               { $$ = $3; }
2913                 | /*EMPTY*/                                                             { $$ = NULL; }
2914                 ;
2915
2916 opt_collate:  COLLATE ColId                                             { $$ = $2; }
2917                 | /*EMPTY*/                                                             { $$ = NULL; }
2918                 ;
2919
2920 Datetime:  datetime
2921                                 {
2922                                         $$ = makeNode(TypeName);
2923                                         $$->name = xlateSqlType($1);
2924                                         $$->typmod = -1;
2925                                 }
2926                 | TIMESTAMP opt_timezone
2927                                 {
2928                                         $$ = makeNode(TypeName);
2929                                         $$->name = xlateSqlType("timestamp");
2930                                         $$->timezone = $2;
2931                                         $$->typmod = -1;
2932                                 }
2933                 | TIME
2934                                 {
2935                                         $$ = makeNode(TypeName);
2936                                         $$->name = xlateSqlType("time");
2937                                         $$->typmod = -1;
2938                                 }
2939                 | INTERVAL opt_interval
2940                                 {
2941                                         $$ = makeNode(TypeName);
2942                                         $$->name = xlateSqlType("interval");
2943                                         $$->typmod = -1;
2944                                 }
2945                 ;
2946
2947 datetime:  YEAR_P                                                               { $$ = "year"; }
2948                 | MONTH_P                                                               { $$ = "month"; }
2949                 | DAY_P                                                                 { $$ = "day"; }
2950                 | HOUR_P                                                                { $$ = "hour"; }
2951                 | MINUTE_P                                                              { $$ = "minute"; }
2952                 | SECOND_P                                                              { $$ = "second"; }
2953                 ;
2954
2955 opt_timezone:  WITH TIME ZONE                                   { $$ = TRUE; }
2956                 | /*EMPTY*/                                                             { $$ = FALSE; }
2957                 ;
2958
2959 opt_interval:  datetime                                                 { $$ = lcons($1, NIL); }
2960                 | YEAR_P TO MONTH_P                                             { $$ = NIL; }
2961                 | DAY_P TO HOUR_P                                               { $$ = NIL; }
2962                 | DAY_P TO MINUTE_P                                             { $$ = NIL; }
2963                 | DAY_P TO SECOND_P                                             { $$ = NIL; }
2964                 | HOUR_P TO MINUTE_P                                    { $$ = NIL; }
2965                 | HOUR_P TO SECOND_P                                    { $$ = NIL; }
2966                 | /*EMPTY*/                                                             { $$ = NIL; }
2967                 ;
2968
2969
2970 /*****************************************************************************
2971  *
2972  *      expression grammar, still needs some cleanup
2973  *
2974  *****************************************************************************/
2975
2976 a_expr_or_null:  a_expr
2977                                 { $$ = $1; }
2978                 | NULL_P
2979                                 {
2980                                         A_Const *n = makeNode(A_Const);
2981                                         n->val.type = T_Null;
2982                                         $$ = (Node *)n;
2983                                 }
2984                 ;
2985
2986 /* Expressions using row descriptors
2987  * Define row_descriptor to allow yacc to break the reduce/reduce conflict
2988  *  with singleton expressions.
2989  */
2990 row_expr: '(' row_descriptor ')' IN '(' SubSelect ')'
2991                                 {
2992                                         SubLink *n = makeNode(SubLink);
2993                                         n->lefthand = $2;
2994                                         n->oper = lcons("=",NIL);
2995                                         n->useor = false;
2996                                         n->subLinkType = ANY_SUBLINK;
2997                                         n->subselect = $6;
2998                                         $$ = (Node *)n;
2999                                 }
3000                 | '(' row_descriptor ')' NOT IN '(' SubSelect ')'
3001                                 {
3002                                         SubLink *n = makeNode(SubLink);
3003                                         n->lefthand = $2;
3004                                         n->oper = lcons("<>",NIL);
3005                                         n->useor = true;
3006                                         n->subLinkType = ALL_SUBLINK;
3007                                         n->subselect = $7;
3008                                         $$ = (Node *)n;
3009                                 }
3010                 | '(' row_descriptor ')' Op '(' SubSelect ')'
3011                                 {
3012                                         SubLink *n = makeNode(SubLink);
3013                                         n->lefthand = $2;
3014                                         n->oper = lcons($4, NIL);
3015                                         if (strcmp($4,"<>") == 0)
3016                                                 n->useor = true;
3017                                         else
3018                                                 n->useor = false;
3019                                         n->subLinkType = EXPR_SUBLINK;
3020                                         n->subselect = $6;
3021                                         $$ = (Node *)n;
3022                                 }
3023                 | '(' row_descriptor ')' '+' '(' SubSelect ')'
3024                                 {
3025                                         SubLink *n = makeNode(SubLink);
3026                                         n->lefthand = $2;
3027                                         n->oper = lcons("+", NIL);
3028                                         n->useor = false;
3029                                         n->subLinkType = EXPR_SUBLINK;
3030                                         n->subselect = $6;
3031                                         $$ = (Node *)n;
3032                                 }
3033                 | '(' row_descriptor ')' '-' '(' SubSelect ')'
3034                                 {
3035                                         SubLink *n = makeNode(SubLink);
3036                                         n->lefthand = $2;
3037                                         n->oper = lcons("-", NIL);
3038                                         n->useor = false;
3039                                         n->subLinkType = EXPR_SUBLINK;
3040                                         n->subselect = $6;
3041                                         $$ = (Node *)n;
3042                                 }
3043                 | '(' row_descriptor ')' '/' '(' SubSelect ')'
3044                                 {
3045                                         SubLink *n = makeNode(SubLink);
3046                                         n->lefthand = $2;
3047                                         n->oper = lcons("/", NIL);
3048                                         n->useor = false;
3049                                         n->subLinkType = EXPR_SUBLINK;
3050                                         n->subselect = $6;
3051                                         $$ = (Node *)n;
3052                                 }
3053                 | '(' row_descriptor ')' '*' '(' SubSelect ')'
3054                                 {
3055                                         SubLink *n = makeNode(SubLink);
3056                                         n->lefthand = $2;
3057                                         n->oper = lcons("*", NIL);
3058                                         n->useor = false;
3059                                         n->subLinkType = EXPR_SUBLINK;
3060                                         n->subselect = $6;
3061                                         $$ = (Node *)n;
3062                                 }
3063                 | '(' row_descriptor ')' '<' '(' SubSelect ')'
3064                                 {
3065                                         SubLink *n = makeNode(SubLink);
3066                                         n->lefthand = $2;
3067                                         n->oper = lcons("<", NIL);
3068                                         n->useor = false;
3069                                         n->subLinkType = EXPR_SUBLINK;
3070                                         n->subselect = $6;
3071                                         $$ = (Node *)n;
3072                                 }
3073                 | '(' row_descriptor ')' '>' '(' SubSelect ')'
3074                                 {
3075                                         SubLink *n = makeNode(SubLink);
3076                                         n->lefthand = $2;
3077                                         n->oper = lcons(">", NIL);
3078                                         n->useor = false;
3079                                         n->subLinkType = EXPR_SUBLINK;
3080                                         n->subselect = $6;
3081                                         $$ = (Node *)n;
3082                                 }
3083                 | '(' row_descriptor ')' '=' '(' SubSelect ')'
3084                                 {
3085                                         SubLink *n = makeNode(SubLink);
3086                                         n->lefthand = $2;
3087                                         n->oper = lcons("=", NIL);
3088                                         n->useor = false;
3089                                         n->subLinkType = EXPR_SUBLINK;
3090                                         n->subselect = $6;
3091                                         $$ = (Node *)n;
3092                                 }
3093                 | '(' row_descriptor ')' Op ANY '(' SubSelect ')'
3094                                 {
3095                                         SubLink *n = makeNode(SubLink);
3096                                         n->lefthand = $2;
3097                                         n->oper = lcons($4,NIL);
3098                                         if (strcmp($4,"<>") == 0)
3099                                                 n->useor = true;
3100                                         else
3101                                                 n->useor = false;
3102                                         n->subLinkType = ANY_SUBLINK;
3103                                         n->subselect = $7;
3104                                         $$ = (Node *)n;
3105                                 }
3106                 | '(' row_descriptor ')' '+' ANY '(' SubSelect ')'
3107                                 {
3108                                         SubLink *n = makeNode(SubLink);
3109                                         n->lefthand = $2;
3110                                         n->oper = lcons("+",NIL);
3111                                         n->useor = false;
3112                                         n->subLinkType = ANY_SUBLINK;
3113                                         n->subselect = $7;
3114                                         $$ = (Node *)n;
3115                                 }
3116                 | '(' row_descriptor ')' '-' ANY '(' SubSelect ')'
3117                                 {
3118                                         SubLink *n = makeNode(SubLink);
3119                                         n->lefthand = $2;
3120                                         n->oper = lcons("-",NIL);
3121                                         n->useor = false;
3122                                         n->subLinkType = ANY_SUBLINK;
3123                                         n->subselect = $7;
3124                                         $$ = (Node *)n;
3125                                 }
3126                 | '(' row_descriptor ')' '/' ANY '(' SubSelect ')'
3127                                 {
3128                                         SubLink *n = makeNode(SubLink);
3129                                         n->lefthand = $2;
3130                                         n->oper = lcons("/",NIL);
3131                                         n->useor = false;
3132                                         n->subLinkType = ANY_SUBLINK;
3133                                         n->subselect = $7;
3134                                         $$ = (Node *)n;
3135                                 }
3136                 | '(' row_descriptor ')' '*' ANY '(' SubSelect ')'
3137                                 {
3138                                         SubLink *n = makeNode(SubLink);
3139                                         n->lefthand = $2;
3140                                         n->oper = lcons("*",NIL);
3141                                         n->useor = false;
3142                                         n->subLinkType = ANY_SUBLINK;
3143                                         n->subselect = $7;
3144                                         $$ = (Node *)n;
3145                                 }
3146                 | '(' row_descriptor ')' '<' ANY '(' SubSelect ')'
3147                                 {
3148                                         SubLink *n = makeNode(SubLink);
3149                                         n->lefthand = $2;
3150                                         n->oper = lcons("<",NIL);
3151                                         n->useor = false;
3152                                         n->subLinkType = ANY_SUBLINK;
3153                                         n->subselect = $7;
3154                                         $$ = (Node *)n;
3155                                 }
3156                 | '(' row_descriptor ')' '>' ANY '(' SubSelect ')'
3157                                 {
3158                                         SubLink *n = makeNode(SubLink);
3159                                         n->lefthand = $2;
3160                                         n->oper = lcons(">",NIL);
3161                                         n->useor = false;
3162                                         n->subLinkType = ANY_SUBLINK;
3163                                         n->subselect = $7;
3164                                         $$ = (Node *)n;
3165                                 }
3166                 | '(' row_descriptor ')' '=' ANY '(' SubSelect ')'
3167                                 {
3168                                         SubLink *n = makeNode(SubLink);
3169                                         n->lefthand = $2;
3170                                         n->oper = lcons("=",NIL);
3171                                         n->useor = false;
3172                                         n->subLinkType = ANY_SUBLINK;
3173                                         n->subselect = $7;
3174                                         $$ = (Node *)n;
3175                                 }
3176                 | '(' row_descriptor ')' Op ALL '(' SubSelect ')'
3177                                 {
3178                                         SubLink *n = makeNode(SubLink);
3179                                         n->lefthand = $2;
3180                                         n->oper = lcons($4,NIL);
3181                                         if (strcmp($4,"<>") == 0)
3182                                                 n->useor = true;
3183                                         else
3184                                                 n->useor = false;
3185                                         n->subLinkType = ALL_SUBLINK;
3186                                         n->subselect = $7;
3187                                         $$ = (Node *)n;
3188                                 }
3189                 | '(' row_descriptor ')' '+' ALL '(' SubSelect ')'
3190                                 {
3191                                         SubLink *n = makeNode(SubLink);
3192                                         n->lefthand = $2;
3193                                         n->oper = lcons("+",NIL);
3194                                         n->useor = false;
3195                                         n->subLinkType = ALL_SUBLINK;
3196                                         n->subselect = $7;
3197                                         $$ = (Node *)n;
3198                                 }
3199                 | '(' row_descriptor ')' '-' ALL '(' SubSelect ')'
3200                                 {
3201                                         SubLink *n = makeNode(SubLink);
3202                                         n->lefthand = $2;
3203                                         n->oper = lcons("-",NIL);
3204                                         n->useor = false;
3205                                         n->subLinkType = ALL_SUBLINK;
3206                                         n->subselect = $7;
3207                                         $$ = (Node *)n;
3208                                 }
3209                 | '(' row_descriptor ')' '/' ALL '(' SubSelect ')'
3210                                 {
3211                                         SubLink *n = makeNode(SubLink);
3212                                         n->lefthand = $2;
3213                                         n->oper = lcons("/",NIL);
3214                                         n->useor = false;
3215                                         n->subLinkType = ALL_SUBLINK;
3216                                         n->subselect = $7;
3217                                         $$ = (Node *)n;
3218                                 }
3219                 | '(' row_descriptor ')' '*' ALL '(' SubSelect ')'
3220                                 {
3221                                         SubLink *n = makeNode(SubLink);
3222                                         n->lefthand = $2;
3223                                         n->oper = lcons("*",NIL);
3224                                         n->useor = false;
3225                                         n->subLinkType = ALL_SUBLINK;
3226                                         n->subselect = $7;
3227                                         $$ = (Node *)n;
3228                                 }
3229                 | '(' row_descriptor ')' '<' ALL '(' SubSelect ')'
3230                                 {
3231                                         SubLink *n = makeNode(SubLink);
3232                                         n->lefthand = $2;
3233                                         n->oper = lcons("<",NIL);
3234                                         n->useor = false;
3235                                         n->subLinkType = ALL_SUBLINK;
3236                                         n->subselect = $7;
3237                                         $$ = (Node *)n;
3238                                 }
3239                 | '(' row_descriptor ')' '>' ALL '(' SubSelect ')'
3240                                 {
3241                                         SubLink *n = makeNode(SubLink);
3242                                         n->lefthand = $2;
3243                                         n->oper = lcons(">",NIL);
3244                                         n->useor = false;
3245                                         n->subLinkType = ALL_SUBLINK;
3246                                         n->subselect = $7;
3247                                         $$ = (Node *)n;
3248                                 }
3249                 | '(' row_descriptor ')' '=' ALL '(' SubSelect ')'
3250                                 {
3251                                         SubLink *n = makeNode(SubLink);
3252                                         n->lefthand = $2;
3253                                         n->oper = lcons("=",NIL);
3254                                         n->useor = false;
3255                                         n->subLinkType = ALL_SUBLINK;
3256                                         n->subselect = $7;
3257                                         $$ = (Node *)n;
3258                                 }
3259                 | '(' row_descriptor ')' Op '(' row_descriptor ')'
3260                                 {
3261                                         $$ = makeRowExpr($4, $2, $6);
3262                                 }
3263                 | '(' row_descriptor ')' '+' '(' row_descriptor ')'
3264                                 {
3265                                         $$ = makeRowExpr("+", $2, $6);
3266                                 }
3267                 | '(' row_descriptor ')' '-' '(' row_descriptor ')'
3268                                 {
3269                                         $$ = makeRowExpr("-", $2, $6);
3270                                 }
3271                 | '(' row_descriptor ')' '/' '(' row_descriptor ')'
3272                                 {
3273                                         $$ = makeRowExpr("/", $2, $6);
3274                                 }
3275                 | '(' row_descriptor ')' '*' '(' row_descriptor ')'
3276                                 {
3277                                         $$ = makeRowExpr("*", $2, $6);
3278                                 }
3279                 | '(' row_descriptor ')' '<' '(' row_descriptor ')'
3280                                 {
3281                                         $$ = makeRowExpr("<", $2, $6);
3282                                 }
3283                 | '(' row_descriptor ')' '>' '(' row_descriptor ')'
3284                                 {
3285                                         $$ = makeRowExpr(">", $2, $6);
3286                                 }
3287                 | '(' row_descriptor ')' '=' '(' row_descriptor ')'
3288                                 {
3289                                         $$ = makeRowExpr("=", $2, $6);
3290                                 }
3291                 ;
3292
3293 row_descriptor:  row_list ',' a_expr
3294                                 {
3295                                         $$ = lappend($1, $3);
3296                                 }
3297                 ;
3298
3299 row_list:  row_list ',' a_expr
3300                                 {
3301                                         $$ = lappend($1, $3);
3302                                 }
3303                 | a_expr
3304                                 {
3305                                         $$ = lcons($1, NIL);
3306                                 }
3307                 ;
3308
3309 /*
3310  * This is the heart of the expression syntax.
3311  * Note that the BETWEEN clause looks similar to a boolean expression
3312  *  and so we must define b_expr which is almost the same as a_expr
3313  *  but without the boolean expressions.
3314  * All operations are allowed in a BETWEEN clause if surrounded by parens.
3315  */
3316
3317 a_expr:  attr opt_indirection
3318                                 {
3319                                         $1->indirection = $2;
3320                                         $$ = (Node *)$1;
3321                                 }
3322                 | row_expr
3323                                 {       $$ = $1;  }
3324                 | AexprConst
3325                                 {       $$ = $1;  }
3326                 | ColId
3327                                 {
3328                                         /* could be a column name or a relation_name */
3329                                         Ident *n = makeNode(Ident);
3330                                         n->name = $1;
3331                                         n->indirection = NULL;
3332                                         $$ = (Node *)n;
3333                                 }
3334                 | '-' a_expr %prec UMINUS
3335                                 {       $$ = makeA_Expr(OP, "-", NULL, $2); }
3336                 | a_expr '+' a_expr
3337                                 {       $$ = makeA_Expr(OP, "+", $1, $3); }
3338                 | a_expr '-' a_expr
3339                                 {       $$ = makeA_Expr(OP, "-", $1, $3); }
3340                 | a_expr '/' a_expr
3341                                 {       $$ = makeA_Expr(OP, "/", $1, $3); }
3342                 | a_expr '*' a_expr
3343                                 {       $$ = makeA_Expr(OP, "*", $1, $3); }
3344                 | a_expr '<' a_expr
3345                                 {       $$ = makeA_Expr(OP, "<", $1, $3); }
3346                 | a_expr '>' a_expr
3347                                 {       $$ = makeA_Expr(OP, ">", $1, $3); }
3348                 | a_expr '=' a_expr
3349                                 {       $$ = makeA_Expr(OP, "=", $1, $3); }
3350                 | ':' a_expr
3351                                 {       $$ = makeA_Expr(OP, ":", NULL, $2); }
3352                 | ';' a_expr
3353                                 {       $$ = makeA_Expr(OP, ";", NULL, $2); }
3354                 | '|' a_expr
3355                                 {       $$ = makeA_Expr(OP, "|", NULL, $2); }
3356                 | a_expr TYPECAST Typename
3357                                 {
3358                                         $$ = (Node *)$1;
3359                                         /* AexprConst can be either A_Const or ParamNo */
3360                                         if (nodeTag($1) == T_A_Const) {
3361                                                 ((A_Const *)$1)->typename = $3;
3362                                         } else if (nodeTag($1) == T_Param) {
3363                                                 ((ParamNo *)$1)->typename = $3;
3364                                         /* otherwise, try to transform to a function call */
3365                                         } else {
3366                                                 FuncCall *n = makeNode(FuncCall);
3367                                                 n->funcname = $3->name;
3368                                                 n->args = lcons($1,NIL);
3369                                                 $$ = (Node *)n;
3370                                         }
3371                                 }
3372                 | CAST '(' a_expr AS Typename ')'
3373                                 {
3374                                         $$ = (Node *)$3;
3375                                         /* AexprConst can be either A_Const or ParamNo */
3376                                         if (nodeTag($3) == T_A_Const) {
3377                                                 ((A_Const *)$3)->typename = $5;
3378                                         } else if (nodeTag($5) == T_Param) {
3379                                                 ((ParamNo *)$3)->typename = $5;
3380                                         /* otherwise, try to transform to a function call */
3381                                         } else {
3382                                                 FuncCall *n = makeNode(FuncCall);
3383                                                 n->funcname = $5->name;
3384                                                 n->args = lcons($3,NIL);
3385                                                 $$ = (Node *)n;
3386                                         }
3387                                 }
3388                 | '(' a_expr_or_null ')'
3389                                 {       $$ = $2; }
3390                 | a_expr Op a_expr
3391                                 {       $$ = makeIndexable($2,$1,$3);   }
3392                 | a_expr LIKE a_expr
3393                                 {       $$ = makeIndexable("~~", $1, $3); }
3394                 | a_expr NOT LIKE a_expr
3395                                 {       $$ = makeA_Expr(OP, "!~~", $1, $4); }
3396                 | Op a_expr
3397                                 {       $$ = makeA_Expr(OP, $1, NULL, $2); }
3398                 | a_expr Op
3399                                 {       $$ = makeA_Expr(OP, $2, $1, NULL); }
3400                 | func_name '(' '*' ')'
3401                                 {
3402                                         /* cheap hack for aggregate (eg. count) */
3403                                         FuncCall *n = makeNode(FuncCall);
3404                                         A_Const *star = makeNode(A_Const);
3405
3406                                         star->val.type = T_String;
3407                                         star->val.val.str = "";
3408                                         n->funcname = $1;
3409                                         n->args = lcons(star, NIL);
3410                                         $$ = (Node *)n;
3411                                 }
3412                 | func_name '(' ')'
3413                                 {
3414                                         FuncCall *n = makeNode(FuncCall);
3415                                         n->funcname = $1;
3416                                         n->args = NIL;
3417                                         $$ = (Node *)n;
3418                                 }
3419                 | func_name '(' expr_list ')'
3420                                 {
3421                                         FuncCall *n = makeNode(FuncCall);
3422                                         n->funcname = $1;
3423                                         n->args = $3;
3424                                         $$ = (Node *)n;
3425                                 }
3426                 | CURRENT_DATE
3427                                 {
3428                                         A_Const *n = makeNode(A_Const);
3429                                         TypeName *t = makeNode(TypeName);
3430
3431                                         n->val.type = T_String;
3432                                         n->val.val.str = "now";
3433                                         n->typename = t;
3434
3435                                         t->name = xlateSqlType("date");
3436                                         t->setof = FALSE;
3437                                         t->typmod = -1;
3438  
3439                                         $$ = (Node *)n;
3440                                 }
3441                 | CURRENT_TIME
3442                                 {
3443                                         A_Const *n = makeNode(A_Const);
3444                                         TypeName *t = makeNode(TypeName);
3445
3446                                         n->val.type = T_String;
3447                                         n->val.val.str = "now";
3448                                         n->typename = t;
3449
3450                                         t->name = xlateSqlType("time");
3451                                         t->setof = FALSE;
3452                                         t->typmod = -1;
3453
3454                                         $$ = (Node *)n;
3455                                 }
3456                 | CURRENT_TIME '(' Iconst ')'
3457                                 {
3458                                         FuncCall *n = makeNode(FuncCall);
3459                                         A_Const *s = makeNode(A_Const);
3460                                         TypeName *t = makeNode(TypeName);
3461
3462                                         n->funcname = xlateSqlType("time");
3463                                         n->args = lcons(s, NIL);
3464
3465                                         s->val.type = T_String;
3466                                         s->val.val.str = "now";
3467                                         s->typename = t;
3468
3469                                         t->name = xlateSqlType("time");
3470                                         t->setof = FALSE;
3471                                         t->typmod = -1;
3472
3473                                         if ($3 != 0)
3474                                                 elog(NOTICE,"CURRENT_TIME(%d) precision not implemented; zero used instead",$3);
3475
3476                                         $$ = (Node *)n;
3477                                 }
3478                 | CURRENT_TIMESTAMP
3479                                 {
3480                                         A_Const *n = makeNode(A_Const);
3481                                         TypeName *t = makeNode(TypeName);
3482
3483                                         n->val.type = T_String;
3484                                         n->val.val.str = "now";
3485                                         n->typename = t;
3486
3487                                         t->name = xlateSqlType("timestamp");
3488                                         t->setof = FALSE;
3489                                         t->typmod = -1;
3490
3491                                         $$ = (Node *)n;
3492                                 }
3493                 | CURRENT_TIMESTAMP '(' Iconst ')'
3494                                 {
3495                                         FuncCall *n = makeNode(FuncCall);
3496                                         A_Const *s = makeNode(A_Const);
3497                                         TypeName *t = makeNode(TypeName);
3498
3499                                         n->funcname = xlateSqlType("timestamp");
3500                                         n->args = lcons(s, NIL);
3501
3502                                         s->val.type = T_String;
3503                                         s->val.val.str = "now";
3504                                         s->typename = t;
3505
3506                                         t->name = xlateSqlType("timestamp");
3507                                         t->setof = FALSE;
3508                                         t->typmod = -1;
3509
3510                                         if ($3 != 0)
3511                                                 elog(NOTICE,"CURRENT_TIMESTAMP(%d) precision not implemented; zero used instead",$3);
3512
3513                                         $$ = (Node *)n;
3514                                 }
3515                 | CURRENT_USER
3516                                 {
3517                                         FuncCall *n = makeNode(FuncCall);
3518                                         n->funcname = "getpgusername";
3519                                         n->args = NIL;
3520                                         $$ = (Node *)n;
3521                                 }
3522                 | EXISTS '(' SubSelect ')'
3523                                 {
3524                                         SubLink *n = makeNode(SubLink);
3525                                         n->lefthand = NIL;
3526                                         n->useor = false;
3527                                         n->oper = NIL;
3528                                         n->subLinkType = EXISTS_SUBLINK;
3529                                         n->subselect = $3;
3530                                         $$ = (Node *)n;
3531                                 }
3532                 | EXTRACT '(' extract_list ')'
3533                                 {
3534                                         FuncCall *n = makeNode(FuncCall);
3535                                         n->funcname = "date_part";
3536                                         n->args = $3;
3537                                         $$ = (Node *)n;
3538                                 }
3539                 | POSITION '(' position_list ')'
3540                                 {
3541                                         FuncCall *n = makeNode(FuncCall);
3542                                         n->funcname = "strpos";
3543                                         n->args = $3;
3544                                         $$ = (Node *)n;
3545                                 }
3546                 | SUBSTRING '(' substr_list ')'
3547                                 {
3548                                         FuncCall *n = makeNode(FuncCall);
3549                                         n->funcname = "substr";
3550                                         n->args = $3;
3551                                         $$ = (Node *)n;
3552                                 }
3553                 /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
3554                 | TRIM '(' BOTH trim_list ')'
3555                                 {
3556                                         FuncCall *n = makeNode(FuncCall);
3557                                         n->funcname = "btrim";
3558                                         n->args = $4;
3559                                         $$ = (Node *)n;
3560                                 }
3561                 | TRIM '(' LEADING trim_list ')'
3562                                 {
3563                                         FuncCall *n = makeNode(FuncCall);
3564                                         n->funcname = "ltrim";
3565                                         n->args = $4;
3566                                         $$ = (Node *)n;
3567                                 }
3568                 | TRIM '(' TRAILING trim_list ')'
3569                                 {
3570                                         FuncCall *n = makeNode(FuncCall);
3571                                         n->funcname = "rtrim";
3572                                         n->args = $4;
3573                                         $$ = (Node *)n;
3574                                 }
3575                 | TRIM '(' trim_list ')'
3576                                 {
3577                                         FuncCall *n = makeNode(FuncCall);
3578                                         n->funcname = "btrim";
3579                                         n->args = $3;
3580                                         $$ = (Node *)n;
3581                                 }
3582                 | a_expr ISNULL
3583                                 {       $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
3584                 | a_expr IS NULL_P
3585                                 {       $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
3586                 | a_expr NOTNULL
3587                                 {       $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); }
3588                 | a_expr IS NOT NULL_P
3589                                 {       $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); }
3590                 /* IS TRUE, IS FALSE, etc used to be function calls
3591                  *  but let's make them expressions to allow the optimizer
3592                  *  a chance to eliminate them if a_expr is a constant string.
3593                  * - thomas 1997-12-22
3594                  */
3595                 | a_expr IS TRUE_P
3596                                 {
3597                                         A_Const *n = makeNode(A_Const);
3598                                         n->val.type = T_String;
3599                                         n->val.val.str = "t";
3600                                         n->typename = makeNode(TypeName);
3601                                         n->typename->name = xlateSqlType("bool");
3602                                         n->typename->typmod = -1;
3603                                         $$ = makeA_Expr(OP, "=", $1,(Node *)n);
3604                                 }
3605                 | a_expr IS NOT FALSE_P
3606                                 {
3607                                         A_Const *n = makeNode(A_Const);
3608                                         n->val.type = T_String;
3609                                         n->val.val.str = "t";
3610                                         n->typename = makeNode(TypeName);
3611                                         n->typename->name = xlateSqlType("bool");
3612                                         n->typename->typmod = -1;
3613                                         $$ = makeA_Expr(OP, "=", $1,(Node *)n);
3614                                 }
3615                 | a_expr IS FALSE_P
3616                                 {
3617                                         A_Const *n = makeNode(A_Const);
3618                                         n->val.type = T_String;
3619                                         n->val.val.str = "f";
3620                                         n->typename = makeNode(TypeName);
3621                                         n->typename->name = xlateSqlType("bool");
3622                                         n->typename->typmod = -1;
3623                                         $$ = makeA_Expr(OP, "=", $1,(Node *)n);
3624                                 }
3625                 | a_expr IS NOT TRUE_P
3626                                 {
3627                                         A_Const *n = makeNode(A_Const);
3628                                         n->val.type = T_String;
3629                                         n->val.val.str = "f";
3630                                         n->typename = makeNode(TypeName);
3631                                         n->typename->name = xlateSqlType("bool");
3632                                         n->typename->typmod = -1;
3633                                         $$ = makeA_Expr(OP, "=", $1,(Node *)n);
3634                                 }
3635                 | a_expr BETWEEN b_expr AND b_expr
3636                                 {
3637                                         $$ = makeA_Expr(AND, NULL,
3638                                                 makeA_Expr(OP, ">=", $1, $3),
3639                                                 makeA_Expr(OP, "<=", $1, $5));
3640                                 }
3641                 | a_expr NOT BETWEEN b_expr AND b_expr
3642                                 {
3643                                         $$ = makeA_Expr(OR, NULL,
3644                                                 makeA_Expr(OP, "<", $1, $4),
3645                                                 makeA_Expr(OP, ">", $1, $6));
3646                                 }
3647                 | a_expr IN { saved_In_Expr = lcons($1,saved_In_Expr); } '(' in_expr ')'
3648                                 {
3649                                         saved_In_Expr = lnext(saved_In_Expr);
3650                                         if (nodeTag($5) == T_SubLink)
3651                                         {
3652                                                         SubLink *n = (SubLink *)$5;
3653                                                         n->lefthand = lcons($1, NIL);
3654                                                         n->oper = lcons("=",NIL);
3655                                                         n->useor = false;
3656                                                         n->subLinkType = ANY_SUBLINK;
3657                                                         $$ = (Node *)n;
3658                                         }
3659                                         else    $$ = $5;
3660                                 }
3661                 | a_expr NOT IN { saved_In_Expr = lcons($1,saved_In_Expr); } '(' not_in_expr ')'
3662                                 {
3663                                         saved_In_Expr = lnext(saved_In_Expr);
3664                                         if (nodeTag($6) == T_SubLink)
3665                                         {
3666                                                         SubLink *n = (SubLink *)$6;
3667                                                         n->lefthand = lcons($1, NIL);
3668                                                         n->oper = lcons("<>",NIL);
3669                                                         n->useor = false;
3670                                                         n->subLinkType = ALL_SUBLINK;
3671                                                         $$ = (Node *)n;
3672                                         }
3673                                         else    $$ = $6;
3674                                 }
3675                 | a_expr Op '(' SubSelect ')'
3676                                 {
3677                                         SubLink *n = makeNode(SubLink);
3678                                         n->lefthand = lcons($1, NULL);
3679                                         n->oper = lcons($2,NIL);
3680                                         n->useor = false;
3681                                         n->subLinkType = EXPR_SUBLINK;
3682                                         n->subselect = $4;
3683                                         $$ = (Node *)n;
3684                                 }
3685                 | a_expr '+' '(' SubSelect ')'
3686                                 {
3687                                         SubLink *n = makeNode(SubLink);
3688                                         n->lefthand = lcons($1, NULL);
3689                                         n->oper = lcons("+",NIL);
3690                                         n->useor = false;
3691                                         n->subLinkType = EXPR_SUBLINK;
3692                                         n->subselect = $4;
3693                                         $$ = (Node *)n;
3694                                 }
3695                 | a_expr '-' '(' SubSelect ')'
3696                                 {
3697                                         SubLink *n = makeNode(SubLink);
3698                                         n->lefthand = lcons($1, NULL);
3699                                         n->oper = lcons("-",NIL);
3700                                         n->useor = false;
3701                                         n->subLinkType = EXPR_SUBLINK;
3702                                         n->subselect = $4;
3703                                         $$ = (Node *)n;
3704                                 }
3705                 | a_expr '/' '(' SubSelect ')'
3706                                 {
3707                                         SubLink *n = makeNode(SubLink);
3708                                         n->lefthand = lcons($1, NULL);
3709                                         n->oper = lcons("/",NIL);
3710                                         n->useor = false;
3711                                         n->subLinkType = EXPR_SUBLINK;
3712                                         n->subselect = $4;
3713                                         $$ = (Node *)n;
3714                                 }
3715                 | a_expr '*' '(' SubSelect ')'
3716                                 {
3717                                         SubLink *n = makeNode(SubLink);
3718                                         n->lefthand = lcons($1, NULL);
3719                                         n->oper = lcons("*",NIL);
3720                                         n->useor = false;
3721                                         n->subLinkType = EXPR_SUBLINK;
3722                                         n->subselect = $4;
3723                                         $$ = (Node *)n;
3724                                 }
3725                 | a_expr '<' '(' SubSelect ')'
3726                                 {
3727                                         SubLink *n = makeNode(SubLink);
3728                                         n->lefthand = lcons($1, NULL);
3729                                         n->oper = lcons("<",NIL);
3730                                         n->useor = false;
3731                                         n->subLinkType = EXPR_SUBLINK;
3732                                         n->subselect = $4;
3733                                         $$ = (Node *)n;
3734                                 }
3735                 | a_expr '>' '(' SubSelect ')'
3736                                 {
3737                                         SubLink *n = makeNode(SubLink);
3738                                         n->lefthand = lcons($1, NULL);
3739                                         n->oper = lcons(">",NIL);
3740                                         n->useor = false;
3741                                         n->subLinkType = EXPR_SUBLINK;
3742                                         n->subselect = $4;
3743                                         $$ = (Node *)n;
3744                                 }
3745                 | a_expr '=' '(' SubSelect ')'
3746                                 {
3747                                         SubLink *n = makeNode(SubLink);
3748                                         n->lefthand = lcons($1, NULL);
3749                                         n->oper = lcons("=",NIL);
3750                                         n->useor = false;
3751                                         n->subLinkType = EXPR_SUBLINK;
3752                                         n->subselect = $4;
3753                                         $$ = (Node *)n;
3754                                 }
3755                 | a_expr Op ANY '(' SubSelect ')'
3756                                 {
3757                                         SubLink *n = makeNode(SubLink);
3758                                         n->lefthand = lcons($1,NIL);
3759                                         n->oper = lcons($2,NIL);
3760                                         n->useor = false;
3761                                         n->subLinkType = ANY_SUBLINK;
3762                                         n->subselect = $5;
3763                                         $$ = (Node *)n;
3764                                 }
3765                 | a_expr '+' ANY '(' SubSelect ')'
3766                                 {
3767                                         SubLink *n = makeNode(SubLink);
3768                                         n->lefthand = lcons($1,NIL);
3769                                         n->oper = lcons("+",NIL);
3770                                         n->useor = false;
3771                                         n->subLinkType = ANY_SUBLINK;
3772                                         n->subselect = $5;
3773                                         $$ = (Node *)n;
3774                                 }
3775                 | a_expr '-' ANY '(' SubSelect ')'
3776                                 {
3777                                         SubLink *n = makeNode(SubLink);
3778                                         n->lefthand = lcons($1,NIL);
3779                                         n->oper = lcons("-",NIL);
3780                                         n->useor = false;
3781                                         n->subLinkType = ANY_SUBLINK;
3782                                         n->subselect = $5;
3783                                         $$ = (Node *)n;
3784                                 }
3785                 | a_expr '/' ANY '(' SubSelect ')'
3786                                 {
3787                                         SubLink *n = makeNode(SubLink);
3788                                         n->lefthand = lcons($1,NIL);
3789                                         n->oper = lcons("/",NIL);
3790                                         n->useor = false;
3791                                         n->subLinkType = ANY_SUBLINK;
3792                                         n->subselect = $5;
3793                                         $$ = (Node *)n;
3794                                 }
3795                 | a_expr '*' ANY '(' SubSelect ')'
3796                                 {
3797                                         SubLink *n = makeNode(SubLink);
3798                                         n->lefthand = lcons($1,NIL);
3799                                         n->oper = lcons("*",NIL);
3800                                         n->useor = false;
3801                                         n->subLinkType = ANY_SUBLINK;
3802                                         n->subselect = $5;
3803                                         $$ = (Node *)n;
3804                                 }
3805                 | a_expr '<' ANY '(' SubSelect ')'
3806                                 {
3807                                         SubLink *n = makeNode(SubLink);
3808                                         n->lefthand = lcons($1,NIL);
3809                                         n->oper = lcons("<",NIL);
3810                                         n->useor = false;
3811                                         n->subLinkType = ANY_SUBLINK;
3812                                         n->subselect = $5;
3813                                         $$ = (Node *)n;
3814                                 }
3815                 | a_expr '>' ANY '(' SubSelect ')'
3816                                 {
3817                                         SubLink *n = makeNode(SubLink);
3818                                         n->lefthand = lcons($1,NIL);
3819                                         n->oper = lcons(">",NIL);
3820                                         n->useor = false;
3821                                         n->subLinkType = ANY_SUBLINK;
3822                                         n->subselect = $5;
3823                                         $$ = (Node *)n;
3824                                 }
3825                 | a_expr '=' ANY '(' SubSelect ')'
3826                                 {
3827                                         SubLink *n = makeNode(SubLink);
3828                                         n->lefthand = lcons($1,NIL);
3829                                         n->oper = lcons("=",NIL);
3830                                         n->useor = false;
3831                                         n->subLinkType = ANY_SUBLINK;
3832                                         n->subselect = $5;
3833                                         $$ = (Node *)n;
3834                                 }
3835                 | a_expr Op ALL '(' SubSelect ')'
3836                                 {
3837                                         SubLink *n = makeNode(SubLink);
3838                                         n->lefthand = lcons($1, NULL);
3839                                         n->oper = lcons($2,NIL);
3840                                         n->useor = false;
3841                                         n->subLinkType = ALL_SUBLINK;
3842                                         n->subselect = $5;
3843                                         $$ = (Node *)n;
3844                                 }
3845                 | a_expr '+' ALL '(' SubSelect ')'
3846                                 {
3847                                         SubLink *n = makeNode(SubLink);
3848                                         n->lefthand = lcons($1, NULL);
3849                                         n->oper = lcons("+",NIL);
3850                                         n->useor = false;
3851                                         n->subLinkType = ALL_SUBLINK;
3852                                         n->subselect = $5;
3853                                         $$ = (Node *)n;
3854                                 }
3855                 | a_expr '-' ALL '(' SubSelect ')'
3856                                 {
3857                                         SubLink *n = makeNode(SubLink);
3858                                         n->lefthand = lcons($1, NULL);
3859                                         n->oper = lcons("-",NIL);
3860                                         n->useor = false;
3861                                         n->subLinkType = ALL_SUBLINK;
3862                                         n->subselect = $5;
3863                                         $$ = (Node *)n;
3864                                 }
3865                 | a_expr '/' ALL '(' SubSelect ')'
3866                                 {
3867                                         SubLink *n = makeNode(SubLink);
3868                                         n->lefthand = lcons($1, NULL);
3869                                         n->oper = lcons("/",NIL);
3870                                         n->useor = false;
3871                                         n->subLinkType = ALL_SUBLINK;
3872                                         n->subselect = $5;
3873                                         $$ = (Node *)n;
3874                                 }
3875                 | a_expr '*' ALL '(' SubSelect ')'
3876                                 {
3877                                         SubLink *n = makeNode(SubLink);
3878                                         n->lefthand = lcons($1, NULL);
3879                                         n->oper = lcons("*",NIL);
3880                                         n->useor = false;
3881                                         n->subLinkType = ALL_SUBLINK;
3882                                         n->subselect = $5;
3883                                         $$ = (Node *)n;
3884                                 }
3885                 | a_expr '<' ALL '(' SubSelect ')'
3886                                 {
3887                                         SubLink *n = makeNode(SubLink);
3888                                         n->lefthand = lcons($1, NULL);
3889                                         n->oper = lcons("<",NIL);
3890                                         n->useor = false;
3891                                         n->subLinkType = ALL_SUBLINK;
3892                                         n->subselect = $5;
3893                                         $$ = (Node *)n;
3894                                 }
3895                 | a_expr '>' ALL '(' SubSelect ')'
3896                                 {
3897                                         SubLink *n = makeNode(SubLink);
3898                                         n->lefthand = lcons($1, NULL);
3899                                         n->oper = lcons(">",NIL);
3900                                         n->useor = false;
3901                                         n->subLinkType = ALL_SUBLINK;
3902                                         n->subselect = $5;
3903                                         $$ = (Node *)n;
3904                                 }
3905                 | a_expr '=' ALL '(' SubSelect ')'
3906                                 {
3907                                         SubLink *n = makeNode(SubLink);
3908                                         n->lefthand = lcons($1, NULL);
3909                                         n->oper = lcons("=",NIL);
3910                                         n->useor = false;
3911                                         n->subLinkType = ALL_SUBLINK;
3912                                         n->subselect = $5;
3913                                         $$ = (Node *)n;
3914                                 }
3915                 | a_expr AND a_expr
3916                                 {       $$ = makeA_Expr(AND, NULL, $1, $3); }
3917                 | a_expr OR a_expr
3918                                 {       $$ = makeA_Expr(OR, NULL, $1, $3); }
3919                 | NOT a_expr
3920                                 {       $$ = makeA_Expr(NOT, NULL, NULL, $2); }
3921                 ;
3922
3923 /*
3924  * b_expr is a subset of the complete expression syntax
3925  *  defined by a_expr. b_expr is used in BETWEEN clauses
3926  *  to eliminate parser ambiguities stemming from the AND keyword.
3927  */
3928
3929 b_expr:  attr opt_indirection
3930                                 {
3931                                         $1->indirection = $2;
3932                                         $$ = (Node *)$1;
3933                                 }
3934                 | AexprConst
3935                                 {       $$ = $1;  }
3936                 | ColId
3937                                 {
3938                                         /* could be a column name or a relation_name */
3939                                         Ident *n = makeNode(Ident);
3940                                         n->name = $1;
3941                                         n->indirection = NULL;
3942                                         $$ = (Node *)n;
3943                                 }
3944                 | '-' b_expr %prec UMINUS
3945                                 {       $$ = makeA_Expr(OP, "-", NULL, $2); }
3946                 | b_expr '+' b_expr
3947                                 {       $$ = makeA_Expr(OP, "+", $1, $3); }
3948                 | b_expr '-' b_expr
3949                                 {       $$ = makeA_Expr(OP, "-", $1, $3); }
3950                 | b_expr '/' b_expr
3951                                 {       $$ = makeA_Expr(OP, "/", $1, $3); }
3952                 | b_expr '*' b_expr
3953                                 {       $$ = makeA_Expr(OP, "*", $1, $3); }
3954                 | ':' b_expr
3955                                 {       $$ = makeA_Expr(OP, ":", NULL, $2); }
3956                 | ';' b_expr
3957                                 {       $$ = makeA_Expr(OP, ";", NULL, $2); }
3958                 | '|' b_expr
3959                                 {       $$ = makeA_Expr(OP, "|", NULL, $2); }
3960                 | b_expr TYPECAST Typename
3961                                 {
3962                                         $$ = (Node *)$1;
3963                                         /* AexprConst can be either A_Const or ParamNo */
3964                                         if (nodeTag($1) == T_A_Const) {
3965                                                 ((A_Const *)$1)->typename = $3;
3966                                         } else if (nodeTag($1) == T_Param) {
3967                                                 ((ParamNo *)$1)->typename = $3;
3968                                         /* otherwise, try to transform to a function call */
3969                                         } else {
3970                                                 FuncCall *n = makeNode(FuncCall);
3971                                                 n->funcname = $3->name;
3972                                                 n->args = lcons($1,NIL);
3973                                                 $$ = (Node *)n;
3974                                         }
3975                                 }
3976                 | CAST '(' b_expr AS Typename ')'
3977                                 {
3978                                         $$ = (Node *)$3;
3979                                         /* AexprConst can be either A_Const or ParamNo */
3980                                         if (nodeTag($3) == T_A_Const) {
3981                                                 ((A_Const *)$3)->typename = $5;
3982                                         } else if (nodeTag($3) == T_Param) {
3983                                                 ((ParamNo *)$3)->typename = $5;
3984                                         /* otherwise, try to transform to a function call */
3985                                         } else {
3986                                                 FuncCall *n = makeNode(FuncCall);
3987                                                 n->funcname = $5->name;
3988                                                 n->args = lcons($3,NIL);
3989                                                 $$ = (Node *)n;
3990                                         }
3991                                 }
3992                 | '(' a_expr ')'
3993                                 {       $$ = $2; }
3994                 | b_expr Op b_expr
3995                                 {       $$ = makeIndexable($2,$1,$3);   }
3996                 | Op b_expr
3997                                 {       $$ = makeA_Expr(OP, $1, NULL, $2); }
3998                 | b_expr Op
3999                                 {       $$ = makeA_Expr(OP, $2, $1, NULL); }
4000                 | func_name '(' ')'
4001                                 {
4002                                         FuncCall *n = makeNode(FuncCall);
4003                                         n->funcname = $1;
4004                                         n->args = NIL;
4005                                         $$ = (Node *)n;
4006                                 }
4007                 | func_name '(' expr_list ')'
4008                                 {
4009                                         FuncCall *n = makeNode(FuncCall);
4010                                         n->funcname = $1;
4011                                         n->args = $3;
4012                                         $$ = (Node *)n;
4013                                 }
4014                 | CURRENT_DATE
4015                                 {
4016                                         A_Const *n = makeNode(A_Const);
4017                                         TypeName *t = makeNode(TypeName);
4018
4019                                         n->val.type = T_String;
4020                                         n->val.val.str = "now";
4021                                         n->typename = t;
4022
4023                                         t->name = xlateSqlType("date");
4024                                         t->setof = FALSE;
4025                                         t->typmod = -1;
4026
4027                                         $$ = (Node *)n;
4028                                 }
4029                 | CURRENT_TIME
4030                                 {
4031                                         A_Const *n = makeNode(A_Const);
4032                                         TypeName *t = makeNode(TypeName);
4033
4034                                         n->val.type = T_String;
4035                                         n->val.val.str = "now";
4036                                         n->typename = t;
4037
4038                                         t->name = xlateSqlType("time");
4039                                         t->setof = FALSE;
4040                                         t->typmod = -1;
4041
4042                                         $$ = (Node *)n;
4043                                 }
4044                 | CURRENT_TIME '(' Iconst ')'
4045                                 {
4046                                         FuncCall *n = makeNode(FuncCall);
4047                                         A_Const *s = makeNode(A_Const);
4048                                         TypeName *t = makeNode(TypeName);
4049
4050                                         n->funcname = xlateSqlType("time");
4051                                         n->args = lcons(s, NIL);
4052
4053                                         s->val.type = T_String;
4054                                         s->val.val.str = "now";
4055                                         s->typename = t;
4056
4057                                         t->name = xlateSqlType("time");
4058                                         t->setof = FALSE;
4059                                         t->typmod = -1;
4060
4061                                         if ($3 != 0)
4062                                                 elog(NOTICE,"CURRENT_TIME(%d) precision not implemented; zero used instead",$3);
4063
4064                                         $$ = (Node *)n;
4065                                 }
4066                 | CURRENT_TIMESTAMP
4067                                 {
4068                                         A_Const *n = makeNode(A_Const);
4069                                         TypeName *t = makeNode(TypeName);
4070
4071                                         n->val.type = T_String;
4072                                         n->val.val.str = "now";
4073                                         n->typename = t;
4074
4075                                         t->name = xlateSqlType("timestamp");
4076                                         t->setof = FALSE;
4077                                         t->typmod = -1;
4078
4079                                         $$ = (Node *)n;
4080                                 }
4081                 | CURRENT_TIMESTAMP '(' Iconst ')'
4082                                 {
4083                                         FuncCall *n = makeNode(FuncCall);
4084                                         A_Const *s = makeNode(A_Const);
4085                                         TypeName *t = makeNode(TypeName);
4086
4087                                         n->funcname = xlateSqlType("timestamp");
4088                                         n->args = lcons(s, NIL);
4089
4090                                         s->val.type = T_String;
4091                                         s->val.val.str = "now";
4092                                         s->typename = t;
4093
4094                                         t->name = xlateSqlType("timestamp");
4095                                         t->setof = FALSE;
4096                                         t->typmod = -1;
4097
4098                                         if ($3 != 0)
4099                                                 elog(NOTICE,"CURRENT_TIMESTAMP(%d) precision not implemented; zero used instead",$3);
4100
4101                                         $$ = (Node *)n;
4102                                 }
4103                 | CURRENT_USER
4104                                 {
4105                                         FuncCall *n = makeNode(FuncCall);
4106                                         n->funcname = "getpgusername";
4107                                         n->args = NIL;
4108                                         $$ = (Node *)n;
4109                                 }
4110                 | POSITION '(' position_list ')'
4111                                 {
4112                                         FuncCall *n = makeNode(FuncCall);
4113                                         n->funcname = "strpos";
4114                                         n->args = $3;
4115                                         $$ = (Node *)n;
4116                                 }
4117                 | SUBSTRING '(' substr_list ')'
4118                                 {
4119                                         FuncCall *n = makeNode(FuncCall);
4120                                         n->funcname = "substr";
4121                                         n->args = $3;
4122                                         $$ = (Node *)n;
4123                                 }
4124                 /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
4125                 | TRIM '(' BOTH trim_list ')'
4126                                 {
4127                                         FuncCall *n = makeNode(FuncCall);
4128                                         n->funcname = "btrim";
4129                                         n->args = $4;
4130                                         $$ = (Node *)n;
4131                                 }
4132                 | TRIM '(' LEADING trim_list ')'
4133                                 {
4134                                         FuncCall *n = makeNode(FuncCall);
4135                                         n->funcname = "ltrim";
4136                                         n->args = $4;
4137                                         $$ = (Node *)n;
4138                                 }
4139                 | TRIM '(' TRAILING trim_list ')'
4140                                 {
4141                                         FuncCall *n = makeNode(FuncCall);
4142                                         n->funcname = "rtrim";
4143                                         n->args = $4;
4144                                         $$ = (Node *)n;
4145                                 }
4146                 | TRIM '(' trim_list ')'
4147                                 {
4148                                         FuncCall *n = makeNode(FuncCall);
4149                                         n->funcname = "btrim";
4150                                         n->args = $3;
4151                                         $$ = (Node *)n;
4152                                 }
4153                 ;
4154
4155 opt_indirection:  '[' a_expr ']' opt_indirection
4156                                 {
4157                                         A_Indices *ai = makeNode(A_Indices);
4158                                         ai->lidx = NULL;
4159                                         ai->uidx = $2;
4160                                         $$ = lcons(ai, $4);
4161                                 }
4162                 | '[' a_expr ':' a_expr ']' opt_indirection
4163                                 {
4164                                         A_Indices *ai = makeNode(A_Indices);
4165                                         ai->lidx = $2;
4166                                         ai->uidx = $4;
4167                                         $$ = lcons(ai, $6);
4168                                 }
4169                 | /* EMPTY */
4170                                 {       $$ = NIL; }
4171                 ;
4172
4173 expr_list:  a_expr_or_null
4174                                 { $$ = lcons($1, NIL); }
4175                 | expr_list ',' a_expr_or_null
4176                                 { $$ = lappend($1, $3); }
4177                 | expr_list USING a_expr
4178                                 { $$ = lappend($1, $3); }
4179                 ;
4180
4181 extract_list:  extract_arg FROM a_expr
4182                                 {
4183                                         A_Const *n = makeNode(A_Const);
4184                                         n->val.type = T_String;
4185                                         n->val.val.str = $1;
4186                                         $$ = lappend(lcons((Node *)n,NIL), $3);
4187                                 }
4188                 | /* EMPTY */
4189                                 {       $$ = NIL; }
4190                 ;
4191
4192 /* Add in TIMEZONE_HOUR and TIMEZONE_MINUTE for SQL92 compliance
4193  *  for next release. Just set up extract_arg for now...
4194  * - thomas 1998-04-08
4195  */
4196 extract_arg:  datetime
4197                                 {       $$ = $1; }
4198                 ;
4199
4200 position_list:  position_expr IN position_expr
4201                                 {       $$ = makeList($3, $1, -1); }
4202                 | /* EMPTY */
4203                                 {       $$ = NIL; }
4204                 ;
4205
4206 position_expr:  attr opt_indirection
4207                                 {
4208                                         $1->indirection = $2;
4209                                         $$ = (Node *)$1;
4210                                 }
4211                 | AexprConst
4212                                 {       $$ = $1;  }
4213                 | '-' position_expr %prec UMINUS
4214                                 {       $$ = makeA_Expr(OP, "-", NULL, $2); }
4215                 | position_expr '+' position_expr
4216                                 {       $$ = makeA_Expr(OP, "+", $1, $3); }
4217                 | position_expr '-' position_expr
4218                                 {       $$ = makeA_Expr(OP, "-", $1, $3); }
4219                 | position_expr '/' position_expr
4220                                 {       $$ = makeA_Expr(OP, "/", $1, $3); }
4221                 | position_expr '*' position_expr
4222                                 {       $$ = makeA_Expr(OP, "*", $1, $3); }
4223                 | '|' position_expr
4224                                 {       $$ = makeA_Expr(OP, "|", NULL, $2); }
4225                 | position_expr TYPECAST Typename
4226                                 {
4227                                         $$ = (Node *)$1;
4228                                         /* AexprConst can be either A_Const or ParamNo */
4229                                         if (nodeTag($1) == T_A_Const) {
4230                                                 ((A_Const *)$1)->typename = $3;
4231                                         } else if (nodeTag($1) == T_Param) {
4232                                                 ((ParamNo *)$1)->typename = $3;
4233                                         /* otherwise, try to transform to a function call */
4234                                         } else {
4235                                                 FuncCall *n = makeNode(FuncCall);
4236                                                 n->funcname = $3->name;
4237                                                 n->args = lcons($1,NIL);
4238                                                 $$ = (Node *)n;
4239                                         }
4240                                 }
4241                 | CAST '(' position_expr AS Typename ')'
4242                                 {
4243                                         $$ = (Node *)$3;
4244                                         /* AexprConst can be either A_Const or ParamNo */
4245                                         if (nodeTag($3) == T_A_Const) {
4246                                                 ((A_Const *)$3)->typename = $5;
4247                                         } else if (nodeTag($3) == T_Param) {
4248                                                 ((ParamNo *)$3)->typename = $5;
4249                                         /* otherwise, try to transform to a function call */
4250                                         } else {
4251                                                 FuncCall *n = makeNode(FuncCall);
4252                                                 n->funcname = $5->name;
4253                                                 n->args = lcons($3,NIL);
4254                                                 $$ = (Node *)n;
4255                                         }
4256                                 }
4257                 | '(' position_expr ')'
4258                                 {       $$ = $2; }
4259                 | position_expr Op position_expr
4260                                 {       $$ = makeA_Expr(OP, $2, $1, $3); }
4261                 | Op position_expr
4262                                 {       $$ = makeA_Expr(OP, $1, NULL, $2); }
4263                 | position_expr Op
4264                                 {       $$ = makeA_Expr(OP, $2, $1, NULL); }
4265                 | ColId
4266                                 {
4267                                         /* could be a column name or a relation_name */
4268                                         Ident *n = makeNode(Ident);
4269                                         n->name = $1;
4270                                         n->indirection = NULL;
4271                                         $$ = (Node *)n;
4272                                 }
4273                 | func_name '(' ')'
4274                                 {
4275                                         FuncCall *n = makeNode(FuncCall);
4276                                         n->funcname = $1;
4277                                         n->args = NIL;
4278                                         $$ = (Node *)n;
4279                                 }
4280                 | func_name '(' expr_list ')'
4281                                 {
4282                                         FuncCall *n = makeNode(FuncCall);
4283                                         n->funcname = $1;
4284                                         n->args = $3;
4285                                         $$ = (Node *)n;
4286                                 }
4287                 | POSITION '(' position_list ')'
4288                                 {
4289                                         FuncCall *n = makeNode(FuncCall);
4290                                         n->funcname = "strpos";
4291                                         n->args = $3;
4292                                         $$ = (Node *)n;
4293                                 }
4294                 | SUBSTRING '(' substr_list ')'
4295                                 {
4296                                         FuncCall *n = makeNode(FuncCall);
4297                                         n->funcname = "substr";
4298                                         n->args = $3;
4299                                         $$ = (Node *)n;
4300                                 }
4301                 /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
4302                 | TRIM '(' BOTH trim_list ')'
4303                                 {
4304                                         FuncCall *n = makeNode(FuncCall);
4305                                         n->funcname = "btrim";
4306                                         n->args = $4;
4307                                         $$ = (Node *)n;
4308                                 }
4309                 | TRIM '(' LEADING trim_list ')'
4310                                 {
4311                                         FuncCall *n = makeNode(FuncCall);
4312                                         n->funcname = "ltrim";
4313                                         n->args = $4;
4314                                         $$ = (Node *)n;
4315                                 }
4316                 | TRIM '(' TRAILING trim_list ')'
4317                                 {
4318                                         FuncCall *n = makeNode(FuncCall);
4319                                         n->funcname = "rtrim";
4320                                         n->args = $4;
4321                                         $$ = (Node *)n;
4322                                 }
4323                 | TRIM '(' trim_list ')'
4324                                 {
4325                                         FuncCall *n = makeNode(FuncCall);
4326                                         n->funcname = "btrim";
4327                                         n->args = $3;
4328                                         $$ = (Node *)n;
4329                                 }
4330                 ;
4331
4332 substr_list:  expr_list substr_from substr_for
4333                                 {
4334                                         $$ = nconc(nconc($1,$2),$3);
4335                                 }
4336                 | /* EMPTY */
4337                                 {       $$ = NIL; }
4338                 ;
4339
4340 substr_from:  FROM expr_list
4341                                 {       $$ = $2; }
4342                 | /* EMPTY */
4343                                 {
4344                                         A_Const *n = makeNode(A_Const);
4345                                         n->val.type = T_Integer;
4346                                         n->val.val.ival = 1;
4347                                         $$ = lcons((Node *)n,NIL);
4348                                 }
4349                 ;
4350
4351 substr_for:  FOR expr_list
4352                                 {       $$ = $2; }
4353                 | /* EMPTY */
4354                                 {       $$ = NIL; }
4355                 ;
4356
4357 trim_list:  a_expr FROM expr_list
4358                                 { $$ = lappend($3, $1); }
4359                 | FROM expr_list
4360                                 { $$ = $2; }
4361                 | expr_list
4362                                 { $$ = $1; }
4363                 ;
4364
4365 in_expr:  SubSelect
4366                                 {
4367                                         SubLink *n = makeNode(SubLink);
4368                                         n->subselect = $1;
4369                                         $$ = (Node *)n;
4370                                 }
4371                 | in_expr_nodes
4372                                 {       $$ = $1; }
4373                 ;
4374
4375 in_expr_nodes:  AexprConst
4376                                 {       $$ = makeA_Expr(OP, "=", lfirst(saved_In_Expr), $1); }
4377                 | in_expr_nodes ',' AexprConst
4378                                 {       $$ = makeA_Expr(OR, NULL, $1,
4379                                                 makeA_Expr(OP, "=", lfirst(saved_In_Expr), $3));
4380                                 }
4381                 ;
4382
4383 not_in_expr:  SubSelect
4384                                 {
4385                                         SubLink *n = makeNode(SubLink);
4386                                         n->subselect = $1;
4387                                         $$ = (Node *)n;
4388                                 }
4389                 | not_in_expr_nodes
4390                                 {       $$ = $1; }
4391                 ;
4392
4393 not_in_expr_nodes:  AexprConst
4394                                 {       $$ = makeA_Expr(OP, "<>", lfirst(saved_In_Expr), $1); }
4395                 | not_in_expr_nodes ',' AexprConst
4396                                 {       $$ = makeA_Expr(AND, NULL, $1,
4397                                                 makeA_Expr(OP, "<>", lfirst(saved_In_Expr), $3));
4398                                 }
4399                 ;
4400
4401 attr:  relation_name '.' attrs
4402                                 {
4403                                         $$ = makeNode(Attr);
4404                                         $$->relname = $1;
4405                                         $$->paramNo = NULL;
4406                                         $$->attrs = $3;
4407                                         $$->indirection = NULL;
4408                                 }
4409                 | ParamNo '.' attrs
4410                                 {
4411                                         $$ = makeNode(Attr);
4412                                         $$->relname = NULL;
4413                                         $$->paramNo = $1;
4414                                         $$->attrs = $3;
4415                                         $$->indirection = NULL;
4416                                 }
4417                 ;
4418
4419 attrs:    attr_name
4420                                 { $$ = lcons(makeString($1), NIL); }
4421                 | attrs '.' attr_name
4422                                 { $$ = lappend($1, makeString($3)); }
4423                 | attrs '.' '*'
4424                                 { $$ = lappend($1, makeString("*")); }
4425                 ;
4426
4427
4428 /*****************************************************************************
4429  *
4430  *      target lists
4431  *
4432  *****************************************************************************/
4433
4434 res_target_list:  res_target_list ',' res_target_el
4435                                 {       $$ = lappend($1,$3);  }
4436                 | res_target_el
4437                                 {       $$ = lcons($1, NIL);  }
4438                 | '*'
4439                                 {
4440                                         ResTarget *rt = makeNode(ResTarget);
4441                                         Attr *att = makeNode(Attr);
4442                                         att->relname = "*";
4443                                         att->paramNo = NULL;
4444                                         att->attrs = NULL;
4445                                         att->indirection = NIL;
4446                                         rt->name = NULL;
4447                                         rt->indirection = NULL;
4448                                         rt->val = (Node *)att;
4449                                         $$ = lcons(rt, NIL);
4450                                 }
4451                 ;
4452
4453 res_target_el:  ColId opt_indirection '=' a_expr_or_null
4454                                 {
4455                                         $$ = makeNode(ResTarget);
4456                                         $$->name = $1;
4457                                         $$->indirection = $2;
4458                                         $$->val = (Node *)$4;
4459                                 }
4460                 | attr opt_indirection
4461                                 {
4462                                         $$ = makeNode(ResTarget);
4463                                         $$->name = NULL;
4464                                         $$->indirection = $2;
4465                                         $$->val = (Node *)$1;
4466                                 }
4467                 | relation_name '.' '*'
4468                                 {
4469                                         Attr *att = makeNode(Attr);
4470                                         att->relname = $1;
4471                                         att->paramNo = NULL;
4472                                         att->attrs = lcons(makeString("*"), NIL);
4473                                         att->indirection = NIL;
4474                                         $$ = makeNode(ResTarget);
4475                                         $$->name = NULL;
4476                                         $$->indirection = NULL;
4477                                         $$->val = (Node *)att;
4478                                 }
4479                 ;
4480
4481 /*
4482 ** target list for select.
4483 ** should get rid of the other but is still needed by the defunct select into
4484 ** and update (uses a subset)
4485 */
4486 res_target_list2:  res_target_list2 ',' res_target_el2
4487                                 {       $$ = lappend($1, $3);  }
4488                 | res_target_el2
4489                                 {       $$ = lcons($1, NIL);  }
4490                 ;
4491
4492 /* AS is not optional because shift/red conflict with unary ops */
4493 res_target_el2:  a_expr_or_null AS ColLabel
4494                                 {
4495                                         $$ = makeNode(ResTarget);
4496                                         $$->name = $3;
4497                                         $$->indirection = NULL;
4498                                         $$->val = (Node *)$1;
4499                                 }
4500                 | a_expr_or_null
4501                                 {
4502                                         $$ = makeNode(ResTarget);
4503                                         $$->name = NULL;
4504                                         $$->indirection = NULL;
4505                                         $$->val = (Node *)$1;
4506                                 }
4507                 | relation_name '.' '*'
4508                                 {
4509                                         Attr *att = makeNode(Attr);
4510                                         att->relname = $1;
4511                                         att->paramNo = NULL;
4512                                         att->attrs = lcons(makeString("*"), NIL);
4513                                         att->indirection = NIL;
4514                                         $$ = makeNode(ResTarget);
4515                                         $$->name = NULL;
4516                                         $$->indirection = NULL;
4517                                         $$->val = (Node *)att;
4518                                 }
4519                 | '*'
4520                                 {
4521                                         Attr *att = makeNode(Attr);
4522                                         att->relname = "*";
4523                                         att->paramNo = NULL;
4524                                         att->attrs = NULL;
4525                                         att->indirection = NIL;
4526                                         $$ = makeNode(ResTarget);
4527                                         $$->name = NULL;
4528                                         $$->indirection = NULL;
4529                                         $$->val = (Node *)att;
4530                                 }
4531                 ;
4532
4533 opt_id:  ColId                                                                  { $$ = $1; }
4534                 | /* EMPTY */                                                   { $$ = NULL; }
4535                 ;
4536
4537 relation_name:  SpecialRuleRelation
4538                                 {
4539                                         $$ = $1;
4540                                         StrNCpy(saved_relname, $1, NAMEDATALEN);
4541                                 }
4542                 | ColId
4543                                 {
4544                                         /* disallow refs to variable system tables */
4545                                         if (strcmp(LogRelationName, $1) == 0
4546                                            || strcmp(VariableRelationName, $1) == 0)
4547                                                 elog(ERROR,"%s cannot be accessed by users",$1);
4548                                         else
4549                                                 $$ = $1;
4550                                         StrNCpy(saved_relname, $1, NAMEDATALEN);
4551                                 }
4552                 ;
4553
4554 database_name:                  ColId                   { $$ = $1; };
4555 access_method:                  IDENT                   { $$ = $1; };
4556 attr_name:                              ColId                   { $$ = $1; };
4557 class:                                  IDENT                   { $$ = $1; };
4558 index_name:                             ColId                   { $$ = $1; };
4559
4560 /* Functions
4561  * Include date/time keywords as SQL92 extension.
4562  * Include TYPE as a SQL92 unreserved keyword. - thomas 1997-10-05
4563  */
4564 name:                                   ColId                   { $$ = $1; };
4565 func_name:                              ColId                   { $$ = xlateSqlFunc($1); };
4566
4567 file_name:                              Sconst                  { $$ = $1; };
4568 recipe_name:                    IDENT                   { $$ = $1; };
4569
4570 /* Constants
4571  * Include TRUE/FALSE for SQL3 support. - thomas 1997-10-24
4572  */
4573 AexprConst:  Iconst
4574                                 {
4575                                         A_Const *n = makeNode(A_Const);
4576                                         n->val.type = T_Integer;
4577                                         n->val.val.ival = $1;
4578                                         $$ = (Node *)n;
4579                                 }
4580                 | FCONST
4581                                 {
4582                                         A_Const *n = makeNode(A_Const);
4583                                         n->val.type = T_Float;
4584                                         n->val.val.dval = $1;
4585                                         $$ = (Node *)n;
4586                                 }
4587                 | Sconst
4588                                 {
4589                                         A_Const *n = makeNode(A_Const);
4590                                         n->val.type = T_String;
4591                                         n->val.val.str = $1;
4592                                         $$ = (Node *)n;
4593                                 }
4594                 | Typename Sconst
4595                                 {
4596                                         A_Const *n = makeNode(A_Const);
4597                                         n->typename = $1;
4598                                         n->val.type = T_String;
4599                                         n->val.val.str = $2;
4600                                         $$ = (Node *)n;
4601                                 }
4602                 | ParamNo
4603                                 {       $$ = (Node *)$1;  }
4604                 | TRUE_P
4605                                 {
4606                                         A_Const *n = makeNode(A_Const);
4607                                         n->val.type = T_String;
4608                                         n->val.val.str = "t";
4609                                         n->typename = makeNode(TypeName);
4610                                         n->typename->name = xlateSqlType("bool");
4611                                         n->typename->typmod = -1;
4612                                         $$ = (Node *)n;
4613                                 }
4614                 | FALSE_P
4615                                 {
4616                                         A_Const *n = makeNode(A_Const);
4617                                         n->val.type = T_String;
4618                                         n->val.val.str = "f";
4619                                         n->typename = makeNode(TypeName);
4620                                         n->typename->name = xlateSqlType("bool");
4621                                         n->typename->typmod = -1;
4622                                         $$ = (Node *)n;
4623                                 }
4624                 ;
4625
4626 ParamNo:  PARAM
4627                                 {
4628                                         $$ = makeNode(ParamNo);
4629                                         $$->number = $1;
4630                                 }
4631                 ;
4632
4633 NumConst:  Iconst                                               { $$ = makeInteger($1); }
4634                 | FCONST                                                { $$ = makeFloat($1); }
4635                 ;
4636
4637 Iconst:  ICONST                                                 { $$ = $1; };
4638 Sconst:  SCONST                                                 { $$ = $1; };
4639 UserId:  IDENT                                                  { $$ = $1; };
4640
4641 /* Column and type identifier
4642  * Does not include explicit datetime types
4643  *  since these must be decoupled in Typename syntax.
4644  * Use ColId for most identifiers. - thomas 1997-10-21
4645  */
4646 TypeId:  ColId
4647                         {       $$ = xlateSqlType($1); }
4648                 | numeric
4649                         {       $$ = xlateSqlType($1); }
4650                 | character
4651                         {       $$ = xlateSqlType($1); }
4652                 ;
4653 /* Column identifier
4654  * Include date/time keywords as SQL92 extension.
4655  * Include TYPE as a SQL92 unreserved keyword. - thomas 1997-10-05
4656  * Add other keywords. Note that as the syntax expands,
4657  *  some of these keywords will have to be removed from this
4658  *  list due to shift/reduce conflicts in yacc. If so, move
4659  *  down to the ColLabel entity. - thomas 1997-11-06
4660  */
4661 ColId:  IDENT                                                   { $$ = $1; }
4662                 | datetime                                              { $$ = $1; }
4663                 | ACTION                                                { $$ = "action"; }
4664                 | CACHE                                                 { $$ = "cache"; }
4665                 | CYCLE                                                 { $$ = "cycle"; }
4666                 | DATABASE                                              { $$ = "database"; }
4667                 | DELIMITERS                                    { $$ = "delimiters"; }
4668                 | DOUBLE                                                { $$ = "double"; }
4669                 | EACH                                                  { $$ = "each"; }
4670                 | FUNCTION                                              { $$ = "function"; }
4671                 | INCREMENT                                             { $$ = "increment"; }
4672                 | INDEX                                                 { $$ = "index"; }
4673                 | KEY                                                   { $$ = "key"; }
4674                 | LANGUAGE                                              { $$ = "language"; }
4675                 | LOCATION                                              { $$ = "location"; }
4676                 | MATCH                                                 { $$ = "match"; }
4677                 | MAXVALUE                                              { $$ = "maxvalue"; }
4678                 | MINVALUE                                              { $$ = "minvalue"; }
4679                 | OPERATOR                                              { $$ = "operator"; }
4680                 | OPTION                                                { $$ = "option"; }
4681                 | PASSWORD                                              { $$ = "password"; }
4682                 | PRIVILEGES                                    { $$ = "privileges"; }
4683                 | RECIPE                                                { $$ = "recipe"; }
4684                 | ROW                                                   { $$ = "row"; }
4685                 | START                                                 { $$ = "start"; }
4686                 | STATEMENT                                             { $$ = "statement"; }
4687                 | TIME                                                  { $$ = "time"; }
4688                 | TRIGGER                                               { $$ = "trigger"; }
4689                 | TYPE_P                                                { $$ = "type"; }
4690                 | USER                                                  { $$ = "user"; }
4691                 | VALID                                                 { $$ = "valid"; }
4692                 | VERSION                                               { $$ = "version"; }
4693                 | ZONE                                                  { $$ = "zone"; }
4694                 ;
4695
4696 /* Column label
4697  * Allowed labels in "AS" clauses.
4698  * Include TRUE/FALSE SQL3 reserved words for Postgres backward
4699  *  compatibility. Cannot allow this for column names since the
4700  *  syntax would not distinguish between the constant value and
4701  *  a column name. - thomas 1997-10-24
4702  * Add other keywords to this list. Note that they appear here
4703  *  rather than in ColId if there was a shift/reduce conflict
4704  *  when used as a full identifier. - thomas 1997-11-06
4705  */
4706 ColLabel:  ColId                                                { $$ = $1; }
4707                 | ARCHIVE                                               { $$ = "archive"; }
4708                 | CLUSTER                                               { $$ = "cluster"; }
4709                 | CONSTRAINT                                    { $$ = "constraint"; }
4710                 | CROSS                                                 { $$ = "cross"; }
4711                 | FOREIGN                                               { $$ = "foreign"; }
4712                 | GROUP                                                 { $$ = "group"; }
4713                 | LOAD                                                  { $$ = "load"; }
4714                 | ORDER                                                 { $$ = "order"; }
4715                 | POSITION                                              { $$ = "position"; }
4716                 | PRECISION                                             { $$ = "precision"; }
4717                 | TABLE                                                 { $$ = "table"; }
4718                 | TRANSACTION                                   { $$ = "transaction"; }
4719                 | TRUE_P                                                { $$ = "true"; }
4720                 | FALSE_P                                               { $$ = "false"; }
4721                 ;
4722
4723 SpecialRuleRelation:  CURRENT
4724                                 {
4725                                         if (QueryIsRule)
4726                                                 $$ = "*CURRENT*";
4727                                         else
4728                                                 elog(ERROR,"CURRENT used in non-rule query");
4729                                 }
4730                 | NEW
4731                                 {
4732                                         if (QueryIsRule)
4733                                                 $$ = "*NEW*";
4734                                         else
4735                                                 elog(ERROR,"NEW used in non-rule query");
4736                                 }
4737                 ;
4738
4739 %%
4740
4741 static Node *
4742 makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr)
4743 {
4744         A_Expr *a = makeNode(A_Expr);
4745         a->oper = oper;
4746         a->opname = opname;
4747         a->lexpr = lexpr;
4748         a->rexpr = rexpr;
4749         return (Node *)a;
4750 }
4751
4752 /* makeRowExpr()
4753  * Generate separate operator nodes for a single row descriptor expression.
4754  * Perhaps this should go deeper in the parser someday... - thomas 1997-12-22
4755  */
4756 static Node *
4757 makeRowExpr(char *opr, List *largs, List *rargs)
4758 {
4759         Node *expr = NULL;
4760         Node *larg, *rarg;
4761
4762         if (length(largs) != length(rargs))
4763                 elog(ERROR,"Unequal number of entries in row expression");
4764
4765         if (lnext(largs) != NIL)
4766                 expr = makeRowExpr(opr,lnext(largs),lnext(rargs));
4767
4768         larg = lfirst(largs);
4769         rarg = lfirst(rargs);
4770
4771         if ((strcmp(opr, "=") == 0)
4772          || (strcmp(opr, "<") == 0)
4773          || (strcmp(opr, "<=") == 0)
4774          || (strcmp(opr, ">") == 0)
4775          || (strcmp(opr, ">=") == 0))
4776         {
4777                 if (expr == NULL)
4778                         expr = makeA_Expr(OP, opr, larg, rarg);
4779                 else
4780                         expr = makeA_Expr(AND, NULL, expr, makeA_Expr(OP, opr, larg, rarg));
4781         }
4782         else if (strcmp(opr, "<>") == 0)
4783         {
4784                 if (expr == NULL)
4785                         expr = makeA_Expr(OP, opr, larg, rarg);
4786                 else
4787                         expr = makeA_Expr(OR, NULL, expr, makeA_Expr(OP, opr, larg, rarg));
4788         }
4789         else
4790         {
4791                 elog(ERROR,"Operator '%s' not implemented for row expressions",opr);
4792         }
4793
4794 #if FALSE
4795         while ((largs != NIL) && (rargs != NIL))
4796         {
4797                 larg = lfirst(largs);
4798                 rarg = lfirst(rargs);
4799
4800                 if (expr == NULL)
4801                         expr = makeA_Expr(OP, opr, larg, rarg);
4802                 else
4803                         expr = makeA_Expr(AND, NULL, expr, makeA_Expr(OP, opr, larg, rarg));
4804
4805                 largs = lnext(largs);
4806                 rargs = lnext(rargs);
4807         }
4808         pprint(expr);
4809 #endif
4810
4811         return expr;
4812 }
4813
4814 void
4815 mapTargetColumns(List *src, List *dst)
4816 {
4817         ColumnDef *s;
4818         ResTarget *d;
4819
4820         if (length(src) != length(dst))
4821                 elog(ERROR,"CREATE TABLE/AS SELECT has mismatched column count");
4822
4823         while ((src != NIL) && (dst != NIL))
4824         {
4825                 s = (ColumnDef *)lfirst(src);
4826                 d = (ResTarget *)lfirst(dst);
4827
4828                 d->name = s->colname;
4829
4830                 src = lnext(src);
4831                 dst = lnext(dst);
4832         }
4833
4834         return;
4835 } /* mapTargetColumns() */
4836
4837 static Node *makeIndexable(char *opname, Node *lexpr, Node *rexpr)
4838 {
4839         Node *result = NULL;
4840
4841         /* we do this so indexes can be used */
4842         if (strcmp(opname,"~") == 0 ||
4843                 strcmp(opname,"~*") == 0)
4844         {
4845                 if (nodeTag(rexpr) == T_A_Const &&
4846                    ((A_Const *)rexpr)->val.type == T_String &&
4847                    ((A_Const *)rexpr)->val.val.str[0] == '^')
4848                 {
4849                         A_Const *n = (A_Const *)rexpr;
4850                         char *match_least = palloc(strlen(n->val.val.str)+2);
4851                         char *match_most = palloc(strlen(n->val.val.str)+2);
4852                         int pos, match_pos=0;
4853
4854                         /* skip leading ^ */
4855                         for (pos = 1; n->val.val.str[pos]; pos++)
4856                         {
4857                                 if (n->val.val.str[pos] == '.' ||
4858                                         n->val.val.str[pos] == '?' ||
4859                                         n->val.val.str[pos] == '*' ||
4860                                         n->val.val.str[pos] == '[' ||
4861                                         n->val.val.str[pos] == '$' ||
4862                                         (strcmp(opname,"~*") == 0 && isalpha(n->val.val.str[pos])))
4863                                 break;
4864                         if (n->val.val.str[pos] == '\\')
4865                                         pos++;
4866                                 match_least[match_pos] = n->val.val.str[pos];
4867                                 match_most[match_pos++] = n->val.val.str[pos];
4868                         }
4869
4870                         if (match_pos != 0)
4871                         {
4872                                 A_Const *least = makeNode(A_Const);
4873                                 A_Const *most = makeNode(A_Const);
4874                                 
4875                                 /* make strings to be used in index use */
4876                                 match_least[match_pos] = '\0';
4877                                 match_most[match_pos] = '\377';
4878                                 match_most[match_pos+1] = '\0';
4879                                 least->val.type = T_String;
4880                                 least->val.val.str = match_least;
4881                                 most->val.type = T_String;
4882                                 most->val.val.str = match_most;
4883                                 result = makeA_Expr(AND, NULL,
4884                                                 makeA_Expr(OP, "~", lexpr, rexpr),
4885                                                 makeA_Expr(AND, NULL,
4886                                                         makeA_Expr(OP, ">=", lexpr, (Node *)least),
4887                                                         makeA_Expr(OP, "<=", lexpr, (Node *)most)));
4888                         }
4889                 }
4890         }
4891         else if (strcmp(opname,"~~") == 0)
4892         {
4893                 if (nodeTag(rexpr) == T_A_Const &&
4894                    ((A_Const *)rexpr)->val.type == T_String)
4895                 {
4896                         A_Const *n = (A_Const *)rexpr;
4897                         char *match_least = palloc(strlen(n->val.val.str)+2);
4898                         char *match_most = palloc(strlen(n->val.val.str)+2);
4899                         int pos, match_pos=0;
4900         
4901                         for (pos = 0; n->val.val.str[pos]; pos++)
4902                         {
4903                                 if (n->val.val.str[pos] == '%' &&
4904                                          n->val.val.str[pos+1] != '%')
4905                                         break;
4906                                 if(n->val.val.str[pos] == '_')
4907                                         break;
4908                                 if (n->val.val.str[pos] == '\\' ||
4909                                         n->val.val.str[pos] == '%')
4910                                         pos++;
4911                                 if (n->val.val.str[pos] == '\0')
4912                                         break;
4913                                 match_least[match_pos] = n->val.val.str[pos];
4914                                 match_most[match_pos++] = n->val.val.str[pos];
4915                         }
4916         
4917                         if (match_pos != 0)
4918                         {
4919                                 A_Const *least = makeNode(A_Const);
4920                                 A_Const *most = makeNode(A_Const);
4921                                 
4922                                 /* make strings to be used in index use */
4923                                 match_least[match_pos] = '\0';
4924                                 match_most[match_pos] = '\377';
4925                                 match_most[match_pos+1] = '\0';
4926                                 least->val.type = T_String;
4927                                 least->val.val.str = match_least;
4928                                 most->val.type = T_String;
4929                                 most->val.val.str = match_most;
4930                                 result = makeA_Expr(AND, NULL,
4931                                                 makeA_Expr(OP, "~~", lexpr, rexpr),
4932                                                 makeA_Expr(AND, NULL,
4933                                                         makeA_Expr(OP, ">=", lexpr, (Node *)least),
4934                                                         makeA_Expr(OP, "<=", lexpr, (Node *)most)));
4935                         }
4936                 }
4937         }
4938         
4939         if (result == NULL)
4940                 result = makeA_Expr(OP, opname, lexpr, rexpr);
4941         return result;
4942 } /* makeIndexable() */
4943
4944
4945 /* xlateSqlFunc()
4946  * Convert alternate type names to internal Postgres types.
4947  * Do not convert "float", since that is handled elsewhere
4948  *  for FLOAT(p) syntax.
4949  */
4950 static char *
4951 xlateSqlFunc(char *name)
4952 {
4953         if (!strcasecmp(name,"character_length")
4954          || !strcasecmp(name,"char_length"))
4955                 return "length";
4956         else
4957                 return name;
4958 } /* xlateSqlFunc() */
4959
4960 /* xlateSqlType()
4961  * Convert alternate type names to internal Postgres types.
4962  */
4963 static char *
4964 xlateSqlType(char *name)
4965 {
4966         if (!strcasecmp(name,"int")
4967          || !strcasecmp(name,"integer"))
4968                 return "int4";
4969         else if (!strcasecmp(name, "smallint"))
4970                 return "int2";
4971         else if (!strcasecmp(name, "real")
4972          || !strcasecmp(name, "float"))
4973                 return "float8";
4974         else if (!strcasecmp(name, "interval"))
4975                 return "timespan";
4976         else if (!strcasecmp(name, "boolean"))
4977                 return "bool";
4978         else
4979                 return name;
4980 } /* xlateSqlType() */
4981
4982
4983 void parser_init(Oid *typev, int nargs)
4984 {
4985         QueryIsRule = FALSE;
4986         saved_relname[0]= '\0';
4987         saved_In_Expr = NULL;
4988
4989         param_type_init(typev, nargs);
4990 }
4991
4992
4993 /* FlattenStringList()
4994  * Traverse list of string nodes and convert to a single string.
4995  * Used for reconstructing string form of complex expressions.
4996  *
4997  * Allocate at least one byte for terminator.
4998  */
4999 static char *
5000 FlattenStringList(List *list)
5001 {
5002         List *l;
5003         Value *v;
5004         char *s;
5005         char *sp;
5006         int nlist, len = 0;
5007
5008         nlist = length(list);
5009         l = list;
5010         while(l != NIL) {
5011                 v = (Value *)lfirst(l);
5012                 sp = v->val.str;
5013                 l = lnext(l);
5014                 len += strlen(sp);
5015         };
5016         len += nlist;
5017
5018         s = (char*) palloc(len+1);
5019         *s = '\0';
5020
5021         l = list;
5022         while(l != NIL) {
5023                 v = (Value *)lfirst(l);
5024                 sp = v->val.str;
5025                 l = lnext(l);
5026                 strcat(s,sp);
5027                 if (l != NIL) strcat(s," ");
5028         };
5029         *(s+len) = '\0';
5030
5031 #ifdef PARSEDEBUG
5032 printf( "flattened string is \"%s\"\n", s);
5033 #endif
5034
5035         return(s);
5036 } /* FlattenStringList() */
5037
5038
5039 /* makeConstantList()
5040  * Convert constant value node into string node.
5041  */
5042 static List *
5043 makeConstantList( A_Const *n)
5044 {
5045         char *defval = NULL;
5046         if (nodeTag(n) != T_A_Const) {
5047                 elog(ERROR,"Cannot handle non-constant parameter");
5048
5049         } else if (n->val.type == T_Float) {
5050                 defval = (char*) palloc(20+1);
5051                 sprintf( defval, "%g", n->val.val.dval);
5052
5053         } else if (n->val.type == T_Integer) {
5054                 defval = (char*) palloc(20+1);
5055                 sprintf( defval, "%ld", n->val.val.ival);
5056
5057         } else if (n->val.type == T_String) {
5058                 defval = (char*) palloc(strlen( ((A_Const *) n)->val.val.str) + 3);
5059                 strcpy( defval, "'");
5060                 strcat( defval, ((A_Const *) n)->val.val.str);
5061                 strcat( defval, "'");
5062
5063         } else {
5064                 elog(ERROR,"Internal error in makeConstantList(): cannot encode node");
5065         };
5066
5067 #ifdef PARSEDEBUG
5068 printf( "AexprConst argument is \"%s\"\n", defval);
5069 #endif
5070
5071         return( lcons( makeString(defval), NIL));
5072 } /* makeConstantList() */
5073
5074
5075 /* fmtId()
5076  * Check input string for non-lowercase/non-numeric characters.
5077  * Returns either input string or input surrounded by double quotes.
5078  */
5079 static char *
5080 fmtId(char *rawid)
5081 {
5082         static char *cp;
5083
5084         for (cp = rawid; *cp != '\0'; cp++)
5085                 if (! (islower(*cp) || isdigit(*cp) || (*cp == '_'))) break;
5086
5087         if (*cp != '\0') {
5088                 cp = palloc(strlen(rawid)+1);
5089                 strcpy(cp,"\"");
5090                 strcat(cp,rawid);
5091                 strcat(cp,"\"");
5092         } else {
5093                 cp = rawid;
5094         };
5095
5096 #ifdef PARSEDEBUG
5097 printf("fmtId- %sconvert %s to %s\n", ((cp == rawid)? "do not ": ""), rawid, cp);
5098 #endif
5099
5100         return(cp);
5101 }
5102
5103 /*
5104  * param_type_init()
5105  *
5106  * keep enough information around fill out the type of param nodes
5107  * used in postquel functions
5108  */
5109 static void
5110 param_type_init(Oid *typev, int nargs)
5111 {
5112         pfunc_num_args = nargs;
5113         param_type_info = typev;
5114 }
5115
5116 Oid param_type(int t)
5117 {
5118         if ((t > pfunc_num_args) || (t == 0))
5119                 return InvalidOid;
5120         return param_type_info[t - 1];
5121 }