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