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