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