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.68 1997/11/17 16:37:24 thomas 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 "parser/catalog_utils.h"
43 #include "parser/parse_query.h"
44 #include "storage/smgr.h"
45 #include "utils/acl.h"
46 #include "catalog/catname.h"
47 #include "utils/elog.h"
48 #include "access/xact.h"
50 static char saved_relname[NAMEDATALEN]; /* need this for complex attributes */
51 static bool QueryIsRule = FALSE;
52 static Node *saved_In_Expr;
53 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);
69 /* old versions of flex define this as a macro */
90 ConstraintDef *constrdef;
94 SortGroupBy *sortgroupby;
111 AddAttrStmt, ClosePortalStmt,
112 CopyStmt, CreateStmt, CreateSeqStmt, DefineStmt, DestroyStmt,
113 ExtendStmt, FetchStmt, GrantStmt, CreateTrigStmt, DropTrigStmt,
114 CreatePLangStmt, DropPLangStmt,
115 IndexStmt, ListenStmt, OptimizableStmt,
116 ProcedureStmt, PurgeStmt,
117 RecipeStmt, RemoveAggrStmt, RemoveOperStmt, RemoveFuncStmt, RemoveStmt,
118 RenameStmt, RevokeStmt, RuleStmt, TransactionStmt, ViewStmt, LoadStmt,
119 CreatedbStmt, DestroydbStmt, VacuumStmt, RetrieveStmt, CursorStmt,
120 ReplaceStmt, AppendStmt, NotifyStmt, DeleteStmt, ClusterStmt,
121 ExplainStmt, VariableSetStmt, VariableShowStmt, VariableResetStmt
123 %type <str> opt_database, location
125 %type <node> SubSelect
126 %type <str> join_expr, join_outer, join_spec
127 %type <boolean> TriggerActionTime, TriggerForSpec, PLangTrusted
129 %type <str> TriggerEvents, TriggerFuncArg
131 %type <str> relation_name, copy_file_name, copy_delimiter, def_name,
132 database_name, access_method_clause, access_method, attr_name,
133 class, index_name, name, file_name, recipe_name, aggr_argtype
135 %type <str> opt_id, opt_portal_name,
136 before_clause, after_clause, all_Op, MathOp, opt_name, opt_unique,
137 result, OptUseOp, opt_class, opt_range_start, opt_range_end,
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, archive_type, OptArchiveType, OptArchiveLocation,
169 def_type, opt_direction, remove_type, opt_column, event
171 %type <ival> OptLocation, fetch_how_many
173 %type <list> OptSeqList
174 %type <defelt> OptSeqElem
176 %type <dstmt> def_rest
177 %type <pstmt> purge_quals
178 %type <astmt> insert_rest
180 %type <coldef> columnDef, alter_clause
181 %type <defelt> def_elem
182 %type <node> def_arg, columnElem, where_clause,
183 a_expr, a_expr_or_null, AexprConst,
184 in_expr, in_expr_nodes, not_in_expr, not_in_expr_nodes,
186 %type <value> NumConst
187 %type <attr> event_object, attr
188 %type <sortgroupby> groupby
189 %type <sortgroupby> sortby
190 %type <ielem> index_elem, func_index
191 %type <range> from_val
192 %type <relexp> relation_expr
193 %type <trange> time_range
194 %type <target> res_target_el, res_target_el2
195 %type <paramno> ParamNo
197 %type <typnam> Typename, opt_type, Array, Generic, Character, Datetime, Numeric
198 %type <str> generic, character, datetime
199 %type <str> opt_charset, opt_collate
200 %type <str> opt_float, opt_numeric, opt_decimal
201 %type <boolean> opt_varying, opt_timezone
205 %type <str> Id, date, var_value, zone_value
206 %type <str> ColId, ColLabel
208 %type <constrdef> ConstraintElem, ConstraintDef
210 %type <list> constraint_elem
211 %type <list> default_expr
212 %type <str> opt_default
213 %type <boolean> opt_constraint
214 %type <list> key_actions, key_action
215 %type <str> key_match, key_reference
218 * If you make any token changes, remember to:
219 * - use "yacc -d" and update parse.h
220 * - update the keyword table in parser/keywords.c
223 /* Reserved word tokens
224 * SQL92 syntax has many type-specific constructs.
225 * So, go ahead and make these types reserved words,
226 * and call-out the syntax explicitly.
227 * This gets annoying when trying to also retain Postgres' nice
228 * type-extensible features, but we don't really have a choice.
229 * - thomas 1997-10-11
232 /* Keywords (in SQL92 reserved words) */
233 %token ACTION, ADD, ALL, ALTER, AND, AS, ASC,
234 BEGIN_TRANS, BETWEEN, BOTH, BY,
235 CASCADE, CAST, CHAR, CHARACTER, CHECK, CLOSE, COLLATE, COLUMN, COMMIT,
236 CONSTRAINT, CREATE, CROSS, CURRENT, CURRENT_DATE, CURRENT_TIME,
237 CURRENT_TIMESTAMP, CURRENT_USER, CURSOR,
238 DAY_P, DECIMAL, DECLARE, DEFAULT, DELETE, DESC, DISTINCT, DOUBLE, DROP,
239 END_TRANS, EXECUTE, EXISTS, EXTRACT,
240 FETCH, FLOAT, FOR, FOREIGN, FROM, FULL,
241 GRANT, GROUP, HAVING, HOUR_P,
242 IN, INNER_P, INSERT, INTERVAL, INTO, IS,
243 JOIN, KEY, LANGUAGE, LEADING, LEFT, LIKE, LOCAL,
244 MATCH, MINUTE_P, MONTH_P,
245 NATIONAL, NATURAL, NCHAR, NO, NOT, NOTIFY, NOTNULL, NULL_P, NUMERIC,
246 ON, OPTION, OR, ORDER, OUTER_P,
247 PARTIAL, POSITION, PRECISION, PRIMARY, PRIVILEGES, PROCEDURE, PUBLIC,
248 REFERENCES, REVOKE, RIGHT, ROLLBACK,
249 SECOND_P, SELECT, SET, SUBSTRING,
250 TABLE, TIME, TIMESTAMP, TO, TRAILING, TRANSACTION, TRIM,
251 UNION, UNIQUE, UPDATE, USING,
252 VALUES, VARCHAR, VARYING, VERBOSE, VERSION, VIEW,
253 WHERE, WITH, WORK, YEAR_P, ZONE
255 /* Keywords (in SQL3 reserved words) */
256 %token FALSE_P, TRIGGER, TRUE_P
258 /* Keywords (in SQL92 non-reserved words) */
261 /* Keywords for Postgres support (not in SQL92 reserved words) */
262 %token ABORT_TRANS, ACL, AFTER, AGGREGATE, ANALYZE,
263 APPEND, ARCHIVE, ARCH_STORE,
264 BACKWARD, BEFORE, BINARY, CHANGE, CLUSTER, COPY,
265 DATABASE, DELIMITERS, DO, EXPLAIN, EXTEND,
266 FORWARD, FUNCTION, HANDLER, HEAVY,
267 INDEX, INHERITS, INSTEAD, ISNULL,
268 LANCOMPILER, LIGHT, LISTEN, LOAD, LOCATION, MERGE, MOVE,
269 NEW, NONE, NOTHING, OIDS, OPERATOR, PROCEDURAL, PURGE,
270 RECIPE, RENAME, REPLACE, RESET, RETRIEVE, RETURNS, RULE,
271 SEQUENCE, SETOF, SHOW, STDIN, STDOUT, STORE, TRUSTED,
272 VACUUM, VERBOSE, VERSION
274 /* Special keywords, not in the query language - see the "lex" file */
275 %token <str> IDENT, SCONST, Op
276 %token <ival> ICONST, PARAM
279 /* these are not real. they are here so that they get generated as #define's*/
296 %left '|' /* this is the relation union op, not logical or */
297 /* Unary Operators */
299 %left ';' /* end of statement or natural log */
312 { parsetree = lcons($1,NIL); }
315 stmtmulti: stmtmulti stmt ';'
316 { $$ = lappend($1, $2); }
318 { $$ = lappend($1, $2); }
320 { $$ = lcons($1,NIL); }
364 /*****************************************************************************
366 * Set PG internal variable
367 * SET name TO 'var_value'
368 * Include SQL92 syntax (thomas 1997-10-22):
369 * SET TIME ZONE 'var_value'
371 *****************************************************************************/
373 VariableSetStmt: SET ColId TO var_value
375 VariableSetStmt *n = makeNode(VariableSetStmt);
380 | SET ColId '=' var_value
382 VariableSetStmt *n = makeNode(VariableSetStmt);
387 | SET TIME ZONE zone_value
389 VariableSetStmt *n = makeNode(VariableSetStmt);
390 n->name = "timezone";
396 var_value: Sconst { $$ = $1; }
397 | DEFAULT { $$ = NULL; }
400 zone_value: Sconst { $$ = $1; }
401 | DEFAULT { $$ = NULL; }
402 | LOCAL { $$ = "default"; }
405 VariableShowStmt: SHOW ColId
407 VariableShowStmt *n = makeNode(VariableShowStmt);
413 VariableShowStmt *n = makeNode(VariableShowStmt);
414 n->name = "timezone";
419 VariableResetStmt: RESET ColId
421 VariableResetStmt *n = makeNode(VariableResetStmt);
427 VariableResetStmt *n = makeNode(VariableResetStmt);
428 n->name = "timezone";
434 /*****************************************************************************
437 * addattr ( attr1 = type1 .. attrn = typen ) to <relname> [*]
439 *****************************************************************************/
441 AddAttrStmt: ALTER TABLE relation_name opt_inh_star alter_clause
443 AddAttrStmt *n = makeNode(AddAttrStmt);
451 alter_clause: ADD opt_column columnDef
455 | ADD '(' tableElementList ')'
457 ColumnDef *lp = lfirst($3);
460 elog(WARN,"ALTER TABLE/ADD() allows one column only",NULL);
463 | DROP opt_column ColId
464 { elog(WARN,"ALTER TABLE/DROP COLUMN not yet implemented",NULL); }
465 | ALTER opt_column ColId SET opt_default
466 { elog(WARN,"ALTER TABLE/ALTER COLUMN/SET DEFAULT not yet implemented",NULL); }
467 | ALTER opt_column ColId DROP DEFAULT
468 { elog(WARN,"ALTER TABLE/ALTER COLUMN/DROP DEFAULT not yet implemented",NULL); }
470 { elog(WARN,"ALTER TABLE/ADD CONSTRAINT not yet implemented",NULL); }
473 columnDef: ColId Typename opt_default opt_constraint
475 $$ = makeNode(ColumnDef);
479 $$->is_not_null = $4;
483 opt_default: DEFAULT default_expr
485 $$ = FlattenStringList($2);
487 | /*EMPTY*/ { $$ = NULL; }
490 default_expr: AexprConst
491 { $$ = makeConstantList((A_Const *) $1); }
493 { $$ = lcons( makeString("NULL"), NIL); }
494 | '-' default_expr %prec UMINUS
495 { $$ = lcons( makeString( "-"), $2); }
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 { $$ = nconc( $1, lcons( makeString( "/"), $3)); }
502 | default_expr '*' default_expr
503 { $$ = nconc( $1, lcons( makeString( "*"), $3)); }
504 | default_expr '=' default_expr
505 { elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
506 | default_expr '<' default_expr
507 { elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
508 | default_expr '>' default_expr
509 { elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
511 { $$ = lcons( makeString( ":"), $2); }
513 { $$ = lcons( makeString( ";"), $2); }
515 { $$ = lcons( makeString( "|"), $2); }
516 | default_expr TYPECAST Typename
518 $3->name = fmtId($3->name);
519 $$ = nconc( lcons( makeString( "CAST"), $1), makeList( makeString("AS"), $3, -1));
521 | CAST default_expr AS Typename
523 $4->name = fmtId($4->name);
524 $$ = nconc( lcons( makeString( "CAST"), $2), makeList( makeString("AS"), $4, -1));
526 | '(' default_expr ')'
527 { $$ = lappend( lcons( makeString( "("), $2), makeString( ")")); }
528 | name '(' default_expr ')'
530 $$ = makeList( makeString($1), makeString("("), -1);
532 $$ = lappend( $$, makeString(")"));
536 $$ = makeList( makeString($1), makeString("("), -1);
537 $$ = lappend( $$, makeString(")"));
539 | default_expr Op default_expr
541 if (!strcmp("<=", $2) || !strcmp(">=", $2))
542 elog(WARN,"boolean expressions not supported in DEFAULT",NULL);
543 $$ = nconc( $1, lcons( makeString( $2), $3));
546 { $$ = lcons( makeString( $1), $2); }
548 { $$ = lappend( $1, makeString( $2)); }
549 /* XXX - thomas 1997-10-07 v6.2 function-specific code to be changed */
551 { $$ = lcons( makeString( "date( 'current'::datetime + '0 sec')"), NIL); }
553 { $$ = lcons( makeString( "'now'::time"), NIL); }
554 | CURRENT_TIME '(' Iconst ')'
557 elog(NOTICE,"CURRENT_TIME(p) precision must be zero",NULL);
558 $$ = lcons( makeString( "'now'::time"), NIL);
561 { $$ = lcons( makeString( "now()"), NIL); }
562 | CURRENT_TIMESTAMP '(' Iconst ')'
565 elog(NOTICE,"CURRENT_TIMESTAMP(p) precision must be zero",NULL);
566 $$ = lcons( makeString( "now()"), NIL);
569 { $$ = lcons( makeString( "CURRENT_USER"), NIL); }
572 opt_constraint: NOT NULL_P { $$ = TRUE; }
573 | NOTNULL { $$ = TRUE; }
576 elog(WARN,"CREATE TABLE/UNIQUE not yet implemented",NULL);
581 elog(WARN,"CREATE TABLE/PRIMARY KEY not yet implemented",NULL);
584 | REFERENCES ColId opt_column_list key_match key_actions
586 elog(WARN,"CREATE TABLE/FOREIGN KEY not yet implemented",NULL);
589 | /* EMPTY */ { $$ = FALSE; }
593 /*****************************************************************************
598 *****************************************************************************/
600 ClosePortalStmt: CLOSE opt_id
602 ClosePortalStmt *n = makeNode(ClosePortalStmt);
609 /*****************************************************************************
612 * COPY [BINARY] <relname> FROM/TO
613 * [USING DELIMITERS <delimiter>]
615 *****************************************************************************/
617 CopyStmt: COPY opt_binary relation_name opt_with_copy copy_dirn copy_file_name copy_delimiter
619 CopyStmt *n = makeNode(CopyStmt);
637 * copy_file_name NULL indicates stdio is used. Whether stdin or stdout is
638 * used depends on the direction. (It really doesn't make sense to copy from
639 * stdout. We silently correct the "typo". - AY 9/94
641 copy_file_name: Sconst { $$ = $1; }
642 | STDIN { $$ = NULL; }
643 | STDOUT { $$ = NULL; }
646 opt_binary: BINARY { $$ = TRUE; }
647 | /*EMPTY*/ { $$ = FALSE; }
650 opt_with_copy: WITH OIDS { $$ = TRUE; }
651 | /* EMPTY */ { $$ = FALSE; }
655 * the default copy delimiter is tab but the user can configure it
657 copy_delimiter: USING DELIMITERS Sconst { $$ = $3;}
658 | /* EMPTY */ { $$ = "\t"; }
662 /*****************************************************************************
667 *****************************************************************************/
669 CreateStmt: CREATE TABLE relation_name '(' OptTableElementList ')'
670 OptInherit OptConstraint OptArchiveType OptLocation
673 CreateStmt *n = makeNode(CreateStmt);
685 OptTableElementList: tableElementList { $$ = $1; }
686 | /* EMPTY */ { $$ = NULL; }
690 tableElementList ',' columnDef
691 { $$ = lappend($1, $3); }
693 { $$ = lcons($1, NIL); }
697 OptArchiveType: ARCHIVE '=' archive_type { $$ = $3; }
698 | /*EMPTY*/ { $$ = ARCH_NONE; }
701 archive_type: HEAVY { $$ = ARCH_HEAVY; }
702 | LIGHT { $$ = ARCH_LIGHT; }
703 | NONE { $$ = ARCH_NONE; }
706 OptLocation: STORE '=' Sconst
712 OptArchiveLocation: ARCH_STORE '=' Sconst
718 OptInherit: INHERITS '(' relation_name_list ')' { $$ = $3; }
719 | /*EMPTY*/ { $$ = NIL; }
722 OptConstraint: ConstraintList { $$ = $1; }
723 | /*EMPTY*/ { $$ = NULL; }
727 ConstraintList ',' ConstraintElem
728 { $$ = lappend($1, $3); }
730 { $$ = lcons($1, NIL); }
734 CONSTRAINT name ConstraintDef
736 $3->name = fmtId($2);
739 | ConstraintDef { $$ = $1; }
742 ConstraintDef: CHECK constraint_elem
744 ConstraintDef *constr = palloc (sizeof(ConstraintDef));
745 constr->type = CONSTR_CHECK;
747 constr->def = FlattenStringList($2);
750 | UNIQUE '(' columnList ')'
751 { elog(WARN,"CREATE TABLE/UNIQUE not yet implemented",NULL); }
752 | PRIMARY KEY '(' columnList ')'
753 { elog(WARN,"CREATE TABLE/PRIMARY KEY not yet implemented",NULL); }
754 | FOREIGN KEY '(' columnList ')' REFERENCES ColId opt_column_list key_match key_actions
755 { elog(WARN,"CREATE TABLE/FOREIGN KEY not yet implemented",NULL); }
758 constraint_elem: AexprConst
759 { $$ = makeConstantList((A_Const *) $1); }
761 { $$ = lcons( makeString("NULL"), NIL); }
764 $$ = lcons( makeString(fmtId($1)), NIL);
766 | '-' constraint_elem %prec UMINUS
767 { $$ = lcons( makeString( "-"), $2); }
768 | constraint_elem '+' constraint_elem
769 { $$ = nconc( $1, lcons( makeString( "+"), $3)); }
770 | constraint_elem '-' constraint_elem
771 { $$ = nconc( $1, lcons( makeString( "-"), $3)); }
772 | constraint_elem '/' constraint_elem
773 { $$ = nconc( $1, lcons( makeString( "/"), $3)); }
774 | constraint_elem '*' constraint_elem
775 { $$ = nconc( $1, lcons( makeString( "*"), $3)); }
776 | constraint_elem '=' constraint_elem
777 { $$ = nconc( $1, lcons( makeString( "="), $3)); }
778 | constraint_elem '<' constraint_elem
779 { $$ = nconc( $1, lcons( makeString( "<"), $3)); }
780 | constraint_elem '>' constraint_elem
781 { $$ = nconc( $1, lcons( makeString( ">"), $3)); }
782 | ':' constraint_elem
783 { $$ = lcons( makeString( ":"), $2); }
784 | ';' constraint_elem
785 { $$ = lcons( makeString( ";"), $2); }
786 | '|' constraint_elem
787 { $$ = lcons( makeString( "|"), $2); }
788 | constraint_elem TYPECAST Typename
790 $3->name = fmtId($3->name);
791 $$ = nconc( lcons( makeString( "CAST"), $1), makeList( makeString("AS"), $3, -1));
793 | CAST constraint_elem AS Typename
795 $4->name = fmtId($4->name);
796 $$ = nconc( lcons( makeString( "CAST"), $2), makeList( makeString("AS"), $4, -1));
798 | '(' constraint_elem ')'
799 { $$ = lappend( lcons( makeString( "("), $2), makeString( ")")); }
800 | name '(' constraint_elem ')'
802 $$ = makeList( makeString($1), makeString("("), -1);
804 $$ = lappend( $$, makeString(")"));
806 | constraint_elem Op constraint_elem
807 { $$ = nconc( $1, lcons( makeString( $2), $3)); }
808 | constraint_elem AND constraint_elem
809 { $$ = nconc( $1, lcons( makeString( "AND"), $3)); }
810 | constraint_elem OR constraint_elem
811 { $$ = nconc( $1, lcons( makeString( "OR"), $3)); }
813 { $$ = lcons( makeString( $1), $2); }
815 { $$ = lappend( $1, makeString( $2)); }
816 | constraint_elem IS TRUE_P
817 { $$ = lappend( $1, makeString( "IS TRUE")); }
818 | constraint_elem IS FALSE_P
819 { $$ = lappend( $1, makeString( "IS FALSE")); }
820 | constraint_elem IS NOT TRUE_P
821 { $$ = lappend( $1, makeString( "IS NOT TRUE")); }
822 | constraint_elem IS NOT FALSE_P
823 { $$ = lappend( $1, makeString( "IS NOT FALSE")); }
826 key_match: MATCH FULL { $$ = NULL; }
827 | MATCH PARTIAL { $$ = NULL; }
828 | /*EMPTY*/ { $$ = NULL; }
831 key_actions: key_action key_action { $$ = NIL; }
832 | key_action { $$ = NIL; }
833 | /*EMPTY*/ { $$ = NIL; }
836 key_action: ON DELETE key_reference { $$ = NIL; }
837 | ON UPDATE key_reference { $$ = NIL; }
840 key_reference: NO ACTION { $$ = NULL; }
841 | CASCADE { $$ = NULL; }
842 | SET DEFAULT { $$ = NULL; }
843 | SET NULL_P { $$ = NULL; }
847 /*****************************************************************************
850 * CREATE SEQUENCE seqname
852 *****************************************************************************/
854 CreateSeqStmt: CREATE SEQUENCE relation_name OptSeqList
856 CreateSeqStmt *n = makeNode(CreateSeqStmt);
864 OptSeqList OptSeqElem
865 { $$ = lappend($1, $2); }
869 OptSeqElem: IDENT NumConst
871 $$ = makeNode(DefElem);
873 $$->arg = (Node *)$2;
877 $$ = makeNode(DefElem);
879 $$->arg = (Node *)NULL;
883 /*****************************************************************************
886 * CREATE PROCEDURAL LANGUAGE ...
887 * DROP PROCEDURAL LANGUAGE ...
889 *****************************************************************************/
891 CreatePLangStmt: CREATE PLangTrusted PROCEDURAL LANGUAGE Sconst
892 HANDLER def_name LANCOMPILER Sconst
894 CreatePLangStmt *n = makeNode(CreatePLangStmt);
903 PLangTrusted: TRUSTED { $$ = TRUE; }
906 DropPLangStmt: DROP PROCEDURAL LANGUAGE Sconst
908 DropPLangStmt *n = makeNode(DropPLangStmt);
914 /*****************************************************************************
920 *****************************************************************************/
922 CreateTrigStmt: CREATE TRIGGER name TriggerActionTime TriggerEvents ON
923 relation_name TriggerForSpec EXECUTE PROCEDURE
924 name '(' TriggerFuncArgs ')'
926 CreateTrigStmt *n = makeNode(CreateTrigStmt);
933 memcpy (n->actions, $5, 4);
938 TriggerActionTime: BEFORE { $$ = TRUE; }
939 | AFTER { $$ = FALSE; }
942 TriggerEvents: TriggerOneEvent
944 char *e = palloc (4);
945 e[0] = $1; e[1] = 0; $$ = e;
947 | TriggerOneEvent OR TriggerOneEvent
949 char *e = palloc (4);
950 e[0] = $1; e[1] = $3; e[2] = 0; $$ = e;
952 | TriggerOneEvent OR TriggerOneEvent OR TriggerOneEvent
954 char *e = palloc (4);
955 e[0] = $1; e[1] = $3; e[2] = $5; e[3] = 0;
960 TriggerOneEvent: INSERT { $$ = 'i'; }
961 | DELETE { $$ = 'd'; }
962 | UPDATE { $$ = 'u'; }
965 TriggerForSpec: FOR name name
967 if ( strcmp ($2, "each") != 0 )
968 elog(WARN,"parser: syntax error near %s",$2);
969 if ( strcmp ($3, "row") == 0 )
971 else if ( strcmp ($3, "statement") == 0 )
974 elog(WARN,"parser: syntax error near %s",$3);
978 TriggerFuncArgs: TriggerFuncArg
979 { $$ = lcons($1, NIL); }
980 | TriggerFuncArgs ',' TriggerFuncArg
981 { $$ = lappend($1, $3); }
986 TriggerFuncArg: ICONST
988 char *s = (char *) palloc (256);
989 sprintf (s, "%d", $1);
994 char *s = (char *) palloc (256);
995 sprintf (s, "%g", $1);
998 | Sconst { $$ = $1; }
1002 DropTrigStmt: DROP TRIGGER name ON relation_name
1004 DropTrigStmt *n = makeNode(DropTrigStmt);
1012 /*****************************************************************************
1015 * define (type,operator,aggregate)
1017 *****************************************************************************/
1019 DefineStmt: CREATE def_type def_rest
1026 def_rest: def_name definition
1028 $$ = makeNode(DefineStmt);
1030 $$->definition = $2;
1034 def_type: OPERATOR { $$ = OPERATOR; }
1035 | Type { $$ = TYPE_P; }
1036 | AGGREGATE { $$ = AGGREGATE; }
1039 def_name: PROCEDURE { $$ = "procedure"; }
1040 | JOIN { $$ = "join"; }
1041 | ColId { $$ = $1; }
1042 | MathOp { $$ = $1; }
1046 definition: '(' def_list ')' { $$ = $2; }
1049 def_list: def_elem { $$ = lcons($1, NIL); }
1050 | def_list ',' def_elem { $$ = lappend($1, $3); }
1053 def_elem: def_name '=' def_arg
1055 $$ = makeNode(DefElem);
1057 $$->arg = (Node *)$3;
1061 $$ = makeNode(DefElem);
1063 $$->arg = (Node *)NULL;
1065 | DEFAULT '=' def_arg
1067 $$ = makeNode(DefElem);
1068 $$->defname = "default";
1069 $$->arg = (Node *)$3;
1073 def_arg: ColId { $$ = (Node *)makeString($1); }
1074 | all_Op { $$ = (Node *)makeString($1); }
1075 | NumConst { $$ = (Node *)$1; /* already a Value */ }
1076 | Sconst { $$ = (Node *)makeString($1); }
1079 TypeName *n = makeNode(TypeName);
1082 n->arrayBounds = NULL;
1085 | DOUBLE { $$ = (Node *)makeString("double"); }
1089 /*****************************************************************************
1092 * destroy <relname1> [, <relname2> .. <relnameN> ]
1094 *****************************************************************************/
1096 DestroyStmt: DROP TABLE relation_name_list
1098 DestroyStmt *n = makeNode(DestroyStmt);
1100 n->sequence = FALSE;
1103 | DROP SEQUENCE relation_name_list
1105 DestroyStmt *n = makeNode(DestroyStmt);
1113 /*****************************************************************************
1116 * fetch/move [forward | backward] [number | all ] [ in <portalname> ]
1118 *****************************************************************************/
1120 FetchStmt: FETCH opt_direction fetch_how_many opt_portal_name
1122 FetchStmt *n = makeNode(FetchStmt);
1129 | MOVE opt_direction fetch_how_many opt_portal_name
1131 FetchStmt *n = makeNode(FetchStmt);
1140 opt_direction: FORWARD { $$ = FORWARD; }
1141 | BACKWARD { $$ = BACKWARD; }
1142 | /*EMPTY*/ { $$ = FORWARD; /* default */ }
1145 fetch_how_many: Iconst
1147 if ($1 <= 0) elog(WARN,"Please specify nonnegative count for fetch",NULL); }
1148 | ALL { $$ = 0; /* 0 means fetch all tuples*/}
1149 | /*EMPTY*/ { $$ = 1; /*default*/ }
1152 opt_portal_name: IN name { $$ = $2;}
1153 | /*EMPTY*/ { $$ = NULL; }
1157 /*****************************************************************************
1160 * GRANT [privileges] ON [relation_name_list] TO [GROUP] grantee
1162 *****************************************************************************/
1164 GrantStmt: GRANT privileges ON relation_name_list TO grantee opt_with_grant
1166 $$ = (Node*)makeAclStmt($2,$4,$6,'+');
1172 privileges: ALL PRIVILEGES
1174 $$ = aclmakepriv("rwaR",0);
1178 $$ = aclmakepriv("rwaR",0);
1180 | operation_commalist
1186 operation_commalist: operation
1188 $$ = aclmakepriv("",$1);
1190 | operation_commalist ',' operation
1192 $$ = aclmakepriv($1,$3);
1199 $$ = ACL_MODE_RD_CHR;
1203 $$ = ACL_MODE_AP_CHR;
1207 $$ = ACL_MODE_WR_CHR;
1211 $$ = ACL_MODE_WR_CHR;
1215 $$ = ACL_MODE_RU_CHR;
1221 $$ = aclmakeuser("A","");
1225 $$ = aclmakeuser("G",$2);
1229 $$ = aclmakeuser("U",$1);
1233 opt_with_grant: WITH GRANT OPTION
1235 yyerror("WITH GRANT OPTION is not supported. Only relation owners can set privileges");
1241 /*****************************************************************************
1244 * REVOKE [privileges] ON [relation_name] FROM [user]
1246 *****************************************************************************/
1248 RevokeStmt: REVOKE privileges ON relation_name_list FROM grantee
1250 $$ = (Node*)makeAclStmt($2,$4,$6,'-');
1257 /*****************************************************************************
1260 * define [archive] index <indexname> on <relname>
1261 * using <access> "(" (<col> with <op>)+ ")" [with
1264 * [where <qual>] is not supported anymore
1265 *****************************************************************************/
1267 IndexStmt: CREATE index_opt_unique INDEX index_name ON relation_name
1268 access_method_clause '(' index_params ')' opt_with
1270 /* should check that access_method is valid,
1271 etc ... but doesn't */
1272 IndexStmt *n = makeNode(IndexStmt);
1276 n->accessMethod = $7;
1277 n->indexParams = $9;
1278 n->withClause = $11;
1279 n->whereClause = NULL;
1284 index_opt_unique: UNIQUE { $$ = TRUE; }
1285 | /*EMPTY*/ { $$ = FALSE; }
1288 access_method_clause: USING access_method { $$ = $2; }
1289 | /*EMPTY*/ { $$ = "btree"; }
1292 index_params: index_list { $$ = $1; }
1293 | func_index { $$ = lcons($1,NIL); }
1296 index_list: index_list ',' index_elem { $$ = lappend($1, $3); }
1297 | index_elem { $$ = lcons($1, NIL); }
1300 func_index: name '(' name_list ')' opt_type opt_class
1302 $$ = makeNode(IndexElem);
1310 index_elem: attr_name opt_type opt_class
1312 $$ = makeNode(IndexElem);
1320 opt_type: ':' Typename { $$ = $2;}
1321 | FOR Typename { $$ = $2;}
1322 | /*EMPTY*/ { $$ = NULL;}
1325 /* opt_class "WITH class" conflicts with preceeding opt_type
1326 * for Typename of "TIMESTAMP WITH TIME ZONE"
1327 * So, remove "WITH class" from the syntax. OK??
1328 * - thomas 1997-10-12
1329 * | WITH class { $$ = $2; }
1331 opt_class: class { $$ = $1; }
1332 | USING class { $$ = $2; }
1333 | /*EMPTY*/ { $$ = NULL; }
1337 /*****************************************************************************
1340 * extend index <indexname> [where <qual>]
1342 *****************************************************************************/
1344 ExtendStmt: EXTEND INDEX index_name where_clause
1346 ExtendStmt *n = makeNode(ExtendStmt);
1348 n->whereClause = $4;
1354 /*****************************************************************************
1357 * execute recipe <recipeName>
1359 *****************************************************************************/
1361 RecipeStmt: EXECUTE RECIPE recipe_name
1364 if (!IsTransactionBlock())
1365 elog(WARN,"EXECUTE RECIPE may only be used in begin/end transaction blocks",NULL);
1367 n = makeNode(RecipeStmt);
1374 /*****************************************************************************
1377 * define function <fname>
1378 * (language = <lang>, returntype = <typename>
1379 * [, arch_pct = <percentage | pre-defined>]
1380 * [, disk_pct = <percentage | pre-defined>]
1381 * [, byte_pct = <percentage | pre-defined>]
1382 * [, perbyte_cpu = <int | pre-defined>]
1383 * [, percall_cpu = <int | pre-defined>]
1385 * [arg is (<type-1> { , <type-n>})]
1386 * as <filename or code in language as appropriate>
1388 *****************************************************************************/
1390 ProcedureStmt: CREATE FUNCTION def_name def_args
1391 RETURNS def_arg opt_with AS Sconst LANGUAGE Sconst
1393 ProcedureStmt *n = makeNode(ProcedureStmt);
1396 n->returnType = (Node *)$6;
1403 opt_with: WITH definition { $$ = $2; }
1404 | /* EMPTY */ { $$ = NIL; }
1407 def_args: '(' def_name_list ')' { $$ = $2; }
1408 | '(' ')' { $$ = NIL; }
1411 def_name_list: name_list;
1414 /*****************************************************************************
1417 * purge <relname> [before <date>] [after <date>]
1419 * purge <relname> [after <date>] [before <date>]
1421 *****************************************************************************/
1423 PurgeStmt: PURGE relation_name purge_quals
1430 purge_quals: before_clause
1432 $$ = makeNode(PurgeStmt);
1433 $$->beforeDate = $1;
1434 $$->afterDate = NULL;
1438 $$ = makeNode(PurgeStmt);
1439 $$->beforeDate = NULL;
1442 | before_clause after_clause
1444 $$ = makeNode(PurgeStmt);
1445 $$->beforeDate = $1;
1448 | after_clause before_clause
1450 $$ = makeNode(PurgeStmt);
1451 $$->beforeDate = $2;
1456 $$ = makeNode(PurgeStmt);
1457 $$->beforeDate = NULL;
1458 $$->afterDate = NULL;
1462 before_clause: BEFORE date { $$ = $2; }
1463 after_clause: AFTER date { $$ = $2; }
1466 /*****************************************************************************
1470 * remove function <funcname>
1471 * (REMOVE FUNCTION "funcname" (arg1, arg2, ...))
1472 * remove aggregate <aggname>
1473 * (REMOVE AGGREGATE "aggname" "aggtype")
1474 * remove operator <opname>
1475 * (REMOVE OPERATOR "opname" (leftoperand_typ rightoperand_typ))
1476 * remove type <typename>
1477 * (REMOVE TYPE "typename")
1478 * remove rule <rulename>
1479 * (REMOVE RULE "rulename")
1481 *****************************************************************************/
1483 RemoveStmt: DROP remove_type name
1485 RemoveStmt *n = makeNode(RemoveStmt);
1492 remove_type: Type { $$ = TYPE_P; }
1493 | INDEX { $$ = INDEX; }
1494 | RULE { $$ = RULE; }
1495 | VIEW { $$ = VIEW; }
1498 RemoveAggrStmt: DROP AGGREGATE name aggr_argtype
1500 RemoveAggrStmt *n = makeNode(RemoveAggrStmt);
1507 aggr_argtype: name { $$ = $1; }
1508 | '*' { $$ = NULL; }
1511 RemoveFuncStmt: DROP FUNCTION name '(' func_argtypes ')'
1513 RemoveFuncStmt *n = makeNode(RemoveFuncStmt);
1520 func_argtypes: name_list { $$ = $1; }
1521 | /*EMPTY*/ { $$ = NIL; }
1524 RemoveOperStmt: DROP OPERATOR all_Op '(' oper_argtypes ')'
1526 RemoveOperStmt *n = makeNode(RemoveOperStmt);
1533 all_Op: Op | MathOp;
1535 MathOp: '+' { $$ = "+"; }
1546 elog(WARN,"parser: argument type missing (use NONE for unary operators)",NULL);
1549 { $$ = makeList(makeString($1), makeString($3), -1); }
1550 | NONE ',' name /* left unary */
1551 { $$ = makeList(NULL, makeString($3), -1); }
1552 | name ',' NONE /* right unary */
1553 { $$ = makeList(makeString($1), NULL, -1); }
1557 /*****************************************************************************
1560 * rename <attrname1> in <relname> [*] to <attrname2>
1561 * rename <relname1> to <relname2>
1563 *****************************************************************************/
1565 RenameStmt: ALTER TABLE relation_name opt_inh_star
1566 RENAME opt_column opt_name TO name
1568 RenameStmt *n = makeNode(RenameStmt);
1577 opt_name: name { $$ = $1; }
1578 | /*EMPTY*/ { $$ = NULL; }
1581 opt_column: COLUMN { $$ = COLUMN; }
1582 | /*EMPTY*/ { $$ = 0; }
1586 /*****************************************************************************
1588 * QUERY: Define Rewrite Rule , Define Tuple Rule
1589 * Define Rule <old rules >
1591 * only rewrite rule is supported -- ay 9/94
1593 *****************************************************************************/
1595 RuleStmt: CREATE RULE name AS
1596 { QueryIsRule=TRUE; }
1597 ON event TO event_object where_clause
1598 DO opt_instead OptStmtList
1600 RuleStmt *n = makeNode(RuleStmt);
1604 n->whereClause = $10;
1611 OptStmtList: NOTHING { $$ = NIL; }
1612 | OptimizableStmt { $$ = lcons($1, NIL); }
1613 | '[' OptStmtBlock ']' { $$ = $2; }
1616 OptStmtBlock: OptStmtMulti
1619 { $$ = lcons($1, NIL); }
1622 OptStmtMulti: OptStmtMulti OptimizableStmt ';'
1623 { $$ = lappend($1, $2); }
1624 | OptStmtMulti OptimizableStmt
1625 { $$ = lappend($1, $2); }
1626 | OptimizableStmt ';'
1627 { $$ = lcons($1, NIL); }
1630 event_object: relation_name '.' attr_name
1632 $$ = makeNode(Attr);
1635 $$->attrs = lcons(makeString($3), NIL);
1636 $$->indirection = NIL;
1640 $$ = makeNode(Attr);
1644 $$->indirection = NIL;
1648 /* change me to select, update, etc. some day */
1649 event: SELECT { $$ = CMD_SELECT; }
1650 | UPDATE { $$ = CMD_UPDATE; }
1651 | DELETE { $$ = CMD_DELETE; }
1652 | INSERT { $$ = CMD_INSERT; }
1655 opt_instead: INSTEAD { $$ = TRUE; }
1656 | /* EMPTY */ { $$ = FALSE; }
1660 /*****************************************************************************
1663 * NOTIFY <relation_name> can appear both in rule bodies and
1664 * as a query-level command
1666 *****************************************************************************/
1668 NotifyStmt: NOTIFY relation_name
1670 NotifyStmt *n = makeNode(NotifyStmt);
1676 ListenStmt: LISTEN relation_name
1678 ListenStmt *n = makeNode(ListenStmt);
1685 /*****************************************************************************
1696 *****************************************************************************/
1698 TransactionStmt: ABORT_TRANS TRANSACTION
1700 TransactionStmt *n = makeNode(TransactionStmt);
1701 n->command = ABORT_TRANS;
1704 | BEGIN_TRANS TRANSACTION
1706 TransactionStmt *n = makeNode(TransactionStmt);
1707 n->command = BEGIN_TRANS;
1712 TransactionStmt *n = makeNode(TransactionStmt);
1713 n->command = BEGIN_TRANS;
1718 TransactionStmt *n = makeNode(TransactionStmt);
1719 n->command = END_TRANS;
1722 | END_TRANS TRANSACTION
1724 TransactionStmt *n = makeNode(TransactionStmt);
1725 n->command = END_TRANS;
1730 TransactionStmt *n = makeNode(TransactionStmt);
1731 n->command = ABORT_TRANS;
1737 TransactionStmt *n = makeNode(TransactionStmt);
1738 n->command = ABORT_TRANS;
1743 TransactionStmt *n = makeNode(TransactionStmt);
1744 n->command = BEGIN_TRANS;
1749 TransactionStmt *n = makeNode(TransactionStmt);
1750 n->command = END_TRANS;
1756 TransactionStmt *n = makeNode(TransactionStmt);
1757 n->command = END_TRANS;
1762 TransactionStmt *n = makeNode(TransactionStmt);
1763 n->command = ABORT_TRANS;
1769 /*****************************************************************************
1772 * define view <viewname> '('target-list ')' [where <quals> ]
1774 *****************************************************************************/
1776 ViewStmt: CREATE VIEW name AS RetrieveStmt
1778 ViewStmt *n = makeNode(ViewStmt);
1780 n->query = (Query *)$5;
1786 /*****************************************************************************
1791 *****************************************************************************/
1793 LoadStmt: LOAD file_name
1795 LoadStmt *n = makeNode(LoadStmt);
1802 /*****************************************************************************
1807 *****************************************************************************/
1809 CreatedbStmt: CREATE DATABASE database_name opt_database
1811 CreatedbStmt *n = makeNode(CreatedbStmt);
1818 opt_database: WITH LOCATION '=' location { $$ = $4; }
1819 | /*EMPTY*/ { $$ = NULL; }
1822 location: Sconst { $$ = $1; }
1823 | DEFAULT { $$ = NULL; }
1824 | /*EMPTY*/ { $$ = NULL; }
1827 /*****************************************************************************
1832 *****************************************************************************/
1834 DestroydbStmt: DROP DATABASE database_name
1836 DestroydbStmt *n = makeNode(DestroydbStmt);
1843 /*****************************************************************************
1846 * cluster <index_name> on <relation_name>
1848 *****************************************************************************/
1850 ClusterStmt: CLUSTER index_name ON relation_name
1852 ClusterStmt *n = makeNode(ClusterStmt);
1860 /*****************************************************************************
1865 *****************************************************************************/
1867 VacuumStmt: VACUUM opt_verbose opt_analyze
1869 VacuumStmt *n = makeNode(VacuumStmt);
1876 | VACUUM opt_verbose relation_name opt_analyze opt_va_list
1878 VacuumStmt *n = makeNode(VacuumStmt);
1883 if ( $5 != NIL && !$4 )
1884 elog(WARN,"parser: syntax error at or near \"(\"",NULL);
1889 opt_verbose: VERBOSE { $$ = TRUE; }
1890 | /* EMPTY */ { $$ = FALSE; }
1893 opt_analyze: ANALYZE { $$ = TRUE; }
1894 | /* EMPTY */ { $$ = FALSE; }
1897 opt_va_list: '(' va_list ')'
1904 { $$=lcons($1,NIL); }
1906 { $$=lappend($1,$3); }
1910 /*****************************************************************************
1915 *****************************************************************************/
1917 ExplainStmt: EXPLAIN opt_verbose OptimizableStmt
1919 ExplainStmt *n = makeNode(ExplainStmt);
1921 n->query = (Query*)$3;
1927 /*****************************************************************************
1929 * Optimizable Stmts: *
1931 * one of the five queries processed by the planner *
1933 * [ultimately] produces query-trees as specified *
1934 * in the query-spec document in ~postgres/ref *
1936 *****************************************************************************/
1938 OptimizableStmt: RetrieveStmt
1943 | DeleteStmt /* by default all are $$=$1 */
1947 /*****************************************************************************
1952 *****************************************************************************/
1954 AppendStmt: INSERT INTO relation_name opt_column_list insert_rest
1962 insert_rest: VALUES '(' res_target_list2 ')'
1964 $$ = makeNode(AppendStmt);
1965 $$->targetList = $3;
1966 $$->fromClause = NIL;
1967 $$->whereClause = NULL;
1969 | SELECT res_target_list2 from_clause where_clause
1971 $$ = makeNode(AppendStmt);
1972 $$->targetList = $2;
1973 $$->fromClause = $3;
1974 $$->whereClause = $4;
1978 opt_column_list: '(' columnList ')' { $$ = $2; }
1979 | /*EMPTY*/ { $$ = NIL; }
1983 columnList ',' columnElem
1984 { $$ = lappend($1, $3); }
1986 { $$ = lcons($1, NIL); }
1989 columnElem: ColId opt_indirection
1991 Ident *id = makeNode(Ident);
1993 id->indirection = $2;
1999 /*****************************************************************************
2004 *****************************************************************************/
2006 DeleteStmt: DELETE FROM relation_name
2009 DeleteStmt *n = makeNode(DeleteStmt);
2011 n->whereClause = $4;
2017 /*****************************************************************************
2020 * ReplaceStmt (UPDATE)
2022 *****************************************************************************/
2024 ReplaceStmt: UPDATE relation_name
2029 ReplaceStmt *n = makeNode(ReplaceStmt);
2033 n->whereClause = $6;
2039 /*****************************************************************************
2044 *****************************************************************************/
2046 CursorStmt: DECLARE name opt_binary CURSOR FOR
2047 SELECT opt_unique res_target_list2
2048 from_clause where_clause group_clause sort_clause
2050 CursorStmt *n = makeNode(CursorStmt);
2052 /* from PORTAL name */
2054 * 15 august 1991 -- since 3.0 postgres does locking
2055 * right, we discovered that portals were violating
2056 * locking protocol. portal locks cannot span xacts.
2057 * as a short-term fix, we installed the check here.
2060 if (!IsTransactionBlock())
2061 elog(WARN,"Named portals may only be used in begin/end transaction blocks",NULL);
2068 n->whereClause = $10;
2069 n->groupClause = $11;
2070 n->sortClause = $12;
2076 /*****************************************************************************
2081 *****************************************************************************/
2083 RetrieveStmt: SELECT opt_unique res_target_list2
2084 result from_clause where_clause
2085 group_clause having_clause
2086 union_clause sort_clause
2088 RetrieveStmt *n = makeNode(RetrieveStmt);
2093 n->whereClause = $6;
2094 n->groupClause = $7;
2095 n->havingClause = $8;
2096 n->selectClause = $9;
2097 n->sortClause = $10;
2102 union_clause: UNION opt_union select_list { $$ = $3; }
2103 | /*EMPTY*/ { $$ = NIL; }
2106 select_list: select_list UNION opt_union SubSelect
2107 { $$ = lappend($1, $4); }
2109 { $$ = lcons($1, NIL); }
2112 SubSelect: SELECT opt_unique res_target_list2
2113 from_clause where_clause
2114 group_clause having_clause
2116 SubSelect *n = makeNode(SubSelect);
2120 n->whereClause = $5;
2121 n->groupClause = $6;
2122 n->havingClause = $7;
2127 result: INTO TABLE relation_name
2128 { $$= $3; /* should check for archive level */ }
2133 opt_union: ALL { $$ = TRUE; }
2134 | /*EMPTY*/ { $$ = FALSE; }
2137 opt_unique: DISTINCT { $$ = "*"; }
2138 | DISTINCT ON ColId { $$ = $3; }
2139 | ALL { $$ = NULL; }
2140 | /*EMPTY*/ { $$ = NULL; }
2143 sort_clause: ORDER BY sortby_list { $$ = $3; }
2144 | /*EMPTY*/ { $$ = NIL; }
2147 sortby_list: sortby { $$ = lcons($1, NIL); }
2148 | sortby_list ',' sortby { $$ = lappend($1, $3); }
2151 sortby: ColId OptUseOp
2153 $$ = makeNode(SortGroupBy);
2159 | ColId '.' ColId OptUseOp
2161 $$ = makeNode(SortGroupBy);
2169 $$ = makeNode(SortGroupBy);
2177 OptUseOp: USING Op { $$ = $2; }
2178 | USING '<' { $$ = "<"; }
2179 | USING '>' { $$ = ">"; }
2181 | DESC { $$ = ">"; }
2182 | /*EMPTY*/ { $$ = "<"; /*default*/ }
2186 * jimmy bell-style recursive queries aren't supported in the
2189 * ...however, recursive addattr and rename supported. make special
2192 * XXX i believe '*' should be the default behavior, but...
2194 opt_inh_star: '*' { $$ = TRUE; }
2195 | /*EMPTY*/ { $$ = FALSE; }
2198 relation_name_list: name_list;
2201 { $$ = lcons(makeString($1),NIL); }
2202 | name_list ',' name
2203 { $$ = lappend($1,makeString($3)); }
2206 group_clause: GROUP BY groupby_list { $$ = $3; }
2207 | /*EMPTY*/ { $$ = NIL; }
2210 groupby_list: groupby { $$ = lcons($1, NIL); }
2211 | groupby_list ',' groupby { $$ = lappend($1, $3); }
2216 $$ = makeNode(SortGroupBy);
2224 $$ = makeNode(SortGroupBy);
2232 $$ = makeNode(SortGroupBy);
2240 having_clause: HAVING a_expr { $$ = $2; }
2241 | /*EMPTY*/ { $$ = NULL; }
2245 /*****************************************************************************
2247 * clauses common to all Optimizable Stmts:
2251 *****************************************************************************/
2253 from_clause: FROM '(' relation_expr join_expr JOIN relation_expr join_spec ')'
2256 elog(WARN,"JOIN not yet implemented",NULL);
2258 | FROM from_list { $$ = $2; }
2259 | /*EMPTY*/ { $$ = NIL; }
2262 from_list: from_list ',' from_val
2263 { $$ = lappend($1, $3); }
2264 | from_val CROSS JOIN from_val
2265 { elog(WARN,"CROSS JOIN not yet implemented",NULL); }
2267 { $$ = lcons($1, NIL); }
2270 from_val: relation_expr AS ColLabel
2272 $$ = makeNode(RangeVar);
2276 | relation_expr ColId
2278 $$ = makeNode(RangeVar);
2284 $$ = makeNode(RangeVar);
2290 join_expr: NATURAL join_expr { $$ = NULL; }
2292 { elog(WARN,"FULL OUTER JOIN not yet implemented",NULL); }
2294 { elog(WARN,"LEFT OUTER JOIN not yet implemented",NULL); }
2296 { elog(WARN,"RIGHT OUTER JOIN not yet implemented",NULL); }
2298 { elog(WARN,"OUTER JOIN not yet implemented",NULL); }
2300 { elog(WARN,"INNER JOIN not yet implemented",NULL); }
2302 { elog(WARN,"UNION JOIN not yet implemented",NULL); }
2304 { elog(WARN,"INNER JOIN not yet implemented",NULL); }
2307 join_outer: OUTER_P { $$ = NULL; }
2308 | /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
2311 join_spec: ON '(' a_expr ')' { $$ = NULL; }
2312 | USING '(' join_list ')' { $$ = NULL; }
2313 | /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
2316 join_list: join_using { $$ = lcons($1, NIL); }
2317 | join_list ',' join_using { $$ = lappend($1, $3); }
2322 $$ = makeNode(SortGroupBy);
2330 $$ = makeNode(SortGroupBy);
2338 $$ = makeNode(SortGroupBy);
2346 where_clause: WHERE a_expr { $$ = $2; }
2347 | /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
2350 relation_expr: relation_name
2352 /* normal relations */
2353 $$ = makeNode(RelExpr);
2356 $$->timeRange = NULL;
2358 | relation_name '*' %prec '='
2360 /* inheiritance query */
2361 $$ = makeNode(RelExpr);
2364 $$->timeRange = NULL;
2366 | relation_name time_range
2368 /* time-qualified query */
2369 $$ = makeNode(RelExpr);
2377 * Range specification clause.
2379 time_range: '[' opt_range_start ',' opt_range_end ']'
2381 $$ = makeNode(TimeRange);
2384 elog (WARN, "time travel is no longer available");
2388 $$ = makeNode(TimeRange);
2391 elog (WARN, "time travel is no longer available");
2395 opt_range_start: date
2396 | /*EMPTY*/ { $$ = "epoch"; }
2400 | /*EMPTY*/ { $$ = "now"; }
2403 opt_array_bounds: '[' ']' nest_array_bounds
2404 { $$ = lcons(makeInteger(-1), $3); }
2405 | '[' Iconst ']' nest_array_bounds
2406 { $$ = lcons(makeInteger($2), $4); }
2411 nest_array_bounds: '[' ']' nest_array_bounds
2412 { $$ = lcons(makeInteger(-1), $3); }
2413 | '[' Iconst ']' nest_array_bounds
2414 { $$ = lcons(makeInteger($2), $4); }
2420 /*****************************************************************************
2423 * SQL92 introduces a large amount of type-specific syntax.
2424 * Define individual clauses to handle these cases, and use
2425 * the generic case to handle regular type-extensible Postgres syntax.
2426 * - thomas 1997-10-10
2428 *****************************************************************************/
2430 Typename: Array opt_array_bounds
2433 $$->arrayBounds = $2;
2435 /* Is this the name of a complex type? If so, implement
2438 if (!strcmp(saved_relname, $$->name))
2439 /* This attr is the same type as the relation
2440 * being defined. The classic example: create
2441 * emp(name=text,mgr=emp)
2444 else if (get_typrelid((Type)type($$->name)) != InvalidOid)
2445 /* (Eventually add in here that the set can only
2446 * contain one element.)
2467 $$ = makeNode(TypeName);
2468 $$->name = xlateSqlType($1);
2472 generic: Id { $$ = $1; }
2473 | TYPE_P { $$ = xlateSqlType("type"); }
2474 | DOUBLE PRECISION { $$ = xlateSqlType("float8"); }
2477 /* SQL92 numeric data types
2478 * Check FLOAT() precision limits assuming IEEE floating types.
2479 * Provide rudimentary DECIMAL() and NUMERIC() implementations
2480 * by checking parameters and making sure they match what is possible with INTEGER.
2481 * - thomas 1997-09-18
2483 Numeric: FLOAT opt_float
2485 $$ = makeNode(TypeName);
2486 $$->name = xlateSqlType($2);
2488 | DECIMAL opt_decimal
2490 $$ = makeNode(TypeName);
2491 $$->name = xlateSqlType("integer");
2493 | NUMERIC opt_numeric
2495 $$ = makeNode(TypeName);
2496 $$->name = xlateSqlType("integer");
2500 opt_float: '(' Iconst ')'
2503 elog(WARN,"precision for FLOAT must be at least 1",NULL);
2505 $$ = xlateSqlType("float4");
2507 $$ = xlateSqlType("float8");
2509 elog(WARN,"precision for FLOAT must be less than 16",NULL);
2513 $$ = xlateSqlType("float8");
2517 opt_numeric: '(' Iconst ',' Iconst ')'
2520 elog(WARN,"NUMERIC precision %d must be 9",$2);
2522 elog(WARN,"NUMERIC scale %d must be zero",$4);
2527 elog(WARN,"NUMERIC precision %d must be 9",$2);
2535 opt_decimal: '(' Iconst ',' Iconst ')'
2538 elog(WARN,"DECIMAL precision %d exceeds implementation limit of 9",$2);
2540 elog(WARN,"DECIMAL scale %d must be zero",$4);
2546 elog(WARN,"DECIMAL precision %d exceeds implementation limit of 9",$2);
2555 /* SQL92 character data types
2556 * The following implements CHAR() and VARCHAR().
2557 * We do it here instead of the 'Generic' production
2558 * because we don't want to allow arrays of VARCHAR().
2559 * I haven't thought about whether that will work or not.
2562 Character: character '(' Iconst ')'
2564 $$ = makeNode(TypeName);
2565 if (!strcasecmp($1, "char"))
2566 $$->name = xlateSqlType("bpchar");
2567 else if (!strcasecmp($1, "varchar"))
2568 $$->name = xlateSqlType("varchar");
2570 yyerror("parse error");
2572 elog(WARN,"length for '%s' type must be at least 1",$1);
2574 /* we can store a char() of length up to the size
2575 * of a page (8KB) - page headers and friends but
2576 * just to be safe here... - ay 6/95
2577 * XXX note this hardcoded limit - thomas 1997-07-13
2579 elog(WARN,"length for type '%s' cannot exceed 4096",$1);
2581 /* we actually implement this sort of like a varlen, so
2582 * the first 4 bytes is the length. (the difference
2583 * between this and "text" is that we blank-pad and
2584 * truncate where necessary
2586 $$->typlen = 4 + $3;
2590 $$ = makeNode(TypeName);
2591 $$->name = xlateSqlType($1);
2595 character: CHARACTER opt_varying opt_charset opt_collate
2598 if (($3 == NULL) || (strcasecmp($3, "sql_text") == 0)) {
2599 if ($2) type = xlateSqlType("varchar");
2600 else type = xlateSqlType("char");
2603 c = palloc(strlen("var") + strlen($3) + 1);
2606 type = xlateSqlType(c);
2608 type = xlateSqlType($3);
2612 elog(WARN,"COLLATE %s not yet implemented",$4);
2615 | CHAR opt_varying { $$ = xlateSqlType($2? "varchar": "char"); }
2616 | VARCHAR { $$ = xlateSqlType("varchar"); }
2617 | NATIONAL CHARACTER opt_varying { $$ = xlateSqlType($3? "varchar": "char"); }
2618 | NCHAR opt_varying { $$ = xlateSqlType($2? "varchar": "char"); }
2621 opt_varying: VARYING { $$ = TRUE; }
2622 | /*EMPTY*/ { $$ = FALSE; }
2625 opt_charset: CHARACTER SET ColId { $$ = $3; }
2626 | /*EMPTY*/ { $$ = NULL; }
2629 opt_collate: COLLATE ColId { $$ = $2; }
2630 | /*EMPTY*/ { $$ = NULL; }
2635 $$ = makeNode(TypeName);
2636 $$->name = xlateSqlType($1);
2638 | TIMESTAMP opt_timezone
2640 $$ = makeNode(TypeName);
2641 $$->name = xlateSqlType("timestamp");
2646 $$ = makeNode(TypeName);
2647 $$->name = xlateSqlType("time");
2649 | INTERVAL opt_interval
2651 $$ = makeNode(TypeName);
2652 $$->name = xlateSqlType("interval");
2656 datetime: YEAR_P { $$ = "year"; }
2657 | MONTH_P { $$ = "month"; }
2658 | DAY_P { $$ = "day"; }
2659 | HOUR_P { $$ = "hour"; }
2660 | MINUTE_P { $$ = "minute"; }
2661 | SECOND_P { $$ = "second"; }
2664 opt_timezone: WITH TIME ZONE { $$ = TRUE; }
2665 | /*EMPTY*/ { $$ = FALSE; }
2668 opt_interval: datetime { $$ = lcons($1, NIL); }
2669 | YEAR_P TO MONTH_P { $$ = NIL; }
2670 | DAY_P TO HOUR_P { $$ = NIL; }
2671 | DAY_P TO MINUTE_P { $$ = NIL; }
2672 | DAY_P TO SECOND_P { $$ = NIL; }
2673 | HOUR_P TO MINUTE_P { $$ = NIL; }
2674 | HOUR_P TO SECOND_P { $$ = NIL; }
2675 | /* EMPTY */ { $$ = NIL; }
2679 /*****************************************************************************
2681 * expression grammar, still needs some cleanup
2683 *****************************************************************************/
2685 a_expr_or_null: a_expr
2689 A_Const *n = makeNode(A_Const);
2690 n->val.type = T_Null;
2694 a_expr: attr opt_indirection
2696 $1->indirection = $2;
2701 | '-' a_expr %prec UMINUS
2702 { $$ = makeA_Expr(OP, "-", NULL, $2); }
2704 { $$ = makeA_Expr(OP, "+", $1, $3); }
2706 { $$ = makeA_Expr(OP, "-", $1, $3); }
2708 { $$ = makeA_Expr(OP, "/", $1, $3); }
2710 { $$ = makeA_Expr(OP, "*", $1, $3); }
2712 { $$ = makeA_Expr(OP, "<", $1, $3); }
2714 { $$ = makeA_Expr(OP, ">", $1, $3); }
2716 { $$ = makeA_Expr(OP, "=", $1, $3); }
2718 { $$ = makeA_Expr(OP, ":", NULL, $2); }
2720 { $$ = makeA_Expr(OP, ";", NULL, $2); }
2722 { $$ = makeA_Expr(OP, "|", NULL, $2); }
2723 | AexprConst TYPECAST Typename
2725 /* AexprConst can be either A_Const or ParamNo */
2726 if (nodeTag($1) == T_A_Const)
2727 ((A_Const *)$1)->typename = $3;
2729 ((ParamNo *)$1)->typename = $3;
2732 | CAST a_expr AS Typename
2735 /* AexprConst can be either A_Const or ParamNo */
2736 if (nodeTag($2) == T_A_Const) {
2737 ((A_Const *)$2)->typename = $4;
2738 } else if (nodeTag($2) == T_Param) {
2739 ((ParamNo *)$2)->typename = $4;
2740 /* otherwise, try to transform to a function call */
2742 FuncCall *n = makeNode(FuncCall);
2743 n->funcname = $4->name;
2744 n->args = lcons($2,NIL);
2748 | '(' a_expr_or_null ')'
2751 { $$ = makeIndexable($2,$1,$3); }
2752 | a_expr LIKE a_expr
2753 { $$ = makeIndexable("~~", $1, $3); }
2754 | a_expr NOT LIKE a_expr
2755 { $$ = makeA_Expr(OP, "!~~", $1, $4); }
2757 { $$ = makeA_Expr(OP, $1, NULL, $2); }
2759 { $$ = makeA_Expr(OP, $2, $1, NULL); }
2762 /* could be a column name or a relation_name */
2763 Ident *n = makeNode(Ident);
2765 n->indirection = NULL;
2770 FuncCall *n = makeNode(FuncCall);
2771 Ident *star = makeNode(Ident);
2773 /* cheap hack for aggregate (eg. count) */
2776 n->args = lcons(star, NIL);
2781 FuncCall *n = makeNode(FuncCall);
2788 A_Const *n = makeNode(A_Const);
2789 TypeName *t = makeNode(TypeName);
2791 n->val.type = T_String;
2792 n->val.val.str = "now";
2795 t->name = xlateSqlType("date");
2802 A_Const *n = makeNode(A_Const);
2803 TypeName *t = makeNode(TypeName);
2805 n->val.type = T_String;
2806 n->val.val.str = "now";
2809 t->name = xlateSqlType("time");
2814 | CURRENT_TIME '(' Iconst ')'
2816 FuncCall *n = makeNode(FuncCall);
2817 A_Const *s = makeNode(A_Const);
2818 TypeName *t = makeNode(TypeName);
2820 n->funcname = xlateSqlType("time");
2821 n->args = lcons(s, NIL);
2823 s->val.type = T_String;
2824 s->val.val.str = "now";
2827 t->name = xlateSqlType("time");
2831 elog(NOTICE,"CURRENT_TIME(p) precision must be zero",NULL);
2837 A_Const *n = makeNode(A_Const);
2838 TypeName *t = makeNode(TypeName);
2840 n->val.type = T_String;
2841 n->val.val.str = "now";
2844 t->name = xlateSqlType("timestamp");
2849 | CURRENT_TIMESTAMP '(' Iconst ')'
2851 FuncCall *n = makeNode(FuncCall);
2852 A_Const *s = makeNode(A_Const);
2853 TypeName *t = makeNode(TypeName);
2855 n->funcname = xlateSqlType("timestamp");
2856 n->args = lcons(s, NIL);
2858 s->val.type = T_String;
2859 s->val.val.str = "now";
2862 t->name = xlateSqlType("timestamp");
2866 elog(NOTICE,"CURRENT_TIMESTAMP(p) precision must be zero",NULL);
2872 FuncCall *n = makeNode(FuncCall);
2873 n->funcname = "getpgusername";
2877 /* We probably need to define an "exists" node,
2878 * since the optimizer could choose to find only one match.
2879 * Perhaps the first implementation could just check for
2880 * count(*) > 0? - thomas 1997-07-19
2882 | EXISTS '(' SubSelect ')'
2884 elog(WARN,"EXISTS not yet implemented",NULL);
2887 | EXTRACT '(' extract_list ')'
2889 FuncCall *n = makeNode(FuncCall);
2890 n->funcname = "date_part";
2894 | POSITION '(' position_list ')'
2896 FuncCall *n = makeNode(FuncCall);
2897 n->funcname = "strpos";
2901 | SUBSTRING '(' substr_list ')'
2903 FuncCall *n = makeNode(FuncCall);
2904 n->funcname = "substr";
2908 /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
2909 | TRIM '(' BOTH trim_list ')'
2911 FuncCall *n = makeNode(FuncCall);
2912 n->funcname = "btrim";
2916 | TRIM '(' LEADING trim_list ')'
2918 FuncCall *n = makeNode(FuncCall);
2919 n->funcname = "ltrim";
2923 | TRIM '(' TRAILING trim_list ')'
2925 FuncCall *n = makeNode(FuncCall);
2926 n->funcname = "rtrim";
2930 | TRIM '(' trim_list ')'
2932 FuncCall *n = makeNode(FuncCall);
2933 n->funcname = "btrim";
2937 | name '(' expr_list ')'
2939 FuncCall *n = makeNode(FuncCall);
2945 { $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
2947 { $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
2949 { $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); }
2950 | a_expr IS NOT NULL_P
2951 { $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); }
2954 FuncCall *n = makeNode(FuncCall);
2955 n->funcname = "istrue";
2956 n->args = lcons($1,NIL);
2961 FuncCall *n = makeNode(FuncCall);
2962 n->funcname = "isfalse";
2963 n->args = lcons($1,NIL);
2966 | a_expr IS NOT TRUE_P
2968 FuncCall *n = makeNode(FuncCall);
2969 n->funcname = "isfalse";
2970 n->args = lcons($1,NIL);
2973 | a_expr IS NOT FALSE_P
2975 FuncCall *n = makeNode(FuncCall);
2976 n->funcname = "istrue";
2977 n->args = lcons($1,NIL);
2980 | a_expr BETWEEN AexprConst AND AexprConst
2982 $$ = makeA_Expr(AND, NULL,
2983 makeA_Expr(OP, ">=", $1, $3),
2984 makeA_Expr(OP, "<=", $1, $5));
2986 | a_expr NOT BETWEEN AexprConst AND AexprConst
2988 $$ = makeA_Expr(OR, NULL,
2989 makeA_Expr(OP, "<", $1, $4),
2990 makeA_Expr(OP, ">", $1, $6));
2992 | a_expr IN { saved_In_Expr = $1; } '(' in_expr ')'
2994 | a_expr NOT IN { saved_In_Expr = $1; } '(' not_in_expr ')'
2997 { $$ = makeA_Expr(AND, NULL, $1, $3); }
2999 { $$ = makeA_Expr(OR, NULL, $1, $3); }
3001 { $$ = makeA_Expr(NOT, NULL, NULL, $2); }
3004 opt_indirection: '[' a_expr ']' opt_indirection
3006 A_Indices *ai = makeNode(A_Indices);
3011 | '[' a_expr ':' a_expr ']' opt_indirection
3013 A_Indices *ai = makeNode(A_Indices);
3022 expr_list: a_expr_or_null
3023 { $$ = lcons($1, NIL); }
3024 | expr_list ',' a_expr_or_null
3025 { $$ = lappend($1, $3); }
3026 | expr_list USING a_expr
3027 { $$ = lappend($1, $3); }
3030 extract_list: datetime FROM a_expr
3032 A_Const *n = makeNode(A_Const);
3033 n->val.type = T_String;
3034 n->val.val.str = $1;
3035 $$ = lappend(lcons((Node *)n,NIL), $3);
3041 position_list: position_expr IN position_expr
3042 { $$ = makeList($3, $1, -1); }
3047 position_expr: attr opt_indirection
3049 $1->indirection = $2;
3054 | '-' position_expr %prec UMINUS
3055 { $$ = makeA_Expr(OP, "-", NULL, $2); }
3056 | position_expr '+' position_expr
3057 { $$ = makeA_Expr(OP, "+", $1, $3); }
3058 | position_expr '-' position_expr
3059 { $$ = makeA_Expr(OP, "-", $1, $3); }
3060 | position_expr '/' position_expr
3061 { $$ = makeA_Expr(OP, "/", $1, $3); }
3062 | position_expr '*' position_expr
3063 { $$ = makeA_Expr(OP, "*", $1, $3); }
3065 { $$ = makeA_Expr(OP, "|", NULL, $2); }
3066 | AexprConst TYPECAST Typename
3068 /* AexprConst can be either A_Const or ParamNo */
3069 if (nodeTag($1) == T_A_Const)
3070 ((A_Const *)$1)->typename = $3;
3072 ((ParamNo *)$1)->typename = $3;
3075 | CAST position_expr AS Typename
3078 /* AexprConst can be either A_Const or ParamNo */
3079 if (nodeTag($2) == T_A_Const) {
3080 ((A_Const *)$2)->typename = $4;
3081 } else if (nodeTag($2) == T_Param) {
3082 ((ParamNo *)$2)->typename = $4;
3083 /* otherwise, try to transform to a function call */
3085 FuncCall *n = makeNode(FuncCall);
3086 n->funcname = $4->name;
3087 n->args = lcons($2,NIL);
3091 | '(' position_expr ')'
3093 | position_expr Op position_expr
3094 { $$ = makeA_Expr(OP, $2, $1, $3); }
3096 { $$ = makeA_Expr(OP, $1, NULL, $2); }
3098 { $$ = makeA_Expr(OP, $2, $1, NULL); }
3101 /* could be a column name or a relation_name */
3102 Ident *n = makeNode(Ident);
3104 n->indirection = NULL;
3109 FuncCall *n = makeNode(FuncCall);
3114 | POSITION '(' position_list ')'
3116 FuncCall *n = makeNode(FuncCall);
3117 n->funcname = "strpos";
3121 | SUBSTRING '(' substr_list ')'
3123 FuncCall *n = makeNode(FuncCall);
3124 n->funcname = "substr";
3128 /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
3129 | TRIM '(' BOTH trim_list ')'
3131 FuncCall *n = makeNode(FuncCall);
3132 n->funcname = "btrim";
3136 | TRIM '(' LEADING trim_list ')'
3138 FuncCall *n = makeNode(FuncCall);
3139 n->funcname = "ltrim";
3143 | TRIM '(' TRAILING trim_list ')'
3145 FuncCall *n = makeNode(FuncCall);
3146 n->funcname = "rtrim";
3150 | TRIM '(' trim_list ')'
3152 FuncCall *n = makeNode(FuncCall);
3153 n->funcname = "btrim";
3157 | name '(' expr_list ')'
3159 FuncCall *n = makeNode(FuncCall);
3166 substr_list: expr_list substr_from substr_for
3168 $$ = nconc(nconc($1,$2),$3);
3174 substr_from: FROM expr_list
3178 A_Const *n = makeNode(A_Const);
3179 n->val.type = T_Integer;
3180 n->val.val.ival = 1;
3181 $$ = lcons((Node *)n,NIL);
3185 substr_for: FOR expr_list
3191 trim_list: a_expr FROM expr_list
3192 { $$ = lappend($3, $1); }
3201 elog(WARN,"IN (SUBSELECT) not yet implemented",NULL);
3208 in_expr_nodes: AexprConst
3209 { $$ = makeA_Expr(OP, "=", saved_In_Expr, $1); }
3210 | in_expr_nodes ',' AexprConst
3211 { $$ = makeA_Expr(OR, NULL, $1,
3212 makeA_Expr(OP, "=", saved_In_Expr, $3));
3216 not_in_expr: SubSelect
3218 elog(WARN,"NOT IN (SUBSELECT) not yet implemented",NULL);
3225 not_in_expr_nodes: AexprConst
3226 { $$ = makeA_Expr(OP, "<>", saved_In_Expr, $1); }
3227 | not_in_expr_nodes ',' AexprConst
3228 { $$ = makeA_Expr(AND, NULL, $1,
3229 makeA_Expr(OP, "<>", saved_In_Expr, $3));
3233 attr: relation_name '.' attrs
3235 $$ = makeNode(Attr);
3239 $$->indirection = NULL;
3243 $$ = makeNode(Attr);
3247 $$->indirection = NULL;
3252 { $$ = lcons(makeString($1), NIL); }
3253 | attrs '.' attr_name
3254 { $$ = lappend($1, makeString($3)); }
3256 { $$ = lappend($1, makeString("*")); }
3260 /*****************************************************************************
3264 *****************************************************************************/
3266 res_target_list: res_target_list ',' res_target_el
3267 { $$ = lappend($1,$3); }
3269 { $$ = lcons($1, NIL); }
3272 ResTarget *rt = makeNode(ResTarget);
3273 Attr *att = makeNode(Attr);
3275 att->paramNo = NULL;
3277 att->indirection = NIL;
3279 rt->indirection = NULL;
3280 rt->val = (Node *)att;
3281 $$ = lcons(rt, NIL);
3285 res_target_el: ColId opt_indirection '=' a_expr_or_null
3287 $$ = makeNode(ResTarget);
3289 $$->indirection = $2;
3290 $$->val = (Node *)$4;
3292 | attr opt_indirection
3294 $$ = makeNode(ResTarget);
3296 $$->indirection = $2;
3297 $$->val = (Node *)$1;
3299 | relation_name '.' '*'
3301 Attr *att = makeNode(Attr);
3303 att->paramNo = NULL;
3304 att->attrs = lcons(makeString("*"), NIL);
3305 att->indirection = NIL;
3306 $$ = makeNode(ResTarget);
3308 $$->indirection = NULL;
3309 $$->val = (Node *)att;
3314 ** target list for select.
3315 ** should get rid of the other but is still needed by the defunct retrieve into
3316 ** and update (uses a subset)
3318 res_target_list2: res_target_list2 ',' res_target_el2
3319 { $$ = lappend($1, $3); }
3321 { $$ = lcons($1, NIL); }
3324 /* AS is not optional because shift/red conflict with unary ops */
3325 res_target_el2: a_expr_or_null AS ColLabel
3327 $$ = makeNode(ResTarget);
3329 $$->indirection = NULL;
3330 $$->val = (Node *)$1;
3334 $$ = makeNode(ResTarget);
3336 $$->indirection = NULL;
3337 $$->val = (Node *)$1;
3339 | relation_name '.' '*'
3341 Attr *att = makeNode(Attr);
3343 att->paramNo = NULL;
3344 att->attrs = lcons(makeString("*"), NIL);
3345 att->indirection = NIL;
3346 $$ = makeNode(ResTarget);
3348 $$->indirection = NULL;
3349 $$->val = (Node *)att;
3353 Attr *att = makeNode(Attr);
3355 att->paramNo = NULL;
3357 att->indirection = NIL;
3358 $$ = makeNode(ResTarget);
3360 $$->indirection = NULL;
3361 $$->val = (Node *)att;
3365 opt_id: ColId { $$ = $1; }
3366 | /* EMPTY */ { $$ = NULL; }
3369 relation_name: SpecialRuleRelation
3372 StrNCpy(saved_relname, $1, NAMEDATALEN);
3376 /* disallow refs to variable system tables */
3377 if (strcmp(LogRelationName, $1) == 0
3378 || strcmp(VariableRelationName, $1) == 0)
3379 elog(WARN,"%s cannot be accessed by users",$1);
3382 StrNCpy(saved_relname, $1, NAMEDATALEN);
3386 database_name: ColId { $$ = $1; };
3387 access_method: Id { $$ = $1; };
3388 attr_name: ColId { $$ = $1; };
3389 class: Id { $$ = $1; };
3390 index_name: ColId { $$ = $1; };
3393 * Include date/time keywords as SQL92 extension.
3394 * Include TYPE as a SQL92 unreserved keyword. - thomas 1997-10-05
3396 name: ColId { $$ = $1; };
3398 date: Sconst { $$ = $1; };
3399 file_name: Sconst { $$ = $1; };
3400 recipe_name: Id { $$ = $1; };
3403 * Include TRUE/FALSE for SQL3 support. - thomas 1997-10-24
3407 A_Const *n = makeNode(A_Const);
3408 n->val.type = T_Integer;
3409 n->val.val.ival = $1;
3414 A_Const *n = makeNode(A_Const);
3415 n->val.type = T_Float;
3416 n->val.val.dval = $1;
3421 A_Const *n = makeNode(A_Const);
3422 n->val.type = T_String;
3423 n->val.val.str = $1;
3428 A_Const *n = makeNode(A_Const);
3430 n->val.type = T_String;
3431 n->val.val.str = $2;
3435 { $$ = (Node *)$1; }
3438 A_Const *n = makeNode(A_Const);
3439 n->val.type = T_String;
3440 n->val.val.str = "t";
3445 A_Const *n = makeNode(A_Const);
3446 n->val.type = T_String;
3447 n->val.val.str = "f";
3454 $$ = makeNode(ParamNo);
3459 NumConst: Iconst { $$ = makeInteger($1); }
3460 | FCONST { $$ = makeFloat($1); }
3463 Iconst: ICONST { $$ = $1; };
3464 Sconst: SCONST { $$ = $1; };
3466 /* Column and type identifier
3467 * Does not include explicit datetime types
3468 * since these must be decoupled in Typename syntax.
3469 * Use ColId for most identifiers. - thomas 1997-10-21
3471 Id: IDENT { $$ = $1; };
3473 /* Column identifier
3474 * Include date/time keywords as SQL92 extension.
3475 * Include TYPE as a SQL92 unreserved keyword. - thomas 1997-10-05
3476 * Add other keywords. Note that as the syntax expands,
3477 * some of these keywords will have to be removed from this
3478 * list due to shift/reduce conflicts in yacc. If so, move
3479 * down to the ColLabel entity. - thomas 1997-11-06
3481 ColId: Id { $$ = $1; }
3482 | datetime { $$ = $1; }
3483 | ACTION { $$ = "action"; }
3484 | DATABASE { $$ = "database"; }
3485 | DELIMITERS { $$ = "delimiters"; }
3486 | FUNCTION { $$ = "function"; }
3487 | INDEX { $$ = "index"; }
3488 | KEY { $$ = "key"; }
3489 | LANGUAGE { $$ = "language"; }
3490 | LIGHT { $$ = "light"; }
3491 | LOCATION { $$ = "location"; }
3492 | MATCH { $$ = "match"; }
3493 | OPERATOR { $$ = "operator"; }
3494 | OPTION { $$ = "option"; }
3495 | PRIVILEGES { $$ = "privileges"; }
3496 | RECIPE { $$ = "recipe"; }
3497 | TIME { $$ = "time"; }
3498 | TRIGGER { $$ = "trigger"; }
3499 | TYPE_P { $$ = "type"; }
3500 | VERSION { $$ = "version"; }
3501 | ZONE { $$ = "zone"; }
3505 * Allowed labels in "AS" clauses.
3506 * Include TRUE/FALSE SQL3 reserved words for Postgres backward
3507 * compatibility. Cannot allow this for column names since the
3508 * syntax would not distinguish between the constant value and
3509 * a column name. - thomas 1997-10-24
3510 * Add other keywords to this list. Note that they appear here
3511 * rather than in ColId if there was a shift/reduce conflict
3512 * when used as a full identifier. - thomas 1997-11-06
3514 ColLabel: ColId { $$ = $1; }
3515 | ARCHIVE { $$ = "archive"; }
3516 | CLUSTER { $$ = "cluster"; }
3517 | CONSTRAINT { $$ = "constraint"; }
3518 | CROSS { $$ = "cross"; }
3519 | FOREIGN { $$ = "foreign"; }
3520 | GROUP { $$ = "group"; }
3521 | LOAD { $$ = "load"; }
3522 | ORDER { $$ = "order"; }
3523 | POSITION { $$ = "position"; }
3524 | PRECISION { $$ = "precision"; }
3525 | STORE { $$ = "store"; }
3526 | TABLE { $$ = "table"; }
3527 | TRANSACTION { $$ = "transaction"; }
3528 | TRUE_P { $$ = "true"; }
3529 | FALSE_P { $$ = "false"; }
3532 SpecialRuleRelation: CURRENT
3537 elog(WARN,"CURRENT used in non-rule query",NULL);
3544 elog(WARN,"NEW used in non-rule query",NULL);
3553 static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr)
3555 A_Expr *a = makeNode(A_Expr);
3564 static Node *makeIndexable(char *opname, Node *lexpr, Node *rexpr)
3566 Node *result = NULL;
3568 /* we do this so indexes can be used */
3569 if (strcmp(opname,"~") == 0 ||
3570 strcmp(opname,"~*") == 0)
3572 if (nodeTag(rexpr) == T_A_Const &&
3573 ((A_Const *)rexpr)->val.type == T_String &&
3574 ((A_Const *)rexpr)->val.val.str[0] == '^')
3576 A_Const *n = (A_Const *)rexpr;
3577 char *match_least = palloc(strlen(n->val.val.str)+2);
3578 char *match_most = palloc(strlen(n->val.val.str)+2);
3579 int pos, match_pos=0;
3581 /* skip leading ^ */
3582 for (pos = 1; n->val.val.str[pos]; pos++)
3584 if (n->val.val.str[pos] == '.' ||
3585 n->val.val.str[pos] == '?' ||
3586 n->val.val.str[pos] == '*' ||
3587 n->val.val.str[pos] == '[' ||
3588 n->val.val.str[pos] == '$' ||
3589 (strcmp(opname,"~*") == 0 && isalpha(n->val.val.str[pos])))
3591 if (n->val.val.str[pos] == '\\')
3593 match_least[match_pos] = n->val.val.str[pos];
3594 match_most[match_pos++] = n->val.val.str[pos];
3599 A_Const *least = makeNode(A_Const);
3600 A_Const *most = makeNode(A_Const);
3602 /* make strings to be used in index use */
3603 match_least[match_pos] = '\0';
3604 match_most[match_pos] = '\377';
3605 match_most[match_pos+1] = '\0';
3606 least->val.type = T_String;
3607 least->val.val.str = match_least;
3608 most->val.type = T_String;
3609 most->val.val.str = match_most;
3610 result = makeA_Expr(AND, NULL,
3611 makeA_Expr(OP, "~", lexpr, rexpr),
3612 makeA_Expr(AND, NULL,
3613 makeA_Expr(OP, ">=", lexpr, (Node *)least),
3614 makeA_Expr(OP, "<=", lexpr, (Node *)most)));
3618 else if (strcmp(opname,"~~") == 0)
3620 if (nodeTag(rexpr) == T_A_Const &&
3621 ((A_Const *)rexpr)->val.type == T_String)
3623 A_Const *n = (A_Const *)rexpr;
3624 char *match_least = palloc(strlen(n->val.val.str)+2);
3625 char *match_most = palloc(strlen(n->val.val.str)+2);
3626 int pos, match_pos=0;
3628 for (pos = 0; n->val.val.str[pos]; pos++)
3630 if ((n->val.val.str[pos] == '%' &&
3631 n->val.val.str[pos+1] != '%') ||
3632 (n->val.val.str[pos] == '_' &&
3633 n->val.val.str[pos+1] != '_'))
3635 if (n->val.val.str[pos] == '%' ||
3636 n->val.val.str[pos] == '_' ||
3637 n->val.val.str[pos] == '\\')
3639 match_least[match_pos] = n->val.val.str[pos];
3640 match_most[match_pos++] = n->val.val.str[pos];
3645 A_Const *least = makeNode(A_Const);
3646 A_Const *most = makeNode(A_Const);
3648 /* make strings to be used in index use */
3649 match_least[match_pos] = '\0';
3650 match_most[match_pos] = '\377';
3651 match_most[match_pos+1] = '\0';
3652 least->val.type = T_String;
3653 least->val.val.str = match_least;
3654 most->val.type = T_String;
3655 most->val.val.str = match_most;
3656 result = makeA_Expr(AND, NULL,
3657 makeA_Expr(OP, "~~", lexpr, rexpr),
3658 makeA_Expr(AND, NULL,
3659 makeA_Expr(OP, ">=", lexpr, (Node *)least),
3660 makeA_Expr(OP, "<=", lexpr, (Node *)most)));
3666 result = makeA_Expr(OP, opname, lexpr, rexpr);
3668 } /* makeIndexable() */
3672 * Convert alternate type names to internal Postgres types.
3673 * Do not convert "float", since that is handled elsewhere
3674 * for FLOAT(p) syntax.
3677 xlateSqlType(char *name)
3679 if (!strcasecmp(name,"int")
3680 || !strcasecmp(name,"integer"))
3682 else if (!strcasecmp(name, "smallint"))
3684 else if (!strcasecmp(name, "real"))
3686 else if (!strcasecmp(name, "interval"))
3688 else if (!strcasecmp(name, "boolean"))
3692 } /* xlateSqlName() */
3695 void parser_init(Oid *typev, int nargs)
3697 QueryIsRule = FALSE;
3698 saved_relname[0]= '\0';
3699 saved_In_Expr = NULL;
3701 param_type_init(typev, nargs);
3705 /* FlattenStringList()
3706 * Traverse list of string nodes and convert to a single string.
3707 * Used for reconstructing string form of complex expressions.
3709 * Allocate at least one byte for terminator.
3712 FlattenStringList(List *list)
3720 nlist = length(list);
3723 v = (Value *)lfirst(l);
3730 s = (char*) palloc(len+1);
3735 v = (Value *)lfirst(l);
3739 if (l != NIL) strcat(s," ");
3744 printf( "flattened string is \"%s\"\n", s);
3748 } /* FlattenStringList() */
3751 /* makeConstantList()
3752 * Convert constant value node into string node.
3755 makeConstantList( A_Const *n)
3757 char *defval = NULL;
3758 if (nodeTag(n) != T_A_Const) {
3759 elog(WARN,"Cannot handle non-constant parameter",NULL);
3761 } else if (n->val.type == T_Float) {
3762 defval = (char*) palloc(20+1);
3763 sprintf( defval, "%g", n->val.val.dval);
3765 } else if (n->val.type == T_Integer) {
3766 defval = (char*) palloc(20+1);
3767 sprintf( defval, "%ld", n->val.val.ival);
3769 } else if (n->val.type == T_String) {
3770 defval = (char*) palloc(strlen( ((A_Const *) n)->val.val.str) + 3);
3771 strcpy( defval, "'");
3772 strcat( defval, ((A_Const *) n)->val.val.str);
3773 strcat( defval, "'");
3776 elog(WARN,"Internal error in makeConstantList(): cannot encode node",NULL);
3780 printf( "AexprConst argument is \"%s\"\n", defval);
3783 return( lcons( makeString(defval), NIL));
3784 } /* makeConstantList() */
3788 * Check input string for non-lowercase/non-numeric characters.
3789 * Returns either input string or input surrounded by double quotes.
3796 for (cp = rawid; *cp != '\0'; cp++)
3797 if (! (islower(*cp) || isdigit(*cp) || (*cp == '_'))) break;
3800 cp = palloc(strlen(rawid)+1);
3809 printf("fmtId- %sconvert %s to %s\n", ((cp == rawid)? "do not ": ""), rawid, cp);