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