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