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.71 1997/11/24 16:55:22 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 "parser/catalog_utils.h"
43 #include "parser/parse_query.h"
44 #include "utils/acl.h"
45 #include "catalog/catname.h"
46 #include "utils/elog.h"
47 #include "access/xact.h"
49 static char saved_relname[NAMEDATALEN]; /* need this for complex attributes */
50 static bool QueryIsRule = FALSE;
51 static Node *saved_In_Expr;
52 extern List *parsetree;
55 * If you need access to certain yacc-generated variables and find that
56 * they're static by default, uncomment the next line. (this is not a
59 /*#define __YYSCLASS*/
61 static char *xlateSqlType(char *);
62 static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
63 static List *makeConstantList( A_Const *node);
64 static char *FlattenStringList(List *list);
65 static char *fmtId(char *rawid);
66 static Node *makeIndexable(char *opname, Node *lexpr, Node *rexpr);
68 /* old versions of flex define this as a macro */
89 ConstraintDef *constrdef;
93 SortGroupBy *sortgroupby;
108 AddAttrStmt, ClosePortalStmt,
109 CopyStmt, CreateStmt, CreateSeqStmt, DefineStmt, DestroyStmt,
110 ExtendStmt, FetchStmt, GrantStmt, CreateTrigStmt, DropTrigStmt,
111 CreatePLangStmt, DropPLangStmt,
112 IndexStmt, ListenStmt, OptimizableStmt,
113 ProcedureStmt, RecipeStmt, RemoveAggrStmt, RemoveOperStmt,
114 RemoveFuncStmt, RemoveStmt,
115 RenameStmt, RevokeStmt, RuleStmt, TransactionStmt, ViewStmt, LoadStmt,
116 CreatedbStmt, DestroydbStmt, VacuumStmt, RetrieveStmt, CursorStmt,
117 ReplaceStmt, AppendStmt, NotifyStmt, DeleteStmt, ClusterStmt,
118 ExplainStmt, VariableSetStmt, VariableShowStmt, VariableResetStmt
120 %type <str> opt_database, location
122 %type <node> SubSelect
123 %type <str> join_expr, join_outer, join_spec
124 %type <boolean> TriggerActionTime, TriggerForSpec, PLangTrusted
126 %type <str> TriggerEvents, TriggerFuncArg
128 %type <str> relation_name, copy_file_name, copy_delimiter, def_name,
129 database_name, access_method_clause, access_method, attr_name,
130 class, index_name, name, file_name, recipe_name, aggr_argtype
132 %type <str> opt_id, opt_portal_name,
133 all_Op, MathOp, opt_name, opt_unique,
134 result, OptUseOp, opt_class, SpecialRuleRelation
136 %type <str> privileges, operation_commalist, grantee
137 %type <chr> operation, TriggerOneEvent
139 %type <list> stmtblock, stmtmulti,
140 relation_name_list, OptTableElementList, tableElementList,
141 OptInherit, OptConstraint, ConstraintList, definition,
142 opt_with, def_args, def_name_list, func_argtypes,
143 oper_argtypes, OptStmtList, OptStmtBlock, OptStmtMulti,
144 opt_column_list, columnList, opt_va_list, va_list,
145 sort_clause, sortby_list, index_params, index_list, name_list,
146 from_clause, from_list, opt_array_bounds, nest_array_bounds,
147 expr_list, attrs, res_target_list, res_target_list2,
148 def_list, opt_indirection, group_clause, groupby_list, TriggerFuncArgs
150 %type <list> union_clause, select_list
151 %type <list> join_list
154 %type <boolean> opt_union
156 %type <node> position_expr
157 %type <list> extract_list, position_list
158 %type <list> substr_list, substr_from, substr_for, trim_list
159 %type <list> opt_interval
161 %type <boolean> opt_inh_star, opt_binary, opt_instead, opt_with_copy,
162 index_opt_unique, opt_verbose, opt_analyze
164 %type <ival> copy_dirn, def_type, opt_direction, remove_type,
167 %type <ival> fetch_how_many
169 %type <list> OptSeqList
170 %type <defelt> OptSeqElem
172 %type <dstmt> def_rest
173 %type <astmt> insert_rest
175 %type <coldef> columnDef, alter_clause
176 %type <defelt> def_elem
177 %type <node> def_arg, columnElem, where_clause,
178 a_expr, a_expr_or_null, AexprConst,
179 in_expr, in_expr_nodes, not_in_expr, not_in_expr_nodes,
181 %type <value> NumConst
182 %type <attr> event_object, attr
183 %type <sortgroupby> groupby
184 %type <sortgroupby> sortby
185 %type <ielem> index_elem, func_index
186 %type <range> from_val
187 %type <relexp> relation_expr
188 %type <target> res_target_el, res_target_el2
189 %type <paramno> ParamNo
191 %type <typnam> Typename, opt_type, Array, Generic, Character, Datetime, Numeric
192 %type <str> generic, character, datetime
193 %type <str> opt_charset, opt_collate
194 %type <str> opt_float, opt_numeric, opt_decimal
195 %type <boolean> opt_varying, opt_timezone
199 %type <str> Id, var_value, zone_value
200 %type <str> ColId, ColLabel
202 %type <constrdef> ConstraintElem, ConstraintDef
204 %type <list> constraint_elem
205 %type <list> default_expr
206 %type <str> opt_default
207 %type <boolean> opt_constraint
208 %type <list> key_actions, key_action
209 %type <str> key_match, key_reference
212 * If you make any token changes, remember to:
213 * - use "yacc -d" and update parse.h
214 * - update the keyword table in parser/keywords.c
217 /* Reserved word tokens
218 * SQL92 syntax has many type-specific constructs.
219 * So, go ahead and make these types reserved words,
220 * and call-out the syntax explicitly.
221 * This gets annoying when trying to also retain Postgres' nice
222 * type-extensible features, but we don't really have a choice.
223 * - thomas 1997-10-11
226 /* Keywords (in SQL92 reserved words) */
227 %token ACTION, ADD, ALL, ALTER, AND, ARCHIVE, AS, ASC,
228 BEGIN_TRANS, BETWEEN, BOTH, BY,
229 CASCADE, CAST, CHAR, CHARACTER, CHECK, CLOSE, COLLATE, COLUMN, COMMIT,
230 CONSTRAINT, CREATE, CROSS, CURRENT, CURRENT_DATE, CURRENT_TIME,
231 CURRENT_TIMESTAMP, CURRENT_USER, CURSOR,
232 DAY_P, DECIMAL, DECLARE, DEFAULT, DELETE, DESC, DISTINCT, DOUBLE, DROP,
233 END_TRANS, EXECUTE, EXISTS, EXTRACT,
234 FETCH, FLOAT, FOR, FOREIGN, FROM, FULL,
235 GRANT, GROUP, HAVING, HOUR_P,
236 IN, INNER_P, INSERT, INTERVAL, INTO, IS,
237 JOIN, KEY, LANGUAGE, LEADING, LEFT, LIKE, LOCAL,
238 MATCH, MINUTE_P, MONTH_P,
239 NATIONAL, NATURAL, NCHAR, NO, NOT, NOTIFY, NOTNULL, NULL_P, NUMERIC,
240 ON, OPTION, OR, ORDER, OUTER_P,
241 PARTIAL, POSITION, PRECISION, PRIMARY, PRIVILEGES, PROCEDURE, PUBLIC,
242 REFERENCES, REVOKE, RIGHT, ROLLBACK,
243 SECOND_P, SELECT, SET, SUBSTRING,
244 TABLE, TIME, TIMESTAMP, TO, TRAILING, TRANSACTION, TRIM,
245 UNION, UNIQUE, UPDATE, USING,
246 VALUES, VARCHAR, VARYING, VERBOSE, VERSION, VIEW,
247 WHERE, WITH, WORK, YEAR_P, ZONE
249 /* Keywords (in SQL3 reserved words) */
250 %token FALSE_P, TRIGGER, TRUE_P
252 /* Keywords (in SQL92 non-reserved words) */
255 /* Keywords for Postgres support (not in SQL92 reserved words) */
256 %token ABORT_TRANS, ACL, AFTER, AGGREGATE, ANALYZE,
257 APPEND, BACKWARD, BEFORE, BINARY, CHANGE, CLUSTER, COPY,
258 DATABASE, DELIMITERS, DO, EXPLAIN, EXTEND,
259 FORWARD, FUNCTION, HANDLER,
260 INDEX, INHERITS, INSTEAD, ISNULL,
261 LANCOMPILER, LISTEN, LOAD, LOCATION, MERGE, MOVE,
262 NEW, NONE, NOTHING, OIDS, OPERATOR, PROCEDURAL,
263 RECIPE, RENAME, REPLACE, RESET, RETRIEVE, RETURNS, RULE,
264 SEQUENCE, SETOF, SHOW, STDIN, STDOUT, TRUSTED,
265 VACUUM, VERBOSE, VERSION
267 /* Special keywords, not in the query language - see the "lex" file */
268 %token <str> IDENT, SCONST, Op
269 %token <ival> ICONST, PARAM
272 /* these are not real. they are here so that they get generated as #define's*/
289 %left '|' /* this is the relation union op, not logical or */
290 /* Unary Operators */
292 %left ';' /* end of statement or natural log */
305 { parsetree = lcons($1,NIL); }
308 stmtmulti: stmtmulti stmt ';'
309 { $$ = lappend($1, $2); }
311 { $$ = lappend($1, $2); }
313 { $$ = lcons($1,NIL); }
356 /*****************************************************************************
358 * Set PG internal variable
359 * SET name TO 'var_value'
360 * Include SQL92 syntax (thomas 1997-10-22):
361 * SET TIME ZONE 'var_value'
363 *****************************************************************************/
365 VariableSetStmt: SET ColId TO var_value
367 VariableSetStmt *n = makeNode(VariableSetStmt);
372 | SET ColId '=' var_value
374 VariableSetStmt *n = makeNode(VariableSetStmt);
379 | SET TIME ZONE zone_value
381 VariableSetStmt *n = makeNode(VariableSetStmt);
382 n->name = "timezone";
388 var_value: Sconst { $$ = $1; }
389 | DEFAULT { $$ = NULL; }
392 zone_value: Sconst { $$ = $1; }
393 | DEFAULT { $$ = NULL; }
394 | LOCAL { $$ = "default"; }
397 VariableShowStmt: SHOW ColId
399 VariableShowStmt *n = makeNode(VariableShowStmt);
405 VariableShowStmt *n = makeNode(VariableShowStmt);
406 n->name = "timezone";
411 VariableResetStmt: RESET ColId
413 VariableResetStmt *n = makeNode(VariableResetStmt);
419 VariableResetStmt *n = makeNode(VariableResetStmt);
420 n->name = "timezone";
426 /*****************************************************************************
429 * addattr ( attr1 = type1 .. attrn = typen ) to <relname> [*]
431 *****************************************************************************/
433 AddAttrStmt: ALTER TABLE relation_name opt_inh_star alter_clause
435 AddAttrStmt *n = makeNode(AddAttrStmt);
443 alter_clause: ADD opt_column columnDef
447 | ADD '(' tableElementList ')'
449 ColumnDef *lp = lfirst($3);
452 elog(WARN,"ALTER TABLE/ADD() allows one column only",NULL);
455 | DROP opt_column ColId
456 { elog(WARN,"ALTER TABLE/DROP COLUMN not yet implemented",NULL); }
457 | ALTER opt_column ColId SET opt_default
458 { elog(WARN,"ALTER TABLE/ALTER COLUMN/SET DEFAULT not yet implemented",NULL); }
459 | ALTER opt_column ColId DROP DEFAULT
460 { elog(WARN,"ALTER TABLE/ALTER COLUMN/DROP DEFAULT not yet implemented",NULL); }
462 { elog(WARN,"ALTER TABLE/ADD CONSTRAINT not yet implemented",NULL); }
465 columnDef: ColId Typename opt_default opt_constraint
467 $$ = makeNode(ColumnDef);
471 $$->is_not_null = $4;
475 opt_default: DEFAULT default_expr
477 $$ = FlattenStringList($2);
479 | /*EMPTY*/ { $$ = NULL; }
482 default_expr: AexprConst
483 { $$ = makeConstantList((A_Const *) $1); }
485 { $$ = lcons( makeString("NULL"), NIL); }
486 | '-' default_expr %prec UMINUS
487 { $$ = lcons( makeString( "-"), $2); }
488 | default_expr '+' default_expr
489 { $$ = nconc( $1, lcons( makeString( "+"), $3)); }
490 | default_expr '-' default_expr
491 { $$ = nconc( $1, lcons( makeString( "-"), $3)); }
492 | default_expr '/' default_expr
493 { $$ = nconc( $1, lcons( makeString( "/"), $3)); }
494 | default_expr '*' default_expr
495 { $$ = nconc( $1, lcons( makeString( "*"), $3)); }
496 | default_expr '=' default_expr
497 { elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
498 | default_expr '<' default_expr
499 { elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
500 | default_expr '>' default_expr
501 { elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
503 { $$ = lcons( makeString( ":"), $2); }
505 { $$ = lcons( makeString( ";"), $2); }
507 { $$ = lcons( makeString( "|"), $2); }
508 | default_expr TYPECAST Typename
510 $3->name = fmtId($3->name);
511 $$ = nconc( lcons( makeString( "CAST"), $1), makeList( makeString("AS"), $3, -1));
513 | CAST default_expr AS Typename
515 $4->name = fmtId($4->name);
516 $$ = nconc( lcons( makeString( "CAST"), $2), makeList( makeString("AS"), $4, -1));
518 | '(' default_expr ')'
519 { $$ = lappend( lcons( makeString( "("), $2), makeString( ")")); }
520 | name '(' default_expr ')'
522 $$ = makeList( makeString($1), makeString("("), -1);
524 $$ = lappend( $$, makeString(")"));
528 $$ = makeList( makeString($1), makeString("("), -1);
529 $$ = lappend( $$, makeString(")"));
531 | default_expr Op default_expr
533 if (!strcmp("<=", $2) || !strcmp(">=", $2))
534 elog(WARN,"boolean expressions not supported in DEFAULT",NULL);
535 $$ = nconc( $1, lcons( makeString( $2), $3));
538 { $$ = lcons( makeString( $1), $2); }
540 { $$ = lappend( $1, makeString( $2)); }
541 /* XXX - thomas 1997-10-07 v6.2 function-specific code to be changed */
543 { $$ = lcons( makeString( "date( 'current'::datetime + '0 sec')"), NIL); }
545 { $$ = lcons( makeString( "'now'::time"), NIL); }
546 | CURRENT_TIME '(' Iconst ')'
549 elog(NOTICE,"CURRENT_TIME(p) precision must be zero",NULL);
550 $$ = lcons( makeString( "'now'::time"), NIL);
553 { $$ = lcons( makeString( "now()"), NIL); }
554 | CURRENT_TIMESTAMP '(' Iconst ')'
557 elog(NOTICE,"CURRENT_TIMESTAMP(p) precision must be zero",NULL);
558 $$ = lcons( makeString( "now()"), NIL);
561 { $$ = lcons( makeString( "CURRENT_USER"), NIL); }
564 opt_constraint: NOT NULL_P { $$ = TRUE; }
565 | NOTNULL { $$ = TRUE; }
568 elog(WARN,"CREATE TABLE/UNIQUE not yet implemented",NULL);
573 elog(WARN,"CREATE TABLE/PRIMARY KEY not yet implemented",NULL);
576 | REFERENCES ColId opt_column_list key_match key_actions
578 elog(WARN,"CREATE TABLE/FOREIGN KEY not yet implemented",NULL);
581 | /* EMPTY */ { $$ = FALSE; }
585 /*****************************************************************************
590 *****************************************************************************/
592 ClosePortalStmt: CLOSE opt_id
594 ClosePortalStmt *n = makeNode(ClosePortalStmt);
601 /*****************************************************************************
604 * COPY [BINARY] <relname> FROM/TO
605 * [USING DELIMITERS <delimiter>]
607 *****************************************************************************/
609 CopyStmt: COPY opt_binary relation_name opt_with_copy copy_dirn copy_file_name copy_delimiter
611 CopyStmt *n = makeNode(CopyStmt);
629 * copy_file_name NULL indicates stdio is used. Whether stdin or stdout is
630 * used depends on the direction. (It really doesn't make sense to copy from
631 * stdout. We silently correct the "typo". - AY 9/94
633 copy_file_name: Sconst { $$ = $1; }
634 | STDIN { $$ = NULL; }
635 | STDOUT { $$ = NULL; }
638 opt_binary: BINARY { $$ = TRUE; }
639 | /*EMPTY*/ { $$ = FALSE; }
642 opt_with_copy: WITH OIDS { $$ = TRUE; }
643 | /* EMPTY */ { $$ = FALSE; }
647 * the default copy delimiter is tab but the user can configure it
649 copy_delimiter: USING DELIMITERS Sconst { $$ = $3;}
650 | /* EMPTY */ { $$ = "\t"; }
654 /*****************************************************************************
659 *****************************************************************************/
661 CreateStmt: CREATE TABLE relation_name '(' OptTableElementList ')'
662 OptInherit OptConstraint OptArchiveType
664 CreateStmt *n = makeNode(CreateStmt);
673 OptTableElementList: tableElementList { $$ = $1; }
674 | /* EMPTY */ { $$ = NULL; }
678 tableElementList ',' columnDef
679 { $$ = lappend($1, $3); }
681 { $$ = lcons($1, NIL); }
685 * This was removed in 6.3, but we keep it so people can upgrade
686 * with old pg_dump scripts.
688 OptArchiveType: ARCHIVE '=' NONE { }
692 OptInherit: INHERITS '(' relation_name_list ')' { $$ = $3; }
693 | /*EMPTY*/ { $$ = NIL; }
696 OptConstraint: ConstraintList { $$ = $1; }
697 | /*EMPTY*/ { $$ = NULL; }
701 ConstraintList ',' ConstraintElem
702 { $$ = lappend($1, $3); }
704 { $$ = lcons($1, NIL); }
708 CONSTRAINT name ConstraintDef
710 $3->name = fmtId($2);
713 | ConstraintDef { $$ = $1; }
716 ConstraintDef: CHECK constraint_elem
718 ConstraintDef *constr = palloc (sizeof(ConstraintDef));
719 constr->type = CONSTR_CHECK;
721 constr->def = FlattenStringList($2);
724 | UNIQUE '(' columnList ')'
725 { elog(WARN,"CREATE TABLE/UNIQUE not yet implemented",NULL); }
726 | PRIMARY KEY '(' columnList ')'
727 { elog(WARN,"CREATE TABLE/PRIMARY KEY not yet implemented",NULL); }
728 | FOREIGN KEY '(' columnList ')' REFERENCES ColId opt_column_list key_match key_actions
729 { elog(WARN,"CREATE TABLE/FOREIGN KEY not yet implemented",NULL); }
732 constraint_elem: AexprConst
733 { $$ = makeConstantList((A_Const *) $1); }
735 { $$ = lcons( makeString("NULL"), NIL); }
738 $$ = lcons( makeString(fmtId($1)), NIL);
740 | '-' constraint_elem %prec UMINUS
741 { $$ = lcons( makeString( "-"), $2); }
742 | constraint_elem '+' constraint_elem
743 { $$ = nconc( $1, lcons( makeString( "+"), $3)); }
744 | constraint_elem '-' constraint_elem
745 { $$ = nconc( $1, lcons( makeString( "-"), $3)); }
746 | constraint_elem '/' constraint_elem
747 { $$ = nconc( $1, lcons( makeString( "/"), $3)); }
748 | constraint_elem '*' constraint_elem
749 { $$ = nconc( $1, lcons( makeString( "*"), $3)); }
750 | constraint_elem '=' constraint_elem
751 { $$ = nconc( $1, lcons( makeString( "="), $3)); }
752 | constraint_elem '<' constraint_elem
753 { $$ = nconc( $1, lcons( makeString( "<"), $3)); }
754 | constraint_elem '>' constraint_elem
755 { $$ = nconc( $1, lcons( makeString( ">"), $3)); }
756 | ':' constraint_elem
757 { $$ = lcons( makeString( ":"), $2); }
758 | ';' constraint_elem
759 { $$ = lcons( makeString( ";"), $2); }
760 | '|' constraint_elem
761 { $$ = lcons( makeString( "|"), $2); }
762 | constraint_elem TYPECAST Typename
764 $3->name = fmtId($3->name);
765 $$ = nconc( lcons( makeString( "CAST"), $1), makeList( makeString("AS"), $3, -1));
767 | CAST constraint_elem AS Typename
769 $4->name = fmtId($4->name);
770 $$ = nconc( lcons( makeString( "CAST"), $2), makeList( makeString("AS"), $4, -1));
772 | '(' constraint_elem ')'
773 { $$ = lappend( lcons( makeString( "("), $2), makeString( ")")); }
774 | name '(' constraint_elem ')'
776 $$ = makeList( makeString($1), makeString("("), -1);
778 $$ = lappend( $$, makeString(")"));
780 | constraint_elem Op constraint_elem
781 { $$ = nconc( $1, lcons( makeString( $2), $3)); }
782 | constraint_elem AND constraint_elem
783 { $$ = nconc( $1, lcons( makeString( "AND"), $3)); }
784 | constraint_elem OR constraint_elem
785 { $$ = nconc( $1, lcons( makeString( "OR"), $3)); }
787 { $$ = lcons( makeString( $1), $2); }
789 { $$ = lappend( $1, makeString( $2)); }
790 | constraint_elem IS TRUE_P
791 { $$ = lappend( $1, makeString( "IS TRUE")); }
792 | constraint_elem IS FALSE_P
793 { $$ = lappend( $1, makeString( "IS FALSE")); }
794 | constraint_elem IS NOT TRUE_P
795 { $$ = lappend( $1, makeString( "IS NOT TRUE")); }
796 | constraint_elem IS NOT FALSE_P
797 { $$ = lappend( $1, makeString( "IS NOT FALSE")); }
800 key_match: MATCH FULL { $$ = NULL; }
801 | MATCH PARTIAL { $$ = NULL; }
802 | /*EMPTY*/ { $$ = NULL; }
805 key_actions: key_action key_action { $$ = NIL; }
806 | key_action { $$ = NIL; }
807 | /*EMPTY*/ { $$ = NIL; }
810 key_action: ON DELETE key_reference { $$ = NIL; }
811 | ON UPDATE key_reference { $$ = NIL; }
814 key_reference: NO ACTION { $$ = NULL; }
815 | CASCADE { $$ = NULL; }
816 | SET DEFAULT { $$ = NULL; }
817 | SET NULL_P { $$ = NULL; }
821 /*****************************************************************************
824 * CREATE SEQUENCE seqname
826 *****************************************************************************/
828 CreateSeqStmt: CREATE SEQUENCE relation_name OptSeqList
830 CreateSeqStmt *n = makeNode(CreateSeqStmt);
838 OptSeqList OptSeqElem
839 { $$ = lappend($1, $2); }
843 OptSeqElem: IDENT NumConst
845 $$ = makeNode(DefElem);
847 $$->arg = (Node *)$2;
851 $$ = makeNode(DefElem);
853 $$->arg = (Node *)NULL;
857 /*****************************************************************************
860 * CREATE PROCEDURAL LANGUAGE ...
861 * DROP PROCEDURAL LANGUAGE ...
863 *****************************************************************************/
865 CreatePLangStmt: CREATE PLangTrusted PROCEDURAL LANGUAGE Sconst
866 HANDLER def_name LANCOMPILER Sconst
868 CreatePLangStmt *n = makeNode(CreatePLangStmt);
877 PLangTrusted: TRUSTED { $$ = TRUE; }
880 DropPLangStmt: DROP PROCEDURAL LANGUAGE Sconst
882 DropPLangStmt *n = makeNode(DropPLangStmt);
888 /*****************************************************************************
894 *****************************************************************************/
896 CreateTrigStmt: CREATE TRIGGER name TriggerActionTime TriggerEvents ON
897 relation_name TriggerForSpec EXECUTE PROCEDURE
898 name '(' TriggerFuncArgs ')'
900 CreateTrigStmt *n = makeNode(CreateTrigStmt);
907 memcpy (n->actions, $5, 4);
912 TriggerActionTime: BEFORE { $$ = TRUE; }
913 | AFTER { $$ = FALSE; }
916 TriggerEvents: TriggerOneEvent
918 char *e = palloc (4);
919 e[0] = $1; e[1] = 0; $$ = e;
921 | TriggerOneEvent OR TriggerOneEvent
923 char *e = palloc (4);
924 e[0] = $1; e[1] = $3; e[2] = 0; $$ = e;
926 | TriggerOneEvent OR TriggerOneEvent OR TriggerOneEvent
928 char *e = palloc (4);
929 e[0] = $1; e[1] = $3; e[2] = $5; e[3] = 0;
934 TriggerOneEvent: INSERT { $$ = 'i'; }
935 | DELETE { $$ = 'd'; }
936 | UPDATE { $$ = 'u'; }
939 TriggerForSpec: FOR name name
941 if ( strcmp ($2, "each") != 0 )
942 elog(WARN,"parser: syntax error near %s",$2);
943 if ( strcmp ($3, "row") == 0 )
945 else if ( strcmp ($3, "statement") == 0 )
948 elog(WARN,"parser: syntax error near %s",$3);
952 TriggerFuncArgs: TriggerFuncArg
953 { $$ = lcons($1, NIL); }
954 | TriggerFuncArgs ',' TriggerFuncArg
955 { $$ = lappend($1, $3); }
960 TriggerFuncArg: ICONST
962 char *s = (char *) palloc (256);
963 sprintf (s, "%d", $1);
968 char *s = (char *) palloc (256);
969 sprintf (s, "%g", $1);
972 | Sconst { $$ = $1; }
976 DropTrigStmt: DROP TRIGGER name ON relation_name
978 DropTrigStmt *n = makeNode(DropTrigStmt);
986 /*****************************************************************************
989 * define (type,operator,aggregate)
991 *****************************************************************************/
993 DefineStmt: CREATE def_type def_rest
1000 def_rest: def_name definition
1002 $$ = makeNode(DefineStmt);
1004 $$->definition = $2;
1008 def_type: OPERATOR { $$ = OPERATOR; }
1009 | Type { $$ = TYPE_P; }
1010 | AGGREGATE { $$ = AGGREGATE; }
1013 def_name: PROCEDURE { $$ = "procedure"; }
1014 | JOIN { $$ = "join"; }
1015 | ColId { $$ = $1; }
1016 | MathOp { $$ = $1; }
1020 definition: '(' def_list ')' { $$ = $2; }
1023 def_list: def_elem { $$ = lcons($1, NIL); }
1024 | def_list ',' def_elem { $$ = lappend($1, $3); }
1027 def_elem: def_name '=' def_arg
1029 $$ = makeNode(DefElem);
1031 $$->arg = (Node *)$3;
1035 $$ = makeNode(DefElem);
1037 $$->arg = (Node *)NULL;
1039 | DEFAULT '=' def_arg
1041 $$ = makeNode(DefElem);
1042 $$->defname = "default";
1043 $$->arg = (Node *)$3;
1047 def_arg: ColId { $$ = (Node *)makeString($1); }
1048 | all_Op { $$ = (Node *)makeString($1); }
1049 | NumConst { $$ = (Node *)$1; /* already a Value */ }
1050 | Sconst { $$ = (Node *)makeString($1); }
1053 TypeName *n = makeNode(TypeName);
1056 n->arrayBounds = NULL;
1059 | DOUBLE { $$ = (Node *)makeString("double"); }
1063 /*****************************************************************************
1066 * destroy <relname1> [, <relname2> .. <relnameN> ]
1068 *****************************************************************************/
1070 DestroyStmt: DROP TABLE relation_name_list
1072 DestroyStmt *n = makeNode(DestroyStmt);
1074 n->sequence = FALSE;
1077 | DROP SEQUENCE relation_name_list
1079 DestroyStmt *n = makeNode(DestroyStmt);
1087 /*****************************************************************************
1090 * fetch/move [forward | backward] [number | all ] [ in <portalname> ]
1092 *****************************************************************************/
1094 FetchStmt: FETCH opt_direction fetch_how_many opt_portal_name
1096 FetchStmt *n = makeNode(FetchStmt);
1103 | MOVE opt_direction fetch_how_many opt_portal_name
1105 FetchStmt *n = makeNode(FetchStmt);
1114 opt_direction: FORWARD { $$ = FORWARD; }
1115 | BACKWARD { $$ = BACKWARD; }
1116 | /*EMPTY*/ { $$ = FORWARD; /* default */ }
1119 fetch_how_many: Iconst
1121 if ($1 <= 0) elog(WARN,"Please specify nonnegative count for fetch",NULL); }
1122 | ALL { $$ = 0; /* 0 means fetch all tuples*/}
1123 | /*EMPTY*/ { $$ = 1; /*default*/ }
1126 opt_portal_name: IN name { $$ = $2;}
1127 | /*EMPTY*/ { $$ = NULL; }
1131 /*****************************************************************************
1134 * GRANT [privileges] ON [relation_name_list] TO [GROUP] grantee
1136 *****************************************************************************/
1138 GrantStmt: GRANT privileges ON relation_name_list TO grantee opt_with_grant
1140 $$ = (Node*)makeAclStmt($2,$4,$6,'+');
1146 privileges: ALL PRIVILEGES
1148 $$ = aclmakepriv("rwaR",0);
1152 $$ = aclmakepriv("rwaR",0);
1154 | operation_commalist
1160 operation_commalist: operation
1162 $$ = aclmakepriv("",$1);
1164 | operation_commalist ',' operation
1166 $$ = aclmakepriv($1,$3);
1173 $$ = ACL_MODE_RD_CHR;
1177 $$ = ACL_MODE_AP_CHR;
1181 $$ = ACL_MODE_WR_CHR;
1185 $$ = ACL_MODE_WR_CHR;
1189 $$ = ACL_MODE_RU_CHR;
1195 $$ = aclmakeuser("A","");
1199 $$ = aclmakeuser("G",$2);
1203 $$ = aclmakeuser("U",$1);
1207 opt_with_grant: WITH GRANT OPTION
1209 yyerror("WITH GRANT OPTION is not supported. Only relation owners can set privileges");
1215 /*****************************************************************************
1218 * REVOKE [privileges] ON [relation_name] FROM [user]
1220 *****************************************************************************/
1222 RevokeStmt: REVOKE privileges ON relation_name_list FROM grantee
1224 $$ = (Node*)makeAclStmt($2,$4,$6,'-');
1231 /*****************************************************************************
1234 * create index <indexname> on <relname>
1235 * using <access> "(" (<col> with <op>)+ ")" [with
1238 * [where <qual>] is not supported anymore
1239 *****************************************************************************/
1241 IndexStmt: CREATE index_opt_unique INDEX index_name ON relation_name
1242 access_method_clause '(' index_params ')' opt_with
1244 /* should check that access_method is valid,
1245 etc ... but doesn't */
1246 IndexStmt *n = makeNode(IndexStmt);
1250 n->accessMethod = $7;
1251 n->indexParams = $9;
1252 n->withClause = $11;
1253 n->whereClause = NULL;
1258 index_opt_unique: UNIQUE { $$ = TRUE; }
1259 | /*EMPTY*/ { $$ = FALSE; }
1262 access_method_clause: USING access_method { $$ = $2; }
1263 | /*EMPTY*/ { $$ = "btree"; }
1266 index_params: index_list { $$ = $1; }
1267 | func_index { $$ = lcons($1,NIL); }
1270 index_list: index_list ',' index_elem { $$ = lappend($1, $3); }
1271 | index_elem { $$ = lcons($1, NIL); }
1274 func_index: name '(' name_list ')' opt_type opt_class
1276 $$ = makeNode(IndexElem);
1284 index_elem: attr_name opt_type opt_class
1286 $$ = makeNode(IndexElem);
1294 opt_type: ':' Typename { $$ = $2;}
1295 | FOR Typename { $$ = $2;}
1296 | /*EMPTY*/ { $$ = NULL;}
1299 /* opt_class "WITH class" conflicts with preceeding opt_type
1300 * for Typename of "TIMESTAMP WITH TIME ZONE"
1301 * So, remove "WITH class" from the syntax. OK??
1302 * - thomas 1997-10-12
1303 * | WITH class { $$ = $2; }
1305 opt_class: class { $$ = $1; }
1306 | USING class { $$ = $2; }
1307 | /*EMPTY*/ { $$ = NULL; }
1311 /*****************************************************************************
1314 * extend index <indexname> [where <qual>]
1316 *****************************************************************************/
1318 ExtendStmt: EXTEND INDEX index_name where_clause
1320 ExtendStmt *n = makeNode(ExtendStmt);
1322 n->whereClause = $4;
1328 /*****************************************************************************
1331 * execute recipe <recipeName>
1333 *****************************************************************************/
1335 RecipeStmt: EXECUTE RECIPE recipe_name
1338 if (!IsTransactionBlock())
1339 elog(WARN,"EXECUTE RECIPE may only be used in begin/end transaction blocks",NULL);
1341 n = makeNode(RecipeStmt);
1348 /*****************************************************************************
1351 * define function <fname>
1352 * (language = <lang>, returntype = <typename>
1353 * [, arch_pct = <percentage | pre-defined>]
1354 * [, disk_pct = <percentage | pre-defined>]
1355 * [, byte_pct = <percentage | pre-defined>]
1356 * [, perbyte_cpu = <int | pre-defined>]
1357 * [, percall_cpu = <int | pre-defined>]
1359 * [arg is (<type-1> { , <type-n>})]
1360 * as <filename or code in language as appropriate>
1362 *****************************************************************************/
1364 ProcedureStmt: CREATE FUNCTION def_name def_args
1365 RETURNS def_arg opt_with AS Sconst LANGUAGE Sconst
1367 ProcedureStmt *n = makeNode(ProcedureStmt);
1370 n->returnType = (Node *)$6;
1377 opt_with: WITH definition { $$ = $2; }
1378 | /* EMPTY */ { $$ = NIL; }
1381 def_args: '(' def_name_list ')' { $$ = $2; }
1382 | '(' ')' { $$ = NIL; }
1385 def_name_list: name_list;
1387 /*****************************************************************************
1391 * remove function <funcname>
1392 * (REMOVE FUNCTION "funcname" (arg1, arg2, ...))
1393 * remove aggregate <aggname>
1394 * (REMOVE AGGREGATE "aggname" "aggtype")
1395 * remove operator <opname>
1396 * (REMOVE OPERATOR "opname" (leftoperand_typ rightoperand_typ))
1397 * remove type <typename>
1398 * (REMOVE TYPE "typename")
1399 * remove rule <rulename>
1400 * (REMOVE RULE "rulename")
1402 *****************************************************************************/
1404 RemoveStmt: DROP remove_type name
1406 RemoveStmt *n = makeNode(RemoveStmt);
1413 remove_type: Type { $$ = TYPE_P; }
1414 | INDEX { $$ = INDEX; }
1415 | RULE { $$ = RULE; }
1416 | VIEW { $$ = VIEW; }
1419 RemoveAggrStmt: DROP AGGREGATE name aggr_argtype
1421 RemoveAggrStmt *n = makeNode(RemoveAggrStmt);
1428 aggr_argtype: name { $$ = $1; }
1429 | '*' { $$ = NULL; }
1432 RemoveFuncStmt: DROP FUNCTION name '(' func_argtypes ')'
1434 RemoveFuncStmt *n = makeNode(RemoveFuncStmt);
1441 func_argtypes: name_list { $$ = $1; }
1442 | /*EMPTY*/ { $$ = NIL; }
1445 RemoveOperStmt: DROP OPERATOR all_Op '(' oper_argtypes ')'
1447 RemoveOperStmt *n = makeNode(RemoveOperStmt);
1454 all_Op: Op | MathOp;
1456 MathOp: '+' { $$ = "+"; }
1467 elog(WARN,"parser: argument type missing (use NONE for unary operators)",NULL);
1470 { $$ = makeList(makeString($1), makeString($3), -1); }
1471 | NONE ',' name /* left unary */
1472 { $$ = makeList(NULL, makeString($3), -1); }
1473 | name ',' NONE /* right unary */
1474 { $$ = makeList(makeString($1), NULL, -1); }
1478 /*****************************************************************************
1481 * rename <attrname1> in <relname> [*] to <attrname2>
1482 * rename <relname1> to <relname2>
1484 *****************************************************************************/
1486 RenameStmt: ALTER TABLE relation_name opt_inh_star
1487 RENAME opt_column opt_name TO name
1489 RenameStmt *n = makeNode(RenameStmt);
1498 opt_name: name { $$ = $1; }
1499 | /*EMPTY*/ { $$ = NULL; }
1502 opt_column: COLUMN { $$ = COLUMN; }
1503 | /*EMPTY*/ { $$ = 0; }
1507 /*****************************************************************************
1509 * QUERY: Define Rewrite Rule , Define Tuple Rule
1510 * Define Rule <old rules >
1512 * only rewrite rule is supported -- ay 9/94
1514 *****************************************************************************/
1516 RuleStmt: CREATE RULE name AS
1517 { QueryIsRule=TRUE; }
1518 ON event TO event_object where_clause
1519 DO opt_instead OptStmtList
1521 RuleStmt *n = makeNode(RuleStmt);
1525 n->whereClause = $10;
1532 OptStmtList: NOTHING { $$ = NIL; }
1533 | OptimizableStmt { $$ = lcons($1, NIL); }
1534 | '[' OptStmtBlock ']' { $$ = $2; }
1537 OptStmtBlock: OptStmtMulti
1540 { $$ = lcons($1, NIL); }
1543 OptStmtMulti: OptStmtMulti OptimizableStmt ';'
1544 { $$ = lappend($1, $2); }
1545 | OptStmtMulti OptimizableStmt
1546 { $$ = lappend($1, $2); }
1547 | OptimizableStmt ';'
1548 { $$ = lcons($1, NIL); }
1551 event_object: relation_name '.' attr_name
1553 $$ = makeNode(Attr);
1556 $$->attrs = lcons(makeString($3), NIL);
1557 $$->indirection = NIL;
1561 $$ = makeNode(Attr);
1565 $$->indirection = NIL;
1569 /* change me to select, update, etc. some day */
1570 event: SELECT { $$ = CMD_SELECT; }
1571 | UPDATE { $$ = CMD_UPDATE; }
1572 | DELETE { $$ = CMD_DELETE; }
1573 | INSERT { $$ = CMD_INSERT; }
1576 opt_instead: INSTEAD { $$ = TRUE; }
1577 | /* EMPTY */ { $$ = FALSE; }
1581 /*****************************************************************************
1584 * NOTIFY <relation_name> can appear both in rule bodies and
1585 * as a query-level command
1587 *****************************************************************************/
1589 NotifyStmt: NOTIFY relation_name
1591 NotifyStmt *n = makeNode(NotifyStmt);
1597 ListenStmt: LISTEN relation_name
1599 ListenStmt *n = makeNode(ListenStmt);
1606 /*****************************************************************************
1617 *****************************************************************************/
1619 TransactionStmt: ABORT_TRANS TRANSACTION
1621 TransactionStmt *n = makeNode(TransactionStmt);
1622 n->command = ABORT_TRANS;
1625 | BEGIN_TRANS TRANSACTION
1627 TransactionStmt *n = makeNode(TransactionStmt);
1628 n->command = BEGIN_TRANS;
1633 TransactionStmt *n = makeNode(TransactionStmt);
1634 n->command = BEGIN_TRANS;
1639 TransactionStmt *n = makeNode(TransactionStmt);
1640 n->command = END_TRANS;
1643 | END_TRANS TRANSACTION
1645 TransactionStmt *n = makeNode(TransactionStmt);
1646 n->command = END_TRANS;
1651 TransactionStmt *n = makeNode(TransactionStmt);
1652 n->command = ABORT_TRANS;
1658 TransactionStmt *n = makeNode(TransactionStmt);
1659 n->command = ABORT_TRANS;
1664 TransactionStmt *n = makeNode(TransactionStmt);
1665 n->command = BEGIN_TRANS;
1670 TransactionStmt *n = makeNode(TransactionStmt);
1671 n->command = END_TRANS;
1677 TransactionStmt *n = makeNode(TransactionStmt);
1678 n->command = END_TRANS;
1683 TransactionStmt *n = makeNode(TransactionStmt);
1684 n->command = ABORT_TRANS;
1690 /*****************************************************************************
1693 * define view <viewname> '('target-list ')' [where <quals> ]
1695 *****************************************************************************/
1697 ViewStmt: CREATE VIEW name AS RetrieveStmt
1699 ViewStmt *n = makeNode(ViewStmt);
1701 n->query = (Query *)$5;
1707 /*****************************************************************************
1712 *****************************************************************************/
1714 LoadStmt: LOAD file_name
1716 LoadStmt *n = makeNode(LoadStmt);
1723 /*****************************************************************************
1728 *****************************************************************************/
1730 CreatedbStmt: CREATE DATABASE database_name opt_database
1732 CreatedbStmt *n = makeNode(CreatedbStmt);
1739 opt_database: WITH LOCATION '=' location { $$ = $4; }
1740 | /*EMPTY*/ { $$ = NULL; }
1743 location: Sconst { $$ = $1; }
1744 | DEFAULT { $$ = NULL; }
1745 | /*EMPTY*/ { $$ = NULL; }
1748 /*****************************************************************************
1753 *****************************************************************************/
1755 DestroydbStmt: DROP DATABASE database_name
1757 DestroydbStmt *n = makeNode(DestroydbStmt);
1764 /*****************************************************************************
1767 * cluster <index_name> on <relation_name>
1769 *****************************************************************************/
1771 ClusterStmt: CLUSTER index_name ON relation_name
1773 ClusterStmt *n = makeNode(ClusterStmt);
1781 /*****************************************************************************
1786 *****************************************************************************/
1788 VacuumStmt: VACUUM opt_verbose opt_analyze
1790 VacuumStmt *n = makeNode(VacuumStmt);
1797 | VACUUM opt_verbose relation_name opt_analyze opt_va_list
1799 VacuumStmt *n = makeNode(VacuumStmt);
1804 if ( $5 != NIL && !$4 )
1805 elog(WARN,"parser: syntax error at or near \"(\"",NULL);
1810 opt_verbose: VERBOSE { $$ = TRUE; }
1811 | /* EMPTY */ { $$ = FALSE; }
1814 opt_analyze: ANALYZE { $$ = TRUE; }
1815 | /* EMPTY */ { $$ = FALSE; }
1818 opt_va_list: '(' va_list ')'
1825 { $$=lcons($1,NIL); }
1827 { $$=lappend($1,$3); }
1831 /*****************************************************************************
1836 *****************************************************************************/
1838 ExplainStmt: EXPLAIN opt_verbose OptimizableStmt
1840 ExplainStmt *n = makeNode(ExplainStmt);
1842 n->query = (Query*)$3;
1848 /*****************************************************************************
1850 * Optimizable Stmts: *
1852 * one of the five queries processed by the planner *
1854 * [ultimately] produces query-trees as specified *
1855 * in the query-spec document in ~postgres/ref *
1857 *****************************************************************************/
1859 OptimizableStmt: RetrieveStmt
1864 | DeleteStmt /* by default all are $$=$1 */
1868 /*****************************************************************************
1873 *****************************************************************************/
1875 AppendStmt: INSERT INTO relation_name opt_column_list insert_rest
1883 insert_rest: VALUES '(' res_target_list2 ')'
1885 $$ = makeNode(AppendStmt);
1886 $$->targetList = $3;
1887 $$->fromClause = NIL;
1888 $$->whereClause = NULL;
1890 | SELECT res_target_list2 from_clause where_clause
1892 $$ = makeNode(AppendStmt);
1893 $$->targetList = $2;
1894 $$->fromClause = $3;
1895 $$->whereClause = $4;
1899 opt_column_list: '(' columnList ')' { $$ = $2; }
1900 | /*EMPTY*/ { $$ = NIL; }
1904 columnList ',' columnElem
1905 { $$ = lappend($1, $3); }
1907 { $$ = lcons($1, NIL); }
1910 columnElem: ColId opt_indirection
1912 Ident *id = makeNode(Ident);
1914 id->indirection = $2;
1920 /*****************************************************************************
1925 *****************************************************************************/
1927 DeleteStmt: DELETE FROM relation_name
1930 DeleteStmt *n = makeNode(DeleteStmt);
1932 n->whereClause = $4;
1938 /*****************************************************************************
1941 * ReplaceStmt (UPDATE)
1943 *****************************************************************************/
1945 ReplaceStmt: UPDATE relation_name
1950 ReplaceStmt *n = makeNode(ReplaceStmt);
1954 n->whereClause = $6;
1960 /*****************************************************************************
1965 *****************************************************************************/
1967 CursorStmt: DECLARE name opt_binary CURSOR FOR
1968 SELECT opt_unique res_target_list2
1969 from_clause where_clause group_clause sort_clause
1971 CursorStmt *n = makeNode(CursorStmt);
1973 /* from PORTAL name */
1975 * 15 august 1991 -- since 3.0 postgres does locking
1976 * right, we discovered that portals were violating
1977 * locking protocol. portal locks cannot span xacts.
1978 * as a short-term fix, we installed the check here.
1981 if (!IsTransactionBlock())
1982 elog(WARN,"Named portals may only be used in begin/end transaction blocks",NULL);
1989 n->whereClause = $10;
1990 n->groupClause = $11;
1991 n->sortClause = $12;
1997 /*****************************************************************************
2002 *****************************************************************************/
2004 RetrieveStmt: SELECT opt_unique res_target_list2
2005 result from_clause where_clause
2006 group_clause having_clause
2007 union_clause sort_clause
2009 RetrieveStmt *n = makeNode(RetrieveStmt);
2014 n->whereClause = $6;
2015 n->groupClause = $7;
2016 n->havingClause = $8;
2017 n->selectClause = $9;
2018 n->sortClause = $10;
2023 union_clause: UNION opt_union select_list { $$ = $3; }
2024 | /*EMPTY*/ { $$ = NIL; }
2027 select_list: select_list UNION opt_union SubSelect
2028 { $$ = lappend($1, $4); }
2030 { $$ = lcons($1, NIL); }
2033 SubSelect: SELECT opt_unique res_target_list2
2034 from_clause where_clause
2035 group_clause having_clause
2037 SubSelect *n = makeNode(SubSelect);
2041 n->whereClause = $5;
2042 n->groupClause = $6;
2043 n->havingClause = $7;
2048 result: INTO TABLE relation_name
2054 opt_union: ALL { $$ = TRUE; }
2055 | /*EMPTY*/ { $$ = FALSE; }
2058 opt_unique: DISTINCT { $$ = "*"; }
2059 | DISTINCT ON ColId { $$ = $3; }
2060 | ALL { $$ = NULL; }
2061 | /*EMPTY*/ { $$ = NULL; }
2064 sort_clause: ORDER BY sortby_list { $$ = $3; }
2065 | /*EMPTY*/ { $$ = NIL; }
2068 sortby_list: sortby { $$ = lcons($1, NIL); }
2069 | sortby_list ',' sortby { $$ = lappend($1, $3); }
2072 sortby: ColId OptUseOp
2074 $$ = makeNode(SortGroupBy);
2080 | ColId '.' ColId OptUseOp
2082 $$ = makeNode(SortGroupBy);
2090 $$ = makeNode(SortGroupBy);
2098 OptUseOp: USING Op { $$ = $2; }
2099 | USING '<' { $$ = "<"; }
2100 | USING '>' { $$ = ">"; }
2102 | DESC { $$ = ">"; }
2103 | /*EMPTY*/ { $$ = "<"; /*default*/ }
2107 * jimmy bell-style recursive queries aren't supported in the
2110 * ...however, recursive addattr and rename supported. make special
2113 * XXX i believe '*' should be the default behavior, but...
2115 opt_inh_star: '*' { $$ = TRUE; }
2116 | /*EMPTY*/ { $$ = FALSE; }
2119 relation_name_list: name_list;
2122 { $$ = lcons(makeString($1),NIL); }
2123 | name_list ',' name
2124 { $$ = lappend($1,makeString($3)); }
2127 group_clause: GROUP BY groupby_list { $$ = $3; }
2128 | /*EMPTY*/ { $$ = NIL; }
2131 groupby_list: groupby { $$ = lcons($1, NIL); }
2132 | groupby_list ',' groupby { $$ = lappend($1, $3); }
2137 $$ = makeNode(SortGroupBy);
2145 $$ = makeNode(SortGroupBy);
2153 $$ = makeNode(SortGroupBy);
2161 having_clause: HAVING a_expr { $$ = $2; }
2162 | /*EMPTY*/ { $$ = NULL; }
2166 /*****************************************************************************
2168 * clauses common to all Optimizable Stmts:
2172 *****************************************************************************/
2174 from_clause: FROM '(' relation_expr join_expr JOIN relation_expr join_spec ')'
2177 elog(WARN,"JOIN not yet implemented",NULL);
2179 | FROM from_list { $$ = $2; }
2180 | /*EMPTY*/ { $$ = NIL; }
2183 from_list: from_list ',' from_val
2184 { $$ = lappend($1, $3); }
2185 | from_val CROSS JOIN from_val
2186 { elog(WARN,"CROSS JOIN not yet implemented",NULL); }
2188 { $$ = lcons($1, NIL); }
2191 from_val: relation_expr AS ColLabel
2193 $$ = makeNode(RangeVar);
2197 | relation_expr ColId
2199 $$ = makeNode(RangeVar);
2205 $$ = makeNode(RangeVar);
2211 join_expr: NATURAL join_expr { $$ = NULL; }
2213 { elog(WARN,"FULL OUTER JOIN not yet implemented",NULL); }
2215 { elog(WARN,"LEFT OUTER JOIN not yet implemented",NULL); }
2217 { elog(WARN,"RIGHT OUTER JOIN not yet implemented",NULL); }
2219 { elog(WARN,"OUTER JOIN not yet implemented",NULL); }
2221 { elog(WARN,"INNER JOIN not yet implemented",NULL); }
2223 { elog(WARN,"UNION JOIN not yet implemented",NULL); }
2225 { elog(WARN,"INNER JOIN not yet implemented",NULL); }
2228 join_outer: OUTER_P { $$ = NULL; }
2229 | /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
2232 join_spec: ON '(' a_expr ')' { $$ = NULL; }
2233 | USING '(' join_list ')' { $$ = NULL; }
2234 | /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
2237 join_list: join_using { $$ = lcons($1, NIL); }
2238 | join_list ',' join_using { $$ = lappend($1, $3); }
2243 $$ = makeNode(SortGroupBy);
2251 $$ = makeNode(SortGroupBy);
2259 $$ = makeNode(SortGroupBy);
2267 where_clause: WHERE a_expr { $$ = $2; }
2268 | /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
2271 relation_expr: relation_name
2273 /* normal relations */
2274 $$ = makeNode(RelExpr);
2278 | relation_name '*' %prec '='
2280 /* inheiritance query */
2281 $$ = makeNode(RelExpr);
2286 opt_array_bounds: '[' ']' nest_array_bounds
2287 { $$ = lcons(makeInteger(-1), $3); }
2288 | '[' Iconst ']' nest_array_bounds
2289 { $$ = lcons(makeInteger($2), $4); }
2294 nest_array_bounds: '[' ']' nest_array_bounds
2295 { $$ = lcons(makeInteger(-1), $3); }
2296 | '[' Iconst ']' nest_array_bounds
2297 { $$ = lcons(makeInteger($2), $4); }
2303 /*****************************************************************************
2306 * SQL92 introduces a large amount of type-specific syntax.
2307 * Define individual clauses to handle these cases, and use
2308 * the generic case to handle regular type-extensible Postgres syntax.
2309 * - thomas 1997-10-10
2311 *****************************************************************************/
2313 Typename: Array opt_array_bounds
2316 $$->arrayBounds = $2;
2318 /* Is this the name of a complex type? If so, implement
2321 if (!strcmp(saved_relname, $$->name))
2322 /* This attr is the same type as the relation
2323 * being defined. The classic example: create
2324 * emp(name=text,mgr=emp)
2327 else if (get_typrelid((Type)type($$->name)) != InvalidOid)
2328 /* (Eventually add in here that the set can only
2329 * contain one element.)
2350 $$ = makeNode(TypeName);
2351 $$->name = xlateSqlType($1);
2355 generic: Id { $$ = $1; }
2356 | TYPE_P { $$ = xlateSqlType("type"); }
2357 | DOUBLE PRECISION { $$ = xlateSqlType("float8"); }
2360 /* SQL92 numeric data types
2361 * Check FLOAT() precision limits assuming IEEE floating types.
2362 * Provide rudimentary DECIMAL() and NUMERIC() implementations
2363 * by checking parameters and making sure they match what is possible with INTEGER.
2364 * - thomas 1997-09-18
2366 Numeric: FLOAT opt_float
2368 $$ = makeNode(TypeName);
2369 $$->name = xlateSqlType($2);
2371 | DECIMAL opt_decimal
2373 $$ = makeNode(TypeName);
2374 $$->name = xlateSqlType("integer");
2376 | NUMERIC opt_numeric
2378 $$ = makeNode(TypeName);
2379 $$->name = xlateSqlType("integer");
2383 opt_float: '(' Iconst ')'
2386 elog(WARN,"precision for FLOAT must be at least 1",NULL);
2388 $$ = xlateSqlType("float4");
2390 $$ = xlateSqlType("float8");
2392 elog(WARN,"precision for FLOAT must be less than 16",NULL);
2396 $$ = xlateSqlType("float8");
2400 opt_numeric: '(' Iconst ',' Iconst ')'
2403 elog(WARN,"NUMERIC precision %d must be 9",$2);
2405 elog(WARN,"NUMERIC scale %d must be zero",$4);
2410 elog(WARN,"NUMERIC precision %d must be 9",$2);
2418 opt_decimal: '(' Iconst ',' Iconst ')'
2421 elog(WARN,"DECIMAL precision %d exceeds implementation limit of 9",$2);
2423 elog(WARN,"DECIMAL scale %d must be zero",$4);
2429 elog(WARN,"DECIMAL precision %d exceeds implementation limit of 9",$2);
2438 /* SQL92 character data types
2439 * The following implements CHAR() and VARCHAR().
2440 * We do it here instead of the 'Generic' production
2441 * because we don't want to allow arrays of VARCHAR().
2442 * I haven't thought about whether that will work or not.
2445 Character: character '(' Iconst ')'
2447 $$ = makeNode(TypeName);
2448 if (!strcasecmp($1, "char"))
2449 $$->name = xlateSqlType("bpchar");
2450 else if (!strcasecmp($1, "varchar"))
2451 $$->name = xlateSqlType("varchar");
2453 yyerror("parse error");
2455 elog(WARN,"length for '%s' type must be at least 1",$1);
2457 /* we can store a char() of length up to the size
2458 * of a page (8KB) - page headers and friends but
2459 * just to be safe here... - ay 6/95
2460 * XXX note this hardcoded limit - thomas 1997-07-13
2462 elog(WARN,"length for type '%s' cannot exceed 4096",$1);
2464 /* we actually implement this sort of like a varlen, so
2465 * the first 4 bytes is the length. (the difference
2466 * between this and "text" is that we blank-pad and
2467 * truncate where necessary
2469 $$->typlen = 4 + $3;
2473 $$ = makeNode(TypeName);
2474 $$->name = xlateSqlType($1);
2478 character: CHARACTER opt_varying opt_charset opt_collate
2481 if (($3 == NULL) || (strcasecmp($3, "sql_text") == 0)) {
2482 if ($2) type = xlateSqlType("varchar");
2483 else type = xlateSqlType("char");
2486 c = palloc(strlen("var") + strlen($3) + 1);
2489 type = xlateSqlType(c);
2491 type = xlateSqlType($3);
2495 elog(WARN,"COLLATE %s not yet implemented",$4);
2498 | CHAR opt_varying { $$ = xlateSqlType($2? "varchar": "char"); }
2499 | VARCHAR { $$ = xlateSqlType("varchar"); }
2500 | NATIONAL CHARACTER opt_varying { $$ = xlateSqlType($3? "varchar": "char"); }
2501 | NCHAR opt_varying { $$ = xlateSqlType($2? "varchar": "char"); }
2504 opt_varying: VARYING { $$ = TRUE; }
2505 | /*EMPTY*/ { $$ = FALSE; }
2508 opt_charset: CHARACTER SET ColId { $$ = $3; }
2509 | /*EMPTY*/ { $$ = NULL; }
2512 opt_collate: COLLATE ColId { $$ = $2; }
2513 | /*EMPTY*/ { $$ = NULL; }
2518 $$ = makeNode(TypeName);
2519 $$->name = xlateSqlType($1);
2521 | TIMESTAMP opt_timezone
2523 $$ = makeNode(TypeName);
2524 $$->name = xlateSqlType("timestamp");
2529 $$ = makeNode(TypeName);
2530 $$->name = xlateSqlType("time");
2532 | INTERVAL opt_interval
2534 $$ = makeNode(TypeName);
2535 $$->name = xlateSqlType("interval");
2539 datetime: YEAR_P { $$ = "year"; }
2540 | MONTH_P { $$ = "month"; }
2541 | DAY_P { $$ = "day"; }
2542 | HOUR_P { $$ = "hour"; }
2543 | MINUTE_P { $$ = "minute"; }
2544 | SECOND_P { $$ = "second"; }
2547 opt_timezone: WITH TIME ZONE { $$ = TRUE; }
2548 | /*EMPTY*/ { $$ = FALSE; }
2551 opt_interval: datetime { $$ = lcons($1, NIL); }
2552 | YEAR_P TO MONTH_P { $$ = NIL; }
2553 | DAY_P TO HOUR_P { $$ = NIL; }
2554 | DAY_P TO MINUTE_P { $$ = NIL; }
2555 | DAY_P TO SECOND_P { $$ = NIL; }
2556 | HOUR_P TO MINUTE_P { $$ = NIL; }
2557 | HOUR_P TO SECOND_P { $$ = NIL; }
2558 | /* EMPTY */ { $$ = NIL; }
2562 /*****************************************************************************
2564 * expression grammar, still needs some cleanup
2566 *****************************************************************************/
2568 a_expr_or_null: a_expr
2572 A_Const *n = makeNode(A_Const);
2573 n->val.type = T_Null;
2577 a_expr: attr opt_indirection
2579 $1->indirection = $2;
2584 | '-' a_expr %prec UMINUS
2585 { $$ = makeA_Expr(OP, "-", NULL, $2); }
2587 { $$ = makeA_Expr(OP, "+", $1, $3); }
2589 { $$ = makeA_Expr(OP, "-", $1, $3); }
2591 { $$ = makeA_Expr(OP, "/", $1, $3); }
2593 { $$ = makeA_Expr(OP, "*", $1, $3); }
2595 { $$ = makeA_Expr(OP, "<", $1, $3); }
2597 { $$ = makeA_Expr(OP, ">", $1, $3); }
2599 { $$ = makeA_Expr(OP, "=", $1, $3); }
2601 { $$ = makeA_Expr(OP, ":", NULL, $2); }
2603 { $$ = makeA_Expr(OP, ";", NULL, $2); }
2605 { $$ = makeA_Expr(OP, "|", NULL, $2); }
2606 | AexprConst TYPECAST Typename
2608 /* AexprConst can be either A_Const or ParamNo */
2609 if (nodeTag($1) == T_A_Const)
2610 ((A_Const *)$1)->typename = $3;
2612 ((ParamNo *)$1)->typename = $3;
2615 | CAST a_expr AS Typename
2618 /* AexprConst can be either A_Const or ParamNo */
2619 if (nodeTag($2) == T_A_Const) {
2620 ((A_Const *)$2)->typename = $4;
2621 } else if (nodeTag($2) == T_Param) {
2622 ((ParamNo *)$2)->typename = $4;
2623 /* otherwise, try to transform to a function call */
2625 FuncCall *n = makeNode(FuncCall);
2626 n->funcname = $4->name;
2627 n->args = lcons($2,NIL);
2631 | '(' a_expr_or_null ')'
2634 { $$ = makeIndexable($2,$1,$3); }
2635 | a_expr LIKE a_expr
2636 { $$ = makeIndexable("~~", $1, $3); }
2637 | a_expr NOT LIKE a_expr
2638 { $$ = makeA_Expr(OP, "!~~", $1, $4); }
2640 { $$ = makeA_Expr(OP, $1, NULL, $2); }
2642 { $$ = makeA_Expr(OP, $2, $1, NULL); }
2645 /* could be a column name or a relation_name */
2646 Ident *n = makeNode(Ident);
2648 n->indirection = NULL;
2653 FuncCall *n = makeNode(FuncCall);
2654 Ident *star = makeNode(Ident);
2656 /* cheap hack for aggregate (eg. count) */
2659 n->args = lcons(star, NIL);
2664 FuncCall *n = makeNode(FuncCall);
2671 A_Const *n = makeNode(A_Const);
2672 TypeName *t = makeNode(TypeName);
2674 n->val.type = T_String;
2675 n->val.val.str = "now";
2678 t->name = xlateSqlType("date");
2685 A_Const *n = makeNode(A_Const);
2686 TypeName *t = makeNode(TypeName);
2688 n->val.type = T_String;
2689 n->val.val.str = "now";
2692 t->name = xlateSqlType("time");
2697 | CURRENT_TIME '(' Iconst ')'
2699 FuncCall *n = makeNode(FuncCall);
2700 A_Const *s = makeNode(A_Const);
2701 TypeName *t = makeNode(TypeName);
2703 n->funcname = xlateSqlType("time");
2704 n->args = lcons(s, NIL);
2706 s->val.type = T_String;
2707 s->val.val.str = "now";
2710 t->name = xlateSqlType("time");
2714 elog(NOTICE,"CURRENT_TIME(p) precision must be zero",NULL);
2720 A_Const *n = makeNode(A_Const);
2721 TypeName *t = makeNode(TypeName);
2723 n->val.type = T_String;
2724 n->val.val.str = "now";
2727 t->name = xlateSqlType("timestamp");
2732 | CURRENT_TIMESTAMP '(' Iconst ')'
2734 FuncCall *n = makeNode(FuncCall);
2735 A_Const *s = makeNode(A_Const);
2736 TypeName *t = makeNode(TypeName);
2738 n->funcname = xlateSqlType("timestamp");
2739 n->args = lcons(s, NIL);
2741 s->val.type = T_String;
2742 s->val.val.str = "now";
2745 t->name = xlateSqlType("timestamp");
2749 elog(NOTICE,"CURRENT_TIMESTAMP(p) precision must be zero",NULL);
2755 FuncCall *n = makeNode(FuncCall);
2756 n->funcname = "getpgusername";
2760 /* We probably need to define an "exists" node,
2761 * since the optimizer could choose to find only one match.
2762 * Perhaps the first implementation could just check for
2763 * count(*) > 0? - thomas 1997-07-19
2765 | EXISTS '(' SubSelect ')'
2767 elog(WARN,"EXISTS not yet implemented",NULL);
2770 | EXTRACT '(' extract_list ')'
2772 FuncCall *n = makeNode(FuncCall);
2773 n->funcname = "date_part";
2777 | POSITION '(' position_list ')'
2779 FuncCall *n = makeNode(FuncCall);
2780 n->funcname = "strpos";
2784 | SUBSTRING '(' substr_list ')'
2786 FuncCall *n = makeNode(FuncCall);
2787 n->funcname = "substr";
2791 /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
2792 | TRIM '(' BOTH trim_list ')'
2794 FuncCall *n = makeNode(FuncCall);
2795 n->funcname = "btrim";
2799 | TRIM '(' LEADING trim_list ')'
2801 FuncCall *n = makeNode(FuncCall);
2802 n->funcname = "ltrim";
2806 | TRIM '(' TRAILING trim_list ')'
2808 FuncCall *n = makeNode(FuncCall);
2809 n->funcname = "rtrim";
2813 | TRIM '(' trim_list ')'
2815 FuncCall *n = makeNode(FuncCall);
2816 n->funcname = "btrim";
2820 | name '(' expr_list ')'
2822 FuncCall *n = makeNode(FuncCall);
2828 { $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
2830 { $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
2832 { $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); }
2833 | a_expr IS NOT NULL_P
2834 { $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); }
2837 FuncCall *n = makeNode(FuncCall);
2838 n->funcname = "istrue";
2839 n->args = lcons($1,NIL);
2844 FuncCall *n = makeNode(FuncCall);
2845 n->funcname = "isfalse";
2846 n->args = lcons($1,NIL);
2849 | a_expr IS NOT TRUE_P
2851 FuncCall *n = makeNode(FuncCall);
2852 n->funcname = "isfalse";
2853 n->args = lcons($1,NIL);
2856 | a_expr IS NOT FALSE_P
2858 FuncCall *n = makeNode(FuncCall);
2859 n->funcname = "istrue";
2860 n->args = lcons($1,NIL);
2863 | a_expr BETWEEN AexprConst AND AexprConst
2865 $$ = makeA_Expr(AND, NULL,
2866 makeA_Expr(OP, ">=", $1, $3),
2867 makeA_Expr(OP, "<=", $1, $5));
2869 | a_expr NOT BETWEEN AexprConst AND AexprConst
2871 $$ = makeA_Expr(OR, NULL,
2872 makeA_Expr(OP, "<", $1, $4),
2873 makeA_Expr(OP, ">", $1, $6));
2875 | a_expr IN { saved_In_Expr = $1; } '(' in_expr ')'
2877 | a_expr NOT IN { saved_In_Expr = $1; } '(' not_in_expr ')'
2880 { $$ = makeA_Expr(AND, NULL, $1, $3); }
2882 { $$ = makeA_Expr(OR, NULL, $1, $3); }
2884 { $$ = makeA_Expr(NOT, NULL, NULL, $2); }
2887 opt_indirection: '[' a_expr ']' opt_indirection
2889 A_Indices *ai = makeNode(A_Indices);
2894 | '[' a_expr ':' a_expr ']' opt_indirection
2896 A_Indices *ai = makeNode(A_Indices);
2905 expr_list: a_expr_or_null
2906 { $$ = lcons($1, NIL); }
2907 | expr_list ',' a_expr_or_null
2908 { $$ = lappend($1, $3); }
2909 | expr_list USING a_expr
2910 { $$ = lappend($1, $3); }
2913 extract_list: datetime FROM a_expr
2915 A_Const *n = makeNode(A_Const);
2916 n->val.type = T_String;
2917 n->val.val.str = $1;
2918 $$ = lappend(lcons((Node *)n,NIL), $3);
2924 position_list: position_expr IN position_expr
2925 { $$ = makeList($3, $1, -1); }
2930 position_expr: attr opt_indirection
2932 $1->indirection = $2;
2937 | '-' position_expr %prec UMINUS
2938 { $$ = makeA_Expr(OP, "-", NULL, $2); }
2939 | position_expr '+' position_expr
2940 { $$ = makeA_Expr(OP, "+", $1, $3); }
2941 | position_expr '-' position_expr
2942 { $$ = makeA_Expr(OP, "-", $1, $3); }
2943 | position_expr '/' position_expr
2944 { $$ = makeA_Expr(OP, "/", $1, $3); }
2945 | position_expr '*' position_expr
2946 { $$ = makeA_Expr(OP, "*", $1, $3); }
2948 { $$ = makeA_Expr(OP, "|", NULL, $2); }
2949 | AexprConst TYPECAST Typename
2951 /* AexprConst can be either A_Const or ParamNo */
2952 if (nodeTag($1) == T_A_Const)
2953 ((A_Const *)$1)->typename = $3;
2955 ((ParamNo *)$1)->typename = $3;
2958 | CAST position_expr AS Typename
2961 /* AexprConst can be either A_Const or ParamNo */
2962 if (nodeTag($2) == T_A_Const) {
2963 ((A_Const *)$2)->typename = $4;
2964 } else if (nodeTag($2) == T_Param) {
2965 ((ParamNo *)$2)->typename = $4;
2966 /* otherwise, try to transform to a function call */
2968 FuncCall *n = makeNode(FuncCall);
2969 n->funcname = $4->name;
2970 n->args = lcons($2,NIL);
2974 | '(' position_expr ')'
2976 | position_expr Op position_expr
2977 { $$ = makeA_Expr(OP, $2, $1, $3); }
2979 { $$ = makeA_Expr(OP, $1, NULL, $2); }
2981 { $$ = makeA_Expr(OP, $2, $1, NULL); }
2984 /* could be a column name or a relation_name */
2985 Ident *n = makeNode(Ident);
2987 n->indirection = NULL;
2992 FuncCall *n = makeNode(FuncCall);
2997 | POSITION '(' position_list ')'
2999 FuncCall *n = makeNode(FuncCall);
3000 n->funcname = "strpos";
3004 | SUBSTRING '(' substr_list ')'
3006 FuncCall *n = makeNode(FuncCall);
3007 n->funcname = "substr";
3011 /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
3012 | TRIM '(' BOTH trim_list ')'
3014 FuncCall *n = makeNode(FuncCall);
3015 n->funcname = "btrim";
3019 | TRIM '(' LEADING trim_list ')'
3021 FuncCall *n = makeNode(FuncCall);
3022 n->funcname = "ltrim";
3026 | TRIM '(' TRAILING trim_list ')'
3028 FuncCall *n = makeNode(FuncCall);
3029 n->funcname = "rtrim";
3033 | TRIM '(' trim_list ')'
3035 FuncCall *n = makeNode(FuncCall);
3036 n->funcname = "btrim";
3040 | name '(' expr_list ')'
3042 FuncCall *n = makeNode(FuncCall);
3049 substr_list: expr_list substr_from substr_for
3051 $$ = nconc(nconc($1,$2),$3);
3057 substr_from: FROM expr_list
3061 A_Const *n = makeNode(A_Const);
3062 n->val.type = T_Integer;
3063 n->val.val.ival = 1;
3064 $$ = lcons((Node *)n,NIL);
3068 substr_for: FOR expr_list
3074 trim_list: a_expr FROM expr_list
3075 { $$ = lappend($3, $1); }
3084 elog(WARN,"IN (SUBSELECT) not yet implemented",NULL);
3091 in_expr_nodes: AexprConst
3092 { $$ = makeA_Expr(OP, "=", saved_In_Expr, $1); }
3093 | in_expr_nodes ',' AexprConst
3094 { $$ = makeA_Expr(OR, NULL, $1,
3095 makeA_Expr(OP, "=", saved_In_Expr, $3));
3099 not_in_expr: SubSelect
3101 elog(WARN,"NOT IN (SUBSELECT) not yet implemented",NULL);
3108 not_in_expr_nodes: AexprConst
3109 { $$ = makeA_Expr(OP, "<>", saved_In_Expr, $1); }
3110 | not_in_expr_nodes ',' AexprConst
3111 { $$ = makeA_Expr(AND, NULL, $1,
3112 makeA_Expr(OP, "<>", saved_In_Expr, $3));
3116 attr: relation_name '.' attrs
3118 $$ = makeNode(Attr);
3122 $$->indirection = NULL;
3126 $$ = makeNode(Attr);
3130 $$->indirection = NULL;
3135 { $$ = lcons(makeString($1), NIL); }
3136 | attrs '.' attr_name
3137 { $$ = lappend($1, makeString($3)); }
3139 { $$ = lappend($1, makeString("*")); }
3143 /*****************************************************************************
3147 *****************************************************************************/
3149 res_target_list: res_target_list ',' res_target_el
3150 { $$ = lappend($1,$3); }
3152 { $$ = lcons($1, NIL); }
3155 ResTarget *rt = makeNode(ResTarget);
3156 Attr *att = makeNode(Attr);
3158 att->paramNo = NULL;
3160 att->indirection = NIL;
3162 rt->indirection = NULL;
3163 rt->val = (Node *)att;
3164 $$ = lcons(rt, NIL);
3168 res_target_el: ColId opt_indirection '=' a_expr_or_null
3170 $$ = makeNode(ResTarget);
3172 $$->indirection = $2;
3173 $$->val = (Node *)$4;
3175 | attr opt_indirection
3177 $$ = makeNode(ResTarget);
3179 $$->indirection = $2;
3180 $$->val = (Node *)$1;
3182 | relation_name '.' '*'
3184 Attr *att = makeNode(Attr);
3186 att->paramNo = NULL;
3187 att->attrs = lcons(makeString("*"), NIL);
3188 att->indirection = NIL;
3189 $$ = makeNode(ResTarget);
3191 $$->indirection = NULL;
3192 $$->val = (Node *)att;
3197 ** target list for select.
3198 ** should get rid of the other but is still needed by the defunct retrieve into
3199 ** and update (uses a subset)
3201 res_target_list2: res_target_list2 ',' res_target_el2
3202 { $$ = lappend($1, $3); }
3204 { $$ = lcons($1, NIL); }
3207 /* AS is not optional because shift/red conflict with unary ops */
3208 res_target_el2: a_expr_or_null AS ColLabel
3210 $$ = makeNode(ResTarget);
3212 $$->indirection = NULL;
3213 $$->val = (Node *)$1;
3217 $$ = makeNode(ResTarget);
3219 $$->indirection = NULL;
3220 $$->val = (Node *)$1;
3222 | relation_name '.' '*'
3224 Attr *att = makeNode(Attr);
3226 att->paramNo = NULL;
3227 att->attrs = lcons(makeString("*"), NIL);
3228 att->indirection = NIL;
3229 $$ = makeNode(ResTarget);
3231 $$->indirection = NULL;
3232 $$->val = (Node *)att;
3236 Attr *att = makeNode(Attr);
3238 att->paramNo = NULL;
3240 att->indirection = NIL;
3241 $$ = makeNode(ResTarget);
3243 $$->indirection = NULL;
3244 $$->val = (Node *)att;
3248 opt_id: ColId { $$ = $1; }
3249 | /* EMPTY */ { $$ = NULL; }
3252 relation_name: SpecialRuleRelation
3255 StrNCpy(saved_relname, $1, NAMEDATALEN);
3259 /* disallow refs to variable system tables */
3260 if (strcmp(LogRelationName, $1) == 0
3261 || strcmp(VariableRelationName, $1) == 0)
3262 elog(WARN,"%s cannot be accessed by users",$1);
3265 StrNCpy(saved_relname, $1, NAMEDATALEN);
3269 database_name: ColId { $$ = $1; };
3270 access_method: Id { $$ = $1; };
3271 attr_name: ColId { $$ = $1; };
3272 class: Id { $$ = $1; };
3273 index_name: ColId { $$ = $1; };
3276 * Include date/time keywords as SQL92 extension.
3277 * Include TYPE as a SQL92 unreserved keyword. - thomas 1997-10-05
3279 name: ColId { $$ = $1; };
3281 file_name: Sconst { $$ = $1; };
3282 recipe_name: Id { $$ = $1; };
3285 * Include TRUE/FALSE for SQL3 support. - thomas 1997-10-24
3289 A_Const *n = makeNode(A_Const);
3290 n->val.type = T_Integer;
3291 n->val.val.ival = $1;
3296 A_Const *n = makeNode(A_Const);
3297 n->val.type = T_Float;
3298 n->val.val.dval = $1;
3303 A_Const *n = makeNode(A_Const);
3304 n->val.type = T_String;
3305 n->val.val.str = $1;
3310 A_Const *n = makeNode(A_Const);
3312 n->val.type = T_String;
3313 n->val.val.str = $2;
3317 { $$ = (Node *)$1; }
3320 A_Const *n = makeNode(A_Const);
3321 n->val.type = T_String;
3322 n->val.val.str = "t";
3327 A_Const *n = makeNode(A_Const);
3328 n->val.type = T_String;
3329 n->val.val.str = "f";
3336 $$ = makeNode(ParamNo);
3341 NumConst: Iconst { $$ = makeInteger($1); }
3342 | FCONST { $$ = makeFloat($1); }
3345 Iconst: ICONST { $$ = $1; };
3346 Sconst: SCONST { $$ = $1; };
3348 /* Column and type identifier
3349 * Does not include explicit datetime types
3350 * since these must be decoupled in Typename syntax.
3351 * Use ColId for most identifiers. - thomas 1997-10-21
3353 Id: IDENT { $$ = $1; };
3355 /* Column identifier
3356 * Include date/time keywords as SQL92 extension.
3357 * Include TYPE as a SQL92 unreserved keyword. - thomas 1997-10-05
3358 * Add other keywords. Note that as the syntax expands,
3359 * some of these keywords will have to be removed from this
3360 * list due to shift/reduce conflicts in yacc. If so, move
3361 * down to the ColLabel entity. - thomas 1997-11-06
3363 ColId: Id { $$ = $1; }
3364 | datetime { $$ = $1; }
3365 | ACTION { $$ = "action"; }
3366 | DATABASE { $$ = "database"; }
3367 | DELIMITERS { $$ = "delimiters"; }
3368 | FUNCTION { $$ = "function"; }
3369 | INDEX { $$ = "index"; }
3370 | KEY { $$ = "key"; }
3371 | LANGUAGE { $$ = "language"; }
3372 | LOCATION { $$ = "location"; }
3373 | MATCH { $$ = "match"; }
3374 | OPERATOR { $$ = "operator"; }
3375 | OPTION { $$ = "option"; }
3376 | PRIVILEGES { $$ = "privileges"; }
3377 | RECIPE { $$ = "recipe"; }
3378 | TIME { $$ = "time"; }
3379 | TRIGGER { $$ = "trigger"; }
3380 | TYPE_P { $$ = "type"; }
3381 | VERSION { $$ = "version"; }
3382 | ZONE { $$ = "zone"; }
3386 * Allowed labels in "AS" clauses.
3387 * Include TRUE/FALSE SQL3 reserved words for Postgres backward
3388 * compatibility. Cannot allow this for column names since the
3389 * syntax would not distinguish between the constant value and
3390 * a column name. - thomas 1997-10-24
3391 * Add other keywords to this list. Note that they appear here
3392 * rather than in ColId if there was a shift/reduce conflict
3393 * when used as a full identifier. - thomas 1997-11-06
3395 ColLabel: ColId { $$ = $1; }
3396 | ARCHIVE { $$ = "archive"; }
3397 | CLUSTER { $$ = "cluster"; }
3398 | CONSTRAINT { $$ = "constraint"; }
3399 | CROSS { $$ = "cross"; }
3400 | FOREIGN { $$ = "foreign"; }
3401 | GROUP { $$ = "group"; }
3402 | LOAD { $$ = "load"; }
3403 | ORDER { $$ = "order"; }
3404 | POSITION { $$ = "position"; }
3405 | PRECISION { $$ = "precision"; }
3406 | TABLE { $$ = "table"; }
3407 | TRANSACTION { $$ = "transaction"; }
3408 | TRUE_P { $$ = "true"; }
3409 | FALSE_P { $$ = "false"; }
3412 SpecialRuleRelation: CURRENT
3417 elog(WARN,"CURRENT used in non-rule query",NULL);
3424 elog(WARN,"NEW used in non-rule query",NULL);
3433 static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr)
3435 A_Expr *a = makeNode(A_Expr);
3444 static Node *makeIndexable(char *opname, Node *lexpr, Node *rexpr)
3446 Node *result = NULL;
3448 /* we do this so indexes can be used */
3449 if (strcmp(opname,"~") == 0 ||
3450 strcmp(opname,"~*") == 0)
3452 if (nodeTag(rexpr) == T_A_Const &&
3453 ((A_Const *)rexpr)->val.type == T_String &&
3454 ((A_Const *)rexpr)->val.val.str[0] == '^')
3456 A_Const *n = (A_Const *)rexpr;
3457 char *match_least = palloc(strlen(n->val.val.str)+2);
3458 char *match_most = palloc(strlen(n->val.val.str)+2);
3459 int pos, match_pos=0;
3461 /* skip leading ^ */
3462 for (pos = 1; n->val.val.str[pos]; pos++)
3464 if (n->val.val.str[pos] == '.' ||
3465 n->val.val.str[pos] == '?' ||
3466 n->val.val.str[pos] == '*' ||
3467 n->val.val.str[pos] == '[' ||
3468 n->val.val.str[pos] == '$' ||
3469 (strcmp(opname,"~*") == 0 && isalpha(n->val.val.str[pos])))
3471 if (n->val.val.str[pos] == '\\')
3473 match_least[match_pos] = n->val.val.str[pos];
3474 match_most[match_pos++] = n->val.val.str[pos];
3479 A_Const *least = makeNode(A_Const);
3480 A_Const *most = makeNode(A_Const);
3482 /* make strings to be used in index use */
3483 match_least[match_pos] = '\0';
3484 match_most[match_pos] = '\377';
3485 match_most[match_pos+1] = '\0';
3486 least->val.type = T_String;
3487 least->val.val.str = match_least;
3488 most->val.type = T_String;
3489 most->val.val.str = match_most;
3490 result = makeA_Expr(AND, NULL,
3491 makeA_Expr(OP, "~", lexpr, rexpr),
3492 makeA_Expr(AND, NULL,
3493 makeA_Expr(OP, ">=", lexpr, (Node *)least),
3494 makeA_Expr(OP, "<=", lexpr, (Node *)most)));
3498 else if (strcmp(opname,"~~") == 0)
3500 if (nodeTag(rexpr) == T_A_Const &&
3501 ((A_Const *)rexpr)->val.type == T_String)
3503 A_Const *n = (A_Const *)rexpr;
3504 char *match_least = palloc(strlen(n->val.val.str)+2);
3505 char *match_most = palloc(strlen(n->val.val.str)+2);
3506 int pos, match_pos=0;
3508 for (pos = 0; n->val.val.str[pos]; pos++)
3510 if ((n->val.val.str[pos] == '%' &&
3511 n->val.val.str[pos+1] != '%') ||
3512 (n->val.val.str[pos] == '_' &&
3513 n->val.val.str[pos+1] != '_'))
3515 if (n->val.val.str[pos] == '%' ||
3516 n->val.val.str[pos] == '_' ||
3517 n->val.val.str[pos] == '\\')
3519 match_least[match_pos] = n->val.val.str[pos];
3520 match_most[match_pos++] = n->val.val.str[pos];
3525 A_Const *least = makeNode(A_Const);
3526 A_Const *most = makeNode(A_Const);
3528 /* make strings to be used in index use */
3529 match_least[match_pos] = '\0';
3530 match_most[match_pos] = '\377';
3531 match_most[match_pos+1] = '\0';
3532 least->val.type = T_String;
3533 least->val.val.str = match_least;
3534 most->val.type = T_String;
3535 most->val.val.str = match_most;
3536 result = makeA_Expr(AND, NULL,
3537 makeA_Expr(OP, "~~", lexpr, rexpr),
3538 makeA_Expr(AND, NULL,
3539 makeA_Expr(OP, ">=", lexpr, (Node *)least),
3540 makeA_Expr(OP, "<=", lexpr, (Node *)most)));
3546 result = makeA_Expr(OP, opname, lexpr, rexpr);
3548 } /* makeIndexable() */
3552 * Convert alternate type names to internal Postgres types.
3553 * Do not convert "float", since that is handled elsewhere
3554 * for FLOAT(p) syntax.
3557 xlateSqlType(char *name)
3559 if (!strcasecmp(name,"int")
3560 || !strcasecmp(name,"integer"))
3562 else if (!strcasecmp(name, "smallint"))
3564 else if (!strcasecmp(name, "real"))
3566 else if (!strcasecmp(name, "interval"))
3568 else if (!strcasecmp(name, "boolean"))
3572 } /* xlateSqlName() */
3575 void parser_init(Oid *typev, int nargs)
3577 QueryIsRule = FALSE;
3578 saved_relname[0]= '\0';
3579 saved_In_Expr = NULL;
3581 param_type_init(typev, nargs);
3585 /* FlattenStringList()
3586 * Traverse list of string nodes and convert to a single string.
3587 * Used for reconstructing string form of complex expressions.
3589 * Allocate at least one byte for terminator.
3592 FlattenStringList(List *list)
3600 nlist = length(list);
3603 v = (Value *)lfirst(l);
3610 s = (char*) palloc(len+1);
3615 v = (Value *)lfirst(l);
3619 if (l != NIL) strcat(s," ");
3624 printf( "flattened string is \"%s\"\n", s);
3628 } /* FlattenStringList() */
3631 /* makeConstantList()
3632 * Convert constant value node into string node.
3635 makeConstantList( A_Const *n)
3637 char *defval = NULL;
3638 if (nodeTag(n) != T_A_Const) {
3639 elog(WARN,"Cannot handle non-constant parameter",NULL);
3641 } else if (n->val.type == T_Float) {
3642 defval = (char*) palloc(20+1);
3643 sprintf( defval, "%g", n->val.val.dval);
3645 } else if (n->val.type == T_Integer) {
3646 defval = (char*) palloc(20+1);
3647 sprintf( defval, "%ld", n->val.val.ival);
3649 } else if (n->val.type == T_String) {
3650 defval = (char*) palloc(strlen( ((A_Const *) n)->val.val.str) + 3);
3651 strcpy( defval, "'");
3652 strcat( defval, ((A_Const *) n)->val.val.str);
3653 strcat( defval, "'");
3656 elog(WARN,"Internal error in makeConstantList(): cannot encode node",NULL);
3660 printf( "AexprConst argument is \"%s\"\n", defval);
3663 return( lcons( makeString(defval), NIL));
3664 } /* makeConstantList() */
3668 * Check input string for non-lowercase/non-numeric characters.
3669 * Returns either input string or input surrounded by double quotes.
3676 for (cp = rawid; *cp != '\0'; cp++)
3677 if (! (islower(*cp) || isdigit(*cp) || (*cp == '_'))) break;
3680 cp = palloc(strlen(rawid)+1);
3689 printf("fmtId- %sconvert %s to %s\n", ((cp == rawid)? "do not ": ""), rawid, cp);