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