4 /*-------------------------------------------------------------------------
7 * POSTGRES SQL YACC rules/actions
9 * Copyright (c) 1994, Regents of the University of California
13 * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.75 1997/12/02 16:09:15 momjian Exp $
16 * AUTHOR DATE MAJOR EVENT
17 * Andrew Yu Sept, 1994 POSTQUEL to SQL conversion
18 * Andrew Yu Oct, 1994 lispy code conversion
21 * CAPITALS are used to represent terminal symbols.
22 * non-capitals are used to represent non-terminals.
23 * SQL92-specific syntax is separated from plain SQL/Postgres syntax
24 * to help isolate the non-extensible portions of the parser.
26 * if you use list, make sure the datum is a node so that the printing
30 * sometimes we assign constants to makeStrings. Make sure we don't free
33 *-------------------------------------------------------------------------
39 #include "nodes/parsenodes.h"
40 #include "nodes/print.h"
41 #include "parser/gramparse.h"
42 #include "utils/acl.h"
43 #include "catalog/catname.h"
44 #include "utils/elog.h"
45 #include "access/xact.h"
47 static char saved_relname[NAMEDATALEN]; /* need this for complex attributes */
48 static bool QueryIsRule = FALSE;
49 static Node *saved_In_Expr;
50 static Oid *param_type_info;
51 static int pfunc_num_args;
52 extern List *parsetree;
56 * If you need access to certain yacc-generated variables and find that
57 * they're static by default, uncomment the next line. (this is not a
60 /*#define __YYSCLASS*/
62 static char *xlateSqlType(char *);
63 static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
64 static List *makeConstantList( A_Const *node);
65 static char *FlattenStringList(List *list);
66 static char *fmtId(char *rawid);
67 static Node *makeIndexable(char *opname, Node *lexpr, Node *rexpr);
68 static void param_type_init(Oid *typev, int nargs);
70 Oid param_type(int t); /* used in parse_expr.c */
72 /* old versions of flex define this as a macro */
93 ConstraintDef *constrdef;
97 SortGroupBy *sortgroupby;
112 AddAttrStmt, ClosePortalStmt,
113 CopyStmt, CreateStmt, CreateSeqStmt, DefineStmt, DestroyStmt,
114 ExtendStmt, FetchStmt, GrantStmt, CreateTrigStmt, DropTrigStmt,
115 CreatePLangStmt, DropPLangStmt,
116 IndexStmt, ListenStmt, OptimizableStmt,
117 ProcedureStmt, RecipeStmt, RemoveAggrStmt, RemoveOperStmt,
118 RemoveFuncStmt, RemoveStmt,
119 RenameStmt, RevokeStmt, RuleStmt, TransactionStmt, ViewStmt, LoadStmt,
120 CreatedbStmt, DestroydbStmt, VacuumStmt, RetrieveStmt, CursorStmt,
121 ReplaceStmt, AppendStmt, NotifyStmt, DeleteStmt, ClusterStmt,
122 ExplainStmt, VariableSetStmt, VariableShowStmt, VariableResetStmt
124 %type <str> opt_database, location
126 %type <node> SubSelect
127 %type <str> join_expr, join_outer, join_spec
128 %type <boolean> TriggerActionTime, TriggerForSpec, PLangTrusted
130 %type <str> TriggerEvents, TriggerFuncArg
132 %type <str> relation_name, copy_file_name, copy_delimiter, def_name,
133 database_name, access_method_clause, access_method, attr_name,
134 class, index_name, name, file_name, recipe_name, aggr_argtype
136 %type <str> opt_id, opt_portal_name,
137 all_Op, MathOp, opt_name, opt_unique,
138 result, OptUseOp, opt_class, SpecialRuleRelation
140 %type <str> privileges, operation_commalist, grantee
141 %type <chr> operation, TriggerOneEvent
143 %type <list> stmtblock, stmtmulti,
144 relation_name_list, OptTableElementList, tableElementList,
145 OptInherit, OptConstraint, ConstraintList, definition,
146 opt_with, def_args, def_name_list, func_argtypes,
147 oper_argtypes, OptStmtList, OptStmtBlock, OptStmtMulti,
148 opt_column_list, columnList, opt_va_list, va_list,
149 sort_clause, sortby_list, index_params, index_list, name_list,
150 from_clause, from_list, opt_array_bounds, nest_array_bounds,
151 expr_list, attrs, res_target_list, res_target_list2,
152 def_list, opt_indirection, group_clause, groupby_list, TriggerFuncArgs
154 %type <list> union_clause, select_list
155 %type <list> join_list
158 %type <boolean> opt_union
160 %type <node> position_expr
161 %type <list> extract_list, position_list
162 %type <list> substr_list, substr_from, substr_for, trim_list
163 %type <list> opt_interval
165 %type <boolean> opt_inh_star, opt_binary, opt_instead, opt_with_copy,
166 index_opt_unique, opt_verbose, opt_analyze
168 %type <ival> copy_dirn, def_type, opt_direction, remove_type,
171 %type <ival> fetch_how_many
173 %type <list> OptSeqList
174 %type <defelt> OptSeqElem
176 %type <dstmt> def_rest
177 %type <astmt> insert_rest
179 %type <coldef> columnDef, alter_clause
180 %type <defelt> def_elem
181 %type <node> def_arg, columnElem, where_clause,
182 a_expr, a_expr_or_null, AexprConst,
183 in_expr, in_expr_nodes, not_in_expr, not_in_expr_nodes,
185 %type <value> NumConst
186 %type <attr> event_object, attr
187 %type <sortgroupby> groupby
188 %type <sortgroupby> sortby
189 %type <ielem> index_elem, func_index
190 %type <range> from_val
191 %type <relexp> relation_expr
192 %type <target> res_target_el, res_target_el2
193 %type <paramno> ParamNo
195 %type <typnam> Typename, opt_type, Array, Generic, Character, Datetime, Numeric
196 %type <str> generic, character, datetime
197 %type <str> opt_charset, opt_collate
198 %type <str> opt_float, opt_numeric, opt_decimal
199 %type <boolean> opt_varying, opt_timezone
203 %type <str> Id, var_value, zone_value
204 %type <str> ColId, ColLabel
206 %type <constrdef> ConstraintElem, ConstraintDef
208 %type <list> constraint_elem
209 %type <list> default_expr
210 %type <str> opt_default
211 %type <boolean> opt_constraint
212 %type <list> key_actions, key_action
213 %type <str> key_match, key_reference
216 * If you make any token changes, remember to:
217 * - use "yacc -d" and update parse.h
218 * - update the keyword table in parser/keywords.c
221 /* Reserved word tokens
222 * SQL92 syntax has many type-specific constructs.
223 * So, go ahead and make these types reserved words,
224 * and call-out the syntax explicitly.
225 * This gets annoying when trying to also retain Postgres' nice
226 * type-extensible features, but we don't really have a choice.
227 * - thomas 1997-10-11
230 /* Keywords (in SQL92 reserved words) */
231 %token ACTION, ADD, ALL, ALTER, AND, ARCHIVE, AS, ASC,
232 BEGIN_TRANS, BETWEEN, BOTH, BY,
233 CASCADE, CAST, CHAR, CHARACTER, CHECK, CLOSE, COLLATE, COLUMN, COMMIT,
234 CONSTRAINT, CREATE, CROSS, CURRENT, CURRENT_DATE, CURRENT_TIME,
235 CURRENT_TIMESTAMP, CURRENT_USER, CURSOR,
236 DAY_P, DECIMAL, DECLARE, DEFAULT, DELETE, DESC, DISTINCT, DOUBLE, DROP,
237 END_TRANS, EXECUTE, EXISTS, EXTRACT,
238 FETCH, FLOAT, FOR, FOREIGN, FROM, FULL,
239 GRANT, GROUP, HAVING, HOUR_P,
240 IN, INNER_P, INSERT, INTERVAL, INTO, IS,
241 JOIN, KEY, LANGUAGE, LEADING, LEFT, LIKE, LOCAL,
242 MATCH, MINUTE_P, MONTH_P,
243 NATIONAL, NATURAL, NCHAR, NO, NOT, NOTIFY, NOTNULL, NULL_P, NUMERIC,
244 ON, OPTION, OR, ORDER, OUTER_P,
245 PARTIAL, POSITION, PRECISION, PRIMARY, PRIVILEGES, PROCEDURE, PUBLIC,
246 REFERENCES, REVOKE, RIGHT, ROLLBACK,
247 SECOND_P, SELECT, SET, SUBSTRING,
248 TABLE, TIME, TIMESTAMP, TO, TRAILING, TRANSACTION, TRIM,
249 UNION, UNIQUE, UPDATE, USING,
250 VALUES, VARCHAR, VARYING, VERBOSE, VERSION, VIEW,
251 WHERE, WITH, WORK, YEAR_P, ZONE
253 /* Keywords (in SQL3 reserved words) */
254 %token FALSE_P, TRIGGER, TRUE_P
256 /* Keywords (in SQL92 non-reserved words) */
259 /* Keywords for Postgres support (not in SQL92 reserved words) */
260 %token ABORT_TRANS, ACL, AFTER, AGGREGATE, ANALYZE,
261 APPEND, BACKWARD, BEFORE, BINARY, CHANGE, CLUSTER, COPY,
262 DATABASE, DELIMITERS, DO, EXPLAIN, EXTEND,
263 FORWARD, FUNCTION, HANDLER,
264 INDEX, INHERITS, INSTEAD, ISNULL,
265 LANCOMPILER, LISTEN, LOAD, LOCATION, MERGE, MOVE,
266 NEW, NONE, NOTHING, OIDS, OPERATOR, PROCEDURAL,
267 RECIPE, RENAME, REPLACE, RESET, RETRIEVE, RETURNS, RULE,
268 SEQUENCE, SETOF, SHOW, STDIN, STDOUT, TRUSTED,
269 VACUUM, VERBOSE, VERSION
271 /* Special keywords, not in the query language - see the "lex" file */
272 %token <str> IDENT, SCONST, Op
273 %token <ival> ICONST, PARAM
276 /* these are not real. they are here so that they get generated as #define's*/
293 %left '|' /* this is the relation union op, not logical or */
294 /* Unary Operators */
296 %left ';' /* end of statement or natural log */
309 { parsetree = lcons($1,NIL); }
312 stmtmulti: stmtmulti stmt ';'
313 { $$ = lappend($1, $2); }
315 { $$ = lappend($1, $2); }
317 { $$ = lcons($1,NIL); }
360 /*****************************************************************************
362 * Set PG internal variable
363 * SET name TO 'var_value'
364 * Include SQL92 syntax (thomas 1997-10-22):
365 * SET TIME ZONE 'var_value'
367 *****************************************************************************/
369 VariableSetStmt: SET ColId TO var_value
371 VariableSetStmt *n = makeNode(VariableSetStmt);
376 | SET ColId '=' var_value
378 VariableSetStmt *n = makeNode(VariableSetStmt);
383 | SET TIME ZONE zone_value
385 VariableSetStmt *n = makeNode(VariableSetStmt);
386 n->name = "timezone";
392 var_value: Sconst { $$ = $1; }
393 | DEFAULT { $$ = NULL; }
396 zone_value: Sconst { $$ = $1; }
397 | DEFAULT { $$ = NULL; }
398 | LOCAL { $$ = "default"; }
401 VariableShowStmt: SHOW ColId
403 VariableShowStmt *n = makeNode(VariableShowStmt);
409 VariableShowStmt *n = makeNode(VariableShowStmt);
410 n->name = "timezone";
415 VariableResetStmt: RESET ColId
417 VariableResetStmt *n = makeNode(VariableResetStmt);
423 VariableResetStmt *n = makeNode(VariableResetStmt);
424 n->name = "timezone";
430 /*****************************************************************************
433 * addattr ( attr1 = type1 .. attrn = typen ) to <relname> [*]
435 *****************************************************************************/
437 AddAttrStmt: ALTER TABLE relation_name opt_inh_star alter_clause
439 AddAttrStmt *n = makeNode(AddAttrStmt);
447 alter_clause: ADD opt_column columnDef
451 | ADD '(' tableElementList ')'
453 ColumnDef *lp = lfirst($3);
456 elog(WARN,"ALTER TABLE/ADD() allows one column only",NULL);
459 | DROP opt_column ColId
460 { elog(WARN,"ALTER TABLE/DROP COLUMN not yet implemented",NULL); }
461 | ALTER opt_column ColId SET opt_default
462 { elog(WARN,"ALTER TABLE/ALTER COLUMN/SET DEFAULT not yet implemented",NULL); }
463 | ALTER opt_column ColId DROP DEFAULT
464 { elog(WARN,"ALTER TABLE/ALTER COLUMN/DROP DEFAULT not yet implemented",NULL); }
466 { elog(WARN,"ALTER TABLE/ADD CONSTRAINT not yet implemented",NULL); }
469 columnDef: ColId Typename opt_default opt_constraint
471 $$ = makeNode(ColumnDef);
475 $$->is_not_null = $4;
479 opt_default: DEFAULT default_expr
481 $$ = FlattenStringList($2);
483 | /*EMPTY*/ { $$ = NULL; }
486 default_expr: AexprConst
487 { $$ = makeConstantList((A_Const *) $1); }
489 { $$ = lcons( makeString("NULL"), NIL); }
490 | '-' default_expr %prec UMINUS
491 { $$ = lcons( makeString( "-"), $2); }
492 | default_expr '+' default_expr
493 { $$ = nconc( $1, lcons( makeString( "+"), $3)); }
494 | default_expr '-' default_expr
495 { $$ = nconc( $1, lcons( makeString( "-"), $3)); }
496 | default_expr '/' default_expr
497 { $$ = nconc( $1, lcons( makeString( "/"), $3)); }
498 | default_expr '*' default_expr
499 { $$ = nconc( $1, lcons( makeString( "*"), $3)); }
500 | default_expr '=' default_expr
501 { elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
502 | default_expr '<' default_expr
503 { elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
504 | default_expr '>' default_expr
505 { elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
507 { $$ = lcons( makeString( ":"), $2); }
509 { $$ = lcons( makeString( ";"), $2); }
511 { $$ = lcons( makeString( "|"), $2); }
512 | default_expr TYPECAST Typename
514 $3->name = fmtId($3->name);
515 $$ = nconc( lcons( makeString( "CAST"), $1), makeList( makeString("AS"), $3, -1));
517 | CAST default_expr AS Typename
519 $4->name = fmtId($4->name);
520 $$ = nconc( lcons( makeString( "CAST"), $2), makeList( makeString("AS"), $4, -1));
522 | '(' default_expr ')'
523 { $$ = lappend( lcons( makeString( "("), $2), makeString( ")")); }
524 | name '(' default_expr ')'
526 $$ = makeList( makeString($1), makeString("("), -1);
528 $$ = lappend( $$, makeString(")"));
532 $$ = makeList( makeString($1), makeString("("), -1);
533 $$ = lappend( $$, makeString(")"));
535 | default_expr Op default_expr
537 if (!strcmp("<=", $2) || !strcmp(">=", $2))
538 elog(WARN,"boolean expressions not supported in DEFAULT",NULL);
539 $$ = nconc( $1, lcons( makeString( $2), $3));
542 { $$ = lcons( makeString( $1), $2); }
544 { $$ = lappend( $1, makeString( $2)); }
545 /* XXX - thomas 1997-10-07 v6.2 function-specific code to be changed */
547 { $$ = lcons( makeString( "date( 'current'::datetime + '0 sec')"), NIL); }
549 { $$ = lcons( makeString( "'now'::time"), NIL); }
550 | CURRENT_TIME '(' Iconst ')'
553 elog(NOTICE,"CURRENT_TIME(p) precision must be zero",NULL);
554 $$ = lcons( makeString( "'now'::time"), NIL);
557 { $$ = lcons( makeString( "now()"), NIL); }
558 | CURRENT_TIMESTAMP '(' Iconst ')'
561 elog(NOTICE,"CURRENT_TIMESTAMP(p) precision must be zero",NULL);
562 $$ = lcons( makeString( "now()"), NIL);
565 { $$ = lcons( makeString( "CURRENT_USER"), NIL); }
568 opt_constraint: NOT NULL_P { $$ = TRUE; }
571 elog(NOTICE,"UNIQUE clause ignored; not yet implemented",NULL);
574 | NOTNULL { $$ = TRUE; }
577 elog(NOTICE,"UNIQUE clause ignored; not yet implemented",NULL);
582 elog(NOTICE,"PRIMARY KEY clause ignored; not yet implemented",NULL);
585 | REFERENCES ColId opt_column_list key_match key_actions
587 elog(NOTICE,"FOREIGN KEY clause ignored; not yet implemented",NULL);
590 | /* EMPTY */ { $$ = FALSE; }
594 /*****************************************************************************
599 *****************************************************************************/
601 ClosePortalStmt: CLOSE opt_id
603 ClosePortalStmt *n = makeNode(ClosePortalStmt);
610 /*****************************************************************************
613 * COPY [BINARY] <relname> FROM/TO
614 * [USING DELIMITERS <delimiter>]
616 *****************************************************************************/
618 CopyStmt: COPY opt_binary relation_name opt_with_copy copy_dirn copy_file_name copy_delimiter
620 CopyStmt *n = makeNode(CopyStmt);
638 * copy_file_name NULL indicates stdio is used. Whether stdin or stdout is
639 * used depends on the direction. (It really doesn't make sense to copy from
640 * stdout. We silently correct the "typo". - AY 9/94
642 copy_file_name: Sconst { $$ = $1; }
643 | STDIN { $$ = NULL; }
644 | STDOUT { $$ = NULL; }
647 opt_binary: BINARY { $$ = TRUE; }
648 | /*EMPTY*/ { $$ = FALSE; }
651 opt_with_copy: WITH OIDS { $$ = TRUE; }
652 | /* EMPTY */ { $$ = FALSE; }
656 * the default copy delimiter is tab but the user can configure it
658 copy_delimiter: USING DELIMITERS Sconst { $$ = $3;}
659 | /* EMPTY */ { $$ = "\t"; }
663 /*****************************************************************************
668 *****************************************************************************/
670 CreateStmt: CREATE TABLE relation_name '(' OptTableElementList ')'
671 OptInherit OptConstraint OptArchiveType
673 CreateStmt *n = makeNode(CreateStmt);
682 OptTableElementList: tableElementList { $$ = $1; }
683 | /* EMPTY */ { $$ = NULL; }
687 tableElementList ',' columnDef
688 { $$ = lappend($1, $3); }
690 { $$ = lcons($1, NIL); }
694 * This was removed in 6.3, but we keep it so people can upgrade
695 * with old pg_dump scripts.
697 OptArchiveType: ARCHIVE '=' NONE { }
701 OptInherit: INHERITS '(' relation_name_list ')' { $$ = $3; }
702 | /*EMPTY*/ { $$ = NIL; }
705 OptConstraint: ConstraintList { $$ = $1; }
706 | /*EMPTY*/ { $$ = NULL; }
710 ConstraintList ',' ConstraintElem
711 { $$ = lappend($1, $3); }
713 { $$ = lcons($1, NIL); }
717 CONSTRAINT name ConstraintDef
719 $3->name = fmtId($2);
722 | ConstraintDef { $$ = $1; }
725 ConstraintDef: CHECK constraint_elem
727 ConstraintDef *constr = palloc (sizeof(ConstraintDef));
728 constr->type = CONSTR_CHECK;
730 constr->def = FlattenStringList($2);
733 | UNIQUE '(' columnList ')'
734 { elog(NOTICE,"CREATE TABLE/UNIQUE clause ignored; not yet implemented",NULL); }
735 | PRIMARY KEY '(' columnList ')'
736 { elog(NOTICE,"CREATE TABLE/PRIMARY KEY clause ignored; not yet implemented",NULL); }
737 | FOREIGN KEY '(' columnList ')' REFERENCES ColId opt_column_list key_match key_actions
738 { elog(NOTICE,"CREATE TABLE/FOREIGN KEY clause ignored; not yet implemented",NULL); }
741 constraint_elem: AexprConst
742 { $$ = makeConstantList((A_Const *) $1); }
744 { $$ = lcons( makeString("NULL"), NIL); }
747 $$ = lcons( makeString(fmtId($1)), NIL);
749 | '-' constraint_elem %prec UMINUS
750 { $$ = lcons( makeString( "-"), $2); }
751 | constraint_elem '+' constraint_elem
752 { $$ = nconc( $1, lcons( makeString( "+"), $3)); }
753 | constraint_elem '-' constraint_elem
754 { $$ = nconc( $1, lcons( makeString( "-"), $3)); }
755 | constraint_elem '/' constraint_elem
756 { $$ = nconc( $1, lcons( makeString( "/"), $3)); }
757 | constraint_elem '*' constraint_elem
758 { $$ = nconc( $1, lcons( makeString( "*"), $3)); }
759 | constraint_elem '=' constraint_elem
760 { $$ = nconc( $1, lcons( makeString( "="), $3)); }
761 | constraint_elem '<' constraint_elem
762 { $$ = nconc( $1, lcons( makeString( "<"), $3)); }
763 | constraint_elem '>' constraint_elem
764 { $$ = nconc( $1, lcons( makeString( ">"), $3)); }
765 | ':' constraint_elem
766 { $$ = lcons( makeString( ":"), $2); }
767 | ';' constraint_elem
768 { $$ = lcons( makeString( ";"), $2); }
769 | '|' constraint_elem
770 { $$ = lcons( makeString( "|"), $2); }
771 | constraint_elem TYPECAST Typename
773 $3->name = fmtId($3->name);
774 $$ = nconc( lcons( makeString( "CAST"), $1), makeList( makeString("AS"), $3, -1));
776 | CAST constraint_elem AS Typename
778 $4->name = fmtId($4->name);
779 $$ = nconc( lcons( makeString( "CAST"), $2), makeList( makeString("AS"), $4, -1));
781 | '(' constraint_elem ')'
782 { $$ = lappend( lcons( makeString( "("), $2), makeString( ")")); }
783 | name '(' constraint_elem ')'
785 $$ = makeList( makeString($1), makeString("("), -1);
787 $$ = lappend( $$, makeString(")"));
789 | constraint_elem Op constraint_elem
790 { $$ = nconc( $1, lcons( makeString( $2), $3)); }
791 | constraint_elem AND constraint_elem
792 { $$ = nconc( $1, lcons( makeString( "AND"), $3)); }
793 | constraint_elem OR constraint_elem
794 { $$ = nconc( $1, lcons( makeString( "OR"), $3)); }
796 { $$ = lcons( makeString( $1), $2); }
798 { $$ = lappend( $1, makeString( $2)); }
799 | constraint_elem IS TRUE_P
800 { $$ = lappend( $1, makeString( "IS TRUE")); }
801 | constraint_elem IS FALSE_P
802 { $$ = lappend( $1, makeString( "IS FALSE")); }
803 | constraint_elem IS NOT TRUE_P
804 { $$ = lappend( $1, makeString( "IS NOT TRUE")); }
805 | constraint_elem IS NOT FALSE_P
806 { $$ = lappend( $1, makeString( "IS NOT FALSE")); }
809 key_match: MATCH FULL { $$ = NULL; }
810 | MATCH PARTIAL { $$ = NULL; }
811 | /*EMPTY*/ { $$ = NULL; }
814 key_actions: key_action key_action { $$ = NIL; }
815 | key_action { $$ = NIL; }
816 | /*EMPTY*/ { $$ = NIL; }
819 key_action: ON DELETE key_reference { $$ = NIL; }
820 | ON UPDATE key_reference { $$ = NIL; }
823 key_reference: NO ACTION { $$ = NULL; }
824 | CASCADE { $$ = NULL; }
825 | SET DEFAULT { $$ = NULL; }
826 | SET NULL_P { $$ = NULL; }
830 /*****************************************************************************
833 * CREATE SEQUENCE seqname
835 *****************************************************************************/
837 CreateSeqStmt: CREATE SEQUENCE relation_name OptSeqList
839 CreateSeqStmt *n = makeNode(CreateSeqStmt);
847 OptSeqList OptSeqElem
848 { $$ = lappend($1, $2); }
852 OptSeqElem: IDENT NumConst
854 $$ = makeNode(DefElem);
856 $$->arg = (Node *)$2;
860 $$ = makeNode(DefElem);
862 $$->arg = (Node *)NULL;
866 /*****************************************************************************
869 * CREATE PROCEDURAL LANGUAGE ...
870 * DROP PROCEDURAL LANGUAGE ...
872 *****************************************************************************/
874 CreatePLangStmt: CREATE PLangTrusted PROCEDURAL LANGUAGE Sconst
875 HANDLER def_name LANCOMPILER Sconst
877 CreatePLangStmt *n = makeNode(CreatePLangStmt);
886 PLangTrusted: TRUSTED { $$ = TRUE; }
889 DropPLangStmt: DROP PROCEDURAL LANGUAGE Sconst
891 DropPLangStmt *n = makeNode(DropPLangStmt);
897 /*****************************************************************************
903 *****************************************************************************/
905 CreateTrigStmt: CREATE TRIGGER name TriggerActionTime TriggerEvents ON
906 relation_name TriggerForSpec EXECUTE PROCEDURE
907 name '(' TriggerFuncArgs ')'
909 CreateTrigStmt *n = makeNode(CreateTrigStmt);
916 memcpy (n->actions, $5, 4);
921 TriggerActionTime: BEFORE { $$ = TRUE; }
922 | AFTER { $$ = FALSE; }
925 TriggerEvents: TriggerOneEvent
927 char *e = palloc (4);
928 e[0] = $1; e[1] = 0; $$ = e;
930 | TriggerOneEvent OR TriggerOneEvent
932 char *e = palloc (4);
933 e[0] = $1; e[1] = $3; e[2] = 0; $$ = e;
935 | TriggerOneEvent OR TriggerOneEvent OR TriggerOneEvent
937 char *e = palloc (4);
938 e[0] = $1; e[1] = $3; e[2] = $5; e[3] = 0;
943 TriggerOneEvent: INSERT { $$ = 'i'; }
944 | DELETE { $$ = 'd'; }
945 | UPDATE { $$ = 'u'; }
948 TriggerForSpec: FOR name name
950 if ( strcmp ($2, "each") != 0 )
951 elog(WARN,"parser: syntax error near %s",$2);
952 if ( strcmp ($3, "row") == 0 )
954 else if ( strcmp ($3, "statement") == 0 )
957 elog(WARN,"parser: syntax error near %s",$3);
961 TriggerFuncArgs: TriggerFuncArg
962 { $$ = lcons($1, NIL); }
963 | TriggerFuncArgs ',' TriggerFuncArg
964 { $$ = lappend($1, $3); }
969 TriggerFuncArg: ICONST
971 char *s = (char *) palloc (256);
972 sprintf (s, "%d", $1);
977 char *s = (char *) palloc (256);
978 sprintf (s, "%g", $1);
981 | Sconst { $$ = $1; }
985 DropTrigStmt: DROP TRIGGER name ON relation_name
987 DropTrigStmt *n = makeNode(DropTrigStmt);
995 /*****************************************************************************
998 * define (type,operator,aggregate)
1000 *****************************************************************************/
1002 DefineStmt: CREATE def_type def_rest
1009 def_rest: def_name definition
1011 $$ = makeNode(DefineStmt);
1013 $$->definition = $2;
1017 def_type: OPERATOR { $$ = OPERATOR; }
1018 | Type { $$ = TYPE_P; }
1019 | AGGREGATE { $$ = AGGREGATE; }
1022 def_name: PROCEDURE { $$ = "procedure"; }
1023 | JOIN { $$ = "join"; }
1024 | ColId { $$ = $1; }
1025 | MathOp { $$ = $1; }
1029 definition: '(' def_list ')' { $$ = $2; }
1032 def_list: def_elem { $$ = lcons($1, NIL); }
1033 | def_list ',' def_elem { $$ = lappend($1, $3); }
1036 def_elem: def_name '=' def_arg
1038 $$ = makeNode(DefElem);
1040 $$->arg = (Node *)$3;
1044 $$ = makeNode(DefElem);
1046 $$->arg = (Node *)NULL;
1048 | DEFAULT '=' def_arg
1050 $$ = makeNode(DefElem);
1051 $$->defname = "default";
1052 $$->arg = (Node *)$3;
1056 def_arg: ColId { $$ = (Node *)makeString($1); }
1057 | all_Op { $$ = (Node *)makeString($1); }
1058 | NumConst { $$ = (Node *)$1; /* already a Value */ }
1059 | Sconst { $$ = (Node *)makeString($1); }
1062 TypeName *n = makeNode(TypeName);
1065 n->arrayBounds = NULL;
1068 | DOUBLE { $$ = (Node *)makeString("double"); }
1072 /*****************************************************************************
1075 * destroy <relname1> [, <relname2> .. <relnameN> ]
1077 *****************************************************************************/
1079 DestroyStmt: DROP TABLE relation_name_list
1081 DestroyStmt *n = makeNode(DestroyStmt);
1083 n->sequence = FALSE;
1086 | DROP SEQUENCE relation_name_list
1088 DestroyStmt *n = makeNode(DestroyStmt);
1096 /*****************************************************************************
1099 * fetch/move [forward | backward] [number | all ] [ in <portalname> ]
1101 *****************************************************************************/
1103 FetchStmt: FETCH opt_direction fetch_how_many opt_portal_name
1105 FetchStmt *n = makeNode(FetchStmt);
1112 | MOVE opt_direction fetch_how_many opt_portal_name
1114 FetchStmt *n = makeNode(FetchStmt);
1123 opt_direction: FORWARD { $$ = FORWARD; }
1124 | BACKWARD { $$ = BACKWARD; }
1125 | /*EMPTY*/ { $$ = FORWARD; /* default */ }
1128 fetch_how_many: Iconst
1130 if ($1 <= 0) elog(WARN,"Please specify nonnegative count for fetch",NULL); }
1131 | ALL { $$ = 0; /* 0 means fetch all tuples*/}
1132 | /*EMPTY*/ { $$ = 1; /*default*/ }
1135 opt_portal_name: IN name { $$ = $2;}
1136 | /*EMPTY*/ { $$ = NULL; }
1140 /*****************************************************************************
1143 * GRANT [privileges] ON [relation_name_list] TO [GROUP] grantee
1145 *****************************************************************************/
1147 GrantStmt: GRANT privileges ON relation_name_list TO grantee opt_with_grant
1149 $$ = (Node*)makeAclStmt($2,$4,$6,'+');
1155 privileges: ALL PRIVILEGES
1157 $$ = aclmakepriv("rwaR",0);
1161 $$ = aclmakepriv("rwaR",0);
1163 | operation_commalist
1169 operation_commalist: operation
1171 $$ = aclmakepriv("",$1);
1173 | operation_commalist ',' operation
1175 $$ = aclmakepriv($1,$3);
1182 $$ = ACL_MODE_RD_CHR;
1186 $$ = ACL_MODE_AP_CHR;
1190 $$ = ACL_MODE_WR_CHR;
1194 $$ = ACL_MODE_WR_CHR;
1198 $$ = ACL_MODE_RU_CHR;
1204 $$ = aclmakeuser("A","");
1208 $$ = aclmakeuser("G",$2);
1212 $$ = aclmakeuser("U",$1);
1216 opt_with_grant: WITH GRANT OPTION
1218 yyerror("WITH GRANT OPTION is not supported. Only relation owners can set privileges");
1224 /*****************************************************************************
1227 * REVOKE [privileges] ON [relation_name] FROM [user]
1229 *****************************************************************************/
1231 RevokeStmt: REVOKE privileges ON relation_name_list FROM grantee
1233 $$ = (Node*)makeAclStmt($2,$4,$6,'-');
1240 /*****************************************************************************
1243 * create index <indexname> on <relname>
1244 * using <access> "(" (<col> with <op>)+ ")" [with
1247 * [where <qual>] is not supported anymore
1248 *****************************************************************************/
1250 IndexStmt: CREATE index_opt_unique INDEX index_name ON relation_name
1251 access_method_clause '(' index_params ')' opt_with
1253 /* should check that access_method is valid,
1254 etc ... but doesn't */
1255 IndexStmt *n = makeNode(IndexStmt);
1259 n->accessMethod = $7;
1260 n->indexParams = $9;
1261 n->withClause = $11;
1262 n->whereClause = NULL;
1267 index_opt_unique: UNIQUE { $$ = TRUE; }
1268 | /*EMPTY*/ { $$ = FALSE; }
1271 access_method_clause: USING access_method { $$ = $2; }
1272 | /*EMPTY*/ { $$ = "btree"; }
1275 index_params: index_list { $$ = $1; }
1276 | func_index { $$ = lcons($1,NIL); }
1279 index_list: index_list ',' index_elem { $$ = lappend($1, $3); }
1280 | index_elem { $$ = lcons($1, NIL); }
1283 func_index: name '(' name_list ')' opt_type opt_class
1285 $$ = makeNode(IndexElem);
1293 index_elem: attr_name opt_type opt_class
1295 $$ = makeNode(IndexElem);
1303 opt_type: ':' Typename { $$ = $2;}
1304 | FOR Typename { $$ = $2;}
1305 | /*EMPTY*/ { $$ = NULL;}
1308 /* opt_class "WITH class" conflicts with preceeding opt_type
1309 * for Typename of "TIMESTAMP WITH TIME ZONE"
1310 * So, remove "WITH class" from the syntax. OK??
1311 * - thomas 1997-10-12
1312 * | WITH class { $$ = $2; }
1314 opt_class: class { $$ = $1; }
1315 | USING class { $$ = $2; }
1316 | /*EMPTY*/ { $$ = NULL; }
1320 /*****************************************************************************
1323 * extend index <indexname> [where <qual>]
1325 *****************************************************************************/
1327 ExtendStmt: EXTEND INDEX index_name where_clause
1329 ExtendStmt *n = makeNode(ExtendStmt);
1331 n->whereClause = $4;
1337 /*****************************************************************************
1340 * execute recipe <recipeName>
1342 *****************************************************************************/
1344 RecipeStmt: EXECUTE RECIPE recipe_name
1347 if (!IsTransactionBlock())
1348 elog(WARN,"EXECUTE RECIPE may only be used in begin/end transaction blocks",NULL);
1350 n = makeNode(RecipeStmt);
1357 /*****************************************************************************
1360 * define function <fname>
1361 * (language = <lang>, returntype = <typename>
1362 * [, arch_pct = <percentage | pre-defined>]
1363 * [, disk_pct = <percentage | pre-defined>]
1364 * [, byte_pct = <percentage | pre-defined>]
1365 * [, perbyte_cpu = <int | pre-defined>]
1366 * [, percall_cpu = <int | pre-defined>]
1368 * [arg is (<type-1> { , <type-n>})]
1369 * as <filename or code in language as appropriate>
1371 *****************************************************************************/
1373 ProcedureStmt: CREATE FUNCTION def_name def_args
1374 RETURNS def_arg opt_with AS Sconst LANGUAGE Sconst
1376 ProcedureStmt *n = makeNode(ProcedureStmt);
1379 n->returnType = (Node *)$6;
1386 opt_with: WITH definition { $$ = $2; }
1387 | /* EMPTY */ { $$ = NIL; }
1390 def_args: '(' def_name_list ')' { $$ = $2; }
1391 | '(' ')' { $$ = NIL; }
1394 def_name_list: name_list;
1396 /*****************************************************************************
1400 * remove function <funcname>
1401 * (REMOVE FUNCTION "funcname" (arg1, arg2, ...))
1402 * remove aggregate <aggname>
1403 * (REMOVE AGGREGATE "aggname" "aggtype")
1404 * remove operator <opname>
1405 * (REMOVE OPERATOR "opname" (leftoperand_typ rightoperand_typ))
1406 * remove type <typename>
1407 * (REMOVE TYPE "typename")
1408 * remove rule <rulename>
1409 * (REMOVE RULE "rulename")
1411 *****************************************************************************/
1413 RemoveStmt: DROP remove_type name
1415 RemoveStmt *n = makeNode(RemoveStmt);
1422 remove_type: Type { $$ = TYPE_P; }
1423 | INDEX { $$ = INDEX; }
1424 | RULE { $$ = RULE; }
1425 | VIEW { $$ = VIEW; }
1428 RemoveAggrStmt: DROP AGGREGATE name aggr_argtype
1430 RemoveAggrStmt *n = makeNode(RemoveAggrStmt);
1437 aggr_argtype: name { $$ = $1; }
1438 | '*' { $$ = NULL; }
1441 RemoveFuncStmt: DROP FUNCTION name '(' func_argtypes ')'
1443 RemoveFuncStmt *n = makeNode(RemoveFuncStmt);
1450 func_argtypes: name_list { $$ = $1; }
1451 | /*EMPTY*/ { $$ = NIL; }
1454 RemoveOperStmt: DROP OPERATOR all_Op '(' oper_argtypes ')'
1456 RemoveOperStmt *n = makeNode(RemoveOperStmt);
1463 all_Op: Op | MathOp;
1465 MathOp: '+' { $$ = "+"; }
1476 elog(WARN,"parser: argument type missing (use NONE for unary operators)",NULL);
1479 { $$ = makeList(makeString($1), makeString($3), -1); }
1480 | NONE ',' name /* left unary */
1481 { $$ = makeList(NULL, makeString($3), -1); }
1482 | name ',' NONE /* right unary */
1483 { $$ = makeList(makeString($1), NULL, -1); }
1487 /*****************************************************************************
1490 * rename <attrname1> in <relname> [*] to <attrname2>
1491 * rename <relname1> to <relname2>
1493 *****************************************************************************/
1495 RenameStmt: ALTER TABLE relation_name opt_inh_star
1496 RENAME opt_column opt_name TO name
1498 RenameStmt *n = makeNode(RenameStmt);
1507 opt_name: name { $$ = $1; }
1508 | /*EMPTY*/ { $$ = NULL; }
1511 opt_column: COLUMN { $$ = COLUMN; }
1512 | /*EMPTY*/ { $$ = 0; }
1516 /*****************************************************************************
1518 * QUERY: Define Rewrite Rule , Define Tuple Rule
1519 * Define Rule <old rules >
1521 * only rewrite rule is supported -- ay 9/94
1523 *****************************************************************************/
1525 RuleStmt: CREATE RULE name AS
1526 { QueryIsRule=TRUE; }
1527 ON event TO event_object where_clause
1528 DO opt_instead OptStmtList
1530 RuleStmt *n = makeNode(RuleStmt);
1534 n->whereClause = $10;
1541 OptStmtList: NOTHING { $$ = NIL; }
1542 | OptimizableStmt { $$ = lcons($1, NIL); }
1543 | '[' OptStmtBlock ']' { $$ = $2; }
1546 OptStmtBlock: OptStmtMulti
1549 { $$ = lcons($1, NIL); }
1552 OptStmtMulti: OptStmtMulti OptimizableStmt ';'
1553 { $$ = lappend($1, $2); }
1554 | OptStmtMulti OptimizableStmt
1555 { $$ = lappend($1, $2); }
1556 | OptimizableStmt ';'
1557 { $$ = lcons($1, NIL); }
1560 event_object: relation_name '.' attr_name
1562 $$ = makeNode(Attr);
1565 $$->attrs = lcons(makeString($3), NIL);
1566 $$->indirection = NIL;
1570 $$ = makeNode(Attr);
1574 $$->indirection = NIL;
1578 /* change me to select, update, etc. some day */
1579 event: SELECT { $$ = CMD_SELECT; }
1580 | UPDATE { $$ = CMD_UPDATE; }
1581 | DELETE { $$ = CMD_DELETE; }
1582 | INSERT { $$ = CMD_INSERT; }
1585 opt_instead: INSTEAD { $$ = TRUE; }
1586 | /* EMPTY */ { $$ = FALSE; }
1590 /*****************************************************************************
1593 * NOTIFY <relation_name> can appear both in rule bodies and
1594 * as a query-level command
1596 *****************************************************************************/
1598 NotifyStmt: NOTIFY relation_name
1600 NotifyStmt *n = makeNode(NotifyStmt);
1606 ListenStmt: LISTEN relation_name
1608 ListenStmt *n = makeNode(ListenStmt);
1615 /*****************************************************************************
1626 *****************************************************************************/
1628 TransactionStmt: ABORT_TRANS TRANSACTION
1630 TransactionStmt *n = makeNode(TransactionStmt);
1631 n->command = ABORT_TRANS;
1634 | BEGIN_TRANS TRANSACTION
1636 TransactionStmt *n = makeNode(TransactionStmt);
1637 n->command = BEGIN_TRANS;
1642 TransactionStmt *n = makeNode(TransactionStmt);
1643 n->command = BEGIN_TRANS;
1648 TransactionStmt *n = makeNode(TransactionStmt);
1649 n->command = END_TRANS;
1652 | END_TRANS TRANSACTION
1654 TransactionStmt *n = makeNode(TransactionStmt);
1655 n->command = END_TRANS;
1660 TransactionStmt *n = makeNode(TransactionStmt);
1661 n->command = ABORT_TRANS;
1667 TransactionStmt *n = makeNode(TransactionStmt);
1668 n->command = ABORT_TRANS;
1673 TransactionStmt *n = makeNode(TransactionStmt);
1674 n->command = BEGIN_TRANS;
1679 TransactionStmt *n = makeNode(TransactionStmt);
1680 n->command = END_TRANS;
1686 TransactionStmt *n = makeNode(TransactionStmt);
1687 n->command = END_TRANS;
1692 TransactionStmt *n = makeNode(TransactionStmt);
1693 n->command = ABORT_TRANS;
1699 /*****************************************************************************
1702 * define view <viewname> '('target-list ')' [where <quals> ]
1704 *****************************************************************************/
1706 ViewStmt: CREATE VIEW name AS RetrieveStmt
1708 ViewStmt *n = makeNode(ViewStmt);
1710 n->query = (Query *)$5;
1716 /*****************************************************************************
1721 *****************************************************************************/
1723 LoadStmt: LOAD file_name
1725 LoadStmt *n = makeNode(LoadStmt);
1732 /*****************************************************************************
1737 *****************************************************************************/
1739 CreatedbStmt: CREATE DATABASE database_name opt_database
1741 CreatedbStmt *n = makeNode(CreatedbStmt);
1748 opt_database: WITH LOCATION '=' location { $$ = $4; }
1749 | /*EMPTY*/ { $$ = NULL; }
1752 location: Sconst { $$ = $1; }
1753 | DEFAULT { $$ = NULL; }
1754 | /*EMPTY*/ { $$ = NULL; }
1757 /*****************************************************************************
1762 *****************************************************************************/
1764 DestroydbStmt: DROP DATABASE database_name
1766 DestroydbStmt *n = makeNode(DestroydbStmt);
1773 /*****************************************************************************
1776 * cluster <index_name> on <relation_name>
1778 *****************************************************************************/
1780 ClusterStmt: CLUSTER index_name ON relation_name
1782 ClusterStmt *n = makeNode(ClusterStmt);
1790 /*****************************************************************************
1795 *****************************************************************************/
1797 VacuumStmt: VACUUM opt_verbose opt_analyze
1799 VacuumStmt *n = makeNode(VacuumStmt);
1806 | VACUUM opt_verbose opt_analyze relation_name opt_va_list
1808 VacuumStmt *n = makeNode(VacuumStmt);
1813 if ( $5 != NIL && !$4 )
1814 elog(WARN,"parser: syntax error at or near \"(\"",NULL);
1819 opt_verbose: VERBOSE { $$ = TRUE; }
1820 | /* EMPTY */ { $$ = FALSE; }
1823 opt_analyze: ANALYZE { $$ = TRUE; }
1824 | /* EMPTY */ { $$ = FALSE; }
1827 opt_va_list: '(' va_list ')'
1834 { $$=lcons($1,NIL); }
1836 { $$=lappend($1,$3); }
1840 /*****************************************************************************
1845 *****************************************************************************/
1847 ExplainStmt: EXPLAIN opt_verbose OptimizableStmt
1849 ExplainStmt *n = makeNode(ExplainStmt);
1851 n->query = (Query*)$3;
1857 /*****************************************************************************
1859 * Optimizable Stmts: *
1861 * one of the five queries processed by the planner *
1863 * [ultimately] produces query-trees as specified *
1864 * in the query-spec document in ~postgres/ref *
1866 *****************************************************************************/
1868 OptimizableStmt: RetrieveStmt
1873 | DeleteStmt /* by default all are $$=$1 */
1877 /*****************************************************************************
1882 *****************************************************************************/
1884 AppendStmt: INSERT INTO relation_name opt_column_list insert_rest
1892 insert_rest: VALUES '(' res_target_list2 ')'
1894 $$ = makeNode(AppendStmt);
1895 $$->targetList = $3;
1896 $$->fromClause = NIL;
1897 $$->whereClause = NULL;
1899 | SELECT res_target_list2 from_clause where_clause
1901 $$ = makeNode(AppendStmt);
1902 $$->targetList = $2;
1903 $$->fromClause = $3;
1904 $$->whereClause = $4;
1908 opt_column_list: '(' columnList ')' { $$ = $2; }
1909 | /*EMPTY*/ { $$ = NIL; }
1913 columnList ',' columnElem
1914 { $$ = lappend($1, $3); }
1916 { $$ = lcons($1, NIL); }
1919 columnElem: ColId opt_indirection
1921 Ident *id = makeNode(Ident);
1923 id->indirection = $2;
1929 /*****************************************************************************
1934 *****************************************************************************/
1936 DeleteStmt: DELETE FROM relation_name
1939 DeleteStmt *n = makeNode(DeleteStmt);
1941 n->whereClause = $4;
1947 /*****************************************************************************
1950 * ReplaceStmt (UPDATE)
1952 *****************************************************************************/
1954 ReplaceStmt: UPDATE relation_name
1959 ReplaceStmt *n = makeNode(ReplaceStmt);
1963 n->whereClause = $6;
1969 /*****************************************************************************
1974 *****************************************************************************/
1976 CursorStmt: DECLARE name opt_binary CURSOR FOR
1977 SELECT opt_unique res_target_list2
1978 from_clause where_clause group_clause sort_clause
1980 CursorStmt *n = makeNode(CursorStmt);
1982 /* from PORTAL name */
1984 * 15 august 1991 -- since 3.0 postgres does locking
1985 * right, we discovered that portals were violating
1986 * locking protocol. portal locks cannot span xacts.
1987 * as a short-term fix, we installed the check here.
1990 if (!IsTransactionBlock())
1991 elog(WARN,"Named portals may only be used in begin/end transaction blocks",NULL);
1998 n->whereClause = $10;
1999 n->groupClause = $11;
2000 n->sortClause = $12;
2006 /*****************************************************************************
2011 *****************************************************************************/
2013 RetrieveStmt: SELECT opt_unique res_target_list2
2014 result from_clause where_clause
2015 group_clause having_clause
2016 union_clause sort_clause
2018 RetrieveStmt *n = makeNode(RetrieveStmt);
2023 n->whereClause = $6;
2024 n->groupClause = $7;
2025 n->havingClause = $8;
2026 n->selectClause = $9;
2027 n->sortClause = $10;
2032 union_clause: UNION opt_union select_list { $$ = $3; }
2033 | /*EMPTY*/ { $$ = NIL; }
2036 select_list: select_list UNION opt_union SubSelect
2037 { $$ = lappend($1, $4); }
2039 { $$ = lcons($1, NIL); }
2042 SubSelect: SELECT opt_unique res_target_list2
2043 from_clause where_clause
2044 group_clause having_clause
2046 SubSelect *n = makeNode(SubSelect);
2050 n->whereClause = $5;
2051 n->groupClause = $6;
2052 n->havingClause = $7;
2057 result: INTO TABLE relation_name
2063 opt_union: ALL { $$ = TRUE; }
2064 | /*EMPTY*/ { $$ = FALSE; }
2067 opt_unique: DISTINCT { $$ = "*"; }
2068 | DISTINCT ON ColId { $$ = $3; }
2069 | ALL { $$ = NULL; }
2070 | /*EMPTY*/ { $$ = NULL; }
2073 sort_clause: ORDER BY sortby_list { $$ = $3; }
2074 | /*EMPTY*/ { $$ = NIL; }
2077 sortby_list: sortby { $$ = lcons($1, NIL); }
2078 | sortby_list ',' sortby { $$ = lappend($1, $3); }
2081 sortby: ColId OptUseOp
2083 $$ = makeNode(SortGroupBy);
2089 | ColId '.' ColId OptUseOp
2091 $$ = makeNode(SortGroupBy);
2099 $$ = makeNode(SortGroupBy);
2107 OptUseOp: USING Op { $$ = $2; }
2108 | USING '<' { $$ = "<"; }
2109 | USING '>' { $$ = ">"; }
2111 | DESC { $$ = ">"; }
2112 | /*EMPTY*/ { $$ = "<"; /*default*/ }
2116 * jimmy bell-style recursive queries aren't supported in the
2119 * ...however, recursive addattr and rename supported. make special
2122 * XXX i believe '*' should be the default behavior, but...
2124 opt_inh_star: '*' { $$ = TRUE; }
2125 | /*EMPTY*/ { $$ = FALSE; }
2128 relation_name_list: name_list;
2131 { $$ = lcons(makeString($1),NIL); }
2132 | name_list ',' name
2133 { $$ = lappend($1,makeString($3)); }
2136 group_clause: GROUP BY groupby_list { $$ = $3; }
2137 | /*EMPTY*/ { $$ = NIL; }
2140 groupby_list: groupby { $$ = lcons($1, NIL); }
2141 | groupby_list ',' groupby { $$ = lappend($1, $3); }
2146 $$ = makeNode(SortGroupBy);
2154 $$ = makeNode(SortGroupBy);
2162 $$ = makeNode(SortGroupBy);
2170 having_clause: HAVING a_expr { $$ = $2; }
2171 | /*EMPTY*/ { $$ = NULL; }
2175 /*****************************************************************************
2177 * clauses common to all Optimizable Stmts:
2181 *****************************************************************************/
2183 from_clause: FROM '(' relation_expr join_expr JOIN relation_expr join_spec ')'
2186 elog(WARN,"JOIN not yet implemented",NULL);
2188 | FROM from_list { $$ = $2; }
2189 | /*EMPTY*/ { $$ = NIL; }
2192 from_list: from_list ',' from_val
2193 { $$ = lappend($1, $3); }
2194 | from_val CROSS JOIN from_val
2195 { elog(WARN,"CROSS JOIN not yet implemented",NULL); }
2197 { $$ = lcons($1, NIL); }
2200 from_val: relation_expr AS ColLabel
2202 $$ = makeNode(RangeVar);
2206 | relation_expr ColId
2208 $$ = makeNode(RangeVar);
2214 $$ = makeNode(RangeVar);
2220 join_expr: NATURAL join_expr { $$ = NULL; }
2222 { elog(WARN,"FULL OUTER JOIN not yet implemented",NULL); }
2224 { elog(WARN,"LEFT OUTER JOIN not yet implemented",NULL); }
2226 { elog(WARN,"RIGHT OUTER JOIN not yet implemented",NULL); }
2228 { elog(WARN,"OUTER JOIN not yet implemented",NULL); }
2230 { elog(WARN,"INNER JOIN not yet implemented",NULL); }
2232 { elog(WARN,"UNION JOIN not yet implemented",NULL); }
2234 { elog(WARN,"INNER JOIN not yet implemented",NULL); }
2237 join_outer: OUTER_P { $$ = NULL; }
2238 | /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
2241 join_spec: ON '(' a_expr ')' { $$ = NULL; }
2242 | USING '(' join_list ')' { $$ = NULL; }
2243 | /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
2246 join_list: join_using { $$ = lcons($1, NIL); }
2247 | join_list ',' join_using { $$ = lappend($1, $3); }
2252 $$ = makeNode(SortGroupBy);
2260 $$ = makeNode(SortGroupBy);
2268 $$ = makeNode(SortGroupBy);
2276 where_clause: WHERE a_expr { $$ = $2; }
2277 | /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
2280 relation_expr: relation_name
2282 /* normal relations */
2283 $$ = makeNode(RelExpr);
2287 | relation_name '*' %prec '='
2289 /* inheiritance query */
2290 $$ = makeNode(RelExpr);
2295 opt_array_bounds: '[' ']' nest_array_bounds
2296 { $$ = lcons(makeInteger(-1), $3); }
2297 | '[' Iconst ']' nest_array_bounds
2298 { $$ = lcons(makeInteger($2), $4); }
2303 nest_array_bounds: '[' ']' nest_array_bounds
2304 { $$ = lcons(makeInteger(-1), $3); }
2305 | '[' Iconst ']' nest_array_bounds
2306 { $$ = lcons(makeInteger($2), $4); }
2312 /*****************************************************************************
2315 * SQL92 introduces a large amount of type-specific syntax.
2316 * Define individual clauses to handle these cases, and use
2317 * the generic case to handle regular type-extensible Postgres syntax.
2318 * - thomas 1997-10-10
2320 *****************************************************************************/
2322 Typename: Array opt_array_bounds
2325 $$->arrayBounds = $2;
2327 /* Is this the name of a complex type? If so, implement
2330 if (!strcmp(saved_relname, $$->name))
2331 /* This attr is the same type as the relation
2332 * being defined. The classic example: create
2333 * emp(name=text,mgr=emp)
2336 else if (typeTypeRelid(typenameType($$->name)) != InvalidOid)
2337 /* (Eventually add in here that the set can only
2338 * contain one element.)
2359 $$ = makeNode(TypeName);
2360 $$->name = xlateSqlType($1);
2364 generic: Id { $$ = $1; }
2365 | TYPE_P { $$ = xlateSqlType("type"); }
2366 | DOUBLE PRECISION { $$ = xlateSqlType("float8"); }
2369 /* SQL92 numeric data types
2370 * Check FLOAT() precision limits assuming IEEE floating types.
2371 * Provide rudimentary DECIMAL() and NUMERIC() implementations
2372 * by checking parameters and making sure they match what is possible with INTEGER.
2373 * - thomas 1997-09-18
2375 Numeric: FLOAT opt_float
2377 $$ = makeNode(TypeName);
2378 $$->name = xlateSqlType($2);
2380 | DECIMAL opt_decimal
2382 $$ = makeNode(TypeName);
2383 $$->name = xlateSqlType("integer");
2385 | NUMERIC opt_numeric
2387 $$ = makeNode(TypeName);
2388 $$->name = xlateSqlType("integer");
2392 opt_float: '(' Iconst ')'
2395 elog(WARN,"precision for FLOAT must be at least 1",NULL);
2397 $$ = xlateSqlType("float4");
2399 $$ = xlateSqlType("float8");
2401 elog(WARN,"precision for FLOAT must be less than 16",NULL);
2405 $$ = xlateSqlType("float8");
2409 opt_numeric: '(' Iconst ',' Iconst ')'
2412 elog(WARN,"NUMERIC precision %d must be 9",$2);
2414 elog(WARN,"NUMERIC scale %d must be zero",$4);
2419 elog(WARN,"NUMERIC precision %d must be 9",$2);
2427 opt_decimal: '(' Iconst ',' Iconst ')'
2430 elog(WARN,"DECIMAL precision %d exceeds implementation limit of 9",$2);
2432 elog(WARN,"DECIMAL scale %d must be zero",$4);
2438 elog(WARN,"DECIMAL precision %d exceeds implementation limit of 9",$2);
2447 /* SQL92 character data types
2448 * The following implements CHAR() and VARCHAR().
2449 * We do it here instead of the 'Generic' production
2450 * because we don't want to allow arrays of VARCHAR().
2451 * I haven't thought about whether that will work or not.
2454 Character: character '(' Iconst ')'
2456 $$ = makeNode(TypeName);
2457 if (!strcasecmp($1, "char"))
2458 $$->name = xlateSqlType("bpchar");
2459 else if (!strcasecmp($1, "varchar"))
2460 $$->name = xlateSqlType("varchar");
2462 yyerror("parse error");
2464 elog(WARN,"length for '%s' type must be at least 1",$1);
2466 /* we can store a char() of length up to the size
2467 * of a page (8KB) - page headers and friends but
2468 * just to be safe here... - ay 6/95
2469 * XXX note this hardcoded limit - thomas 1997-07-13
2471 elog(WARN,"length for type '%s' cannot exceed 4096",$1);
2473 /* we actually implement this sort of like a varlen, so
2474 * the first 4 bytes is the length. (the difference
2475 * between this and "text" is that we blank-pad and
2476 * truncate where necessary
2478 $$->typlen = 4 + $3;
2482 $$ = makeNode(TypeName);
2483 $$->name = xlateSqlType($1);
2487 character: CHARACTER opt_varying opt_charset opt_collate
2490 if (($3 == NULL) || (strcasecmp($3, "sql_text") == 0)) {
2491 if ($2) type = xlateSqlType("varchar");
2492 else type = xlateSqlType("char");
2495 c = palloc(strlen("var") + strlen($3) + 1);
2498 type = xlateSqlType(c);
2500 type = xlateSqlType($3);
2504 elog(WARN,"COLLATE %s not yet implemented",$4);
2507 | CHAR opt_varying { $$ = xlateSqlType($2? "varchar": "char"); }
2508 | VARCHAR { $$ = xlateSqlType("varchar"); }
2509 | NATIONAL CHARACTER opt_varying { $$ = xlateSqlType($3? "varchar": "char"); }
2510 | NCHAR opt_varying { $$ = xlateSqlType($2? "varchar": "char"); }
2513 opt_varying: VARYING { $$ = TRUE; }
2514 | /*EMPTY*/ { $$ = FALSE; }
2517 opt_charset: CHARACTER SET ColId { $$ = $3; }
2518 | /*EMPTY*/ { $$ = NULL; }
2521 opt_collate: COLLATE ColId { $$ = $2; }
2522 | /*EMPTY*/ { $$ = NULL; }
2527 $$ = makeNode(TypeName);
2528 $$->name = xlateSqlType($1);
2530 | TIMESTAMP opt_timezone
2532 $$ = makeNode(TypeName);
2533 $$->name = xlateSqlType("timestamp");
2538 $$ = makeNode(TypeName);
2539 $$->name = xlateSqlType("time");
2541 | INTERVAL opt_interval
2543 $$ = makeNode(TypeName);
2544 $$->name = xlateSqlType("interval");
2548 datetime: YEAR_P { $$ = "year"; }
2549 | MONTH_P { $$ = "month"; }
2550 | DAY_P { $$ = "day"; }
2551 | HOUR_P { $$ = "hour"; }
2552 | MINUTE_P { $$ = "minute"; }
2553 | SECOND_P { $$ = "second"; }
2556 opt_timezone: WITH TIME ZONE { $$ = TRUE; }
2557 | /*EMPTY*/ { $$ = FALSE; }
2560 opt_interval: datetime { $$ = lcons($1, NIL); }
2561 | YEAR_P TO MONTH_P { $$ = NIL; }
2562 | DAY_P TO HOUR_P { $$ = NIL; }
2563 | DAY_P TO MINUTE_P { $$ = NIL; }
2564 | DAY_P TO SECOND_P { $$ = NIL; }
2565 | HOUR_P TO MINUTE_P { $$ = NIL; }
2566 | HOUR_P TO SECOND_P { $$ = NIL; }
2567 | /* EMPTY */ { $$ = NIL; }
2571 /*****************************************************************************
2573 * expression grammar, still needs some cleanup
2575 *****************************************************************************/
2577 a_expr_or_null: a_expr
2581 A_Const *n = makeNode(A_Const);
2582 n->val.type = T_Null;
2586 a_expr: attr opt_indirection
2588 $1->indirection = $2;
2593 | '-' a_expr %prec UMINUS
2594 { $$ = makeA_Expr(OP, "-", NULL, $2); }
2596 { $$ = makeA_Expr(OP, "+", $1, $3); }
2598 { $$ = makeA_Expr(OP, "-", $1, $3); }
2600 { $$ = makeA_Expr(OP, "/", $1, $3); }
2602 { $$ = makeA_Expr(OP, "*", $1, $3); }
2604 { $$ = makeA_Expr(OP, "<", $1, $3); }
2606 { $$ = makeA_Expr(OP, ">", $1, $3); }
2608 { $$ = makeA_Expr(OP, "=", $1, $3); }
2610 { $$ = makeA_Expr(OP, ":", NULL, $2); }
2612 { $$ = makeA_Expr(OP, ";", NULL, $2); }
2614 { $$ = makeA_Expr(OP, "|", NULL, $2); }
2615 | a_expr TYPECAST Typename
2618 /* AexprConst can be either A_Const or ParamNo */
2619 if (nodeTag($1) == T_A_Const) {
2620 ((A_Const *)$1)->typename = $3;
2621 } else if (nodeTag($1) == T_Param) {
2622 ((ParamNo *)$1)->typename = $3;
2623 /* otherwise, try to transform to a function call */
2625 FuncCall *n = makeNode(FuncCall);
2626 n->funcname = $3->name;
2627 n->args = lcons($1,NIL);
2631 | CAST a_expr AS Typename
2634 /* AexprConst can be either A_Const or ParamNo */
2635 if (nodeTag($2) == T_A_Const) {
2636 ((A_Const *)$2)->typename = $4;
2637 } else if (nodeTag($2) == T_Param) {
2638 ((ParamNo *)$2)->typename = $4;
2639 /* otherwise, try to transform to a function call */
2641 FuncCall *n = makeNode(FuncCall);
2642 n->funcname = $4->name;
2643 n->args = lcons($2,NIL);
2647 | '(' a_expr_or_null ')'
2650 { $$ = makeIndexable($2,$1,$3); }
2651 | a_expr LIKE a_expr
2652 { $$ = makeIndexable("~~", $1, $3); }
2653 | a_expr NOT LIKE a_expr
2654 { $$ = makeA_Expr(OP, "!~~", $1, $4); }
2656 { $$ = makeA_Expr(OP, $1, NULL, $2); }
2658 { $$ = makeA_Expr(OP, $2, $1, NULL); }
2661 /* could be a column name or a relation_name */
2662 Ident *n = makeNode(Ident);
2664 n->indirection = NULL;
2669 FuncCall *n = makeNode(FuncCall);
2670 Ident *star = makeNode(Ident);
2672 /* cheap hack for aggregate (eg. count) */
2675 n->args = lcons(star, NIL);
2680 FuncCall *n = makeNode(FuncCall);
2687 A_Const *n = makeNode(A_Const);
2688 TypeName *t = makeNode(TypeName);
2690 n->val.type = T_String;
2691 n->val.val.str = "now";
2694 t->name = xlateSqlType("date");
2701 A_Const *n = makeNode(A_Const);
2702 TypeName *t = makeNode(TypeName);
2704 n->val.type = T_String;
2705 n->val.val.str = "now";
2708 t->name = xlateSqlType("time");
2713 | CURRENT_TIME '(' Iconst ')'
2715 FuncCall *n = makeNode(FuncCall);
2716 A_Const *s = makeNode(A_Const);
2717 TypeName *t = makeNode(TypeName);
2719 n->funcname = xlateSqlType("time");
2720 n->args = lcons(s, NIL);
2722 s->val.type = T_String;
2723 s->val.val.str = "now";
2726 t->name = xlateSqlType("time");
2730 elog(NOTICE,"CURRENT_TIME(p) precision must be zero",NULL);
2736 A_Const *n = makeNode(A_Const);
2737 TypeName *t = makeNode(TypeName);
2739 n->val.type = T_String;
2740 n->val.val.str = "now";
2743 t->name = xlateSqlType("timestamp");
2748 | CURRENT_TIMESTAMP '(' Iconst ')'
2750 FuncCall *n = makeNode(FuncCall);
2751 A_Const *s = makeNode(A_Const);
2752 TypeName *t = makeNode(TypeName);
2754 n->funcname = xlateSqlType("timestamp");
2755 n->args = lcons(s, NIL);
2757 s->val.type = T_String;
2758 s->val.val.str = "now";
2761 t->name = xlateSqlType("timestamp");
2765 elog(NOTICE,"CURRENT_TIMESTAMP(p) precision must be zero",NULL);
2771 FuncCall *n = makeNode(FuncCall);
2772 n->funcname = "getpgusername";
2776 /* We probably need to define an "exists" node,
2777 * since the optimizer could choose to find only one match.
2778 * Perhaps the first implementation could just check for
2779 * count(*) > 0? - thomas 1997-07-19
2781 | EXISTS '(' SubSelect ')'
2783 elog(WARN,"EXISTS not yet implemented",NULL);
2786 | EXTRACT '(' extract_list ')'
2788 FuncCall *n = makeNode(FuncCall);
2789 n->funcname = "date_part";
2793 | POSITION '(' position_list ')'
2795 FuncCall *n = makeNode(FuncCall);
2796 n->funcname = "strpos";
2800 | SUBSTRING '(' substr_list ')'
2802 FuncCall *n = makeNode(FuncCall);
2803 n->funcname = "substr";
2807 /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
2808 | TRIM '(' BOTH trim_list ')'
2810 FuncCall *n = makeNode(FuncCall);
2811 n->funcname = "btrim";
2815 | TRIM '(' LEADING trim_list ')'
2817 FuncCall *n = makeNode(FuncCall);
2818 n->funcname = "ltrim";
2822 | TRIM '(' TRAILING trim_list ')'
2824 FuncCall *n = makeNode(FuncCall);
2825 n->funcname = "rtrim";
2829 | TRIM '(' trim_list ')'
2831 FuncCall *n = makeNode(FuncCall);
2832 n->funcname = "btrim";
2836 | name '(' expr_list ')'
2838 FuncCall *n = makeNode(FuncCall);
2844 { $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
2846 { $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
2848 { $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); }
2849 | a_expr IS NOT NULL_P
2850 { $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); }
2853 FuncCall *n = makeNode(FuncCall);
2854 n->funcname = "istrue";
2855 n->args = lcons($1,NIL);
2860 FuncCall *n = makeNode(FuncCall);
2861 n->funcname = "isfalse";
2862 n->args = lcons($1,NIL);
2865 | a_expr IS NOT TRUE_P
2867 FuncCall *n = makeNode(FuncCall);
2868 n->funcname = "isfalse";
2869 n->args = lcons($1,NIL);
2872 | a_expr IS NOT FALSE_P
2874 FuncCall *n = makeNode(FuncCall);
2875 n->funcname = "istrue";
2876 n->args = lcons($1,NIL);
2879 | a_expr BETWEEN AexprConst AND AexprConst
2881 $$ = makeA_Expr(AND, NULL,
2882 makeA_Expr(OP, ">=", $1, $3),
2883 makeA_Expr(OP, "<=", $1, $5));
2885 | a_expr NOT BETWEEN AexprConst AND AexprConst
2887 $$ = makeA_Expr(OR, NULL,
2888 makeA_Expr(OP, "<", $1, $4),
2889 makeA_Expr(OP, ">", $1, $6));
2891 | a_expr IN { saved_In_Expr = $1; } '(' in_expr ')'
2893 | a_expr NOT IN { saved_In_Expr = $1; } '(' not_in_expr ')'
2896 { $$ = makeA_Expr(AND, NULL, $1, $3); }
2898 { $$ = makeA_Expr(OR, NULL, $1, $3); }
2900 { $$ = makeA_Expr(NOT, NULL, NULL, $2); }
2903 opt_indirection: '[' a_expr ']' opt_indirection
2905 A_Indices *ai = makeNode(A_Indices);
2910 | '[' a_expr ':' a_expr ']' opt_indirection
2912 A_Indices *ai = makeNode(A_Indices);
2921 expr_list: a_expr_or_null
2922 { $$ = lcons($1, NIL); }
2923 | expr_list ',' a_expr_or_null
2924 { $$ = lappend($1, $3); }
2925 | expr_list USING a_expr
2926 { $$ = lappend($1, $3); }
2929 extract_list: datetime FROM a_expr
2931 A_Const *n = makeNode(A_Const);
2932 n->val.type = T_String;
2933 n->val.val.str = $1;
2934 $$ = lappend(lcons((Node *)n,NIL), $3);
2940 position_list: position_expr IN position_expr
2941 { $$ = makeList($3, $1, -1); }
2946 position_expr: attr opt_indirection
2948 $1->indirection = $2;
2953 | '-' position_expr %prec UMINUS
2954 { $$ = makeA_Expr(OP, "-", NULL, $2); }
2955 | position_expr '+' position_expr
2956 { $$ = makeA_Expr(OP, "+", $1, $3); }
2957 | position_expr '-' position_expr
2958 { $$ = makeA_Expr(OP, "-", $1, $3); }
2959 | position_expr '/' position_expr
2960 { $$ = makeA_Expr(OP, "/", $1, $3); }
2961 | position_expr '*' position_expr
2962 { $$ = makeA_Expr(OP, "*", $1, $3); }
2964 { $$ = makeA_Expr(OP, "|", NULL, $2); }
2965 | position_expr TYPECAST Typename
2968 /* AexprConst can be either A_Const or ParamNo */
2969 if (nodeTag($1) == T_A_Const) {
2970 ((A_Const *)$1)->typename = $3;
2971 } else if (nodeTag($1) == T_Param) {
2972 ((ParamNo *)$1)->typename = $3;
2973 /* otherwise, try to transform to a function call */
2975 FuncCall *n = makeNode(FuncCall);
2976 n->funcname = $3->name;
2977 n->args = lcons($1,NIL);
2981 | CAST position_expr AS Typename
2984 /* AexprConst can be either A_Const or ParamNo */
2985 if (nodeTag($2) == T_A_Const) {
2986 ((A_Const *)$2)->typename = $4;
2987 } else if (nodeTag($2) == T_Param) {
2988 ((ParamNo *)$2)->typename = $4;
2989 /* otherwise, try to transform to a function call */
2991 FuncCall *n = makeNode(FuncCall);
2992 n->funcname = $4->name;
2993 n->args = lcons($2,NIL);
2997 | '(' position_expr ')'
2999 | position_expr Op position_expr
3000 { $$ = makeA_Expr(OP, $2, $1, $3); }
3002 { $$ = makeA_Expr(OP, $1, NULL, $2); }
3004 { $$ = makeA_Expr(OP, $2, $1, NULL); }
3007 /* could be a column name or a relation_name */
3008 Ident *n = makeNode(Ident);
3010 n->indirection = NULL;
3015 FuncCall *n = makeNode(FuncCall);
3020 | POSITION '(' position_list ')'
3022 FuncCall *n = makeNode(FuncCall);
3023 n->funcname = "strpos";
3027 | SUBSTRING '(' substr_list ')'
3029 FuncCall *n = makeNode(FuncCall);
3030 n->funcname = "substr";
3034 /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
3035 | TRIM '(' BOTH trim_list ')'
3037 FuncCall *n = makeNode(FuncCall);
3038 n->funcname = "btrim";
3042 | TRIM '(' LEADING trim_list ')'
3044 FuncCall *n = makeNode(FuncCall);
3045 n->funcname = "ltrim";
3049 | TRIM '(' TRAILING trim_list ')'
3051 FuncCall *n = makeNode(FuncCall);
3052 n->funcname = "rtrim";
3056 | TRIM '(' trim_list ')'
3058 FuncCall *n = makeNode(FuncCall);
3059 n->funcname = "btrim";
3063 | name '(' expr_list ')'
3065 FuncCall *n = makeNode(FuncCall);
3072 substr_list: expr_list substr_from substr_for
3074 $$ = nconc(nconc($1,$2),$3);
3080 substr_from: FROM expr_list
3084 A_Const *n = makeNode(A_Const);
3085 n->val.type = T_Integer;
3086 n->val.val.ival = 1;
3087 $$ = lcons((Node *)n,NIL);
3091 substr_for: FOR expr_list
3097 trim_list: a_expr FROM expr_list
3098 { $$ = lappend($3, $1); }
3107 elog(WARN,"IN (SUBSELECT) not yet implemented",NULL);
3114 in_expr_nodes: AexprConst
3115 { $$ = makeA_Expr(OP, "=", saved_In_Expr, $1); }
3116 | in_expr_nodes ',' AexprConst
3117 { $$ = makeA_Expr(OR, NULL, $1,
3118 makeA_Expr(OP, "=", saved_In_Expr, $3));
3122 not_in_expr: SubSelect
3124 elog(WARN,"NOT IN (SUBSELECT) not yet implemented",NULL);
3131 not_in_expr_nodes: AexprConst
3132 { $$ = makeA_Expr(OP, "<>", saved_In_Expr, $1); }
3133 | not_in_expr_nodes ',' AexprConst
3134 { $$ = makeA_Expr(AND, NULL, $1,
3135 makeA_Expr(OP, "<>", saved_In_Expr, $3));
3139 attr: relation_name '.' attrs
3141 $$ = makeNode(Attr);
3145 $$->indirection = NULL;
3149 $$ = makeNode(Attr);
3153 $$->indirection = NULL;
3158 { $$ = lcons(makeString($1), NIL); }
3159 | attrs '.' attr_name
3160 { $$ = lappend($1, makeString($3)); }
3162 { $$ = lappend($1, makeString("*")); }
3166 /*****************************************************************************
3170 *****************************************************************************/
3172 res_target_list: res_target_list ',' res_target_el
3173 { $$ = lappend($1,$3); }
3175 { $$ = lcons($1, NIL); }
3178 ResTarget *rt = makeNode(ResTarget);
3179 Attr *att = makeNode(Attr);
3181 att->paramNo = NULL;
3183 att->indirection = NIL;
3185 rt->indirection = NULL;
3186 rt->val = (Node *)att;
3187 $$ = lcons(rt, NIL);
3191 res_target_el: ColId opt_indirection '=' a_expr_or_null
3193 $$ = makeNode(ResTarget);
3195 $$->indirection = $2;
3196 $$->val = (Node *)$4;
3198 | attr opt_indirection
3200 $$ = makeNode(ResTarget);
3202 $$->indirection = $2;
3203 $$->val = (Node *)$1;
3205 | relation_name '.' '*'
3207 Attr *att = makeNode(Attr);
3209 att->paramNo = NULL;
3210 att->attrs = lcons(makeString("*"), NIL);
3211 att->indirection = NIL;
3212 $$ = makeNode(ResTarget);
3214 $$->indirection = NULL;
3215 $$->val = (Node *)att;
3220 ** target list for select.
3221 ** should get rid of the other but is still needed by the defunct retrieve into
3222 ** and update (uses a subset)
3224 res_target_list2: res_target_list2 ',' res_target_el2
3225 { $$ = lappend($1, $3); }
3227 { $$ = lcons($1, NIL); }
3230 /* AS is not optional because shift/red conflict with unary ops */
3231 res_target_el2: a_expr_or_null AS ColLabel
3233 $$ = makeNode(ResTarget);
3235 $$->indirection = NULL;
3236 $$->val = (Node *)$1;
3240 $$ = makeNode(ResTarget);
3242 $$->indirection = NULL;
3243 $$->val = (Node *)$1;
3245 | relation_name '.' '*'
3247 Attr *att = makeNode(Attr);
3249 att->paramNo = NULL;
3250 att->attrs = lcons(makeString("*"), NIL);
3251 att->indirection = NIL;
3252 $$ = makeNode(ResTarget);
3254 $$->indirection = NULL;
3255 $$->val = (Node *)att;
3259 Attr *att = makeNode(Attr);
3261 att->paramNo = NULL;
3263 att->indirection = NIL;
3264 $$ = makeNode(ResTarget);
3266 $$->indirection = NULL;
3267 $$->val = (Node *)att;
3271 opt_id: ColId { $$ = $1; }
3272 | /* EMPTY */ { $$ = NULL; }
3275 relation_name: SpecialRuleRelation
3278 StrNCpy(saved_relname, $1, NAMEDATALEN);
3282 /* disallow refs to variable system tables */
3283 if (strcmp(LogRelationName, $1) == 0
3284 || strcmp(VariableRelationName, $1) == 0)
3285 elog(WARN,"%s cannot be accessed by users",$1);
3288 StrNCpy(saved_relname, $1, NAMEDATALEN);
3292 database_name: ColId { $$ = $1; };
3293 access_method: Id { $$ = $1; };
3294 attr_name: ColId { $$ = $1; };
3295 class: Id { $$ = $1; };
3296 index_name: ColId { $$ = $1; };
3299 * Include date/time keywords as SQL92 extension.
3300 * Include TYPE as a SQL92 unreserved keyword. - thomas 1997-10-05
3302 name: ColId { $$ = $1; };
3304 file_name: Sconst { $$ = $1; };
3305 recipe_name: Id { $$ = $1; };
3308 * Include TRUE/FALSE for SQL3 support. - thomas 1997-10-24
3312 A_Const *n = makeNode(A_Const);
3313 n->val.type = T_Integer;
3314 n->val.val.ival = $1;
3319 A_Const *n = makeNode(A_Const);
3320 n->val.type = T_Float;
3321 n->val.val.dval = $1;
3326 A_Const *n = makeNode(A_Const);
3327 n->val.type = T_String;
3328 n->val.val.str = $1;
3333 A_Const *n = makeNode(A_Const);
3335 n->val.type = T_String;
3336 n->val.val.str = $2;
3340 { $$ = (Node *)$1; }
3343 A_Const *n = makeNode(A_Const);
3344 n->val.type = T_String;
3345 n->val.val.str = "t";
3350 A_Const *n = makeNode(A_Const);
3351 n->val.type = T_String;
3352 n->val.val.str = "f";
3359 $$ = makeNode(ParamNo);
3364 NumConst: Iconst { $$ = makeInteger($1); }
3365 | FCONST { $$ = makeFloat($1); }
3368 Iconst: ICONST { $$ = $1; };
3369 Sconst: SCONST { $$ = $1; };
3371 /* Column and type identifier
3372 * Does not include explicit datetime types
3373 * since these must be decoupled in Typename syntax.
3374 * Use ColId for most identifiers. - thomas 1997-10-21
3376 Id: IDENT { $$ = $1; };
3378 /* Column identifier
3379 * Include date/time keywords as SQL92 extension.
3380 * Include TYPE as a SQL92 unreserved keyword. - thomas 1997-10-05
3381 * Add other keywords. Note that as the syntax expands,
3382 * some of these keywords will have to be removed from this
3383 * list due to shift/reduce conflicts in yacc. If so, move
3384 * down to the ColLabel entity. - thomas 1997-11-06
3386 ColId: Id { $$ = $1; }
3387 | datetime { $$ = $1; }
3388 | ACTION { $$ = "action"; }
3389 | DATABASE { $$ = "database"; }
3390 | DELIMITERS { $$ = "delimiters"; }
3391 | FUNCTION { $$ = "function"; }
3392 | INDEX { $$ = "index"; }
3393 | KEY { $$ = "key"; }
3394 | LANGUAGE { $$ = "language"; }
3395 | LOCATION { $$ = "location"; }
3396 | MATCH { $$ = "match"; }
3397 | OPERATOR { $$ = "operator"; }
3398 | OPTION { $$ = "option"; }
3399 | PRIVILEGES { $$ = "privileges"; }
3400 | RECIPE { $$ = "recipe"; }
3401 | TIME { $$ = "time"; }
3402 | TRIGGER { $$ = "trigger"; }
3403 | TYPE_P { $$ = "type"; }
3404 | VERSION { $$ = "version"; }
3405 | ZONE { $$ = "zone"; }
3409 * Allowed labels in "AS" clauses.
3410 * Include TRUE/FALSE SQL3 reserved words for Postgres backward
3411 * compatibility. Cannot allow this for column names since the
3412 * syntax would not distinguish between the constant value and
3413 * a column name. - thomas 1997-10-24
3414 * Add other keywords to this list. Note that they appear here
3415 * rather than in ColId if there was a shift/reduce conflict
3416 * when used as a full identifier. - thomas 1997-11-06
3418 ColLabel: ColId { $$ = $1; }
3419 | ARCHIVE { $$ = "archive"; }
3420 | CLUSTER { $$ = "cluster"; }
3421 | CONSTRAINT { $$ = "constraint"; }
3422 | CROSS { $$ = "cross"; }
3423 | FOREIGN { $$ = "foreign"; }
3424 | GROUP { $$ = "group"; }
3425 | LOAD { $$ = "load"; }
3426 | ORDER { $$ = "order"; }
3427 | POSITION { $$ = "position"; }
3428 | PRECISION { $$ = "precision"; }
3429 | TABLE { $$ = "table"; }
3430 | TRANSACTION { $$ = "transaction"; }
3431 | TRUE_P { $$ = "true"; }
3432 | FALSE_P { $$ = "false"; }
3435 SpecialRuleRelation: CURRENT
3440 elog(WARN,"CURRENT used in non-rule query",NULL);
3447 elog(WARN,"NEW used in non-rule query",NULL);
3456 static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr)
3458 A_Expr *a = makeNode(A_Expr);
3467 static Node *makeIndexable(char *opname, Node *lexpr, Node *rexpr)
3469 Node *result = NULL;
3471 /* we do this so indexes can be used */
3472 if (strcmp(opname,"~") == 0 ||
3473 strcmp(opname,"~*") == 0)
3475 if (nodeTag(rexpr) == T_A_Const &&
3476 ((A_Const *)rexpr)->val.type == T_String &&
3477 ((A_Const *)rexpr)->val.val.str[0] == '^')
3479 A_Const *n = (A_Const *)rexpr;
3480 char *match_least = palloc(strlen(n->val.val.str)+2);
3481 char *match_most = palloc(strlen(n->val.val.str)+2);
3482 int pos, match_pos=0;
3484 /* skip leading ^ */
3485 for (pos = 1; n->val.val.str[pos]; pos++)
3487 if (n->val.val.str[pos] == '.' ||
3488 n->val.val.str[pos] == '?' ||
3489 n->val.val.str[pos] == '*' ||
3490 n->val.val.str[pos] == '[' ||
3491 n->val.val.str[pos] == '$' ||
3492 (strcmp(opname,"~*") == 0 && isalpha(n->val.val.str[pos])))
3494 if (n->val.val.str[pos] == '\\')
3496 match_least[match_pos] = n->val.val.str[pos];
3497 match_most[match_pos++] = n->val.val.str[pos];
3502 A_Const *least = makeNode(A_Const);
3503 A_Const *most = makeNode(A_Const);
3505 /* make strings to be used in index use */
3506 match_least[match_pos] = '\0';
3507 match_most[match_pos] = '\377';
3508 match_most[match_pos+1] = '\0';
3509 least->val.type = T_String;
3510 least->val.val.str = match_least;
3511 most->val.type = T_String;
3512 most->val.val.str = match_most;
3513 result = makeA_Expr(AND, NULL,
3514 makeA_Expr(OP, "~", lexpr, rexpr),
3515 makeA_Expr(AND, NULL,
3516 makeA_Expr(OP, ">=", lexpr, (Node *)least),
3517 makeA_Expr(OP, "<=", lexpr, (Node *)most)));
3521 else if (strcmp(opname,"~~") == 0)
3523 if (nodeTag(rexpr) == T_A_Const &&
3524 ((A_Const *)rexpr)->val.type == T_String)
3526 A_Const *n = (A_Const *)rexpr;
3527 char *match_least = palloc(strlen(n->val.val.str)+2);
3528 char *match_most = palloc(strlen(n->val.val.str)+2);
3529 int pos, match_pos=0;
3531 for (pos = 0; n->val.val.str[pos]; pos++)
3533 if ((n->val.val.str[pos] == '%' &&
3534 n->val.val.str[pos+1] != '%') ||
3535 (n->val.val.str[pos] == '_' &&
3536 n->val.val.str[pos+1] != '_'))
3538 if (n->val.val.str[pos] == '%' ||
3539 n->val.val.str[pos] == '_' ||
3540 n->val.val.str[pos] == '\\')
3542 match_least[match_pos] = n->val.val.str[pos];
3543 match_most[match_pos++] = n->val.val.str[pos];
3548 A_Const *least = makeNode(A_Const);
3549 A_Const *most = makeNode(A_Const);
3551 /* make strings to be used in index use */
3552 match_least[match_pos] = '\0';
3553 match_most[match_pos] = '\377';
3554 match_most[match_pos+1] = '\0';
3555 least->val.type = T_String;
3556 least->val.val.str = match_least;
3557 most->val.type = T_String;
3558 most->val.val.str = match_most;
3559 result = makeA_Expr(AND, NULL,
3560 makeA_Expr(OP, "~~", lexpr, rexpr),
3561 makeA_Expr(AND, NULL,
3562 makeA_Expr(OP, ">=", lexpr, (Node *)least),
3563 makeA_Expr(OP, "<=", lexpr, (Node *)most)));
3569 result = makeA_Expr(OP, opname, lexpr, rexpr);
3571 } /* makeIndexable() */
3575 * Convert alternate type names to internal Postgres types.
3576 * Do not convert "float", since that is handled elsewhere
3577 * for FLOAT(p) syntax.
3580 xlateSqlType(char *name)
3582 if (!strcasecmp(name,"int")
3583 || !strcasecmp(name,"integer"))
3585 else if (!strcasecmp(name, "smallint"))
3587 else if (!strcasecmp(name, "real"))
3589 else if (!strcasecmp(name, "interval"))
3591 else if (!strcasecmp(name, "boolean"))
3595 } /* xlateSqlName() */
3598 void parser_init(Oid *typev, int nargs)
3600 QueryIsRule = FALSE;
3601 saved_relname[0]= '\0';
3602 saved_In_Expr = NULL;
3604 param_type_init(typev, nargs);
3608 /* FlattenStringList()
3609 * Traverse list of string nodes and convert to a single string.
3610 * Used for reconstructing string form of complex expressions.
3612 * Allocate at least one byte for terminator.
3615 FlattenStringList(List *list)
3623 nlist = length(list);
3626 v = (Value *)lfirst(l);
3633 s = (char*) palloc(len+1);
3638 v = (Value *)lfirst(l);
3642 if (l != NIL) strcat(s," ");
3647 printf( "flattened string is \"%s\"\n", s);
3651 } /* FlattenStringList() */
3654 /* makeConstantList()
3655 * Convert constant value node into string node.
3658 makeConstantList( A_Const *n)
3660 char *defval = NULL;
3661 if (nodeTag(n) != T_A_Const) {
3662 elog(WARN,"Cannot handle non-constant parameter",NULL);
3664 } else if (n->val.type == T_Float) {
3665 defval = (char*) palloc(20+1);
3666 sprintf( defval, "%g", n->val.val.dval);
3668 } else if (n->val.type == T_Integer) {
3669 defval = (char*) palloc(20+1);
3670 sprintf( defval, "%ld", n->val.val.ival);
3672 } else if (n->val.type == T_String) {
3673 defval = (char*) palloc(strlen( ((A_Const *) n)->val.val.str) + 3);
3674 strcpy( defval, "'");
3675 strcat( defval, ((A_Const *) n)->val.val.str);
3676 strcat( defval, "'");
3679 elog(WARN,"Internal error in makeConstantList(): cannot encode node",NULL);
3683 printf( "AexprConst argument is \"%s\"\n", defval);
3686 return( lcons( makeString(defval), NIL));
3687 } /* makeConstantList() */
3691 * Check input string for non-lowercase/non-numeric characters.
3692 * Returns either input string or input surrounded by double quotes.
3699 for (cp = rawid; *cp != '\0'; cp++)
3700 if (! (islower(*cp) || isdigit(*cp) || (*cp == '_'))) break;
3703 cp = palloc(strlen(rawid)+1);
3712 printf("fmtId- %sconvert %s to %s\n", ((cp == rawid)? "do not ": ""), rawid, cp);
3721 * keep enough information around fill out the type of param nodes
3722 * used in postquel functions
3725 param_type_init(Oid *typev, int nargs)
3727 pfunc_num_args = nargs;
3728 param_type_info = typev;
3731 Oid param_type(int t)
3733 if ((t > pfunc_num_args) || (t == 0))
3735 return param_type_info[t - 1];