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