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