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