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.55 1997/10/09 05:35:30 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.
24 * if you use list, make sure the datum is a node so that the printing
28 * sometimes we assign constants to makeStrings. Make sure we don't free
31 *-------------------------------------------------------------------------
37 #include "nodes/parsenodes.h"
38 #include "nodes/print.h"
39 #include "parser/gramparse.h"
40 #include "parser/catalog_utils.h"
41 #include "parser/parse_query.h"
42 #include "storage/smgr.h"
43 #include "utils/acl.h"
44 #include "catalog/catname.h"
45 #include "utils/elog.h"
46 #include "access/xact.h"
48 static char saved_relname[NAMEDATALEN]; /* need this for complex attributes */
49 static bool QueryIsRule = FALSE;
50 static Node *saved_In_Expr;
51 extern List *parsetree;
54 * If you need access to certain yacc-generated variables and find that
55 * they're static by default, uncomment the next line. (this is not a
58 /*#define __YYSCLASS*/
60 static char *xlateSqlType(char *);
61 static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
62 static List *makeConstantList( A_Const *node);
63 static char *FlattenStringList(List *list);
65 /* old versions of flex define this as a macro */
86 ConstraintDef *constrdef;
90 SortGroupBy *sortgroupby;
107 AddAttrStmt, ClosePortalStmt,
108 CopyStmt, CreateStmt, CreateSeqStmt, DefineStmt, DestroyStmt,
109 ExtendStmt, FetchStmt, GrantStmt, CreateTrigStmt, DropTrigStmt,
110 IndexStmt, ListenStmt, OptimizableStmt,
111 ProcedureStmt, PurgeStmt,
112 RecipeStmt, RemoveAggrStmt, RemoveOperStmt, RemoveFuncStmt, RemoveStmt,
113 RenameStmt, RevokeStmt, RuleStmt, TransactionStmt, ViewStmt, LoadStmt,
114 CreatedbStmt, DestroydbStmt, VacuumStmt, RetrieveStmt, CursorStmt,
115 ReplaceStmt, AppendStmt, NotifyStmt, DeleteStmt, ClusterStmt,
116 ExplainStmt, VariableSetStmt, VariableShowStmt, VariableResetStmt
118 %type <str> txname, char_type
119 %type <node> SubSelect
120 %type <str> join_expr, join_outer, join_spec
121 %type <boolean> TriggerActionTime, TriggerForSpec
123 %type <str> DateTime, TriggerEvents, TriggerFuncArg
125 %type <str> relation_name, copy_file_name, copy_delimiter, def_name,
126 database_name, access_method_clause, access_method, attr_name,
127 class, index_name, name, file_name, recipe_name, aggr_argtype
129 %type <constrdef> ConstraintElem, ConstraintDef
131 %type <str> opt_id, opt_portal_name,
132 before_clause, after_clause, all_Op, MathOp, opt_name, opt_unique,
133 result, OptUseOp, opt_class, opt_range_start, opt_range_end,
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
152 %type <sortgroupby> join_using
154 %type <node> position_expr
155 %type <list> extract_list, position_list
156 %type <list> substr_list, substr_from, substr_for, trim_list
157 %type <list> interval_opts
159 %type <boolean> opt_inh_star, opt_binary, opt_instead, opt_with_col, opt_with_copy,
160 index_opt_unique, opt_verbose, opt_analyze, opt_null
162 %type <ival> copy_dirn, archive_type, OptArchiveType, OptArchiveLocation,
163 def_type, opt_direction, remove_type, opt_column, event
165 %type <ival> OptLocation, fetch_how_many
167 %type <list> OptSeqList
168 %type <defelt> OptSeqElem
170 %type <dstmt> def_rest
171 %type <pstmt> purge_quals
172 %type <astmt> insert_rest
174 %type <typnam> Typename, typname, opt_type
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_nodes, 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 <trange> time_range
189 %type <target> res_target_el, res_target_el2
190 %type <paramno> ParamNo
194 %type <str> Id, date, var_value, zone_value
197 %type <list> default_expr
198 %type <str> opt_default
199 %type <list> constraint_elem
202 * If you make any token changes, remember to:
203 * - use "yacc -d" and update parse.h
204 * - update the keyword table in parser/keywords.c
208 %token ABORT_TRANS, ACL, ADD, AFTER, AGGREGATE, ALL, ALTER, ANALYZE,
209 AND, APPEND, ARCHIVE, ARCH_STORE, AS, ASC,
210 BACKWARD, BEFORE, BEGIN_TRANS, BETWEEN, BINARY, BY,
211 CAST, CHANGE, CHECK, CLOSE, CLUSTER, COLUMN,
212 COMMIT, CONSTRAINT, COPY, CREATE, CROSS, CURRENT, CURSOR,
213 DATABASE, DECLARE, DEFAULT, DELETE, DELIMITERS, DESC,
214 DISTINCT, DO, DROP, END_TRANS, EXISTS, EXTEND,
215 FETCH, FOR, FORWARD, FROM, FULL, FUNCTION, GRANT, GROUP, HAVING, HEAVY,
216 IN, INDEX, INHERITS, INNERJOIN, INSERT, INSTEAD, INTO, IS, ISNULL,
217 JOIN, LANGUAGE, LEFT, LIGHT, LISTEN, LOAD, LOCAL, MERGE, MOVE,
218 NATURAL, NEW, NONE, NOT, NOTHING, NOTIFY, NOTNULL,
219 OIDS, ON, OPERATOR, OPTION, OR, ORDER, OUTERJOIN,
220 PNULL, PRIVILEGES, PROCEDURE, PUBLIC, PURGE, P_TYPE,
221 RENAME, REPLACE, RESET, RETRIEVE, RETURNS, REVOKE, RIGHT, ROLLBACK, RULE,
222 SELECT, SET, SETOF, SHOW, STDIN, STDOUT, STORE,
223 TABLE, TO, TRANSACTION, TRIGGER,
224 UNION, UNIQUE, UPDATE, USING, VACUUM, VALUES,
225 VERBOSE, VERSION, VIEW, WHERE, WITH, WORK
226 %token EXECUTE, RECIPE, EXPLAIN, LIKE, SEQUENCE
229 %token INTERVAL, TIME, ZONE
230 %token DAYINTERVAL, HOURINTERVAL, MINUTEINTERVAL, MONTHINTERVAL,
231 SECONDINTERVAL, YEARINTERVAL
232 %token BOTH, LEADING, TRAILING,
233 %token EXTRACT, POSITION, SUBSTRING, TRIM
234 %token DOUBLE, PRECISION, FLOAT
235 %token DECIMAL, NUMERIC
236 %token CHARACTER, VARYING
237 %token CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP
239 /* Special keywords, not in the query language - see the "lex" file */
240 %token <str> IDENT, SCONST, Op
241 %token <ival> ICONST, PARAM
244 /* these are not real. they are here so that they get generated as #define's*/
261 %left '|' /* this is the relation union op, not logical or */
262 %right ':' /* Unary Operators */
263 %left ';' /* end of statement or natural log */
276 { parsetree = lcons($1,NIL); }
279 stmtmulti: stmtmulti stmt ';'
280 { $$ = lappend($1, $2); }
282 { $$ = lappend($1, $2); }
284 { $$ = lcons($1,NIL); }
325 /*****************************************************************************
327 * Set PG internal variable
328 * SET name TO 'var_value'
330 *****************************************************************************/
332 VariableSetStmt: SET Id TO var_value
334 VariableSetStmt *n = makeNode(VariableSetStmt);
339 | SET Id '=' var_value
341 VariableSetStmt *n = makeNode(VariableSetStmt);
346 | SET TIME ZONE zone_value
348 VariableSetStmt *n = makeNode(VariableSetStmt);
349 n->name = "timezone";
355 var_value: Sconst { $$ = $1; }
358 zone_value: Sconst { $$ = $1; }
359 | LOCAL { $$ = NULL; }
362 VariableShowStmt: SHOW Id
364 VariableShowStmt *n = makeNode(VariableShowStmt);
370 VariableResetStmt: RESET Id
372 VariableResetStmt *n = makeNode(VariableResetStmt);
378 /*****************************************************************************
381 * addattr ( attr1 = type1 .. attrn = typen ) to <relname> [*]
383 *****************************************************************************/
385 AddAttrStmt: ALTER TABLE relation_name opt_inh_star alter_clause
387 AddAttrStmt *n = makeNode(AddAttrStmt);
395 alter_clause: ADD opt_column columnDef
399 | ADD '(' tableElementList ')'
401 ColumnDef *lp = lfirst($3);
404 elog(WARN,"ALTER TABLE/ADD() allows one column only",NULL);
406 printf( "list has %d elements\n", length($3));
411 { elog(WARN,"ALTER TABLE/DROP COLUMN not yet implemented",NULL); }
412 | ALTER opt_column Id SET opt_default
413 { elog(WARN,"ALTER TABLE/ALTER COLUMN/SET DEFAULT not yet implemented",NULL); }
414 | ALTER opt_column Id DROP DEFAULT
415 { elog(WARN,"ALTER TABLE/ALTER COLUMN/DROP DEFAULT not yet implemented",NULL); }
417 { elog(WARN,"ALTER TABLE/ADD CONSTRAINT not yet implemented",NULL); }
420 /* Column definition might include WITH TIME ZONE, but only for the data types
421 * called out in SQL92 date/time definitions. So, check explicitly for "timestamp"
422 * and "time". - thomas 1997-07-14
424 columnDef: Id Typename opt_with_col opt_default opt_null
426 $$ = makeNode(ColumnDef);
429 $$->typename->timezone = $3;
431 $$->is_not_null = $5;
432 if ($$->typename->timezone
433 && (strcasecmp($$->typename->name, "timestamp")
434 && strcasecmp($$->typename->name, "time")))
435 elog(NOTICE,"%s does not use WITH TIME ZONE",$$->typename->name);
439 opt_default: DEFAULT default_expr
441 $$ = FlattenStringList($2);
443 | /*EMPTY*/ { $$ = NULL; }
446 default_expr: AexprConst
447 { $$ = makeConstantList((A_Const *) $1); }
449 { $$ = lcons( makeString("NULL"), NIL); }
450 | '-' default_expr %prec UMINUS
451 { $$ = lcons( makeString( "-"), $2); }
452 | default_expr '+' default_expr
453 { $$ = nconc( $1, lcons( makeString( "+"), $3)); }
454 | default_expr '-' default_expr
455 { $$ = nconc( $1, lcons( makeString( "-"), $3)); }
456 | default_expr '/' default_expr
457 { $$ = nconc( $1, lcons( makeString( "/"), $3)); }
458 | default_expr '*' default_expr
459 { $$ = nconc( $1, lcons( makeString( "*"), $3)); }
460 | default_expr '=' default_expr
461 { elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
462 | default_expr '<' default_expr
463 { elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
464 | default_expr '>' default_expr
465 { elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
467 { $$ = lcons( makeString( ":"), $2); }
469 { $$ = lcons( makeString( ";"), $2); }
471 { $$ = lcons( makeString( "|"), $2); }
472 | default_expr TYPECAST Typename
474 $$ = nconc( lcons( makeString( "CAST"), $1), makeList( makeString("AS"), $3, -1));
476 | CAST default_expr AS Typename
478 $$ = nconc( lcons( makeString( "CAST"), $2), makeList( makeString("AS"), $4, -1));
480 | '(' default_expr ')'
481 { $$ = lappend( lcons( makeString( "("), $2), makeString( ")")); }
482 | name '(' default_expr ')'
484 $$ = makeList( makeString($1), makeString("("), -1);
486 $$ = lappend( $$, makeString(")"));
490 $$ = makeList( makeString($1), makeString("("), -1);
491 $$ = lappend( $$, makeString(")"));
493 | default_expr Op default_expr
495 if (!strcmp("<=", $2) || !strcmp(">=", $2))
496 elog(WARN,"boolean expressions not supported in DEFAULT",NULL);
497 $$ = nconc( $1, lcons( makeString( $2), $3));
500 { $$ = lcons( makeString( $1), $2); }
502 { $$ = lappend( $1, makeString( $2)); }
505 opt_null: NOT PNULL { $$ = TRUE; }
506 | NOTNULL { $$ = TRUE; }
507 | /* EMPTY */ { $$ = FALSE; }
510 opt_with_col: WITH TIME ZONE { $$ = TRUE; }
511 | /* EMPTY */ { $$ = FALSE; }
514 /*****************************************************************************
519 *****************************************************************************/
521 ClosePortalStmt: CLOSE opt_id
523 ClosePortalStmt *n = makeNode(ClosePortalStmt);
530 /*****************************************************************************
533 * COPY [BINARY] <relname> FROM/TO
534 * [USING DELIMITERS <delimiter>]
536 *****************************************************************************/
538 CopyStmt: COPY opt_binary relation_name opt_with_copy copy_dirn copy_file_name copy_delimiter
540 CopyStmt *n = makeNode(CopyStmt);
558 * copy_file_name NULL indicates stdio is used. Whether stdin or stdout is
559 * used depends on the direction. (It really doesn't make sense to copy from
560 * stdout. We silently correct the "typo". - AY 9/94
562 copy_file_name: Sconst { $$ = $1; }
563 | STDIN { $$ = NULL; }
564 | STDOUT { $$ = NULL; }
567 opt_binary: BINARY { $$ = TRUE; }
568 | /*EMPTY*/ { $$ = FALSE; }
571 opt_with_copy: WITH OIDS { $$ = TRUE; }
572 | /* EMPTY */ { $$ = FALSE; }
576 * the default copy delimiter is tab but the user can configure it
578 copy_delimiter: USING DELIMITERS Sconst { $$ = $3;}
579 | /* EMPTY */ { $$ = "\t"; }
583 /*****************************************************************************
588 *****************************************************************************/
590 CreateStmt: CREATE TABLE relation_name '(' OptTableElementList ')'
591 OptInherit OptConstraint OptArchiveType OptLocation
594 CreateStmt *n = makeNode(CreateStmt);
606 OptTableElementList: tableElementList { $$ = $1; }
607 | /* EMPTY */ { $$ = NULL; }
611 tableElementList ',' columnDef
612 { $$ = lappend($1, $3); }
614 { $$ = lcons($1, NIL); }
618 OptArchiveType: ARCHIVE '=' archive_type { $$ = $3; }
619 | /*EMPTY*/ { $$ = ARCH_NONE; }
622 archive_type: HEAVY { $$ = ARCH_HEAVY; }
623 | LIGHT { $$ = ARCH_LIGHT; }
624 | NONE { $$ = ARCH_NONE; }
627 OptLocation: STORE '=' Sconst
633 OptArchiveLocation: ARCH_STORE '=' Sconst
639 OptInherit: INHERITS '(' relation_name_list ')' { $$ = $3; }
640 | /*EMPTY*/ { $$ = NIL; }
643 OptConstraint: ConstraintList { $$ = $1; }
644 | /*EMPTY*/ { $$ = NULL; }
648 ConstraintList ',' ConstraintElem
649 { $$ = lappend($1, $3); }
651 { $$ = lcons($1, NIL); }
655 CONSTRAINT name ConstraintDef
660 | ConstraintDef { $$ = $1; }
663 ConstraintDef: CHECK constraint_elem
665 ConstraintDef *constr = palloc (sizeof(ConstraintDef));
667 printf("in ConstraintDef\n");
669 constr->type = CONSTR_CHECK;
671 constr->def = FlattenStringList($2);
673 printf("ConstraintDef: string is %s\n", (char *) constr->def);
679 constraint_elem: AexprConst
680 { $$ = makeConstantList((A_Const *) $1); }
682 { $$ = lcons( makeString("NULL"), NIL); }
686 printf( "Id is %s\n", $1);
688 $$ = lcons( makeString($1), NIL);
690 | '-' constraint_elem %prec UMINUS
691 { $$ = lcons( makeString( "-"), $2); }
692 | constraint_elem '+' constraint_elem
693 { $$ = nconc( $1, lcons( makeString( "+"), $3)); }
694 | constraint_elem '-' constraint_elem
695 { $$ = nconc( $1, lcons( makeString( "-"), $3)); }
696 | constraint_elem '/' constraint_elem
697 { $$ = nconc( $1, lcons( makeString( "/"), $3)); }
698 | constraint_elem '*' constraint_elem
699 { $$ = nconc( $1, lcons( makeString( "*"), $3)); }
700 | constraint_elem '=' constraint_elem
701 { $$ = nconc( $1, lcons( makeString( "="), $3)); }
702 | constraint_elem '<' constraint_elem
703 { $$ = nconc( $1, lcons( makeString( "<"), $3)); }
704 | constraint_elem '>' constraint_elem
705 { $$ = nconc( $1, lcons( makeString( ">"), $3)); }
706 | ':' constraint_elem
707 { $$ = lcons( makeString( ":"), $2); }
708 | ';' constraint_elem
709 { $$ = lcons( makeString( ";"), $2); }
710 | '|' constraint_elem
711 { $$ = lcons( makeString( "|"), $2); }
712 | constraint_elem TYPECAST Typename
714 $$ = nconc( lcons( makeString( "CAST"), $1), makeList( makeString("AS"), $3, -1));
716 | CAST constraint_elem AS Typename
718 $$ = nconc( lcons( makeString( "CAST"), $2), makeList( makeString("AS"), $4, -1));
720 | '(' constraint_elem ')'
721 { $$ = lappend( lcons( makeString( "("), $2), makeString( ")")); }
722 | name '(' constraint_elem ')'
724 $$ = makeList( makeString($1), makeString("("), -1);
726 $$ = lappend( $$, makeString(")"));
728 | constraint_elem Op constraint_elem
729 { $$ = nconc( $1, lcons( makeString( $2), $3)); }
730 | constraint_elem AND constraint_elem
731 { $$ = nconc( $1, lcons( makeString( "AND"), $3)); }
732 | constraint_elem OR constraint_elem
733 { $$ = nconc( $1, lcons( makeString( "OR"), $3)); }
735 { $$ = lcons( makeString( $1), $2); }
737 { $$ = lappend( $1, makeString( $2)); }
741 /*****************************************************************************
744 * CREATE SEQUENCE seqname
746 *****************************************************************************/
748 CreateSeqStmt: CREATE SEQUENCE relation_name OptSeqList
750 CreateSeqStmt *n = makeNode(CreateSeqStmt);
758 OptSeqList OptSeqElem
759 { $$ = lappend($1, $2); }
763 OptSeqElem: IDENT NumConst
765 $$ = makeNode(DefElem);
767 $$->arg = (Node *)$2;
771 $$ = makeNode(DefElem);
773 $$->arg = (Node *)NULL;
778 /*****************************************************************************
784 *****************************************************************************/
786 CreateTrigStmt: CREATE TRIGGER name TriggerActionTime TriggerEvents ON
787 relation_name TriggerForSpec EXECUTE PROCEDURE
788 name '(' TriggerFuncArgs ')'
790 CreateTrigStmt *n = makeNode(CreateTrigStmt);
797 memcpy (n->actions, $5, 4);
802 TriggerActionTime: BEFORE { $$ = TRUE; }
803 | AFTER { $$ = FALSE; }
806 TriggerEvents: TriggerOneEvent
808 char *e = palloc (4);
809 e[0] = $1; e[1] = 0; $$ = e;
811 | TriggerOneEvent OR TriggerOneEvent
813 char *e = palloc (4);
814 e[0] = $1; e[1] = $3; e[2] = 0; $$ = e;
816 | TriggerOneEvent OR TriggerOneEvent OR TriggerOneEvent
818 char *e = palloc (4);
819 e[0] = $1; e[1] = $3; e[2] = $5; e[3] = 0;
824 TriggerOneEvent: INSERT { $$ = 'i'; }
825 | DELETE { $$ = 'd'; }
826 | UPDATE { $$ = 'u'; }
829 TriggerForSpec: FOR name name
831 if ( strcmp ($2, "each") != 0 )
832 elog(WARN,"parser: syntax error near %s",$2);
833 if ( strcmp ($3, "row") == 0 )
835 else if ( strcmp ($3, "statement") == 0 )
838 elog(WARN,"parser: syntax error near %s",$3);
842 TriggerFuncArgs: TriggerFuncArg
843 { $$ = lcons($1, NIL); }
844 | TriggerFuncArgs ',' TriggerFuncArg
845 { $$ = lappend($1, $3); }
846 | /* EMPTY */ { $$ = NIL; }
849 TriggerFuncArg: ICONST
851 char *s = (char *) palloc (256);
852 sprintf (s, "%d", $1);
857 char *s = (char *) palloc (256);
858 sprintf (s, "%g", $1);
861 | Sconst { $$ = $1; }
865 DropTrigStmt: DROP TRIGGER name ON relation_name
867 DropTrigStmt *n = makeNode(DropTrigStmt);
874 /*****************************************************************************
877 * define (type,operator,aggregate)
879 *****************************************************************************/
881 DefineStmt: CREATE def_type def_rest
888 def_rest: def_name definition
890 $$ = makeNode(DefineStmt);
893 printf("def_rest: defname is %s\n", $1);
899 def_type: OPERATOR { $$ = OPERATOR; }
903 printf("def_type: decoding P_TYPE\n");
907 | AGGREGATE { $$ = AGGREGATE; }
910 def_name: PROCEDURE { $$ = "procedure"; }
912 | MathOp { $$ = $1; }
916 definition: '(' def_list ')' { $$ = $2; }
919 def_list: def_elem { $$ = lcons($1, NIL); }
920 | def_list ',' def_elem { $$ = lappend($1, $3); }
923 def_elem: def_name '=' def_arg
926 printf("def_elem: decoding %s =\n", $1);
929 $$ = makeNode(DefElem);
931 $$->arg = (Node *)$3;
936 printf("def_elem: decoding %s\n", $1);
938 $$ = makeNode(DefElem);
940 $$->arg = (Node *)NULL;
942 | DEFAULT '=' def_arg
945 printf("def_elem: decoding DEFAULT =\n");
948 $$ = makeNode(DefElem);
949 $$->defname = "default";
950 $$->arg = (Node *)$3;
954 def_arg: Id { $$ = (Node *)makeString($1); }
955 | all_Op { $$ = (Node *)makeString($1); }
956 | NumConst { $$ = (Node *)$1; /* already a Value */ }
957 | Sconst { $$ = (Node *)makeString($1); }
960 TypeName *n = makeNode(TypeName);
963 n->arrayBounds = NULL;
966 | DOUBLE { $$ = (Node *)makeString("double"); }
970 /*****************************************************************************
973 * destroy <relname1> [, <relname2> .. <relnameN> ]
975 *****************************************************************************/
977 DestroyStmt: DROP TABLE relation_name_list
979 DestroyStmt *n = makeNode(DestroyStmt);
984 | DROP SEQUENCE relation_name_list
986 DestroyStmt *n = makeNode(DestroyStmt);
994 /*****************************************************************************
997 * fetch/move [forward | backward] [number | all ] [ in <portalname> ]
999 *****************************************************************************/
1001 FetchStmt: FETCH opt_direction fetch_how_many opt_portal_name
1003 FetchStmt *n = makeNode(FetchStmt);
1010 | MOVE opt_direction fetch_how_many opt_portal_name
1012 FetchStmt *n = makeNode(FetchStmt);
1021 opt_direction: FORWARD { $$ = FORWARD; }
1022 | BACKWARD { $$ = BACKWARD; }
1023 | /*EMPTY*/ { $$ = FORWARD; /* default */ }
1026 fetch_how_many: Iconst
1028 if ($1 <= 0) elog(WARN,"Please specify nonnegative count for fetch",NULL); }
1029 | ALL { $$ = 0; /* 0 means fetch all tuples*/}
1030 | /*EMPTY*/ { $$ = 1; /*default*/ }
1033 opt_portal_name: IN name { $$ = $2;}
1034 | /*EMPTY*/ { $$ = NULL; }
1037 /*****************************************************************************
1040 * GRANT [privileges] ON [relation_name_list] TO [GROUP] grantee
1042 *****************************************************************************/
1044 GrantStmt: GRANT privileges ON relation_name_list TO grantee opt_with_grant
1046 $$ = (Node*)makeAclStmt($2,$4,$6,'+');
1052 privileges: ALL PRIVILEGES
1054 $$ = aclmakepriv("rwaR",0);
1058 $$ = aclmakepriv("rwaR",0);
1060 | operation_commalist
1066 operation_commalist: operation
1068 $$ = aclmakepriv("",$1);
1070 | operation_commalist ',' operation
1072 $$ = aclmakepriv($1,$3);
1079 $$ = ACL_MODE_RD_CHR;
1083 $$ = ACL_MODE_AP_CHR;
1087 $$ = ACL_MODE_WR_CHR;
1091 $$ = ACL_MODE_WR_CHR;
1095 $$ = ACL_MODE_RU_CHR;
1101 $$ = aclmakeuser("A","");
1105 $$ = aclmakeuser("G",$2);
1109 $$ = aclmakeuser("U",$1);
1113 opt_with_grant : /* empty */
1116 yyerror("WITH GRANT OPTION is not supported. Only relation owners can set privileges");
1120 /*****************************************************************************
1123 * REVOKE [privileges] ON [relation_name] FROM [user]
1125 *****************************************************************************/
1127 RevokeStmt: REVOKE privileges ON relation_name_list FROM grantee
1129 $$ = (Node*)makeAclStmt($2,$4,$6,'-');
1135 /*****************************************************************************
1138 * define [archive] index <indexname> on <relname>
1139 * using <access> "(" (<col> with <op>)+ ")" [with
1142 * [where <qual>] is not supported anymore
1143 *****************************************************************************/
1145 IndexStmt: CREATE index_opt_unique INDEX index_name ON relation_name
1146 access_method_clause '(' index_params ')' opt_with
1148 /* should check that access_method is valid,
1149 etc ... but doesn't */
1150 IndexStmt *n = makeNode(IndexStmt);
1154 n->accessMethod = $7;
1155 n->indexParams = $9;
1156 n->withClause = $11;
1157 n->whereClause = NULL;
1162 access_method_clause: USING access_method { $$ = $2; }
1163 | /* empty -- 'btree' is default access method */
1167 index_opt_unique: UNIQUE { $$ = TRUE; }
1168 | /*empty*/ { $$ = FALSE; }
1171 /*****************************************************************************
1174 * extend index <indexname> [where <qual>]
1176 *****************************************************************************/
1178 ExtendStmt: EXTEND INDEX index_name where_clause
1180 ExtendStmt *n = makeNode(ExtendStmt);
1182 n->whereClause = $4;
1187 /*****************************************************************************
1190 * execute recipe <recipeName>
1192 *****************************************************************************/
1194 RecipeStmt: EXECUTE RECIPE recipe_name
1197 if (!IsTransactionBlock())
1198 elog(WARN,"EXECUTE RECIPE may only be used in begin/end transaction blocks",NULL);
1200 n = makeNode(RecipeStmt);
1207 /*****************************************************************************
1210 * define function <fname>
1211 * (language = <lang>, returntype = <typename>
1212 * [, arch_pct = <percentage | pre-defined>]
1213 * [, disk_pct = <percentage | pre-defined>]
1214 * [, byte_pct = <percentage | pre-defined>]
1215 * [, perbyte_cpu = <int | pre-defined>]
1216 * [, percall_cpu = <int | pre-defined>]
1218 * [arg is (<type-1> { , <type-n>})]
1219 * as <filename or code in language as appropriate>
1221 *****************************************************************************/
1223 ProcedureStmt: CREATE FUNCTION def_name def_args
1224 RETURNS def_arg opt_with AS Sconst LANGUAGE Sconst
1226 ProcedureStmt *n = makeNode(ProcedureStmt);
1229 n->returnType = (Node *)$6;
1236 opt_with: WITH definition { $$ = $2; }
1237 | /* EMPTY */ { $$ = NIL; }
1240 def_args: '(' def_name_list ')' { $$ = $2; }
1241 | '(' ')' { $$ = NIL; }
1244 def_name_list: name_list;
1247 /*****************************************************************************
1250 * purge <relname> [before <date>] [after <date>]
1252 * purge <relname> [after <date>] [before <date>]
1254 *****************************************************************************/
1256 PurgeStmt: PURGE relation_name purge_quals
1263 purge_quals: before_clause
1265 $$ = makeNode(PurgeStmt);
1266 $$->beforeDate = $1;
1267 $$->afterDate = NULL;
1271 $$ = makeNode(PurgeStmt);
1272 $$->beforeDate = NULL;
1275 | before_clause after_clause
1277 $$ = makeNode(PurgeStmt);
1278 $$->beforeDate = $1;
1281 | after_clause before_clause
1283 $$ = makeNode(PurgeStmt);
1284 $$->beforeDate = $2;
1289 $$ = makeNode(PurgeStmt);
1290 $$->beforeDate = NULL;
1291 $$->afterDate = NULL;
1295 before_clause: BEFORE date { $$ = $2; }
1296 after_clause: AFTER date { $$ = $2; }
1299 /*****************************************************************************
1303 * remove function <funcname>
1304 * (REMOVE FUNCTION "funcname" (arg1, arg2, ...))
1305 * remove aggregate <aggname>
1306 * (REMOVE AGGREGATE "aggname" "aggtype")
1307 * remove operator <opname>
1308 * (REMOVE OPERATOR "opname" (leftoperand_typ rightoperand_typ))
1309 * remove type <typename>
1310 * (REMOVE TYPE "typename")
1311 * remove rule <rulename>
1312 * (REMOVE RULE "rulename")
1314 *****************************************************************************/
1316 RemoveStmt: DROP remove_type name
1318 RemoveStmt *n = makeNode(RemoveStmt);
1325 remove_type: Type { $$ = P_TYPE; }
1326 | INDEX { $$ = INDEX; }
1327 | RULE { $$ = RULE; }
1328 | VIEW { $$ = VIEW; }
1331 RemoveAggrStmt: DROP AGGREGATE name aggr_argtype
1333 RemoveAggrStmt *n = makeNode(RemoveAggrStmt);
1340 aggr_argtype: name { $$ = $1; }
1341 | '*' { $$ = NULL; }
1344 RemoveFuncStmt: DROP FUNCTION name '(' func_argtypes ')'
1346 RemoveFuncStmt *n = makeNode(RemoveFuncStmt);
1353 func_argtypes: name_list { $$ = $1; }
1354 | /*EMPTY*/ { $$ = NIL; }
1357 RemoveOperStmt: DROP OPERATOR all_Op '(' oper_argtypes ')'
1359 RemoveOperStmt *n = makeNode(RemoveOperStmt);
1366 all_Op: Op | MathOp;
1368 MathOp: '+' { $$ = "+"; }
1379 elog(WARN,"parser: argument type missing (use NONE for unary operators)",NULL);
1382 { $$ = makeList(makeString($1), makeString($3), -1); }
1383 | NONE ',' name /* left unary */
1384 { $$ = makeList(NULL, makeString($3), -1); }
1385 | name ',' NONE /* right unary */
1386 { $$ = makeList(makeString($1), NULL, -1); }
1389 /*****************************************************************************
1392 * rename <attrname1> in <relname> [*] to <attrname2>
1393 * rename <relname1> to <relname2>
1395 *****************************************************************************/
1397 RenameStmt: ALTER TABLE relation_name opt_inh_star
1398 RENAME opt_column opt_name TO name
1400 RenameStmt *n = makeNode(RenameStmt);
1409 opt_name: name { $$ = $1; }
1410 | /*EMPTY*/ { $$ = NULL; }
1413 opt_column: COLUMN { $$ = COLUMN; }
1414 | /*EMPTY*/ { $$ = 0; }
1418 /*****************************************************************************
1420 * QUERY: Define Rewrite Rule , Define Tuple Rule
1421 * Define Rule <old rules >
1423 * only rewrite rule is supported -- ay 9/94
1425 *****************************************************************************/
1427 RuleStmt: CREATE RULE name AS
1428 { QueryIsRule=TRUE; }
1429 ON event TO event_object where_clause
1430 DO opt_instead OptStmtList
1432 RuleStmt *n = makeNode(RuleStmt);
1436 n->whereClause = $10;
1443 OptStmtList: NOTHING { $$ = NIL; }
1444 | OptimizableStmt { $$ = lcons($1, NIL); }
1445 | '[' OptStmtBlock ']' { $$ = $2; }
1448 OptStmtBlock: OptStmtMulti
1451 { $$ = lcons($1, NIL); }
1454 OptStmtMulti: OptStmtMulti OptimizableStmt ';'
1455 { $$ = lappend($1, $2); }
1456 | OptStmtMulti OptimizableStmt
1457 { $$ = lappend($1, $2); }
1458 | OptimizableStmt ';'
1459 { $$ = lcons($1, NIL); }
1462 event_object: relation_name '.' attr_name
1464 $$ = makeNode(Attr);
1467 $$->attrs = lcons(makeString($3), NIL);
1468 $$->indirection = NIL;
1472 $$ = makeNode(Attr);
1476 $$->indirection = NIL;
1480 /* change me to select, update, etc. some day */
1481 event: SELECT { $$ = CMD_SELECT; }
1482 | UPDATE { $$ = CMD_UPDATE; }
1483 | DELETE { $$ = CMD_DELETE; }
1484 | INSERT { $$ = CMD_INSERT; }
1487 opt_instead: INSTEAD { $$ = TRUE; }
1488 | /* EMPTY */ { $$ = FALSE; }
1492 /*****************************************************************************
1495 * NOTIFY <relation_name> can appear both in rule bodies and
1496 * as a query-level command
1498 *****************************************************************************/
1500 NotifyStmt: NOTIFY relation_name
1502 NotifyStmt *n = makeNode(NotifyStmt);
1508 ListenStmt: LISTEN relation_name
1510 ListenStmt *n = makeNode(ListenStmt);
1517 /*****************************************************************************
1528 *****************************************************************************/
1530 TransactionStmt: ABORT_TRANS TRANSACTION
1532 TransactionStmt *n = makeNode(TransactionStmt);
1533 n->command = ABORT_TRANS;
1536 | BEGIN_TRANS TRANSACTION
1538 TransactionStmt *n = makeNode(TransactionStmt);
1539 n->command = BEGIN_TRANS;
1544 TransactionStmt *n = makeNode(TransactionStmt);
1545 n->command = BEGIN_TRANS;
1550 TransactionStmt *n = makeNode(TransactionStmt);
1551 n->command = END_TRANS;
1554 | END_TRANS TRANSACTION
1556 TransactionStmt *n = makeNode(TransactionStmt);
1557 n->command = END_TRANS;
1562 TransactionStmt *n = makeNode(TransactionStmt);
1563 n->command = ABORT_TRANS;
1569 TransactionStmt *n = makeNode(TransactionStmt);
1570 n->command = ABORT_TRANS;
1575 TransactionStmt *n = makeNode(TransactionStmt);
1576 n->command = BEGIN_TRANS;
1581 TransactionStmt *n = makeNode(TransactionStmt);
1582 n->command = END_TRANS;
1588 TransactionStmt *n = makeNode(TransactionStmt);
1589 n->command = END_TRANS;
1594 TransactionStmt *n = makeNode(TransactionStmt);
1595 n->command = ABORT_TRANS;
1601 /*****************************************************************************
1604 * define view <viewname> '('target-list ')' [where <quals> ]
1606 *****************************************************************************/
1608 ViewStmt: CREATE VIEW name AS RetrieveStmt
1610 ViewStmt *n = makeNode(ViewStmt);
1612 n->query = (Query *)$5;
1618 /*****************************************************************************
1623 *****************************************************************************/
1625 LoadStmt: LOAD file_name
1627 LoadStmt *n = makeNode(LoadStmt);
1634 /*****************************************************************************
1639 *****************************************************************************/
1641 CreatedbStmt: CREATE DATABASE database_name
1643 CreatedbStmt *n = makeNode(CreatedbStmt);
1650 /*****************************************************************************
1655 *****************************************************************************/
1657 DestroydbStmt: DROP DATABASE database_name
1659 DestroydbStmt *n = makeNode(DestroydbStmt);
1666 /*****************************************************************************
1669 * cluster <index_name> on <relation_name>
1671 *****************************************************************************/
1673 ClusterStmt: CLUSTER index_name ON relation_name
1675 ClusterStmt *n = makeNode(ClusterStmt);
1682 /*****************************************************************************
1687 *****************************************************************************/
1689 VacuumStmt: VACUUM opt_verbose opt_analyze
1691 VacuumStmt *n = makeNode(VacuumStmt);
1698 | VACUUM opt_verbose relation_name opt_analyze opt_va_list
1700 VacuumStmt *n = makeNode(VacuumStmt);
1705 if ( $5 != NIL && !$4 )
1706 elog(WARN,"parser: syntax error at or near \"(\"",NULL);
1711 opt_verbose: VERBOSE { $$ = TRUE; }
1712 | /* EMPTY */ { $$ = FALSE; }
1715 opt_analyze: ANALYZE { $$ = TRUE; }
1716 | /* EMPTY */ { $$ = FALSE; }
1719 opt_va_list: '(' va_list ')'
1726 { $$=lcons($1,NIL); }
1728 { $$=lappend($1,$3); }
1731 /*****************************************************************************
1736 *****************************************************************************/
1738 ExplainStmt: EXPLAIN opt_verbose OptimizableStmt
1740 ExplainStmt *n = makeNode(ExplainStmt);
1742 n->query = (Query*)$3;
1747 /*****************************************************************************
1749 * Optimizable Stmts: *
1751 * one of the five queries processed by the planner *
1753 * [ultimately] produces query-trees as specified *
1754 * in the query-spec document in ~postgres/ref *
1756 *****************************************************************************/
1758 OptimizableStmt: RetrieveStmt
1763 | DeleteStmt /* by default all are $$=$1 */
1767 /*****************************************************************************
1772 *****************************************************************************/
1774 AppendStmt: INSERT INTO relation_name opt_column_list insert_rest
1782 insert_rest: VALUES '(' res_target_list2 ')'
1784 $$ = makeNode(AppendStmt);
1785 $$->targetList = $3;
1786 $$->fromClause = NIL;
1787 $$->whereClause = NULL;
1789 | SELECT res_target_list2 from_clause where_clause
1791 $$ = makeNode(AppendStmt);
1792 $$->targetList = $2;
1793 $$->fromClause = $3;
1794 $$->whereClause = $4;
1798 opt_column_list: '(' columnList ')' { $$ = $2; }
1799 | /*EMPTY*/ { $$ = NIL; }
1803 columnList ',' columnElem
1804 { $$ = lappend($1, $3); }
1806 { $$ = lcons($1, NIL); }
1809 columnElem: Id opt_indirection
1811 Ident *id = makeNode(Ident);
1813 id->indirection = $2;
1818 /*****************************************************************************
1823 *****************************************************************************/
1825 DeleteStmt: DELETE FROM relation_name
1828 DeleteStmt *n = makeNode(DeleteStmt);
1830 n->whereClause = $4;
1836 /*****************************************************************************
1839 * ReplaceStmt (UPDATE)
1841 *****************************************************************************/
1843 ReplaceStmt: UPDATE relation_name
1848 ReplaceStmt *n = makeNode(ReplaceStmt);
1852 n->whereClause = $6;
1858 /*****************************************************************************
1863 *****************************************************************************/
1865 CursorStmt: DECLARE name opt_binary CURSOR FOR
1866 SELECT opt_unique res_target_list2
1867 from_clause where_clause group_clause sort_clause
1869 CursorStmt *n = makeNode(CursorStmt);
1871 /* from PORTAL name */
1873 * 15 august 1991 -- since 3.0 postgres does locking
1874 * right, we discovered that portals were violating
1875 * locking protocol. portal locks cannot span xacts.
1876 * as a short-term fix, we installed the check here.
1879 if (!IsTransactionBlock())
1880 elog(WARN,"Named portals may only be used in begin/end transaction blocks",NULL);
1887 n->whereClause = $10;
1888 n->groupClause = $11;
1889 n->sortClause = $12;
1895 /*****************************************************************************
1900 *****************************************************************************/
1902 /******************************************************************************
1903 RetrieveStmt: SELECT opt_unique res_target_list2
1904 result from_clause where_clause
1905 group_clause having_clause
1908 RetrieveStmt *n = makeNode(RetrieveStmt);
1913 n->whereClause = $6;
1914 n->groupClause = $7;
1915 n->havingClause = $8;
1921 RetrieveStmt: Select UNION select_list sort_clause
1922 | Select sort_clause
1923 Select: SELECT opt_unique res_target_list2
1924 result from_clause where_clause
1925 group_clause having_clause
1927 Select *n = makeNode(Select);
1932 n->whereClause = $6;
1933 n->groupClause = $7;
1934 n->havingClause = $8;
1938 ******************************************************************************/
1940 RetrieveStmt: SELECT opt_unique res_target_list2
1941 result from_clause where_clause
1942 group_clause having_clause
1943 union_clause sort_clause
1945 RetrieveStmt *n = makeNode(RetrieveStmt);
1950 n->whereClause = $6;
1951 n->groupClause = $7;
1952 n->havingClause = $8;
1953 n->selectClause = $9;
1954 n->sortClause = $10;
1959 union_clause: UNION select_list { $$ = $2; }
1960 | /*EMPTY*/ { $$ = NIL; }
1963 select_list: select_list UNION SubSelect
1964 { $$ = lappend($1, $3); }
1966 { $$ = lcons($1, NIL); }
1969 SubSelect: SELECT opt_unique res_target_list2
1970 result from_clause where_clause
1971 group_clause having_clause
1973 SubSelect *n = makeNode(SubSelect);
1977 n->whereClause = $6;
1978 n->groupClause = $7;
1979 n->havingClause = $8;
1984 result: INTO TABLE relation_name
1985 { $$= $3; /* should check for archive level */ }
1990 opt_unique: DISTINCT { $$ = "*"; }
1991 | DISTINCT ON Id { $$ = $3; }
1992 | /*EMPTY*/ { $$ = NULL;}
1995 sort_clause: ORDER BY sortby_list { $$ = $3; }
1996 | /*EMPTY*/ { $$ = NIL; }
2000 { $$ = lcons($1, NIL); }
2001 | sortby_list ',' sortby
2002 { $$ = lappend($1, $3); }
2007 $$ = makeNode(SortGroupBy);
2013 | Id '.' Id OptUseOp
2015 $$ = makeNode(SortGroupBy);
2023 $$ = makeNode(SortGroupBy);
2031 OptUseOp: USING Op { $$ = $2; }
2032 | USING '<' { $$ = "<"; }
2033 | USING '>' { $$ = ">"; }
2035 | DESC { $$ = ">"; }
2036 | /*EMPTY*/ { $$ = "<"; /*default*/ }
2039 index_params: index_list { $$ = $1; }
2040 | func_index { $$ = lcons($1,NIL); }
2044 index_list ',' index_elem
2045 { $$ = lappend($1, $3); }
2047 { $$ = lcons($1, NIL); }
2050 func_index: name '(' name_list ')' opt_type opt_class
2052 $$ = makeNode(IndexElem);
2060 index_elem: attr_name opt_type opt_class
2062 $$ = makeNode(IndexElem);
2070 opt_type: ':' Typename { $$ = $2;}
2071 | /*EMPTY*/ { $$ = NULL;}
2075 | WITH class { $$ = $2; }
2076 | /*EMPTY*/ { $$ = NULL; }
2080 * jimmy bell-style recursive queries aren't supported in the
2083 * ...however, recursive addattr and rename supported. make special
2086 * XXX i believe '*' should be the default behavior, but...
2088 opt_inh_star: '*' { $$ = TRUE; }
2089 | /*EMPTY*/ { $$ = FALSE; }
2092 relation_name_list: name_list;
2095 { $$ = lcons(makeString($1),NIL); }
2096 | name_list ',' name
2097 { $$ = lappend($1,makeString($3)); }
2100 group_clause: GROUP BY groupby_list { $$ = $3; }
2101 | /*EMPTY*/ { $$ = NIL; }
2104 groupby_list: groupby { $$ = lcons($1, NIL); }
2105 | groupby_list ',' groupby { $$ = lappend($1, $3); }
2110 $$ = makeNode(SortGroupBy);
2118 $$ = makeNode(SortGroupBy);
2126 $$ = makeNode(SortGroupBy);
2134 having_clause: HAVING a_expr { $$ = $2; }
2135 | /*EMPTY*/ { $$ = NULL; }
2138 /*****************************************************************************
2140 * clauses common to all Optimizable Stmts:
2144 *****************************************************************************/
2146 from_clause: FROM '(' relation_expr join_expr JOIN relation_expr join_spec ')'
2149 elog(WARN,"JOIN not yet implemented",NULL);
2151 | FROM from_list { $$ = $2; }
2152 | /*EMPTY*/ { $$ = NIL; }
2155 from_list: from_list ',' from_val
2156 { $$ = lappend($1, $3); }
2157 | from_val CROSS JOIN from_val
2158 { elog(WARN,"CROSS JOIN not yet implemented",NULL); }
2160 { $$ = lcons($1, NIL); }
2163 from_val: relation_expr AS Id
2165 $$ = makeNode(RangeVar);
2171 $$ = makeNode(RangeVar);
2177 $$ = makeNode(RangeVar);
2183 join_expr: NATURAL join_expr { $$ = NULL; }
2185 { elog(WARN,"FULL OUTER JOIN not yet implemented",NULL); }
2187 { elog(WARN,"LEFT OUTER JOIN not yet implemented",NULL); }
2189 { elog(WARN,"RIGHT OUTER JOIN not yet implemented",NULL); }
2191 { elog(WARN,"OUTER JOIN not yet implemented",NULL); }
2193 { elog(WARN,"INNER JOIN not yet implemented",NULL); }
2195 { elog(WARN,"UNION JOIN not yet implemented",NULL); }
2197 { elog(WARN,"INNER JOIN not yet implemented",NULL); }
2200 join_outer: OUTERJOIN { $$ = NULL; }
2201 | /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
2204 join_spec: ON '(' a_expr ')' { $$ = NULL; }
2205 | USING '(' join_list ')' { $$ = NULL; }
2206 | /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
2209 join_list: join_using { $$ = lcons($1, NIL); }
2210 | join_list ',' join_using { $$ = lappend($1, $3); }
2215 $$ = makeNode(SortGroupBy);
2223 $$ = makeNode(SortGroupBy);
2231 $$ = makeNode(SortGroupBy);
2239 where_clause: WHERE a_expr { $$ = $2; }
2240 | /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
2243 relation_expr: relation_name
2245 /* normal relations */
2246 $$ = makeNode(RelExpr);
2249 $$->timeRange = NULL;
2251 | relation_name '*' %prec '='
2253 /* inheiritance query */
2254 $$ = makeNode(RelExpr);
2257 $$->timeRange = NULL;
2259 | relation_name time_range
2261 /* time-qualified query */
2262 $$ = makeNode(RelExpr);
2270 time_range: '[' opt_range_start ',' opt_range_end ']'
2272 $$ = makeNode(TimeRange);
2278 $$ = makeNode(TimeRange);
2284 opt_range_start: date
2285 | /*EMPTY*/ { $$ = "epoch"; }
2289 | /*EMPTY*/ { $$ = "now"; }
2292 opt_array_bounds: '[' ']' nest_array_bounds
2293 { $$ = lcons(makeInteger(-1), $3); }
2294 | '[' Iconst ']' nest_array_bounds
2295 { $$ = lcons(makeInteger($2), $4); }
2300 nest_array_bounds: '[' ']' nest_array_bounds
2301 { $$ = lcons(makeInteger(-1), $3); }
2302 | '[' Iconst ']' nest_array_bounds
2303 { $$ = lcons(makeInteger($2), $4); }
2309 * typname handles types without trailing parens for size specification.
2310 * Typename uses either typname or explicit txname(size).
2311 * So, must handle FLOAT in both places. - thomas 1997-09-20
2316 $$ = makeNode(TypeName);
2318 if (!strcasecmp($1, "float"))
2319 tname = xlateSqlType("float8");
2320 else if (!strcasecmp($1, "decimal"))
2321 tname = xlateSqlType("integer");
2322 else if (!strcasecmp($1, "numeric"))
2323 tname = xlateSqlType("integer");
2325 tname = xlateSqlType($1);
2328 /* Is this the name of a complex type? If so, implement
2331 if (!strcmp(saved_relname, tname))
2332 /* This attr is the same type as the relation
2333 * being defined. The classic example: create
2334 * emp(name=text,mgr=emp)
2337 else if (get_typrelid((Type)type(tname)) != InvalidOid)
2338 /* (Eventually add in here that the set can only
2339 * contain one element.)
2347 char *tname = xlateSqlType($2);
2348 $$ = makeNode(TypeName);
2355 * Allow the following parsing categories:
2356 * - strings which are not keywords (Id)
2357 * - some explicit SQL/92 data types (e.g. DOUBLE PRECISION)
2358 * - TYPE as an SQL/92 non-reserved word, but parser keyword
2359 * - other date/time strings (e.g. YEAR)
2360 * - thomas 1997-10-08
2362 txname: Id { $$ = $1; }
2363 | DateTime { $$ = $1; }
2364 | TIME { $$ = xlateSqlType("time"); }
2365 | TYPE_P { $$ = xlateSqlType("type"); }
2366 | INTERVAL interval_opts { $$ = xlateSqlType("interval"); }
2367 | CHARACTER char_type { $$ = $2; }
2368 | DOUBLE PRECISION { $$ = xlateSqlType("float8"); }
2369 | FLOAT { $$ = xlateSqlType("float"); }
2370 | DECIMAL { $$ = "decimal"; }
2371 | NUMERIC { $$ = "numeric"; }
2374 char_type: VARYING { $$ = xlateSqlType("varchar"); }
2375 | /*EMPTY*/ { $$ = xlateSqlType("char"); }
2378 interval_opts: YEARINTERVAL { $$ = lcons("year", NIL); }
2379 | MONTHINTERVAL { $$ = NIL; }
2380 | DAYINTERVAL { $$ = NIL; }
2381 | HOURINTERVAL { $$ = NIL; }
2382 | MINUTEINTERVAL { $$ = NIL; }
2383 | SECONDINTERVAL { $$ = NIL; }
2384 | YEARINTERVAL TO MONTHINTERVAL { $$ = NIL; }
2385 | DAYINTERVAL TO HOURINTERVAL { $$ = NIL; }
2386 | DAYINTERVAL TO MINUTEINTERVAL { $$ = NIL; }
2387 | DAYINTERVAL TO SECONDINTERVAL { $$ = NIL; }
2388 | HOURINTERVAL TO MINUTEINTERVAL { $$ = NIL; }
2389 | HOURINTERVAL TO SECONDINTERVAL { $$ = NIL; }
2390 | /* EMPTY */ { $$ = NIL; }
2393 Typename: typname opt_array_bounds
2396 $$->arrayBounds = $2;
2398 if (!strcasecmp($1->name, "varchar"))
2402 | txname '(' Iconst ')'
2405 * The following implements CHAR() and VARCHAR().
2406 * We do it here instead of the 'typname:' production
2407 * because we don't want to allow arrays of VARCHAR().
2408 * I haven't thought about whether that will work or not.
2410 * Also implements FLOAT().
2411 * Check precision limits assuming IEEE floating types.
2412 * - thomas 1997-09-18
2414 $$ = makeNode(TypeName);
2415 if (!strcasecmp($1, "float")) {
2417 elog(WARN,"precision for FLOAT must be at least 1",NULL);
2419 $$->name = xlateSqlType("float4");
2421 $$->name = xlateSqlType("float8");
2423 elog(WARN,"precision for FLOAT must be less than 16",NULL);
2424 } else if (!strcasecmp($1, "decimal")) {
2425 /* DECIMAL is allowed to have more precision than specified */
2427 elog(WARN,"DECIMAL precision %d exceeds implementation limit of 9",$3);
2428 $$->name = xlateSqlType("integer");
2430 } else if (!strcasecmp($1, "numeric")) {
2431 /* integer holds 9.33 decimal places, so assume an even 9 for now */
2433 elog(WARN,"NUMERIC precision %d must be 9",$3);
2434 $$->name = xlateSqlType("integer");
2437 if (!strcasecmp($1, "char"))
2438 $$->name = xlateSqlType("bpchar");
2439 else if (!strcasecmp($1, "varchar"))
2440 $$->name = xlateSqlType("varchar");
2442 yyerror("parse error");
2444 elog(WARN,"length for '%s' type must be at least 1",$1);
2446 /* we can store a char() of length up to the size
2447 * of a page (8KB) - page headers and friends but
2448 * just to be safe here... - ay 6/95
2449 * XXX note this hardcoded limit - thomas 1997-07-13
2451 elog(WARN,"length for '%s' type cannot exceed 4096",$1);
2453 /* we actually implement this sort of like a varlen, so
2454 * the first 4 bytes is the length. (the difference
2455 * between this and "text" is that we blank-pad and
2456 * truncate where necessary
2458 $$->typlen = 4 + $3;
2461 | txname '(' Iconst ',' Iconst ')'
2463 $$ = makeNode(TypeName);
2464 if (!strcasecmp($1, "decimal")) {
2466 elog(WARN,"DECIMAL precision %d exceeds implementation limit of 9",$3);
2468 elog(WARN,"DECIMAL scale %d must be zero",$5);
2469 $$->name = xlateSqlType("integer");
2471 } else if (!strcasecmp($1, "numeric")) {
2473 elog(WARN,"NUMERIC precision %d must be 9",$3);
2475 elog(WARN,"NUMERIC scale %d must be zero",$5);
2476 $$->name = xlateSqlType("integer");
2479 elog(WARN,"%s(%d,%d) not implemented",$1,$3,$5);
2481 $$->name = xlateSqlType("integer");
2486 /*****************************************************************************
2488 * expression grammar, still needs some cleanup
2490 *****************************************************************************/
2492 a_expr_or_null: a_expr
2496 A_Const *n = makeNode(A_Const);
2497 n->val.type = T_Null;
2501 a_expr: attr opt_indirection
2503 $1->indirection = $2;
2508 | '-' a_expr %prec UMINUS
2509 { $$ = makeA_Expr(OP, "-", NULL, $2); }
2511 { $$ = makeA_Expr(OP, "+", $1, $3); }
2513 { $$ = makeA_Expr(OP, "-", $1, $3); }
2515 { $$ = makeA_Expr(OP, "/", $1, $3); }
2517 { $$ = makeA_Expr(OP, "*", $1, $3); }
2519 { $$ = makeA_Expr(OP, "<", $1, $3); }
2521 { $$ = makeA_Expr(OP, ">", $1, $3); }
2523 { $$ = makeA_Expr(OP, "=", $1, $3); }
2525 { $$ = makeA_Expr(OP, ":", NULL, $2); }
2527 { $$ = makeA_Expr(OP, ";", NULL, $2); }
2529 { $$ = makeA_Expr(OP, "|", NULL, $2); }
2530 | AexprConst TYPECAST Typename
2532 /* AexprConst can be either A_Const or ParamNo */
2533 if (nodeTag($1) == T_A_Const)
2534 ((A_Const *)$1)->typename = $3;
2536 ((ParamNo *)$1)->typename = $3;
2539 | CAST AexprConst AS Typename
2541 /* AexprConst can be either A_Const or ParamNo */
2542 if (nodeTag($2) == T_A_Const)
2543 ((A_Const *)$2)->typename = $4;
2545 ((ParamNo *)$2)->typename = $4;
2548 | '(' a_expr_or_null ')'
2551 { $$ = makeA_Expr(OP, $2, $1, $3); }
2552 | a_expr LIKE a_expr
2553 { $$ = makeA_Expr(OP, "~~", $1, $3); }
2554 | a_expr NOT LIKE a_expr
2555 { $$ = makeA_Expr(OP, "!~~", $1, $4); }
2557 { $$ = makeA_Expr(OP, $1, NULL, $2); }
2559 { $$ = makeA_Expr(OP, $2, $1, NULL); }
2562 /* could be a column name or a relation_name */
2563 Ident *n = makeNode(Ident);
2565 n->indirection = NULL;
2570 FuncCall *n = makeNode(FuncCall);
2571 Ident *star = makeNode(Ident);
2573 /* cheap hack for aggregate (eg. count) */
2576 n->args = lcons(star, NIL);
2581 FuncCall *n = makeNode(FuncCall);
2588 A_Const *n = makeNode(A_Const);
2589 TypeName *t = makeNode(TypeName);
2591 n->val.type = T_String;
2592 n->val.val.str = "now";
2595 t->name = xlateSqlType("date");
2602 A_Const *n = makeNode(A_Const);
2603 TypeName *t = makeNode(TypeName);
2605 n->val.type = T_String;
2606 n->val.val.str = "now";
2609 t->name = xlateSqlType("time");
2614 | CURRENT_TIME '(' AexprConst ')'
2616 FuncCall *n = makeNode(FuncCall);
2617 A_Const *s = makeNode(A_Const);
2618 TypeName *t = makeNode(TypeName);
2620 n->funcname = xlateSqlType("time");
2621 n->args = lcons(s, NIL);
2623 s->val.type = T_String;
2624 s->val.val.str = "now";
2627 t->name = xlateSqlType("time");
2630 elog(NOTICE,"CURRENT_TIME(p) precision not implemented",NULL);
2636 A_Const *n = makeNode(A_Const);
2637 TypeName *t = makeNode(TypeName);
2639 n->val.type = T_String;
2640 n->val.val.str = "now";
2643 t->name = xlateSqlType("timestamp");
2648 | CURRENT_TIMESTAMP '(' AexprConst ')'
2650 FuncCall *n = makeNode(FuncCall);
2651 A_Const *s = makeNode(A_Const);
2652 TypeName *t = makeNode(TypeName);
2654 n->funcname = xlateSqlType("timestamp");
2655 n->args = lcons(s, NIL);
2657 s->val.type = T_String;
2658 s->val.val.str = "now";
2661 t->name = xlateSqlType("timestamp");
2664 elog(NOTICE,"CURRENT_TIMESTAMP(p) precision not implemented",NULL);
2668 /* We probably need to define an "exists" node,
2669 * since the optimizer could choose to find only one match.
2670 * Perhaps the first implementation could just check for
2671 * count(*) > 0? - thomas 1997-07-19
2673 | EXISTS '(' SubSelect ')'
2675 elog(WARN,"EXISTS not yet supported",NULL);
2678 | EXTRACT '(' extract_list ')'
2680 FuncCall *n = makeNode(FuncCall);
2681 n->funcname = "date_part";
2685 | POSITION '(' position_list ')'
2687 FuncCall *n = makeNode(FuncCall);
2688 n->funcname = "strpos";
2692 | SUBSTRING '(' substr_list ')'
2694 FuncCall *n = makeNode(FuncCall);
2695 n->funcname = "substr";
2699 /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
2700 | TRIM '(' BOTH trim_list ')'
2702 FuncCall *n = makeNode(FuncCall);
2703 n->funcname = "btrim";
2707 | TRIM '(' LEADING trim_list ')'
2709 FuncCall *n = makeNode(FuncCall);
2710 n->funcname = "ltrim";
2714 | TRIM '(' TRAILING trim_list ')'
2716 FuncCall *n = makeNode(FuncCall);
2717 n->funcname = "rtrim";
2721 | TRIM '(' trim_list ')'
2723 FuncCall *n = makeNode(FuncCall);
2724 n->funcname = "btrim";
2728 | name '(' expr_list ')'
2730 FuncCall *n = makeNode(FuncCall);
2736 { $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
2738 { $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
2740 { $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); }
2741 | a_expr IS NOT PNULL
2742 { $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); }
2743 | a_expr BETWEEN AexprConst AND AexprConst
2745 $$ = makeA_Expr(AND, NULL,
2746 makeA_Expr(OP, ">=", $1, $3),
2747 makeA_Expr(OP, "<=", $1, $5));
2749 | a_expr NOT BETWEEN AexprConst AND AexprConst
2751 $$ = makeA_Expr(OR, NULL,
2752 makeA_Expr(OP, "<", $1, $4),
2753 makeA_Expr(OP, ">", $1, $6));
2755 | a_expr IN { saved_In_Expr = $1; } '(' in_expr_nodes ')'
2757 | a_expr NOT IN { saved_In_Expr = $1; } '(' not_in_expr_nodes ')'
2760 { $$ = makeA_Expr(AND, NULL, $1, $3); }
2762 { $$ = makeA_Expr(OR, NULL, $1, $3); }
2764 { $$ = makeA_Expr(NOT, NULL, NULL, $2); }
2767 opt_indirection: '[' a_expr ']' opt_indirection
2769 A_Indices *ai = makeNode(A_Indices);
2774 | '[' a_expr ':' a_expr ']' opt_indirection
2776 A_Indices *ai = makeNode(A_Indices);
2785 expr_list: a_expr_or_null
2786 { $$ = lcons($1, NIL); }
2787 | expr_list ',' a_expr_or_null
2788 { $$ = lappend($1, $3); }
2789 | expr_list USING a_expr
2790 { $$ = lappend($1, $3); }
2793 extract_list: DateTime FROM a_expr
2795 A_Const *n = makeNode(A_Const);
2796 n->val.type = T_String;
2797 n->val.val.str = $1;
2799 printf( "string is %s\n", $1);
2801 $$ = lappend(lcons((Node *)n,NIL), $3);
2807 position_list: position_expr IN position_expr
2808 { $$ = makeList($3, $1, -1); }
2813 position_expr: attr opt_indirection
2815 $1->indirection = $2;
2820 | '-' position_expr %prec UMINUS
2821 { $$ = makeA_Expr(OP, "-", NULL, $2); }
2822 | position_expr '+' position_expr
2823 { $$ = makeA_Expr(OP, "+", $1, $3); }
2824 | position_expr '-' position_expr
2825 { $$ = makeA_Expr(OP, "-", $1, $3); }
2826 | position_expr '/' position_expr
2827 { $$ = makeA_Expr(OP, "/", $1, $3); }
2828 | position_expr '*' position_expr
2829 { $$ = makeA_Expr(OP, "*", $1, $3); }
2831 { $$ = makeA_Expr(OP, "|", NULL, $2); }
2832 | AexprConst TYPECAST Typename
2834 /* AexprConst can be either A_Const or ParamNo */
2835 if (nodeTag($1) == T_A_Const)
2836 ((A_Const *)$1)->typename = $3;
2838 ((ParamNo *)$1)->typename = $3;
2841 | CAST AexprConst AS Typename
2843 /* AexprConst can be either A_Const or ParamNo */
2844 if (nodeTag($2) == T_A_Const)
2845 ((A_Const *)$2)->typename = $4;
2847 ((ParamNo *)$2)->typename = $4;
2850 | '(' position_expr ')'
2852 | position_expr Op position_expr
2853 { $$ = makeA_Expr(OP, $2, $1, $3); }
2855 { $$ = makeA_Expr(OP, $1, NULL, $2); }
2857 { $$ = makeA_Expr(OP, $2, $1, NULL); }
2860 /* could be a column name or a relation_name */
2861 Ident *n = makeNode(Ident);
2863 n->indirection = NULL;
2868 FuncCall *n = makeNode(FuncCall);
2873 | POSITION '(' position_list ')'
2875 FuncCall *n = makeNode(FuncCall);
2876 n->funcname = "strpos";
2880 | SUBSTRING '(' substr_list ')'
2882 FuncCall *n = makeNode(FuncCall);
2883 n->funcname = "substr";
2887 /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
2888 | TRIM '(' BOTH trim_list ')'
2890 FuncCall *n = makeNode(FuncCall);
2891 n->funcname = "btrim";
2895 | TRIM '(' LEADING trim_list ')'
2897 FuncCall *n = makeNode(FuncCall);
2898 n->funcname = "ltrim";
2902 | TRIM '(' TRAILING trim_list ')'
2904 FuncCall *n = makeNode(FuncCall);
2905 n->funcname = "rtrim";
2909 | TRIM '(' trim_list ')'
2911 FuncCall *n = makeNode(FuncCall);
2912 n->funcname = "btrim";
2916 | name '(' expr_list ')'
2918 FuncCall *n = makeNode(FuncCall);
2925 substr_list: expr_list substr_from substr_for
2927 $$ = nconc(nconc($1,$2),$3);
2933 substr_from: FROM expr_list
2937 A_Const *n = makeNode(A_Const);
2938 n->val.type = T_Integer;
2939 n->val.val.ival = 1;
2940 $$ = lcons((Node *)n,NIL);
2944 substr_for: FOR expr_list
2950 trim_list: a_expr FROM expr_list
2951 { $$ = lappend($3, $1); }
2958 in_expr_nodes: AexprConst
2959 { $$ = makeA_Expr(OP, "=", saved_In_Expr, $1); }
2960 | in_expr_nodes ',' AexprConst
2961 { $$ = makeA_Expr(OR, NULL, $1,
2962 makeA_Expr(OP, "=", saved_In_Expr, $3));
2966 not_in_expr_nodes: AexprConst
2967 { $$ = makeA_Expr(OP, "<>", saved_In_Expr, $1); }
2968 | not_in_expr_nodes ',' AexprConst
2969 { $$ = makeA_Expr(AND, NULL, $1,
2970 makeA_Expr(OP, "<>", saved_In_Expr, $3));
2974 attr: relation_name '.' attrs
2976 $$ = makeNode(Attr);
2980 $$->indirection = NULL;
2984 $$ = makeNode(Attr);
2988 $$->indirection = NULL;
2993 { $$ = lcons(makeString($1), NIL); }
2994 | attrs '.' attr_name
2995 { $$ = lappend($1, makeString($3)); }
2997 { $$ = lappend($1, makeString("*")); }
3000 DateTime: YEARINTERVAL { $$ = "year"; }
3001 | MONTHINTERVAL { $$ = "month"; }
3002 | DAYINTERVAL { $$ = "day"; }
3003 | HOURINTERVAL { $$ = "hour"; }
3004 | MINUTEINTERVAL { $$ = "minute"; }
3005 | SECONDINTERVAL { $$ = "second"; }
3008 /*****************************************************************************
3012 *****************************************************************************/
3014 res_target_list: res_target_list ',' res_target_el
3015 { $$ = lappend($1,$3); }
3017 { $$ = lcons($1, NIL); }
3020 ResTarget *rt = makeNode(ResTarget);
3021 Attr *att = makeNode(Attr);
3023 att->paramNo = NULL;
3025 att->indirection = NIL;
3027 rt->indirection = NULL;
3028 rt->val = (Node *)att;
3029 $$ = lcons(rt, NIL);
3033 res_target_el: Id opt_indirection '=' a_expr_or_null
3035 $$ = makeNode(ResTarget);
3037 $$->indirection = $2;
3038 $$->val = (Node *)$4;
3040 | attr opt_indirection
3042 $$ = makeNode(ResTarget);
3044 $$->indirection = $2;
3045 $$->val = (Node *)$1;
3047 | relation_name '.' '*'
3049 Attr *att = makeNode(Attr);
3051 att->paramNo = NULL;
3052 att->attrs = lcons(makeString("*"), NIL);
3053 att->indirection = NIL;
3054 $$ = makeNode(ResTarget);
3056 $$->indirection = NULL;
3057 $$->val = (Node *)att;
3062 ** target list for select.
3063 ** should get rid of the other but is still needed by the defunct retrieve into
3064 ** and update (uses a subset)
3066 res_target_list2: res_target_list2 ',' res_target_el2
3067 { $$ = lappend($1, $3); }
3069 { $$ = lcons($1, NIL); }
3072 /* AS is not optional because shift/red conflict with unary ops */
3073 res_target_el2: a_expr_or_null AS ColId
3075 $$ = makeNode(ResTarget);
3077 $$->indirection = NULL;
3078 $$->val = (Node *)$1;
3082 $$ = makeNode(ResTarget);
3084 $$->indirection = NULL;
3085 $$->val = (Node *)$1;
3087 | relation_name '.' '*'
3089 Attr *att = makeNode(Attr);
3091 att->paramNo = NULL;
3092 att->attrs = lcons(makeString("*"), NIL);
3093 att->indirection = NIL;
3094 $$ = makeNode(ResTarget);
3096 $$->indirection = NULL;
3097 $$->val = (Node *)att;
3101 Attr *att = makeNode(Attr);
3103 att->paramNo = NULL;
3105 att->indirection = NIL;
3106 $$ = makeNode(ResTarget);
3108 $$->indirection = NULL;
3109 $$->val = (Node *)att;
3113 opt_id: Id { $$ = $1; }
3114 | /* EMPTY */ { $$ = NULL; }
3117 relation_name: SpecialRuleRelation
3120 strNcpy(saved_relname, $1, NAMEDATALEN-1);
3124 /* disallow refs to magic system tables */
3125 if (strcmp(LogRelationName, $1) == 0
3126 || strcmp(VariableRelationName, $1) == 0
3127 || strcmp(TimeRelationName, $1) == 0
3128 || strcmp(MagicRelationName, $1) == 0)
3129 elog(WARN,"%s cannot be accessed by users",$1);
3132 strNcpy(saved_relname, $1, NAMEDATALEN-1);
3136 database_name: Id { $$ = $1; };
3137 access_method: Id { $$ = $1; };
3138 attr_name: ColId { $$ = $1; };
3139 class: Id { $$ = $1; };
3140 index_name: Id { $$ = $1; };
3142 name: Id { $$ = $1; }
3143 | DateTime { $$ = $1; }
3144 | TIME { $$ = xlateSqlType("time"); }
3145 | TYPE_P { $$ = xlateSqlType("type"); }
3148 date: Sconst { $$ = $1; };
3149 file_name: Sconst { $$ = $1; };
3150 recipe_name: Id { $$ = $1; };
3154 A_Const *n = makeNode(A_Const);
3155 n->val.type = T_Integer;
3156 n->val.val.ival = $1;
3161 A_Const *n = makeNode(A_Const);
3162 n->val.type = T_Float;
3163 n->val.val.dval = $1;
3168 A_Const *n = makeNode(A_Const);
3169 n->val.type = T_String;
3170 n->val.val.str = $1;
3174 { $$ = (Node *)$1; }
3179 $$ = makeNode(ParamNo);
3184 NumConst: Iconst { $$ = makeInteger($1); }
3185 | FCONST { $$ = makeFloat($1); }
3188 Iconst: ICONST { $$ = $1; };
3189 Sconst: SCONST { $$ = $1; };
3191 Id: IDENT { $$ = $1; };
3193 /* Column identifier (also used for table identifier)
3194 * Allow date/time names ("year", etc.) (SQL/92 extension).
3195 * Allow TYPE (SQL/92 non-reserved word).
3196 * - thomas 1997-10-08
3198 ColId: Id { $$ = $1; }
3199 | DateTime { $$ = $1; }
3200 | TIME { $$ = "time"; }
3201 | TYPE_P { $$ = "type"; }
3204 SpecialRuleRelation: CURRENT
3209 elog(WARN,"CURRENT used in non-rule query",NULL);
3216 elog(WARN,"NEW used in non-rule query",NULL);
3226 static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr)
3228 A_Expr *a = makeNode(A_Expr);
3237 * Convert alternate type names to internal Postgres types.
3238 * Do not convert "float", since that is handled elsewhere
3239 * for FLOAT(p) syntax.
3242 xlateSqlType(char *name)
3244 if (!strcasecmp(name,"int") ||
3245 !strcasecmp(name,"integer"))
3246 return "int4"; /* strdup("int4") -- strdup leaks memory here */
3247 else if (!strcasecmp(name, "smallint"))
3249 else if (!strcasecmp(name, "real"))
3251 else if (!strcasecmp(name, "interval"))
3257 void parser_init(Oid *typev, int nargs)
3259 QueryIsRule = FALSE;
3260 saved_relname[0]= '\0';
3261 saved_In_Expr = NULL;
3263 param_type_init(typev, nargs);
3266 /* FlattenStringList()
3267 * Traverse list of string nodes and convert to a single string.
3268 * Used for reconstructing string form of complex expressions.
3270 * Allocate at least one byte for terminator.
3273 FlattenStringList(List *list)
3281 nlist = length(list);
3283 printf( "list has %d elements\n", nlist);
3287 v = (Value *)lfirst(l);
3291 printf( "sp is x%8p; length of %s is %d\n", sp, sp, strlen(sp));
3297 s = (char*) palloc(len+1);
3302 v = (Value *)lfirst(l);
3306 printf( "length of %s is %d\n", sp, strlen(sp));
3309 if (l != NIL) strcat(s," ");
3314 printf( "flattened string is \"%s\"\n", s);
3318 } /* FlattenStringList() */
3320 /* makeConstantList()
3321 * Convert constant value node into string node.
3324 makeConstantList( A_Const *n)
3326 char *defval = NULL;
3328 printf( "in AexprConst\n");
3330 if (nodeTag(n) != T_A_Const) {
3331 elog(WARN,"Cannot handle non-constant parameter",NULL);
3333 } else if (n->val.type == T_Float) {
3335 printf( "AexprConst float is %f\n", n->val.val.dval);
3337 defval = (char*) palloc(20+1);
3338 sprintf( defval, "%g", n->val.val.dval);
3340 } else if (n->val.type == T_Integer) {
3342 printf( "AexprConst integer is %ld\n", n->val.val.ival);
3344 defval = (char*) palloc(20+1);
3345 sprintf( defval, "%ld", n->val.val.ival);
3347 } else if (n->val.type == T_String) {
3350 printf( "AexprConst string is \"%s\"\n", n->val.val.str);
3353 defval = (char*) palloc(strlen( ((A_Const *) n)->val.val.str) + 3);
3354 strcpy( defval, "'");
3355 strcat( defval, ((A_Const *) n)->val.val.str);
3356 strcat( defval, "'");
3359 elog(WARN,"Internal error: cannot encode node",NULL);
3363 printf( "AexprConst argument is \"%s\"\n", defval);
3366 return( lcons( makeString(defval), NIL));
3367 } /* makeConstantList() */