1 /*-------------------------------------------------------------------------
4 * Functions to convert stored expressions/querytrees back to
7 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
12 * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.296 2009/02/25 18:00:01 tgl Exp $
14 *-------------------------------------------------------------------------
21 #include "access/genam.h"
22 #include "access/sysattr.h"
23 #include "catalog/dependency.h"
24 #include "catalog/indexing.h"
25 #include "catalog/pg_authid.h"
26 #include "catalog/pg_constraint.h"
27 #include "catalog/pg_depend.h"
28 #include "catalog/pg_language.h"
29 #include "catalog/pg_opclass.h"
30 #include "catalog/pg_operator.h"
31 #include "catalog/pg_proc.h"
32 #include "catalog/pg_trigger.h"
33 #include "catalog/pg_type.h"
34 #include "commands/defrem.h"
35 #include "commands/tablespace.h"
36 #include "executor/spi.h"
38 #include "nodes/makefuncs.h"
39 #include "nodes/nodeFuncs.h"
40 #include "optimizer/clauses.h"
41 #include "optimizer/tlist.h"
42 #include "parser/gramparse.h"
43 #include "parser/keywords.h"
44 #include "parser/parse_func.h"
45 #include "parser/parse_oper.h"
46 #include "parser/parsetree.h"
47 #include "rewrite/rewriteHandler.h"
48 #include "rewrite/rewriteManip.h"
49 #include "rewrite/rewriteSupport.h"
50 #include "utils/array.h"
51 #include "utils/builtins.h"
52 #include "utils/fmgroids.h"
53 #include "utils/lsyscache.h"
54 #include "utils/tqual.h"
55 #include "utils/syscache.h"
56 #include "utils/typcache.h"
57 #include "utils/xml.h"
61 * Pretty formatting constants
66 #define PRETTYINDENT_STD 8
67 #define PRETTYINDENT_JOIN 13
68 #define PRETTYINDENT_JOIN_ON (PRETTYINDENT_JOIN-PRETTYINDENT_STD)
69 #define PRETTYINDENT_VAR 4
72 #define PRETTYFLAG_PAREN 1
73 #define PRETTYFLAG_INDENT 2
75 /* macro to test if pretty action needed */
76 #define PRETTY_PAREN(context) ((context)->prettyFlags & PRETTYFLAG_PAREN)
77 #define PRETTY_INDENT(context) ((context)->prettyFlags & PRETTYFLAG_INDENT)
85 /* Context info needed for invoking a recursive querytree display routine */
88 StringInfo buf; /* output buffer to append to */
89 List *namespaces; /* List of deparse_namespace nodes */
90 List *windowClause; /* Current query level's WINDOW clause */
91 List *windowTList; /* targetlist for resolving WINDOW clause */
92 int prettyFlags; /* enabling of pretty-print functions */
93 int indentLevel; /* current indent level for prettyprint */
94 bool varprefix; /* TRUE to print prefixes on Vars */
98 * Each level of query context around a subtree needs a level of Var namespace.
99 * A Var having varlevelsup=N refers to the N'th item (counting from 0) in
100 * the current context's namespaces list.
102 * The rangetable is the list of actual RTEs from the query tree, and the
103 * cte list is the list of actual CTEs.
105 * For deparsing plan trees, we provide for outer and inner subplan nodes.
106 * The tlists of these nodes are used to resolve OUTER and INNER varnos.
107 * Also, in the plan-tree case we don't have access to the parse-time CTE
108 * list, so we need a list of subplans instead.
112 List *rtable; /* List of RangeTblEntry nodes */
113 List *ctes; /* List of CommonTableExpr nodes */
114 List *subplans; /* List of subplans, in plan-tree case */
115 Plan *outer_plan; /* OUTER subplan, or NULL if none */
116 Plan *inner_plan; /* INNER subplan, or NULL if none */
124 static SPIPlanPtr plan_getrulebyoid = NULL;
125 static const char *query_getrulebyoid = "SELECT * FROM pg_catalog.pg_rewrite WHERE oid = $1";
126 static SPIPlanPtr plan_getviewrule = NULL;
127 static const char *query_getviewrule = "SELECT * FROM pg_catalog.pg_rewrite WHERE ev_class = $1 AND rulename = $2";
133 * Most of these functions used to use fixed-size buffers to build their
134 * results. Now, they take an (already initialized) StringInfo object
135 * as a parameter, and append their text output to its contents.
138 static char *deparse_expression_pretty(Node *expr, List *dpcontext,
139 bool forceprefix, bool showimplicit,
140 int prettyFlags, int startIndent);
141 static char *pg_get_viewdef_worker(Oid viewoid, int prettyFlags);
142 static void decompile_column_index_array(Datum column_index_array, Oid relId,
144 static char *pg_get_ruledef_worker(Oid ruleoid, int prettyFlags);
145 static char *pg_get_indexdef_worker(Oid indexrelid, int colno, bool showTblSpc,
147 static char *pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
149 static char *pg_get_expr_worker(text *expr, Oid relid, char *relname,
151 static int print_function_arguments(StringInfo buf, HeapTuple proctup,
152 bool print_table_args, bool print_defaults);
153 static void print_function_rettype(StringInfo buf, HeapTuple proctup);
154 static void make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
156 static void make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
158 static void get_query_def(Query *query, StringInfo buf, List *parentnamespace,
159 TupleDesc resultDesc, int prettyFlags, int startIndent);
160 static void get_values_def(List *values_lists, deparse_context *context);
161 static void get_with_clause(Query *query, deparse_context *context);
162 static void get_select_query_def(Query *query, deparse_context *context,
163 TupleDesc resultDesc);
164 static void get_insert_query_def(Query *query, deparse_context *context);
165 static void get_update_query_def(Query *query, deparse_context *context);
166 static void get_delete_query_def(Query *query, deparse_context *context);
167 static void get_utility_query_def(Query *query, deparse_context *context);
168 static void get_basic_select_query(Query *query, deparse_context *context,
169 TupleDesc resultDesc);
170 static void get_target_list(List *targetList, deparse_context *context,
171 TupleDesc resultDesc);
172 static void get_setop_query(Node *setOp, Query *query,
173 deparse_context *context,
174 TupleDesc resultDesc);
175 static Node *get_rule_sortgroupclause(SortGroupClause *srt, List *tlist,
177 deparse_context *context);
178 static void get_rule_orderby(List *orderList, List *targetList,
179 bool force_colno, deparse_context *context);
180 static void get_rule_windowclause(Query *query, deparse_context *context);
181 static void get_rule_windowspec(WindowClause *wc, List *targetList,
182 deparse_context *context);
183 static void push_plan(deparse_namespace *dpns, Plan *subplan);
184 static char *get_variable(Var *var, int levelsup, bool showstar,
185 deparse_context *context);
186 static RangeTblEntry *find_rte_by_refname(const char *refname,
187 deparse_context *context);
188 static const char *get_simple_binary_op_name(OpExpr *expr);
189 static bool isSimpleNode(Node *node, Node *parentNode, int prettyFlags);
190 static void appendStringInfoSpaces(StringInfo buf, int count);
191 static void appendContextKeyword(deparse_context *context, const char *str,
192 int indentBefore, int indentAfter, int indentPlus);
193 static void get_rule_expr(Node *node, deparse_context *context,
195 static void get_oper_expr(OpExpr *expr, deparse_context *context);
196 static void get_func_expr(FuncExpr *expr, deparse_context *context,
198 static void get_agg_expr(Aggref *aggref, deparse_context *context);
199 static void get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context);
200 static void get_coercion_expr(Node *arg, deparse_context *context,
201 Oid resulttype, int32 resulttypmod,
203 static void get_const_expr(Const *constval, deparse_context *context,
205 static void simple_quote_literal(StringInfo buf, const char *val);
206 static void get_sublink_expr(SubLink *sublink, deparse_context *context);
207 static void get_from_clause(Query *query, const char *prefix,
208 deparse_context *context);
209 static void get_from_clause_item(Node *jtnode, Query *query,
210 deparse_context *context);
211 static void get_from_clause_alias(Alias *alias, RangeTblEntry *rte,
212 deparse_context *context);
213 static void get_from_clause_coldeflist(List *names, List *types, List *typmods,
214 deparse_context *context);
215 static void get_opclass_name(Oid opclass, Oid actual_datatype,
217 static Node *processIndirection(Node *node, deparse_context *context,
219 static void printSubscripts(ArrayRef *aref, deparse_context *context);
220 static char *generate_relation_name(Oid relid, List *namespaces);
221 static char *generate_function_name(Oid funcid, int nargs, Oid *argtypes,
223 static char *generate_operator_name(Oid operid, Oid arg1, Oid arg2);
224 static text *string_to_text(char *str);
225 static char *flatten_reloptions(Oid relid);
227 #define only_marker(rte) ((rte)->inh ? "" : "ONLY ")
231 * get_ruledef - Do it all and return a text
232 * that could be used as a statement
233 * to recreate the rule
237 pg_get_ruledef(PG_FUNCTION_ARGS)
239 Oid ruleoid = PG_GETARG_OID(0);
241 PG_RETURN_TEXT_P(string_to_text(pg_get_ruledef_worker(ruleoid, 0)));
246 pg_get_ruledef_ext(PG_FUNCTION_ARGS)
248 Oid ruleoid = PG_GETARG_OID(0);
249 bool pretty = PG_GETARG_BOOL(1);
252 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
253 PG_RETURN_TEXT_P(string_to_text(pg_get_ruledef_worker(ruleoid, prettyFlags)));
258 pg_get_ruledef_worker(Oid ruleoid, int prettyFlags)
268 * Do this first so that string is alloc'd in outer context not SPI's.
270 initStringInfo(&buf);
273 * Connect to SPI manager
275 if (SPI_connect() != SPI_OK_CONNECT)
276 elog(ERROR, "SPI_connect failed");
279 * On the first call prepare the plan to lookup pg_rewrite. We read
280 * pg_rewrite over the SPI manager instead of using the syscache to be
281 * checked for read access on pg_rewrite.
283 if (plan_getrulebyoid == NULL)
288 argtypes[0] = OIDOID;
289 plan = SPI_prepare(query_getrulebyoid, 1, argtypes);
291 elog(ERROR, "SPI_prepare failed for \"%s\"", query_getrulebyoid);
292 plan_getrulebyoid = SPI_saveplan(plan);
296 * Get the pg_rewrite tuple for this rule
298 args[0] = ObjectIdGetDatum(ruleoid);
300 spirc = SPI_execute_plan(plan_getrulebyoid, args, nulls, true, 1);
301 if (spirc != SPI_OK_SELECT)
302 elog(ERROR, "failed to get pg_rewrite tuple for rule %u", ruleoid);
303 if (SPI_processed != 1)
304 appendStringInfo(&buf, "-");
308 * Get the rule's definition and put it into executor's memory
310 ruletup = SPI_tuptable->vals[0];
311 rulettc = SPI_tuptable->tupdesc;
312 make_ruledef(&buf, ruletup, rulettc, prettyFlags);
316 * Disconnect from SPI manager
318 if (SPI_finish() != SPI_OK_FINISH)
319 elog(ERROR, "SPI_finish failed");
326 * get_viewdef - Mainly the same thing, but we
327 * only return the SELECT part of a view
331 pg_get_viewdef(PG_FUNCTION_ARGS)
334 Oid viewoid = PG_GETARG_OID(0);
336 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, 0)));
341 pg_get_viewdef_ext(PG_FUNCTION_ARGS)
344 Oid viewoid = PG_GETARG_OID(0);
345 bool pretty = PG_GETARG_BOOL(1);
348 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
349 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, prettyFlags)));
353 pg_get_viewdef_name(PG_FUNCTION_ARGS)
355 /* By qualified name */
356 text *viewname = PG_GETARG_TEXT_P(0);
360 viewrel = makeRangeVarFromNameList(textToQualifiedNameList(viewname));
361 viewoid = RangeVarGetRelid(viewrel, false);
363 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, 0)));
368 pg_get_viewdef_name_ext(PG_FUNCTION_ARGS)
370 /* By qualified name */
371 text *viewname = PG_GETARG_TEXT_P(0);
372 bool pretty = PG_GETARG_BOOL(1);
377 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
378 viewrel = makeRangeVarFromNameList(textToQualifiedNameList(viewname));
379 viewoid = RangeVarGetRelid(viewrel, false);
381 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, prettyFlags)));
385 * Common code for by-OID and by-name variants of pg_get_viewdef
388 pg_get_viewdef_worker(Oid viewoid, int prettyFlags)
398 * Do this first so that string is alloc'd in outer context not SPI's.
400 initStringInfo(&buf);
403 * Connect to SPI manager
405 if (SPI_connect() != SPI_OK_CONNECT)
406 elog(ERROR, "SPI_connect failed");
409 * On the first call prepare the plan to lookup pg_rewrite. We read
410 * pg_rewrite over the SPI manager instead of using the syscache to be
411 * checked for read access on pg_rewrite.
413 if (plan_getviewrule == NULL)
418 argtypes[0] = OIDOID;
419 argtypes[1] = NAMEOID;
420 plan = SPI_prepare(query_getviewrule, 2, argtypes);
422 elog(ERROR, "SPI_prepare failed for \"%s\"", query_getviewrule);
423 plan_getviewrule = SPI_saveplan(plan);
427 * Get the pg_rewrite tuple for the view's SELECT rule
429 args[0] = ObjectIdGetDatum(viewoid);
430 args[1] = PointerGetDatum(ViewSelectRuleName);
433 spirc = SPI_execute_plan(plan_getviewrule, args, nulls, true, 2);
434 if (spirc != SPI_OK_SELECT)
435 elog(ERROR, "failed to get pg_rewrite tuple for view %u", viewoid);
436 if (SPI_processed != 1)
437 appendStringInfo(&buf, "Not a view");
441 * Get the rule's definition and put it into executor's memory
443 ruletup = SPI_tuptable->vals[0];
444 rulettc = SPI_tuptable->tupdesc;
445 make_viewdef(&buf, ruletup, rulettc, prettyFlags);
449 * Disconnect from SPI manager
451 if (SPI_finish() != SPI_OK_FINISH)
452 elog(ERROR, "SPI_finish failed");
458 * get_triggerdef - Get the definition of a trigger
462 pg_get_triggerdef(PG_FUNCTION_ARGS)
464 Oid trigid = PG_GETARG_OID(0);
466 Form_pg_trigger trigrec;
475 * Fetch the pg_trigger tuple by the Oid of the trigger
477 tgrel = heap_open(TriggerRelationId, AccessShareLock);
479 ScanKeyInit(&skey[0],
480 ObjectIdAttributeNumber,
481 BTEqualStrategyNumber, F_OIDEQ,
482 ObjectIdGetDatum(trigid));
484 tgscan = systable_beginscan(tgrel, TriggerOidIndexId, true,
485 SnapshotNow, 1, skey);
487 ht_trig = systable_getnext(tgscan);
489 if (!HeapTupleIsValid(ht_trig))
490 elog(ERROR, "could not find tuple for trigger %u", trigid);
492 trigrec = (Form_pg_trigger) GETSTRUCT(ht_trig);
495 * Start the trigger definition. Note that the trigger's name should never
496 * be schema-qualified, but the trigger rel's name may be.
498 initStringInfo(&buf);
500 tgname = NameStr(trigrec->tgname);
501 appendStringInfo(&buf, "CREATE %sTRIGGER %s ",
502 trigrec->tgisconstraint ? "CONSTRAINT " : "",
503 quote_identifier(tgname));
505 if (TRIGGER_FOR_BEFORE(trigrec->tgtype))
506 appendStringInfo(&buf, "BEFORE");
508 appendStringInfo(&buf, "AFTER");
509 if (TRIGGER_FOR_INSERT(trigrec->tgtype))
511 appendStringInfo(&buf, " INSERT");
514 if (TRIGGER_FOR_DELETE(trigrec->tgtype))
517 appendStringInfo(&buf, " OR DELETE");
519 appendStringInfo(&buf, " DELETE");
522 if (TRIGGER_FOR_UPDATE(trigrec->tgtype))
525 appendStringInfo(&buf, " OR UPDATE");
527 appendStringInfo(&buf, " UPDATE");
529 if (TRIGGER_FOR_TRUNCATE(trigrec->tgtype))
532 appendStringInfo(&buf, " OR TRUNCATE");
534 appendStringInfo(&buf, " TRUNCATE");
536 appendStringInfo(&buf, " ON %s ",
537 generate_relation_name(trigrec->tgrelid, NIL));
539 if (trigrec->tgisconstraint)
541 if (trigrec->tgconstrrelid != InvalidOid)
542 appendStringInfo(&buf, "FROM %s ",
543 generate_relation_name(trigrec->tgconstrrelid,
545 if (!trigrec->tgdeferrable)
546 appendStringInfo(&buf, "NOT ");
547 appendStringInfo(&buf, "DEFERRABLE INITIALLY ");
548 if (trigrec->tginitdeferred)
549 appendStringInfo(&buf, "DEFERRED ");
551 appendStringInfo(&buf, "IMMEDIATE ");
555 if (TRIGGER_FOR_ROW(trigrec->tgtype))
556 appendStringInfo(&buf, "FOR EACH ROW ");
558 appendStringInfo(&buf, "FOR EACH STATEMENT ");
560 appendStringInfo(&buf, "EXECUTE PROCEDURE %s(",
561 generate_function_name(trigrec->tgfoid, 0, NULL, NULL));
563 if (trigrec->tgnargs > 0)
570 val = DatumGetByteaP(fastgetattr(ht_trig,
571 Anum_pg_trigger_tgargs,
572 tgrel->rd_att, &isnull));
574 elog(ERROR, "tgargs is null for trigger %u", trigid);
575 p = (char *) VARDATA(val);
576 for (i = 0; i < trigrec->tgnargs; i++)
579 appendStringInfo(&buf, ", ");
580 simple_quote_literal(&buf, p);
581 /* advance p to next string embedded in tgargs */
588 /* We deliberately do not put semi-colon at end */
589 appendStringInfo(&buf, ")");
592 systable_endscan(tgscan);
594 heap_close(tgrel, AccessShareLock);
596 PG_RETURN_TEXT_P(string_to_text(buf.data));
600 * get_indexdef - Get the definition of an index
602 * In the extended version, there is a colno argument as well as pretty bool.
603 * if colno == 0, we want a complete index definition.
604 * if colno > 0, we only want the Nth index key's variable or expression.
606 * Note that the SQL-function versions of this omit any info about the
607 * index tablespace; this is intentional because pg_dump wants it that way.
608 * However pg_get_indexdef_string() includes index tablespace if not default.
612 pg_get_indexdef(PG_FUNCTION_ARGS)
614 Oid indexrelid = PG_GETARG_OID(0);
616 PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, 0,
621 pg_get_indexdef_ext(PG_FUNCTION_ARGS)
623 Oid indexrelid = PG_GETARG_OID(0);
624 int32 colno = PG_GETARG_INT32(1);
625 bool pretty = PG_GETARG_BOOL(2);
628 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
629 PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, colno,
630 false, prettyFlags)));
633 /* Internal version that returns a palloc'd C string */
635 pg_get_indexdef_string(Oid indexrelid)
637 return pg_get_indexdef_worker(indexrelid, 0, true, 0);
641 pg_get_indexdef_worker(Oid indexrelid, int colno, bool showTblSpc,
647 Form_pg_index idxrec;
648 Form_pg_class idxrelrec;
651 ListCell *indexpr_item;
657 Datum indoptionDatum;
660 int2vector *indoption;
666 * Fetch the pg_index tuple by the Oid of the index
668 ht_idx = SearchSysCache(INDEXRELID,
669 ObjectIdGetDatum(indexrelid),
671 if (!HeapTupleIsValid(ht_idx))
672 elog(ERROR, "cache lookup failed for index %u", indexrelid);
673 idxrec = (Form_pg_index) GETSTRUCT(ht_idx);
675 indrelid = idxrec->indrelid;
676 Assert(indexrelid == idxrec->indexrelid);
678 /* Must get indclass and indoption the hard way */
679 indclassDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
680 Anum_pg_index_indclass, &isnull);
682 indclass = (oidvector *) DatumGetPointer(indclassDatum);
683 indoptionDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
684 Anum_pg_index_indoption, &isnull);
686 indoption = (int2vector *) DatumGetPointer(indoptionDatum);
689 * Fetch the pg_class tuple of the index relation
691 ht_idxrel = SearchSysCache(RELOID,
692 ObjectIdGetDatum(indexrelid),
694 if (!HeapTupleIsValid(ht_idxrel))
695 elog(ERROR, "cache lookup failed for relation %u", indexrelid);
696 idxrelrec = (Form_pg_class) GETSTRUCT(ht_idxrel);
699 * Fetch the pg_am tuple of the index' access method
701 ht_am = SearchSysCache(AMOID,
702 ObjectIdGetDatum(idxrelrec->relam),
704 if (!HeapTupleIsValid(ht_am))
705 elog(ERROR, "cache lookup failed for access method %u",
707 amrec = (Form_pg_am) GETSTRUCT(ht_am);
710 * Get the index expressions, if any. (NOTE: we do not use the relcache
711 * versions of the expressions and predicate, because we want to display
712 * non-const-folded expressions.)
714 if (!heap_attisnull(ht_idx, Anum_pg_index_indexprs))
720 exprsDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
721 Anum_pg_index_indexprs, &isnull);
723 exprsString = TextDatumGetCString(exprsDatum);
724 indexprs = (List *) stringToNode(exprsString);
730 indexpr_item = list_head(indexprs);
732 context = deparse_context_for(get_rel_name(indrelid), indrelid);
735 * Start the index definition. Note that the index's name should never be
736 * schema-qualified, but the indexed rel's name may be.
738 initStringInfo(&buf);
741 appendStringInfo(&buf, "CREATE %sINDEX %s ON %s USING %s (",
742 idxrec->indisunique ? "UNIQUE " : "",
743 quote_identifier(NameStr(idxrelrec->relname)),
744 generate_relation_name(indrelid, NIL),
745 quote_identifier(NameStr(amrec->amname)));
748 * Report the indexed attributes
751 for (keyno = 0; keyno < idxrec->indnatts; keyno++)
753 AttrNumber attnum = idxrec->indkey.values[keyno];
754 int16 opt = indoption->values[keyno];
757 appendStringInfoString(&buf, sep);
762 /* Simple index column */
765 attname = get_relid_attribute_name(indrelid, attnum);
766 if (!colno || colno == keyno + 1)
767 appendStringInfoString(&buf, quote_identifier(attname));
768 keycoltype = get_atttype(indrelid, attnum);
772 /* expressional index */
775 if (indexpr_item == NULL)
776 elog(ERROR, "too few entries in indexprs list");
777 indexkey = (Node *) lfirst(indexpr_item);
778 indexpr_item = lnext(indexpr_item);
780 str = deparse_expression_pretty(indexkey, context, false, false,
782 if (!colno || colno == keyno + 1)
784 /* Need parens if it's not a bare function call */
785 if (indexkey && IsA(indexkey, FuncExpr) &&
786 ((FuncExpr *) indexkey)->funcformat == COERCE_EXPLICIT_CALL)
787 appendStringInfoString(&buf, str);
789 appendStringInfo(&buf, "(%s)", str);
791 keycoltype = exprType(indexkey);
794 /* Provide decoration only in the colno=0 case */
797 /* Add the operator class name, if not default */
798 get_opclass_name(indclass->values[keyno], keycoltype, &buf);
800 /* Add options if relevant */
801 if (amrec->amcanorder)
803 /* if it supports sort ordering, report DESC and NULLS opts */
804 if (opt & INDOPTION_DESC)
806 appendStringInfo(&buf, " DESC");
807 /* NULLS FIRST is the default in this case */
808 if (!(opt & INDOPTION_NULLS_FIRST))
809 appendStringInfo(&buf, " NULLS LAST");
813 if (opt & INDOPTION_NULLS_FIRST)
814 appendStringInfo(&buf, " NULLS FIRST");
822 appendStringInfoChar(&buf, ')');
825 * If it has options, append "WITH (options)"
827 str = flatten_reloptions(indexrelid);
830 appendStringInfo(&buf, " WITH (%s)", str);
835 * If it's in a nondefault tablespace, say so, but only if requested
841 tblspc = get_rel_tablespace(indexrelid);
842 if (OidIsValid(tblspc))
843 appendStringInfo(&buf, " TABLESPACE %s",
844 quote_identifier(get_tablespace_name(tblspc)));
848 * If it's a partial index, decompile and append the predicate
850 if (!heap_attisnull(ht_idx, Anum_pg_index_indpred))
857 /* Convert text string to node tree */
858 predDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
859 Anum_pg_index_indpred, &isnull);
861 predString = TextDatumGetCString(predDatum);
862 node = (Node *) stringToNode(predString);
866 str = deparse_expression_pretty(node, context, false, false,
868 appendStringInfo(&buf, " WHERE %s", str);
873 ReleaseSysCache(ht_idx);
874 ReleaseSysCache(ht_idxrel);
875 ReleaseSysCache(ht_am);
882 * pg_get_constraintdef
884 * Returns the definition for the constraint, ie, everything that needs to
885 * appear after "ALTER TABLE ... ADD CONSTRAINT <constraintname>".
888 pg_get_constraintdef(PG_FUNCTION_ARGS)
890 Oid constraintId = PG_GETARG_OID(0);
892 PG_RETURN_TEXT_P(string_to_text(pg_get_constraintdef_worker(constraintId,
897 pg_get_constraintdef_ext(PG_FUNCTION_ARGS)
899 Oid constraintId = PG_GETARG_OID(0);
900 bool pretty = PG_GETARG_BOOL(1);
903 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
904 PG_RETURN_TEXT_P(string_to_text(pg_get_constraintdef_worker(constraintId,
905 false, prettyFlags)));
908 /* Internal version that returns a palloc'd C string */
910 pg_get_constraintdef_string(Oid constraintId)
912 return pg_get_constraintdef_worker(constraintId, true, 0);
916 pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
920 Form_pg_constraint conForm;
923 tup = SearchSysCache(CONSTROID,
924 ObjectIdGetDatum(constraintId),
926 if (!HeapTupleIsValid(tup)) /* should not happen */
927 elog(ERROR, "cache lookup failed for constraint %u", constraintId);
928 conForm = (Form_pg_constraint) GETSTRUCT(tup);
930 initStringInfo(&buf);
932 if (fullCommand && OidIsValid(conForm->conrelid))
934 appendStringInfo(&buf, "ALTER TABLE ONLY %s ADD CONSTRAINT %s ",
935 generate_relation_name(conForm->conrelid, NIL),
936 quote_identifier(NameStr(conForm->conname)));
939 switch (conForm->contype)
941 case CONSTRAINT_FOREIGN:
947 /* Start off the constraint definition */
948 appendStringInfo(&buf, "FOREIGN KEY (");
950 /* Fetch and build referencing-column list */
951 val = SysCacheGetAttr(CONSTROID, tup,
952 Anum_pg_constraint_conkey, &isnull);
954 elog(ERROR, "null conkey for constraint %u",
957 decompile_column_index_array(val, conForm->conrelid, &buf);
959 /* add foreign relation name */
960 appendStringInfo(&buf, ") REFERENCES %s(",
961 generate_relation_name(conForm->confrelid,
964 /* Fetch and build referenced-column list */
965 val = SysCacheGetAttr(CONSTROID, tup,
966 Anum_pg_constraint_confkey, &isnull);
968 elog(ERROR, "null confkey for constraint %u",
971 decompile_column_index_array(val, conForm->confrelid, &buf);
973 appendStringInfo(&buf, ")");
976 switch (conForm->confmatchtype)
978 case FKCONSTR_MATCH_FULL:
979 string = " MATCH FULL";
981 case FKCONSTR_MATCH_PARTIAL:
982 string = " MATCH PARTIAL";
984 case FKCONSTR_MATCH_UNSPECIFIED:
988 elog(ERROR, "unrecognized confmatchtype: %d",
989 conForm->confmatchtype);
990 string = ""; /* keep compiler quiet */
993 appendStringInfoString(&buf, string);
995 /* Add ON UPDATE and ON DELETE clauses, if needed */
996 switch (conForm->confupdtype)
998 case FKCONSTR_ACTION_NOACTION:
999 string = NULL; /* suppress default */
1001 case FKCONSTR_ACTION_RESTRICT:
1002 string = "RESTRICT";
1004 case FKCONSTR_ACTION_CASCADE:
1007 case FKCONSTR_ACTION_SETNULL:
1008 string = "SET NULL";
1010 case FKCONSTR_ACTION_SETDEFAULT:
1011 string = "SET DEFAULT";
1014 elog(ERROR, "unrecognized confupdtype: %d",
1015 conForm->confupdtype);
1016 string = NULL; /* keep compiler quiet */
1020 appendStringInfo(&buf, " ON UPDATE %s", string);
1022 switch (conForm->confdeltype)
1024 case FKCONSTR_ACTION_NOACTION:
1025 string = NULL; /* suppress default */
1027 case FKCONSTR_ACTION_RESTRICT:
1028 string = "RESTRICT";
1030 case FKCONSTR_ACTION_CASCADE:
1033 case FKCONSTR_ACTION_SETNULL:
1034 string = "SET NULL";
1036 case FKCONSTR_ACTION_SETDEFAULT:
1037 string = "SET DEFAULT";
1040 elog(ERROR, "unrecognized confdeltype: %d",
1041 conForm->confdeltype);
1042 string = NULL; /* keep compiler quiet */
1046 appendStringInfo(&buf, " ON DELETE %s", string);
1048 if (conForm->condeferrable)
1049 appendStringInfo(&buf, " DEFERRABLE");
1050 if (conForm->condeferred)
1051 appendStringInfo(&buf, " INITIALLY DEFERRED");
1055 case CONSTRAINT_PRIMARY:
1056 case CONSTRAINT_UNIQUE:
1062 /* Start off the constraint definition */
1063 if (conForm->contype == CONSTRAINT_PRIMARY)
1064 appendStringInfo(&buf, "PRIMARY KEY (");
1066 appendStringInfo(&buf, "UNIQUE (");
1068 /* Fetch and build target column list */
1069 val = SysCacheGetAttr(CONSTROID, tup,
1070 Anum_pg_constraint_conkey, &isnull);
1072 elog(ERROR, "null conkey for constraint %u",
1075 decompile_column_index_array(val, conForm->conrelid, &buf);
1077 appendStringInfo(&buf, ")");
1079 indexId = get_constraint_index(constraintId);
1081 /* XXX why do we only print these bits if fullCommand? */
1082 if (fullCommand && OidIsValid(indexId))
1084 char *options = flatten_reloptions(indexId);
1089 appendStringInfo(&buf, " WITH (%s)", options);
1093 tblspc = get_rel_tablespace(indexId);
1094 if (OidIsValid(tblspc))
1095 appendStringInfo(&buf, " USING INDEX TABLESPACE %s",
1096 quote_identifier(get_tablespace_name(tblspc)));
1101 case CONSTRAINT_CHECK:
1110 /* Fetch constraint expression in parsetree form */
1111 val = SysCacheGetAttr(CONSTROID, tup,
1112 Anum_pg_constraint_conbin, &isnull);
1114 elog(ERROR, "null conbin for constraint %u",
1117 conbin = TextDatumGetCString(val);
1118 expr = stringToNode(conbin);
1120 /* Set up deparsing context for Var nodes in constraint */
1121 if (conForm->conrelid != InvalidOid)
1123 /* relation constraint */
1124 context = deparse_context_for(get_rel_name(conForm->conrelid),
1129 /* domain constraint --- can't have Vars */
1133 consrc = deparse_expression_pretty(expr, context, false, false,
1137 * Now emit the constraint definition. There are cases where
1138 * the constraint expression will be fully parenthesized and
1139 * we don't need the outer parens ... but there are other
1140 * cases where we do need 'em. Be conservative for now.
1142 * Note that simply checking for leading '(' and trailing ')'
1143 * would NOT be good enough, consider "(x > 0) AND (y > 0)".
1145 appendStringInfo(&buf, "CHECK (%s)", consrc);
1150 elog(ERROR, "invalid constraint type \"%c\"", conForm->contype);
1155 ReleaseSysCache(tup);
1162 * Convert an int16[] Datum into a comma-separated list of column names
1163 * for the indicated relation; append the list to buf.
1166 decompile_column_index_array(Datum column_index_array, Oid relId,
1173 /* Extract data from array of int16 */
1174 deconstruct_array(DatumGetArrayTypeP(column_index_array),
1175 INT2OID, 2, true, 's',
1176 &keys, NULL, &nKeys);
1178 for (j = 0; j < nKeys; j++)
1182 colName = get_relid_attribute_name(relId, DatumGetInt16(keys[j]));
1185 appendStringInfoString(buf, quote_identifier(colName));
1187 appendStringInfo(buf, ", %s", quote_identifier(colName));
1193 * get_expr - Decompile an expression tree
1195 * Input: an expression tree in nodeToString form, and a relation OID
1197 * Output: reverse-listed expression
1199 * Currently, the expression can only refer to a single relation, namely
1200 * the one specified by the second parameter. This is sufficient for
1201 * partial indexes, column default expressions, etc.
1205 pg_get_expr(PG_FUNCTION_ARGS)
1207 text *expr = PG_GETARG_TEXT_P(0);
1208 Oid relid = PG_GETARG_OID(1);
1211 /* Get the name for the relation */
1212 relname = get_rel_name(relid);
1213 if (relname == NULL)
1214 PG_RETURN_NULL(); /* should we raise an error? */
1216 PG_RETURN_TEXT_P(string_to_text(pg_get_expr_worker(expr, relid, relname, 0)));
1220 pg_get_expr_ext(PG_FUNCTION_ARGS)
1222 text *expr = PG_GETARG_TEXT_P(0);
1223 Oid relid = PG_GETARG_OID(1);
1224 bool pretty = PG_GETARG_BOOL(2);
1228 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
1230 /* Get the name for the relation */
1231 relname = get_rel_name(relid);
1232 if (relname == NULL)
1233 PG_RETURN_NULL(); /* should we raise an error? */
1235 PG_RETURN_TEXT_P(string_to_text(pg_get_expr_worker(expr, relid, relname, prettyFlags)));
1239 pg_get_expr_worker(text *expr, Oid relid, char *relname, int prettyFlags)
1246 /* Convert input TEXT object to C string */
1247 exprstr = text_to_cstring(expr);
1249 /* Convert expression to node tree */
1250 node = (Node *) stringToNode(exprstr);
1253 context = deparse_context_for(relname, relid);
1254 str = deparse_expression_pretty(node, context, false, false,
1264 * get_userbyid - Get a user name by roleid and
1265 * fallback to 'unknown (OID=n)'
1269 pg_get_userbyid(PG_FUNCTION_ARGS)
1271 Oid roleid = PG_GETARG_OID(0);
1274 Form_pg_authid role_rec;
1277 * Allocate space for the result
1279 result = (Name) palloc(NAMEDATALEN);
1280 memset(NameStr(*result), 0, NAMEDATALEN);
1283 * Get the pg_authid entry and print the result
1285 roletup = SearchSysCache(AUTHOID,
1286 ObjectIdGetDatum(roleid),
1288 if (HeapTupleIsValid(roletup))
1290 role_rec = (Form_pg_authid) GETSTRUCT(roletup);
1291 StrNCpy(NameStr(*result), NameStr(role_rec->rolname), NAMEDATALEN);
1292 ReleaseSysCache(roletup);
1295 sprintf(NameStr(*result), "unknown (OID=%u)", roleid);
1297 PG_RETURN_NAME(result);
1302 * pg_get_serial_sequence
1303 * Get the name of the sequence used by a serial column,
1304 * formatted suitably for passing to setval, nextval or currval.
1305 * First parameter is not treated as double-quoted, second parameter
1306 * is --- see documentation for reason.
1309 pg_get_serial_sequence(PG_FUNCTION_ARGS)
1311 text *tablename = PG_GETARG_TEXT_P(0);
1312 text *columnname = PG_GETARG_TEXT_PP(1);
1317 Oid sequenceId = InvalidOid;
1323 /* Get the OID of the table */
1324 tablerv = makeRangeVarFromNameList(textToQualifiedNameList(tablename));
1325 tableOid = RangeVarGetRelid(tablerv, false);
1327 /* Get the number of the column */
1328 column = text_to_cstring(columnname);
1330 attnum = get_attnum(tableOid, column);
1331 if (attnum == InvalidAttrNumber)
1333 (errcode(ERRCODE_UNDEFINED_COLUMN),
1334 errmsg("column \"%s\" of relation \"%s\" does not exist",
1335 column, tablerv->relname)));
1337 /* Search the dependency table for the dependent sequence */
1338 depRel = heap_open(DependRelationId, AccessShareLock);
1340 ScanKeyInit(&key[0],
1341 Anum_pg_depend_refclassid,
1342 BTEqualStrategyNumber, F_OIDEQ,
1343 ObjectIdGetDatum(RelationRelationId));
1344 ScanKeyInit(&key[1],
1345 Anum_pg_depend_refobjid,
1346 BTEqualStrategyNumber, F_OIDEQ,
1347 ObjectIdGetDatum(tableOid));
1348 ScanKeyInit(&key[2],
1349 Anum_pg_depend_refobjsubid,
1350 BTEqualStrategyNumber, F_INT4EQ,
1351 Int32GetDatum(attnum));
1353 scan = systable_beginscan(depRel, DependReferenceIndexId, true,
1354 SnapshotNow, 3, key);
1356 while (HeapTupleIsValid(tup = systable_getnext(scan)))
1358 Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
1361 * We assume any auto dependency of a sequence on a column must be
1362 * what we are looking for. (We need the relkind test because indexes
1363 * can also have auto dependencies on columns.)
1365 if (deprec->classid == RelationRelationId &&
1366 deprec->objsubid == 0 &&
1367 deprec->deptype == DEPENDENCY_AUTO &&
1368 get_rel_relkind(deprec->objid) == RELKIND_SEQUENCE)
1370 sequenceId = deprec->objid;
1375 systable_endscan(scan);
1376 heap_close(depRel, AccessShareLock);
1378 if (OidIsValid(sequenceId))
1381 Form_pg_class classtuple;
1385 /* Get the sequence's pg_class entry */
1386 classtup = SearchSysCache(RELOID,
1387 ObjectIdGetDatum(sequenceId),
1389 if (!HeapTupleIsValid(classtup))
1390 elog(ERROR, "cache lookup failed for relation %u", sequenceId);
1391 classtuple = (Form_pg_class) GETSTRUCT(classtup);
1393 /* Get the namespace */
1394 nspname = get_namespace_name(classtuple->relnamespace);
1396 elog(ERROR, "cache lookup failed for namespace %u",
1397 classtuple->relnamespace);
1399 /* And construct the result string */
1400 result = quote_qualified_identifier(nspname,
1401 NameStr(classtuple->relname));
1403 ReleaseSysCache(classtup);
1405 PG_RETURN_TEXT_P(string_to_text(result));
1413 * pg_get_functiondef
1414 * Returns the complete "CREATE OR REPLACE FUNCTION ..." statement for
1415 * the specified function.
1418 pg_get_functiondef(PG_FUNCTION_ARGS)
1420 Oid funcid = PG_GETARG_OID(0);
1426 Form_pg_language lang;
1435 initStringInfo(&buf);
1437 /* Look up the function */
1438 proctup = SearchSysCache(PROCOID,
1439 ObjectIdGetDatum(funcid),
1441 if (!HeapTupleIsValid(proctup))
1442 elog(ERROR, "cache lookup failed for function %u", funcid);
1443 proc = (Form_pg_proc) GETSTRUCT(proctup);
1444 name = NameStr(proc->proname);
1448 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1449 errmsg("\"%s\" is an aggregate function", name)));
1451 /* Need its pg_language tuple for the language name */
1452 langtup = SearchSysCache(LANGOID,
1453 ObjectIdGetDatum(proc->prolang),
1455 if (!HeapTupleIsValid(langtup))
1456 elog(ERROR, "cache lookup failed for language %u", proc->prolang);
1457 lang = (Form_pg_language) GETSTRUCT(langtup);
1460 * We always qualify the function name, to ensure the right function
1463 nsp = get_namespace_name(proc->pronamespace);
1464 appendStringInfo(&buf, "CREATE OR REPLACE FUNCTION %s(",
1465 quote_qualified_identifier(nsp, name));
1466 (void) print_function_arguments(&buf, proctup, false, true);
1467 appendStringInfoString(&buf, ")\n RETURNS ");
1468 print_function_rettype(&buf, proctup);
1469 appendStringInfo(&buf, "\n LANGUAGE %s\n",
1470 quote_identifier(NameStr(lang->lanname)));
1472 /* Emit some miscellaneous options on one line */
1475 if (proc->proiswindow)
1476 appendStringInfoString(&buf, " WINDOW");
1477 switch (proc->provolatile)
1479 case PROVOLATILE_IMMUTABLE:
1480 appendStringInfoString(&buf, " IMMUTABLE");
1482 case PROVOLATILE_STABLE:
1483 appendStringInfoString(&buf, " STABLE");
1485 case PROVOLATILE_VOLATILE:
1488 if (proc->proisstrict)
1489 appendStringInfoString(&buf, " STRICT");
1490 if (proc->prosecdef)
1491 appendStringInfoString(&buf, " SECURITY DEFINER");
1493 /* This code for the default cost and rows should match functioncmds.c */
1494 if (proc->prolang == INTERNALlanguageId ||
1495 proc->prolang == ClanguageId)
1499 if (proc->procost != procost)
1500 appendStringInfo(&buf, " COST %g", proc->procost);
1502 if (proc->prorows > 0 && proc->prorows != 1000)
1503 appendStringInfo(&buf, " ROWS %g", proc->prorows);
1505 if (oldlen != buf.len)
1506 appendStringInfoChar(&buf, '\n');
1508 /* Emit any proconfig options, one per line */
1509 tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_proconfig, &isnull);
1512 ArrayType *a = DatumGetArrayTypeP(tmp);
1515 Assert(ARR_ELEMTYPE(a) == TEXTOID);
1516 Assert(ARR_NDIM(a) == 1);
1517 Assert(ARR_LBOUND(a)[0] == 1);
1519 for (i = 1; i <= ARR_DIMS(a)[0]; i++)
1523 d = array_ref(a, 1, &i,
1524 -1 /* varlenarray */ ,
1525 -1 /* TEXT's typlen */ ,
1526 false /* TEXT's typbyval */ ,
1527 'i' /* TEXT's typalign */ ,
1531 char *configitem = TextDatumGetCString(d);
1534 pos = strchr(configitem, '=');
1539 appendStringInfo(&buf, " SET %s TO ",
1540 quote_identifier(configitem));
1543 * Some GUC variable names are 'LIST' type and hence must not
1546 if (pg_strcasecmp(configitem, "DateStyle") == 0
1547 || pg_strcasecmp(configitem, "search_path") == 0)
1548 appendStringInfoString(&buf, pos);
1550 simple_quote_literal(&buf, pos);
1551 appendStringInfoChar(&buf, '\n');
1556 /* And finally the function definition ... */
1557 appendStringInfoString(&buf, "AS ");
1559 tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_probin, &isnull);
1562 simple_quote_literal(&buf, TextDatumGetCString(tmp));
1563 appendStringInfoString(&buf, ", "); /* assume prosrc isn't null */
1566 tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_prosrc, &isnull);
1568 elog(ERROR, "null prosrc");
1569 prosrc = TextDatumGetCString(tmp);
1572 * We always use dollar quoting. Figure out a suitable delimiter.
1574 * Since the user is likely to be editing the function body string,
1575 * we shouldn't use a short delimiter that he might easily create a
1576 * conflict with. Hence prefer "$function$", but extend if needed.
1578 initStringInfo(&dq);
1579 appendStringInfoString(&dq, "$function");
1580 while (strstr(prosrc, dq.data) != NULL)
1581 appendStringInfoChar(&dq, 'x');
1582 appendStringInfoChar(&dq, '$');
1584 appendStringInfoString(&buf, dq.data);
1585 appendStringInfoString(&buf, prosrc);
1586 appendStringInfoString(&buf, dq.data);
1588 appendStringInfoString(&buf, "\n");
1590 ReleaseSysCache(langtup);
1591 ReleaseSysCache(proctup);
1593 PG_RETURN_TEXT_P(string_to_text(buf.data));
1597 * pg_get_function_arguments
1598 * Get a nicely-formatted list of arguments for a function.
1599 * This is everything that would go between the parentheses in
1603 pg_get_function_arguments(PG_FUNCTION_ARGS)
1605 Oid funcid = PG_GETARG_OID(0);
1609 initStringInfo(&buf);
1611 proctup = SearchSysCache(PROCOID,
1612 ObjectIdGetDatum(funcid),
1614 if (!HeapTupleIsValid(proctup))
1615 elog(ERROR, "cache lookup failed for function %u", funcid);
1617 (void) print_function_arguments(&buf, proctup, false, true);
1619 ReleaseSysCache(proctup);
1621 PG_RETURN_TEXT_P(string_to_text(buf.data));
1625 * pg_get_function_identity_arguments
1626 * Get a formatted list of arguments for a function.
1627 * This is everything that would go between the parentheses in
1628 * ALTER FUNCTION, etc. In particular, don't print defaults.
1631 pg_get_function_identity_arguments(PG_FUNCTION_ARGS)
1633 Oid funcid = PG_GETARG_OID(0);
1637 initStringInfo(&buf);
1639 proctup = SearchSysCache(PROCOID,
1640 ObjectIdGetDatum(funcid),
1642 if (!HeapTupleIsValid(proctup))
1643 elog(ERROR, "cache lookup failed for function %u", funcid);
1645 (void) print_function_arguments(&buf, proctup, false, false);
1647 ReleaseSysCache(proctup);
1649 PG_RETURN_TEXT_P(string_to_text(buf.data));
1653 * pg_get_function_result
1654 * Get a nicely-formatted version of the result type of a function.
1655 * This is what would appear after RETURNS in CREATE FUNCTION.
1658 pg_get_function_result(PG_FUNCTION_ARGS)
1660 Oid funcid = PG_GETARG_OID(0);
1664 initStringInfo(&buf);
1666 proctup = SearchSysCache(PROCOID,
1667 ObjectIdGetDatum(funcid),
1669 if (!HeapTupleIsValid(proctup))
1670 elog(ERROR, "cache lookup failed for function %u", funcid);
1672 print_function_rettype(&buf, proctup);
1674 ReleaseSysCache(proctup);
1676 PG_RETURN_TEXT_P(string_to_text(buf.data));
1680 * Guts of pg_get_function_result: append the function's return type
1681 * to the specified buffer.
1684 print_function_rettype(StringInfo buf, HeapTuple proctup)
1686 Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(proctup);
1688 StringInfoData rbuf;
1690 initStringInfo(&rbuf);
1692 if (proc->proretset)
1694 /* It might be a table function; try to print the arguments */
1695 appendStringInfoString(&rbuf, "TABLE(");
1696 ntabargs = print_function_arguments(&rbuf, proctup, true, false);
1698 appendStringInfoString(&rbuf, ")");
1700 resetStringInfo(&rbuf);
1705 /* Not a table function, so do the normal thing */
1706 if (proc->proretset)
1707 appendStringInfoString(&rbuf, "SETOF ");
1708 appendStringInfoString(&rbuf, format_type_be(proc->prorettype));
1711 appendStringInfoString(buf, rbuf.data);
1715 * Common code for pg_get_function_arguments and pg_get_function_result:
1716 * append the desired subset of arguments to buf. We print only TABLE
1717 * arguments when print_table_args is true, and all the others when it's false.
1718 * We print argument defaults only if print_defaults is true.
1719 * Function return value is the number of arguments printed.
1722 print_function_arguments(StringInfo buf, HeapTuple proctup,
1723 bool print_table_args, bool print_defaults)
1725 Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(proctup);
1733 ListCell *nextargdefault = NULL;
1736 numargs = get_func_arg_info(proctup,
1737 &argtypes, &argnames, &argmodes);
1739 nlackdefaults = numargs;
1740 if (print_defaults && proc->pronargdefaults > 0)
1742 Datum proargdefaults;
1745 proargdefaults = SysCacheGetAttr(PROCOID, proctup,
1746 Anum_pg_proc_proargdefaults,
1753 str = TextDatumGetCString(proargdefaults);
1754 argdefaults = (List *) stringToNode(str);
1755 Assert(IsA(argdefaults, List));
1757 nextargdefault = list_head(argdefaults);
1758 /* nlackdefaults counts only *input* arguments lacking defaults */
1759 nlackdefaults = proc->pronargs - list_length(argdefaults);
1765 for (i = 0; i < numargs; i++)
1767 Oid argtype = argtypes[i];
1768 char *argname = argnames ? argnames[i] : NULL;
1769 char argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
1770 const char *modename;
1779 case PROARGMODE_INOUT:
1780 modename = "INOUT ";
1783 case PROARGMODE_OUT:
1787 case PROARGMODE_VARIADIC:
1788 modename = "VARIADIC ";
1791 case PROARGMODE_TABLE:
1796 elog(ERROR, "invalid parameter mode '%c'", argmode);
1797 modename = NULL; /* keep compiler quiet */
1802 inputargno++; /* this is a 1-based counter */
1804 if (print_table_args != (argmode == PROARGMODE_TABLE))
1808 appendStringInfoString(buf, ", ");
1809 appendStringInfoString(buf, modename);
1810 if (argname && argname[0])
1811 appendStringInfo(buf, "%s ", argname);
1812 appendStringInfoString(buf, format_type_be(argtype));
1813 if (print_defaults && isinput && inputargno > nlackdefaults)
1817 Assert(nextargdefault != NULL);
1818 expr = (Node *) lfirst(nextargdefault);
1819 nextargdefault = lnext(nextargdefault);
1821 appendStringInfo(buf, " DEFAULT %s",
1822 deparse_expression(expr, NIL, false, false));
1832 * deparse_expression - General utility for deparsing expressions
1834 * calls deparse_expression_pretty with all prettyPrinting disabled
1837 deparse_expression(Node *expr, List *dpcontext,
1838 bool forceprefix, bool showimplicit)
1840 return deparse_expression_pretty(expr, dpcontext, forceprefix,
1841 showimplicit, 0, 0);
1845 * deparse_expression_pretty - General utility for deparsing expressions
1847 * expr is the node tree to be deparsed. It must be a transformed expression
1848 * tree (ie, not the raw output of gram.y).
1850 * dpcontext is a list of deparse_namespace nodes representing the context
1851 * for interpreting Vars in the node tree.
1853 * forceprefix is TRUE to force all Vars to be prefixed with their table names.
1855 * showimplicit is TRUE to force all implicit casts to be shown explicitly.
1857 * tries to pretty up the output according to prettyFlags and startIndent.
1859 * The result is a palloc'd string.
1863 deparse_expression_pretty(Node *expr, List *dpcontext,
1864 bool forceprefix, bool showimplicit,
1865 int prettyFlags, int startIndent)
1868 deparse_context context;
1870 initStringInfo(&buf);
1872 context.namespaces = dpcontext;
1873 context.windowClause = NIL;
1874 context.windowTList = NIL;
1875 context.varprefix = forceprefix;
1876 context.prettyFlags = prettyFlags;
1877 context.indentLevel = startIndent;
1879 get_rule_expr(expr, &context, showimplicit);
1885 * deparse_context_for - Build deparse context for a single relation
1887 * Given the reference name (alias) and OID of a relation, build deparsing
1888 * context for an expression referencing only that relation (as varno 1,
1889 * varlevelsup 0). This is sufficient for many uses of deparse_expression.
1893 deparse_context_for(const char *aliasname, Oid relid)
1895 deparse_namespace *dpns;
1898 dpns = (deparse_namespace *) palloc(sizeof(deparse_namespace));
1900 /* Build a minimal RTE for the rel */
1901 rte = makeNode(RangeTblEntry);
1902 rte->rtekind = RTE_RELATION;
1904 rte->eref = makeAlias(aliasname, NIL);
1906 rte->inFromCl = true;
1908 /* Build one-element rtable */
1909 dpns->rtable = list_make1(rte);
1911 dpns->subplans = NIL;
1912 dpns->outer_plan = dpns->inner_plan = NULL;
1914 /* Return a one-deep namespace stack */
1915 return list_make1(dpns);
1919 * deparse_context_for_plan - Build deparse context for a plan node
1921 * When deparsing an expression in a Plan tree, we might have to resolve
1922 * OUTER or INNER references. To do this, the caller must provide the
1923 * parent Plan node. In the normal case of a join plan node, OUTER and
1924 * INNER references can be resolved by drilling down into the left and
1925 * right child plans. A special case is that a nestloop inner indexscan
1926 * might have OUTER Vars, but the outer side of the join is not a child
1927 * plan node. To handle such cases the outer plan node must be passed
1928 * separately. (Pass NULL for outer_plan otherwise.)
1930 * Note: plan and outer_plan really ought to be declared as "Plan *", but
1931 * we use "Node *" to avoid having to include plannodes.h in builtins.h.
1933 * The plan's rangetable list must also be passed. We actually prefer to use
1934 * the rangetable to resolve simple Vars, but the plan inputs are necessary
1935 * for Vars that reference expressions computed in subplan target lists.
1937 * We also need the list of subplans associated with the Plan tree; this
1938 * is for resolving references to CTE subplans.
1941 deparse_context_for_plan(Node *plan, Node *outer_plan,
1942 List *rtable, List *subplans)
1944 deparse_namespace *dpns;
1946 dpns = (deparse_namespace *) palloc(sizeof(deparse_namespace));
1948 dpns->rtable = rtable;
1950 dpns->subplans = subplans;
1953 * Set up outer_plan and inner_plan from the Plan node (this includes
1954 * various special cases for particular Plan types).
1956 push_plan(dpns, (Plan *) plan);
1959 * If outer_plan is given, that overrides whatever we got from the plan.
1962 dpns->outer_plan = (Plan *) outer_plan;
1964 /* Return a one-deep namespace stack */
1965 return list_make1(dpns);
1969 * make_ruledef - reconstruct the CREATE RULE command
1970 * for a given pg_rewrite tuple
1974 make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
1984 List *actions = NIL;
1990 * Get the attribute values from the rules tuple
1992 fno = SPI_fnumber(rulettc, "rulename");
1993 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
1995 rulename = NameStr(*(DatumGetName(dat)));
1997 fno = SPI_fnumber(rulettc, "ev_type");
1998 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
2000 ev_type = DatumGetChar(dat);
2002 fno = SPI_fnumber(rulettc, "ev_class");
2003 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
2005 ev_class = DatumGetObjectId(dat);
2007 fno = SPI_fnumber(rulettc, "ev_attr");
2008 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
2010 ev_attr = DatumGetInt16(dat);
2012 fno = SPI_fnumber(rulettc, "is_instead");
2013 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
2015 is_instead = DatumGetBool(dat);
2017 /* these could be nulls */
2018 fno = SPI_fnumber(rulettc, "ev_qual");
2019 ev_qual = SPI_getvalue(ruletup, rulettc, fno);
2021 fno = SPI_fnumber(rulettc, "ev_action");
2022 ev_action = SPI_getvalue(ruletup, rulettc, fno);
2023 if (ev_action != NULL)
2024 actions = (List *) stringToNode(ev_action);
2027 * Build the rules definition text
2029 appendStringInfo(buf, "CREATE RULE %s AS",
2030 quote_identifier(rulename));
2032 if (prettyFlags & PRETTYFLAG_INDENT)
2033 appendStringInfoString(buf, "\n ON ");
2035 appendStringInfoString(buf, " ON ");
2037 /* The event the rule is fired for */
2041 appendStringInfo(buf, "SELECT");
2045 appendStringInfo(buf, "UPDATE");
2049 appendStringInfo(buf, "INSERT");
2053 appendStringInfo(buf, "DELETE");
2058 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2059 errmsg("rule \"%s\" has unsupported event type %d",
2060 rulename, ev_type)));
2064 /* The relation the rule is fired on */
2065 appendStringInfo(buf, " TO %s", generate_relation_name(ev_class, NIL));
2067 appendStringInfo(buf, ".%s",
2068 quote_identifier(get_relid_attribute_name(ev_class,
2071 /* If the rule has an event qualification, add it */
2072 if (ev_qual == NULL)
2074 if (strlen(ev_qual) > 0 && strcmp(ev_qual, "<>") != 0)
2078 deparse_context context;
2079 deparse_namespace dpns;
2081 if (prettyFlags & PRETTYFLAG_INDENT)
2082 appendStringInfoString(buf, "\n ");
2083 appendStringInfo(buf, " WHERE ");
2085 qual = stringToNode(ev_qual);
2088 * We need to make a context for recognizing any Vars in the qual
2089 * (which can only be references to OLD and NEW). Use the rtable of
2090 * the first query in the action list for this purpose.
2092 query = (Query *) linitial(actions);
2095 * If the action is INSERT...SELECT, OLD/NEW have been pushed down
2096 * into the SELECT, and that's what we need to look at. (Ugly kluge
2097 * ... try to fix this when we redesign querytrees.)
2099 query = getInsertSelectQuery(query, NULL);
2101 /* Must acquire locks right away; see notes in get_query_def() */
2102 AcquireRewriteLocks(query);
2105 context.namespaces = list_make1(&dpns);
2106 context.windowClause = NIL;
2107 context.windowTList = NIL;
2108 context.varprefix = (list_length(query->rtable) != 1);
2109 context.prettyFlags = prettyFlags;
2110 context.indentLevel = PRETTYINDENT_STD;
2111 dpns.rtable = query->rtable;
2112 dpns.ctes = query->cteList;
2113 dpns.subplans = NIL;
2114 dpns.outer_plan = dpns.inner_plan = NULL;
2116 get_rule_expr(qual, &context, false);
2119 appendStringInfo(buf, " DO ");
2121 /* The INSTEAD keyword (if so) */
2123 appendStringInfo(buf, "INSTEAD ");
2125 /* Finally the rules actions */
2126 if (list_length(actions) > 1)
2131 appendStringInfo(buf, "(");
2132 foreach(action, actions)
2134 query = (Query *) lfirst(action);
2135 get_query_def(query, buf, NIL, NULL, prettyFlags, 0);
2137 appendStringInfo(buf, ";\n");
2139 appendStringInfo(buf, "; ");
2141 appendStringInfo(buf, ");");
2143 else if (list_length(actions) == 0)
2145 appendStringInfo(buf, "NOTHING;");
2151 query = (Query *) linitial(actions);
2152 get_query_def(query, buf, NIL, NULL, prettyFlags, 0);
2153 appendStringInfo(buf, ";");
2159 * make_viewdef - reconstruct the SELECT part of a
2164 make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
2174 List *actions = NIL;
2175 Relation ev_relation;
2180 * Get the attribute values from the rules tuple
2182 fno = SPI_fnumber(rulettc, "ev_type");
2183 ev_type = (char) SPI_getbinval(ruletup, rulettc, fno, &isnull);
2185 fno = SPI_fnumber(rulettc, "ev_class");
2186 ev_class = (Oid) SPI_getbinval(ruletup, rulettc, fno, &isnull);
2188 fno = SPI_fnumber(rulettc, "ev_attr");
2189 ev_attr = (int2) SPI_getbinval(ruletup, rulettc, fno, &isnull);
2191 fno = SPI_fnumber(rulettc, "is_instead");
2192 is_instead = (bool) SPI_getbinval(ruletup, rulettc, fno, &isnull);
2194 fno = SPI_fnumber(rulettc, "ev_qual");
2195 ev_qual = SPI_getvalue(ruletup, rulettc, fno);
2197 fno = SPI_fnumber(rulettc, "ev_action");
2198 ev_action = SPI_getvalue(ruletup, rulettc, fno);
2199 if (ev_action != NULL)
2200 actions = (List *) stringToNode(ev_action);
2202 if (list_length(actions) != 1)
2204 appendStringInfo(buf, "Not a view");
2208 query = (Query *) linitial(actions);
2210 if (ev_type != '1' || ev_attr >= 0 || !is_instead ||
2211 strcmp(ev_qual, "<>") != 0 || query->commandType != CMD_SELECT)
2213 appendStringInfo(buf, "Not a view");
2217 ev_relation = heap_open(ev_class, AccessShareLock);
2219 get_query_def(query, buf, NIL, RelationGetDescr(ev_relation),
2221 appendStringInfo(buf, ";");
2223 heap_close(ev_relation, AccessShareLock);
2228 * get_query_def - Parse back one query parsetree
2230 * If resultDesc is not NULL, then it is the output tuple descriptor for
2231 * the view represented by a SELECT query.
2235 get_query_def(Query *query, StringInfo buf, List *parentnamespace,
2236 TupleDesc resultDesc, int prettyFlags, int startIndent)
2238 deparse_context context;
2239 deparse_namespace dpns;
2242 * Before we begin to examine the query, acquire locks on referenced
2243 * relations, and fix up deleted columns in JOIN RTEs. This ensures
2244 * consistent results. Note we assume it's OK to scribble on the passed
2247 AcquireRewriteLocks(query);
2250 context.namespaces = lcons(&dpns, list_copy(parentnamespace));
2251 context.windowClause = NIL;
2252 context.windowTList = NIL;
2253 context.varprefix = (parentnamespace != NIL ||
2254 list_length(query->rtable) != 1);
2255 context.prettyFlags = prettyFlags;
2256 context.indentLevel = startIndent;
2258 dpns.rtable = query->rtable;
2259 dpns.ctes = query->cteList;
2260 dpns.subplans = NIL;
2261 dpns.outer_plan = dpns.inner_plan = NULL;
2263 switch (query->commandType)
2266 get_select_query_def(query, &context, resultDesc);
2270 get_update_query_def(query, &context);
2274 get_insert_query_def(query, &context);
2278 get_delete_query_def(query, &context);
2282 appendStringInfo(buf, "NOTHING");
2286 get_utility_query_def(query, &context);
2290 elog(ERROR, "unrecognized query command type: %d",
2291 query->commandType);
2297 * get_values_def - Parse back a VALUES list
2301 get_values_def(List *values_lists, deparse_context *context)
2303 StringInfo buf = context->buf;
2304 bool first_list = true;
2307 appendStringInfoString(buf, "VALUES ");
2309 foreach(vtl, values_lists)
2311 List *sublist = (List *) lfirst(vtl);
2312 bool first_col = true;
2318 appendStringInfoString(buf, ", ");
2320 appendStringInfoChar(buf, '(');
2321 foreach(lc, sublist)
2323 Node *col = (Node *) lfirst(lc);
2328 appendStringInfoChar(buf, ',');
2331 * Strip any top-level nodes representing indirection assignments,
2332 * then print the result.
2334 get_rule_expr(processIndirection(col, context, false),
2337 appendStringInfoChar(buf, ')');
2342 * get_with_clause - Parse back a WITH clause
2346 get_with_clause(Query *query, deparse_context *context)
2348 StringInfo buf = context->buf;
2352 if (query->cteList == NIL)
2355 if (PRETTY_INDENT(context))
2357 context->indentLevel += PRETTYINDENT_STD;
2358 appendStringInfoChar(buf, ' ');
2361 if (query->hasRecursive)
2362 sep = "WITH RECURSIVE ";
2365 foreach(l, query->cteList)
2367 CommonTableExpr *cte = (CommonTableExpr *) lfirst(l);
2369 appendStringInfoString(buf, sep);
2370 appendStringInfoString(buf, quote_identifier(cte->ctename));
2371 if (cte->aliascolnames)
2376 appendStringInfoChar(buf, '(');
2377 foreach(col, cte->aliascolnames)
2382 appendStringInfoString(buf, ", ");
2383 appendStringInfoString(buf,
2384 quote_identifier(strVal(lfirst(col))));
2386 appendStringInfoChar(buf, ')');
2388 appendStringInfoString(buf, " AS (");
2389 if (PRETTY_INDENT(context))
2390 appendContextKeyword(context, "", 0, 0, 0);
2391 get_query_def((Query *) cte->ctequery, buf, context->namespaces, NULL,
2392 context->prettyFlags, context->indentLevel);
2393 if (PRETTY_INDENT(context))
2394 appendContextKeyword(context, "", 0, 0, 0);
2395 appendStringInfoChar(buf, ')');
2399 if (PRETTY_INDENT(context))
2401 context->indentLevel -= PRETTYINDENT_STD;
2402 appendContextKeyword(context, "", 0, 0, 0);
2405 appendStringInfoChar(buf, ' ');
2409 * get_select_query_def - Parse back a SELECT parsetree
2413 get_select_query_def(Query *query, deparse_context *context,
2414 TupleDesc resultDesc)
2416 StringInfo buf = context->buf;
2417 List *save_windowclause;
2418 List *save_windowtlist;
2422 /* Insert the WITH clause if given */
2423 get_with_clause(query, context);
2425 /* Set up context for possible window functions */
2426 save_windowclause = context->windowClause;
2427 context->windowClause = query->windowClause;
2428 save_windowtlist = context->windowTList;
2429 context->windowTList = query->targetList;
2432 * If the Query node has a setOperations tree, then it's the top level of
2433 * a UNION/INTERSECT/EXCEPT query; only the WITH, ORDER BY and LIMIT
2434 * fields are interesting in the top query itself.
2436 if (query->setOperations)
2438 get_setop_query(query->setOperations, query, context, resultDesc);
2439 /* ORDER BY clauses must be simple in this case */
2444 get_basic_select_query(query, context, resultDesc);
2445 force_colno = false;
2448 /* Add the ORDER BY clause if given */
2449 if (query->sortClause != NIL)
2451 appendContextKeyword(context, " ORDER BY ",
2452 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2453 get_rule_orderby(query->sortClause, query->targetList,
2454 force_colno, context);
2457 /* Add the LIMIT clause if given */
2458 if (query->limitOffset != NULL)
2460 appendContextKeyword(context, " OFFSET ",
2461 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2462 get_rule_expr(query->limitOffset, context, false);
2464 if (query->limitCount != NULL)
2466 appendContextKeyword(context, " LIMIT ",
2467 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2468 if (IsA(query->limitCount, Const) &&
2469 ((Const *) query->limitCount)->constisnull)
2470 appendStringInfo(buf, "ALL");
2472 get_rule_expr(query->limitCount, context, false);
2475 /* Add FOR UPDATE/SHARE clauses if present */
2476 foreach(l, query->rowMarks)
2478 RowMarkClause *rc = (RowMarkClause *) lfirst(l);
2479 RangeTblEntry *rte = rt_fetch(rc->rti, query->rtable);
2482 appendContextKeyword(context, " FOR UPDATE",
2483 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2485 appendContextKeyword(context, " FOR SHARE",
2486 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2487 appendStringInfo(buf, " OF %s",
2488 quote_identifier(rte->eref->aliasname));
2490 appendStringInfo(buf, " NOWAIT");
2493 context->windowClause = save_windowclause;
2494 context->windowTList = save_windowtlist;
2498 get_basic_select_query(Query *query, deparse_context *context,
2499 TupleDesc resultDesc)
2501 StringInfo buf = context->buf;
2505 if (PRETTY_INDENT(context))
2507 context->indentLevel += PRETTYINDENT_STD;
2508 appendStringInfoChar(buf, ' ');
2512 * If the query looks like SELECT * FROM (VALUES ...), then print just the
2513 * VALUES part. This reverses what transformValuesClause() did at parse
2514 * time. If the jointree contains just a single VALUES RTE, we assume
2515 * this case applies (without looking at the targetlist...)
2517 if (list_length(query->jointree->fromlist) == 1)
2519 RangeTblRef *rtr = (RangeTblRef *) linitial(query->jointree->fromlist);
2521 if (IsA(rtr, RangeTblRef))
2523 RangeTblEntry *rte = rt_fetch(rtr->rtindex, query->rtable);
2525 if (rte->rtekind == RTE_VALUES)
2527 get_values_def(rte->values_lists, context);
2534 * Build up the query string - first we say SELECT
2536 appendStringInfo(buf, "SELECT");
2538 /* Add the DISTINCT clause if given */
2539 if (query->distinctClause != NIL)
2541 if (query->hasDistinctOn)
2543 appendStringInfo(buf, " DISTINCT ON (");
2545 foreach(l, query->distinctClause)
2547 SortGroupClause *srt = (SortGroupClause *) lfirst(l);
2549 appendStringInfoString(buf, sep);
2550 get_rule_sortgroupclause(srt, query->targetList,
2554 appendStringInfo(buf, ")");
2557 appendStringInfo(buf, " DISTINCT");
2560 /* Then we tell what to select (the targetlist) */
2561 get_target_list(query->targetList, context, resultDesc);
2563 /* Add the FROM clause if needed */
2564 get_from_clause(query, " FROM ", context);
2566 /* Add the WHERE clause if given */
2567 if (query->jointree->quals != NULL)
2569 appendContextKeyword(context, " WHERE ",
2570 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2571 get_rule_expr(query->jointree->quals, context, false);
2574 /* Add the GROUP BY clause if given */
2575 if (query->groupClause != NULL)
2577 appendContextKeyword(context, " GROUP BY ",
2578 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2580 foreach(l, query->groupClause)
2582 SortGroupClause *grp = (SortGroupClause *) lfirst(l);
2584 appendStringInfoString(buf, sep);
2585 get_rule_sortgroupclause(grp, query->targetList,
2591 /* Add the HAVING clause if given */
2592 if (query->havingQual != NULL)
2594 appendContextKeyword(context, " HAVING ",
2595 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2596 get_rule_expr(query->havingQual, context, false);
2599 /* Add the WINDOW clause if needed */
2600 if (query->windowClause != NIL)
2601 get_rule_windowclause(query, context);
2605 * get_target_list - Parse back a SELECT target list
2607 * This is also used for RETURNING lists in INSERT/UPDATE/DELETE.
2611 get_target_list(List *targetList, deparse_context *context,
2612 TupleDesc resultDesc)
2614 StringInfo buf = context->buf;
2621 foreach(l, targetList)
2623 TargetEntry *tle = (TargetEntry *) lfirst(l);
2628 continue; /* ignore junk entries */
2630 appendStringInfoString(buf, sep);
2635 * We special-case Var nodes rather than using get_rule_expr. This is
2636 * needed because get_rule_expr will display a whole-row Var as
2637 * "foo.*", which is the preferred notation in most contexts, but at
2638 * the top level of a SELECT list it's not right (the parser will
2639 * expand that notation into multiple columns, yielding behavior
2640 * different from a whole-row Var). We want just "foo", instead.
2642 if (tle->expr && IsA(tle->expr, Var))
2644 attname = get_variable((Var *) tle->expr, 0, false, context);
2648 get_rule_expr((Node *) tle->expr, context, true);
2649 /* We'll show the AS name unless it's this: */
2650 attname = "?column?";
2654 * Figure out what the result column should be called. In the context
2655 * of a view, use the view's tuple descriptor (so as to pick up the
2656 * effects of any column RENAME that's been done on the view).
2657 * Otherwise, just use what we can find in the TLE.
2659 if (resultDesc && colno <= resultDesc->natts)
2660 colname = NameStr(resultDesc->attrs[colno - 1]->attname);
2662 colname = tle->resname;
2664 /* Show AS unless the column's name is correct as-is */
2665 if (colname) /* resname could be NULL */
2667 if (attname == NULL || strcmp(attname, colname) != 0)
2668 appendStringInfo(buf, " AS %s", quote_identifier(colname));
2674 get_setop_query(Node *setOp, Query *query, deparse_context *context,
2675 TupleDesc resultDesc)
2677 StringInfo buf = context->buf;
2680 if (IsA(setOp, RangeTblRef))
2682 RangeTblRef *rtr = (RangeTblRef *) setOp;
2683 RangeTblEntry *rte = rt_fetch(rtr->rtindex, query->rtable);
2684 Query *subquery = rte->subquery;
2686 Assert(subquery != NULL);
2687 Assert(subquery->setOperations == NULL);
2688 /* Need parens if WITH, ORDER BY, FOR UPDATE, or LIMIT; see gram.y */
2689 need_paren = (subquery->cteList ||
2690 subquery->sortClause ||
2691 subquery->rowMarks ||
2692 subquery->limitOffset ||
2693 subquery->limitCount);
2695 appendStringInfoChar(buf, '(');
2696 get_query_def(subquery, buf, context->namespaces, resultDesc,
2697 context->prettyFlags, context->indentLevel);
2699 appendStringInfoChar(buf, ')');
2701 else if (IsA(setOp, SetOperationStmt))
2703 SetOperationStmt *op = (SetOperationStmt *) setOp;
2705 if (PRETTY_INDENT(context))
2707 context->indentLevel += PRETTYINDENT_STD;
2708 appendStringInfoSpaces(buf, PRETTYINDENT_STD);
2712 * We force parens whenever nesting two SetOperationStmts. There are
2713 * some cases in which parens are needed around a leaf query too, but
2714 * those are more easily handled at the next level down (see code
2717 need_paren = !IsA(op->larg, RangeTblRef);
2720 appendStringInfoChar(buf, '(');
2721 get_setop_query(op->larg, query, context, resultDesc);
2723 appendStringInfoChar(buf, ')');
2725 if (!PRETTY_INDENT(context))
2726 appendStringInfoChar(buf, ' ');
2730 appendContextKeyword(context, "UNION ",
2731 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2733 case SETOP_INTERSECT:
2734 appendContextKeyword(context, "INTERSECT ",
2735 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2738 appendContextKeyword(context, "EXCEPT ",
2739 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2742 elog(ERROR, "unrecognized set op: %d",
2746 appendStringInfo(buf, "ALL ");
2748 if (PRETTY_INDENT(context))
2749 appendContextKeyword(context, "", 0, 0, 0);
2751 need_paren = !IsA(op->rarg, RangeTblRef);
2754 appendStringInfoChar(buf, '(');
2755 get_setop_query(op->rarg, query, context, resultDesc);
2757 appendStringInfoChar(buf, ')');
2759 if (PRETTY_INDENT(context))
2760 context->indentLevel -= PRETTYINDENT_STD;
2764 elog(ERROR, "unrecognized node type: %d",
2765 (int) nodeTag(setOp));
2770 * Display a sort/group clause.
2772 * Also returns the expression tree, so caller need not find it again.
2775 get_rule_sortgroupclause(SortGroupClause *srt, List *tlist, bool force_colno,
2776 deparse_context *context)
2778 StringInfo buf = context->buf;
2782 tle = get_sortgroupclause_tle(srt, tlist);
2783 expr = (Node *) tle->expr;
2786 * Use column-number form if requested by caller. Otherwise, if
2787 * expression is a constant, force it to be dumped with an explicit
2788 * cast as decoration --- this is because a simple integer constant
2789 * is ambiguous (and will be misinterpreted by findTargetlistEntry())
2790 * if we dump it without any decoration. Otherwise, just dump the
2791 * expression normally.
2795 Assert(!tle->resjunk);
2796 appendStringInfo(buf, "%d", tle->resno);
2798 else if (expr && IsA(expr, Const))
2799 get_const_expr((Const *) expr, context, 1);
2801 get_rule_expr(expr, context, true);
2807 * Display an ORDER BY list.
2810 get_rule_orderby(List *orderList, List *targetList,
2811 bool force_colno, deparse_context *context)
2813 StringInfo buf = context->buf;
2818 foreach(l, orderList)
2820 SortGroupClause *srt = (SortGroupClause *) lfirst(l);
2823 TypeCacheEntry *typentry;
2825 appendStringInfoString(buf, sep);
2826 sortexpr = get_rule_sortgroupclause(srt, targetList,
2827 force_colno, context);
2828 sortcoltype = exprType(sortexpr);
2829 /* See whether operator is default < or > for datatype */
2830 typentry = lookup_type_cache(sortcoltype,
2831 TYPECACHE_LT_OPR | TYPECACHE_GT_OPR);
2832 if (srt->sortop == typentry->lt_opr)
2834 /* ASC is default, so emit nothing for it */
2835 if (srt->nulls_first)
2836 appendStringInfo(buf, " NULLS FIRST");
2838 else if (srt->sortop == typentry->gt_opr)
2840 appendStringInfo(buf, " DESC");
2841 /* DESC defaults to NULLS FIRST */
2842 if (!srt->nulls_first)
2843 appendStringInfo(buf, " NULLS LAST");
2847 appendStringInfo(buf, " USING %s",
2848 generate_operator_name(srt->sortop,
2851 /* be specific to eliminate ambiguity */
2852 if (srt->nulls_first)
2853 appendStringInfo(buf, " NULLS FIRST");
2855 appendStringInfo(buf, " NULLS LAST");
2862 * Display a WINDOW clause.
2864 * Note that the windowClause list might contain only anonymous window
2865 * specifications, in which case we should print nothing here.
2868 get_rule_windowclause(Query *query, deparse_context *context)
2870 StringInfo buf = context->buf;
2875 foreach(l, query->windowClause)
2877 WindowClause *wc = (WindowClause *) lfirst(l);
2879 if (wc->name == NULL)
2880 continue; /* ignore anonymous windows */
2883 appendContextKeyword(context, " WINDOW ",
2884 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2886 appendStringInfoString(buf, sep);
2888 appendStringInfo(buf, "%s AS ", quote_identifier(wc->name));
2890 get_rule_windowspec(wc, query->targetList, context);
2897 * Display a window definition
2900 get_rule_windowspec(WindowClause *wc, List *targetList,
2901 deparse_context *context)
2903 StringInfo buf = context->buf;
2904 bool needspace = false;
2908 appendStringInfoChar(buf, '(');
2911 appendStringInfoString(buf, quote_identifier(wc->refname));
2914 /* partition clauses are always inherited, so only print if no refname */
2915 if (wc->partitionClause && !wc->refname)
2918 appendStringInfoChar(buf, ' ');
2919 appendStringInfoString(buf, "PARTITION BY ");
2921 foreach(l, wc->partitionClause)
2923 SortGroupClause *grp = (SortGroupClause *) lfirst(l);
2925 appendStringInfoString(buf, sep);
2926 get_rule_sortgroupclause(grp, targetList,
2932 /* print ordering clause only if not inherited */
2933 if (wc->orderClause && !wc->copiedOrder)
2936 appendStringInfoChar(buf, ' ');
2937 appendStringInfoString(buf, "ORDER BY ");
2938 get_rule_orderby(wc->orderClause, targetList, false, context);
2941 /* framing clause is never inherited, so print unless it's default */
2942 if (wc->frameOptions & FRAMEOPTION_NONDEFAULT)
2945 appendStringInfoChar(buf, ' ');
2946 if (wc->frameOptions & FRAMEOPTION_RANGE)
2947 appendStringInfoString(buf, "RANGE ");
2948 else if (wc->frameOptions & FRAMEOPTION_ROWS)
2949 appendStringInfoString(buf, "ROWS ");
2952 if (wc->frameOptions & FRAMEOPTION_BETWEEN)
2953 appendStringInfoString(buf, "BETWEEN ");
2954 if (wc->frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING)
2955 appendStringInfoString(buf, "UNBOUNDED PRECEDING ");
2956 else if (wc->frameOptions & FRAMEOPTION_START_CURRENT_ROW)
2957 appendStringInfoString(buf, "CURRENT ROW ");
2960 if (wc->frameOptions & FRAMEOPTION_BETWEEN)
2962 appendStringInfoString(buf, "AND ");
2963 if (wc->frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING)
2964 appendStringInfoString(buf, "UNBOUNDED FOLLOWING ");
2965 else if (wc->frameOptions & FRAMEOPTION_END_CURRENT_ROW)
2966 appendStringInfoString(buf, "CURRENT ROW ");
2970 /* we will now have a trailing space; remove it */
2973 appendStringInfoChar(buf, ')');
2977 * get_insert_query_def - Parse back an INSERT parsetree
2981 get_insert_query_def(Query *query, deparse_context *context)
2983 StringInfo buf = context->buf;
2984 RangeTblEntry *select_rte = NULL;
2985 RangeTblEntry *values_rte = NULL;
2988 ListCell *values_cell;
2990 List *strippedexprs;
2993 * If it's an INSERT ... SELECT or VALUES (...), (...), ... there will be
2994 * a single RTE for the SELECT or VALUES.
2996 foreach(l, query->rtable)
2998 rte = (RangeTblEntry *) lfirst(l);
3000 if (rte->rtekind == RTE_SUBQUERY)
3003 elog(ERROR, "too many subquery RTEs in INSERT");
3007 if (rte->rtekind == RTE_VALUES)
3010 elog(ERROR, "too many values RTEs in INSERT");
3014 if (select_rte && values_rte)
3015 elog(ERROR, "both subquery and values RTEs in INSERT");
3018 * Start the query with INSERT INTO relname
3020 rte = rt_fetch(query->resultRelation, query->rtable);
3021 Assert(rte->rtekind == RTE_RELATION);
3023 if (PRETTY_INDENT(context))
3025 context->indentLevel += PRETTYINDENT_STD;
3026 appendStringInfoChar(buf, ' ');
3028 appendStringInfo(buf, "INSERT INTO %s (",
3029 generate_relation_name(rte->relid, NIL));
3032 * Add the insert-column-names list. To handle indirection properly, we
3033 * need to look for indirection nodes in the top targetlist (if it's
3034 * INSERT ... SELECT or INSERT ... single VALUES), or in the first
3035 * expression list of the VALUES RTE (if it's INSERT ... multi VALUES). We
3036 * assume that all the expression lists will have similar indirection in
3040 values_cell = list_head((List *) linitial(values_rte->values_lists));
3043 strippedexprs = NIL;
3045 foreach(l, query->targetList)
3047 TargetEntry *tle = (TargetEntry *) lfirst(l);
3050 continue; /* ignore junk entries */
3052 appendStringInfoString(buf, sep);
3056 * Put out name of target column; look in the catalogs, not at
3057 * tle->resname, since resname will fail to track RENAME.
3059 appendStringInfoString(buf,
3060 quote_identifier(get_relid_attribute_name(rte->relid,
3064 * Print any indirection needed (subfields or subscripts), and strip
3065 * off the top-level nodes representing the indirection assignments.
3069 /* we discard the stripped expression in this case */
3070 processIndirection((Node *) lfirst(values_cell), context, true);
3071 values_cell = lnext(values_cell);
3075 /* we keep a list of the stripped expressions in this case */
3076 strippedexprs = lappend(strippedexprs,
3077 processIndirection((Node *) tle->expr,
3081 appendStringInfo(buf, ") ");
3085 /* Add the SELECT */
3086 get_query_def(select_rte->subquery, buf, NIL, NULL,
3087 context->prettyFlags, context->indentLevel);
3089 else if (values_rte)
3091 /* A WITH clause is possible here */
3092 get_with_clause(query, context);
3093 /* Add the multi-VALUES expression lists */
3094 get_values_def(values_rte->values_lists, context);
3098 /* A WITH clause is possible here */
3099 get_with_clause(query, context);
3100 /* Add the single-VALUES expression list */
3101 appendContextKeyword(context, "VALUES (",
3102 -PRETTYINDENT_STD, PRETTYINDENT_STD, 2);
3103 get_rule_expr((Node *) strippedexprs, context, false);
3104 appendStringInfoChar(buf, ')');
3107 /* Add RETURNING if present */
3108 if (query->returningList)
3110 appendContextKeyword(context, " RETURNING",
3111 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
3112 get_target_list(query->returningList, context, NULL);
3118 * get_update_query_def - Parse back an UPDATE parsetree
3122 get_update_query_def(Query *query, deparse_context *context)
3124 StringInfo buf = context->buf;
3130 * Start the query with UPDATE relname SET
3132 rte = rt_fetch(query->resultRelation, query->rtable);
3133 Assert(rte->rtekind == RTE_RELATION);
3134 if (PRETTY_INDENT(context))
3136 appendStringInfoChar(buf, ' ');
3137 context->indentLevel += PRETTYINDENT_STD;
3139 appendStringInfo(buf, "UPDATE %s%s",
3141 generate_relation_name(rte->relid, NIL));
3142 if (rte->alias != NULL)
3143 appendStringInfo(buf, " %s",
3144 quote_identifier(rte->alias->aliasname));
3145 appendStringInfoString(buf, " SET ");
3147 /* Add the comma separated list of 'attname = value' */
3149 foreach(l, query->targetList)
3151 TargetEntry *tle = (TargetEntry *) lfirst(l);
3155 continue; /* ignore junk entries */
3157 appendStringInfoString(buf, sep);
3161 * Put out name of target column; look in the catalogs, not at
3162 * tle->resname, since resname will fail to track RENAME.
3164 appendStringInfoString(buf,
3165 quote_identifier(get_relid_attribute_name(rte->relid,
3169 * Print any indirection needed (subfields or subscripts), and strip
3170 * off the top-level nodes representing the indirection assignments.
3172 expr = processIndirection((Node *) tle->expr, context, true);
3174 appendStringInfo(buf, " = ");
3176 get_rule_expr(expr, context, false);
3179 /* Add the FROM clause if needed */
3180 get_from_clause(query, " FROM ", context);
3182 /* Add a WHERE clause if given */
3183 if (query->jointree->quals != NULL)
3185 appendContextKeyword(context, " WHERE ",
3186 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
3187 get_rule_expr(query->jointree->quals, context, false);
3190 /* Add RETURNING if present */
3191 if (query->returningList)
3193 appendContextKeyword(context, " RETURNING",
3194 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
3195 get_target_list(query->returningList, context, NULL);
3201 * get_delete_query_def - Parse back a DELETE parsetree
3205 get_delete_query_def(Query *query, deparse_context *context)
3207 StringInfo buf = context->buf;
3211 * Start the query with DELETE FROM relname
3213 rte = rt_fetch(query->resultRelation, query->rtable);
3214 Assert(rte->rtekind == RTE_RELATION);
3215 if (PRETTY_INDENT(context))
3217 appendStringInfoChar(buf, ' ');
3218 context->indentLevel += PRETTYINDENT_STD;
3220 appendStringInfo(buf, "DELETE FROM %s%s",
3222 generate_relation_name(rte->relid, NIL));
3223 if (rte->alias != NULL)
3224 appendStringInfo(buf, " %s",
3225 quote_identifier(rte->alias->aliasname));
3227 /* Add the USING clause if given */
3228 get_from_clause(query, " USING ", context);
3230 /* Add a WHERE clause if given */
3231 if (query->jointree->quals != NULL)
3233 appendContextKeyword(context, " WHERE ",
3234 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
3235 get_rule_expr(query->jointree->quals, context, false);
3238 /* Add RETURNING if present */
3239 if (query->returningList)
3241 appendContextKeyword(context, " RETURNING",
3242 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
3243 get_target_list(query->returningList, context, NULL);
3249 * get_utility_query_def - Parse back a UTILITY parsetree
3253 get_utility_query_def(Query *query, deparse_context *context)
3255 StringInfo buf = context->buf;
3257 if (query->utilityStmt && IsA(query->utilityStmt, NotifyStmt))
3259 NotifyStmt *stmt = (NotifyStmt *) query->utilityStmt;
3261 appendContextKeyword(context, "",
3262 0, PRETTYINDENT_STD, 1);
3263 appendStringInfo(buf, "NOTIFY %s",
3264 quote_identifier(stmt->conditionname));
3268 /* Currently only NOTIFY utility commands can appear in rules */
3269 elog(ERROR, "unexpected utility statement type");
3275 * push_plan: set up deparse_namespace to recurse into the tlist of a subplan
3277 * When expanding an OUTER or INNER reference, we must push new outer/inner
3278 * subplans in case the referenced expression itself uses OUTER/INNER. We
3279 * modify the top stack entry in-place to avoid affecting levelsup issues
3280 * (although in a Plan tree there really shouldn't be any).
3282 * Caller must save and restore outer_plan and inner_plan around this.
3284 * We also use this to initialize the fields during deparse_context_for_plan.
3287 push_plan(deparse_namespace *dpns, Plan *subplan)
3290 * We special-case Append to pretend that the first child plan is the
3291 * OUTER referent; otherwise normal.
3293 if (IsA(subplan, Append))
3294 dpns->outer_plan = (Plan *) linitial(((Append *) subplan)->appendplans);
3296 dpns->outer_plan = outerPlan(subplan);
3299 * For a SubqueryScan, pretend the subplan is INNER referent. (We don't
3300 * use OUTER because that could someday conflict with the normal meaning.)
3301 * Likewise, for a CteScan, pretend the subquery's plan is INNER referent.
3303 if (IsA(subplan, SubqueryScan))
3304 dpns->inner_plan = ((SubqueryScan *) subplan)->subplan;
3305 else if (IsA(subplan, CteScan))
3307 int ctePlanId = ((CteScan *) subplan)->ctePlanId;
3309 if (ctePlanId > 0 && ctePlanId <= list_length(dpns->subplans))
3310 dpns->inner_plan = list_nth(dpns->subplans, ctePlanId - 1);
3312 dpns->inner_plan = NULL;
3315 dpns->inner_plan = innerPlan(subplan);
3320 * Display a Var appropriately.
3322 * In some cases (currently only when recursing into an unnamed join)
3323 * the Var's varlevelsup has to be interpreted with respect to a context
3324 * above the current one; levelsup indicates the offset.
3326 * If showstar is TRUE, whole-row Vars are displayed as "foo.*";
3327 * if FALSE, merely as "foo".
3329 * Returns the attname of the Var, or NULL if not determinable.
3332 get_variable(Var *var, int levelsup, bool showstar, deparse_context *context)
3334 StringInfo buf = context->buf;
3338 deparse_namespace *dpns;
3343 /* Find appropriate nesting depth */
3344 netlevelsup = var->varlevelsup + levelsup;
3345 if (netlevelsup >= list_length(context->namespaces))
3346 elog(ERROR, "bogus varlevelsup: %d offset %d",
3347 var->varlevelsup, levelsup);
3348 dpns = (deparse_namespace *) list_nth(context->namespaces,
3352 * Try to find the relevant RTE in this rtable. In a plan tree, it's
3353 * likely that varno is OUTER or INNER, in which case we must dig down
3354 * into the subplans.
3356 if (var->varno >= 1 && var->varno <= list_length(dpns->rtable))
3358 rte = rt_fetch(var->varno, dpns->rtable);
3359 attnum = var->varattno;
3361 else if (var->varno == OUTER && dpns->outer_plan)
3367 tle = get_tle_by_resno(dpns->outer_plan->targetlist, var->varattno);
3369 elog(ERROR, "bogus varattno for OUTER var: %d", var->varattno);
3371 Assert(netlevelsup == 0);
3372 save_outer = dpns->outer_plan;
3373 save_inner = dpns->inner_plan;
3374 push_plan(dpns, dpns->outer_plan);
3377 * Force parentheses because our caller probably assumed a Var is a
3378 * simple expression.
3380 if (!IsA(tle->expr, Var))
3381 appendStringInfoChar(buf, '(');
3382 get_rule_expr((Node *) tle->expr, context, true);
3383 if (!IsA(tle->expr, Var))
3384 appendStringInfoChar(buf, ')');
3386 dpns->outer_plan = save_outer;
3387 dpns->inner_plan = save_inner;
3390 else if (var->varno == INNER && dpns->inner_plan)
3396 tle = get_tle_by_resno(dpns->inner_plan->targetlist, var->varattno);
3398 elog(ERROR, "bogus varattno for INNER var: %d", var->varattno);
3400 Assert(netlevelsup == 0);
3401 save_outer = dpns->outer_plan;
3402 save_inner = dpns->inner_plan;
3403 push_plan(dpns, dpns->inner_plan);
3406 * Force parentheses because our caller probably assumed a Var is a
3407 * simple expression.
3409 if (!IsA(tle->expr, Var))
3410 appendStringInfoChar(buf, '(');
3411 get_rule_expr((Node *) tle->expr, context, true);
3412 if (!IsA(tle->expr, Var))
3413 appendStringInfoChar(buf, ')');
3415 dpns->outer_plan = save_outer;
3416 dpns->inner_plan = save_inner;
3421 elog(ERROR, "bogus varno: %d", var->varno);
3422 return NULL; /* keep compiler quiet */
3425 /* Identify names to use */
3426 schemaname = NULL; /* default assumptions */
3427 refname = rte->eref->aliasname;
3429 /* Exceptions occur only if the RTE is alias-less */
3430 if (rte->alias == NULL)
3432 if (rte->rtekind == RTE_RELATION)
3435 * It's possible that use of the bare refname would find another
3436 * more-closely-nested RTE, or be ambiguous, in which case we need
3437 * to specify the schemaname to avoid these errors.
3439 if (find_rte_by_refname(rte->eref->aliasname, context) != rte)
3440 schemaname = get_namespace_name(get_rel_namespace(rte->relid));
3442 else if (rte->rtekind == RTE_JOIN)
3445 * If it's an unnamed join, look at the expansion of the alias
3446 * variable. If it's a simple reference to one of the input vars
3447 * then recursively print the name of that var, instead. (This
3448 * allows correct decompiling of cases where there are identically
3449 * named columns on both sides of the join.) When it's not a
3450 * simple reference, we have to just print the unqualified
3451 * variable name (this can only happen with columns that were
3452 * merged by USING or NATURAL clauses).
3454 * This wouldn't work in decompiling plan trees, because we don't
3455 * store joinaliasvars lists after planning; but a plan tree
3456 * should never contain a join alias variable.
3458 if (rte->joinaliasvars == NIL)
3459 elog(ERROR, "cannot decompile join alias var in plan tree");
3464 aliasvar = (Var *) list_nth(rte->joinaliasvars, attnum - 1);
3465 if (IsA(aliasvar, Var))
3467 return get_variable(aliasvar, var->varlevelsup + levelsup,
3471 /* Unnamed join has neither schemaname nor refname */
3476 if (attnum == InvalidAttrNumber)
3479 attname = get_rte_attribute_name(rte, attnum);
3481 if (refname && (context->varprefix || attname == NULL))
3484 appendStringInfo(buf, "%s.",
3485 quote_identifier(schemaname));
3487 if (strcmp(refname, "*NEW*") == 0)
3488 appendStringInfoString(buf, "new");
3489 else if (strcmp(refname, "*OLD*") == 0)
3490 appendStringInfoString(buf, "old");
3492 appendStringInfoString(buf, quote_identifier(refname));
3494 if (attname || showstar)
3495 appendStringInfoChar(buf, '.');
3498 appendStringInfoString(buf, quote_identifier(attname));
3500 appendStringInfoChar(buf, '*');
3507 * Get the name of a field of an expression of composite type.
3509 * This is fairly straightforward except for the case of a Var of type RECORD.
3510 * Since no actual table or view column is allowed to have type RECORD, such
3511 * a Var must refer to a JOIN or FUNCTION RTE or to a subquery output. We
3512 * drill down to find the ultimate defining expression and attempt to infer
3513 * the field name from it. We ereport if we can't determine the name.
3515 * levelsup is an extra offset to interpret the Var's varlevelsup correctly.
3518 get_name_for_var_field(Var *var, int fieldno,
3519 int levelsup, deparse_context *context)
3524 deparse_namespace *dpns;
3525 TupleDesc tupleDesc;
3529 * If it's a RowExpr that was expanded from a whole-row Var, use the
3530 * column names attached to it.
3532 if (IsA(var, RowExpr))
3534 RowExpr *r = (RowExpr *) var;
3536 if (fieldno > 0 && fieldno <= list_length(r->colnames))
3537 return strVal(list_nth(r->colnames, fieldno - 1));
3541 * If it's a Var of type RECORD, we have to find what the Var refers to;
3542 * if not, we can use get_expr_result_type. If that fails, we try
3543 * lookup_rowtype_tupdesc, which will probably fail too, but will ereport
3544 * an acceptable message.
3546 if (!IsA(var, Var) ||
3547 var->vartype != RECORDOID)
3549 if (get_expr_result_type((Node *) var, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
3550 tupleDesc = lookup_rowtype_tupdesc_copy(exprType((Node *) var),
3551 exprTypmod((Node *) var));
3553 /* Got the tupdesc, so we can extract the field name */
3554 Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
3555 return NameStr(tupleDesc->attrs[fieldno - 1]->attname);
3558 /* Find appropriate nesting depth */
3559 netlevelsup = var->varlevelsup + levelsup;
3560 if (netlevelsup >= list_length(context->namespaces))
3561 elog(ERROR, "bogus varlevelsup: %d offset %d",
3562 var->varlevelsup, levelsup);
3563 dpns = (deparse_namespace *) list_nth(context->namespaces,
3567 * Try to find the relevant RTE in this rtable. In a plan tree, it's
3568 * likely that varno is OUTER or INNER, in which case we must dig down
3569 * into the subplans.
3571 if (var->varno >= 1 && var->varno <= list_length(dpns->rtable))
3573 rte = rt_fetch(var->varno, dpns->rtable);
3574 attnum = var->varattno;
3576 else if (var->varno == OUTER && dpns->outer_plan)
3583 tle = get_tle_by_resno(dpns->outer_plan->targetlist, var->varattno);
3585 elog(ERROR, "bogus varattno for OUTER var: %d", var->varattno);
3587 Assert(netlevelsup == 0);
3588 save_outer = dpns->outer_plan;
3589 save_inner = dpns->inner_plan;
3590 push_plan(dpns, dpns->outer_plan);
3592 result = get_name_for_var_field((Var *) tle->expr, fieldno,
3595 dpns->outer_plan = save_outer;
3596 dpns->inner_plan = save_inner;
3599 else if (var->varno == INNER && dpns->inner_plan)
3606 tle = get_tle_by_resno(dpns->inner_plan->targetlist, var->varattno);
3608 elog(ERROR, "bogus varattno for INNER var: %d", var->varattno);
3610 Assert(netlevelsup == 0);
3611 save_outer = dpns->outer_plan;
3612 save_inner = dpns->inner_plan;
3613 push_plan(dpns, dpns->inner_plan);
3615 result = get_name_for_var_field((Var *) tle->expr, fieldno,
3618 dpns->outer_plan = save_outer;
3619 dpns->inner_plan = save_inner;
3624 elog(ERROR, "bogus varno: %d", var->varno);
3625 return NULL; /* keep compiler quiet */
3628 if (attnum == InvalidAttrNumber)
3630 /* Var is whole-row reference to RTE, so select the right field */
3631 return get_rte_attribute_name(rte, fieldno);
3635 * This part has essentially the same logic as the parser's
3636 * expandRecordVariable() function, but we are dealing with a different
3637 * representation of the input context, and we only need one field name
3638 * not a TupleDesc. Also, we need special cases for finding subquery
3639 * and CTE subplans when deparsing Plan trees.
3641 expr = (Node *) var; /* default if we can't drill down */
3643 switch (rte->rtekind)
3650 * This case should not occur: a column of a table or values list
3651 * shouldn't have type RECORD. Fall through and fail (most
3652 * likely) at the bottom.
3656 /* Subselect-in-FROM: examine sub-select's output expr */
3660 TargetEntry *ste = get_tle_by_resno(rte->subquery->targetList,
3663 if (ste == NULL || ste->resjunk)
3664 elog(ERROR, "subquery %s does not have attribute %d",
3665 rte->eref->aliasname, attnum);
3666 expr = (Node *) ste->expr;
3670 * Recurse into the sub-select to see what its Var
3671 * refers to. We have to build an additional level of
3672 * namespace to keep in step with varlevelsup in the
3675 deparse_namespace mydpns;
3678 mydpns.rtable = rte->subquery->rtable;
3679 mydpns.ctes = rte->subquery->cteList;
3680 mydpns.subplans = NIL;
3681 mydpns.outer_plan = mydpns.inner_plan = NULL;
3683 context->namespaces = lcons(&mydpns,
3684 context->namespaces);
3686 result = get_name_for_var_field((Var *) expr, fieldno,
3689 context->namespaces =
3690 list_delete_first(context->namespaces);
3694 /* else fall through to inspect the expression */
3699 * We're deparsing a Plan tree so we don't have complete
3700 * RTE entries (in particular, rte->subquery is NULL).
3701 * But the only place we'd see a Var directly referencing
3702 * a SUBQUERY RTE is in a SubqueryScan plan node, and we
3703 * can look into the child plan's tlist instead.
3710 if (!dpns->inner_plan)
3711 elog(ERROR, "failed to find plan for subquery %s",
3712 rte->eref->aliasname);
3713 tle = get_tle_by_resno(dpns->inner_plan->targetlist,
3716 elog(ERROR, "bogus varattno for subquery var: %d",
3718 Assert(netlevelsup == 0);
3719 save_outer = dpns->outer_plan;
3720 save_inner = dpns->inner_plan;
3721 push_plan(dpns, dpns->inner_plan);
3723 result = get_name_for_var_field((Var *) tle->expr, fieldno,
3726 dpns->outer_plan = save_outer;
3727 dpns->inner_plan = save_inner;
3733 /* Join RTE --- recursively inspect the alias variable */
3734 if (rte->joinaliasvars == NIL)
3735 elog(ERROR, "cannot decompile join alias var in plan tree");
3736 Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars));
3737 expr = (Node *) list_nth(rte->joinaliasvars, attnum - 1);
3739 return get_name_for_var_field((Var *) expr, fieldno,
3740 var->varlevelsup + levelsup,
3742 /* else fall through to inspect the expression */
3747 * We couldn't get here unless a function is declared with one of
3748 * its result columns as RECORD, which is not allowed.
3752 /* CTE reference: examine subquery's output expr */
3754 CommonTableExpr *cte = NULL;
3759 * Try to find the referenced CTE using the namespace stack.
3761 ctelevelsup = rte->ctelevelsup + netlevelsup;
3762 if (ctelevelsup >= list_length(context->namespaces))
3766 deparse_namespace *ctedpns;
3768 ctedpns = (deparse_namespace *)
3769 list_nth(context->namespaces, ctelevelsup);
3770 foreach(lc, ctedpns->ctes)
3772 cte = (CommonTableExpr *) lfirst(lc);
3773 if (strcmp(cte->ctename, rte->ctename) == 0)
3779 Query *ctequery = (Query *) cte->ctequery;
3780 TargetEntry *ste = get_tle_by_resno(ctequery->targetList,
3783 if (ste == NULL || ste->resjunk)
3784 elog(ERROR, "subquery %s does not have attribute %d",
3785 rte->eref->aliasname, attnum);
3786 expr = (Node *) ste->expr;
3790 * Recurse into the CTE to see what its Var refers
3791 * to. We have to build an additional level of
3792 * namespace to keep in step with varlevelsup in the
3793 * CTE. Furthermore it could be an outer CTE, so
3794 * we may have to delete some levels of namespace.
3796 List *save_nslist = context->namespaces;
3798 deparse_namespace mydpns;
3801 mydpns.rtable = ctequery->rtable;
3802 mydpns.ctes = ctequery->cteList;
3803 mydpns.subplans = NIL;
3804 mydpns.outer_plan = mydpns.inner_plan = NULL;
3806 new_nslist = list_copy_tail(context->namespaces,
3808 context->namespaces = lcons(&mydpns, new_nslist);
3810 result = get_name_for_var_field((Var *) expr, fieldno,
3813 context->namespaces = save_nslist;
3817 /* else fall through to inspect the expression */
3822 * We're deparsing a Plan tree so we don't have a CTE
3823 * list. But the only place we'd see a Var directly
3824 * referencing a CTE RTE is in a CteScan plan node, and
3825 * we can look into the subplan's tlist instead.
3832 if (!dpns->inner_plan)
3833 elog(ERROR, "failed to find plan for CTE %s",
3834 rte->eref->aliasname);
3835 tle = get_tle_by_resno(dpns->inner_plan->targetlist,
3838 elog(ERROR, "bogus varattno for subquery var: %d",
3840 Assert(netlevelsup == 0);
3841 save_outer = dpns->outer_plan;
3842 save_inner = dpns->inner_plan;
3843 push_plan(dpns, dpns->inner_plan);
3845 result = get_name_for_var_field((Var *) tle->expr, fieldno,
3848 dpns->outer_plan = save_outer;
3849 dpns->inner_plan = save_inner;
3857 * We now have an expression we can't expand any more, so see if
3858 * get_expr_result_type() can do anything with it. If not, pass to
3859 * lookup_rowtype_tupdesc() which will probably fail, but will give an
3860 * appropriate error message while failing.
3862 if (get_expr_result_type(expr, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
3863 tupleDesc = lookup_rowtype_tupdesc_copy(exprType(expr),
3866 /* Got the tupdesc, so we can extract the field name */
3867 Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
3868 return NameStr(tupleDesc->attrs[fieldno - 1]->attname);
3873 * find_rte_by_refname - look up an RTE by refname in a deparse context
3875 * Returns NULL if there is no matching RTE or the refname is ambiguous.
3877 * NOTE: this code is not really correct since it does not take account of
3878 * the fact that not all the RTEs in a rangetable may be visible from the
3879 * point where a Var reference appears. For the purposes we need, however,
3880 * the only consequence of a false match is that we might stick a schema
3881 * qualifier on a Var that doesn't really need it. So it seems close
3884 static RangeTblEntry *
3885 find_rte_by_refname(const char *refname, deparse_context *context)
3887 RangeTblEntry *result = NULL;
3890 foreach(nslist, context->namespaces)
3892 deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist);
3895 foreach(rtlist, dpns->rtable)
3897 RangeTblEntry *rte = (RangeTblEntry *) lfirst(rtlist);
3899 if (strcmp(rte->eref->aliasname, refname) == 0)
3902 return NULL; /* it's ambiguous */
3914 * get_simple_binary_op_name
3916 * helper function for isSimpleNode
3917 * will return single char binary operator name, or NULL if it's not
3920 get_simple_binary_op_name(OpExpr *expr)
3922 List *args = expr->args;
3924 if (list_length(args) == 2)
3926 /* binary operator */
3927 Node *arg1 = (Node *) linitial(args);
3928 Node *arg2 = (Node *) lsecond(args);
3931 op = generate_operator_name(expr->opno, exprType(arg1), exprType(arg2));
3932 if (strlen(op) == 1)
3940 * isSimpleNode - check if given node is simple (doesn't need parenthesizing)
3942 * true : simple in the context of parent node's type
3943 * false : not simple
3946 isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
3951 switch (nodeTag(node))
3956 case T_CoerceToDomainValue:
3957 case T_SetToDefault:
3958 case T_CurrentOfExpr:
3959 /* single words: always simple */
3965 case T_CoalesceExpr:
3972 /* function-like: name(..) or name[..] */
3975 /* CASE keywords act as parentheses */
3982 * appears simple since . has top precedence, unless parent is
3983 * T_FieldSelect itself!
3985 return (IsA(parentNode, FieldSelect) ? false : true);
3990 * treat like FieldSelect (probably doesn't matter)
3992 return (IsA(parentNode, FieldStore) ? false : true);
3994 case T_CoerceToDomain:
3995 /* maybe simple, check args */
3996 return isSimpleNode((Node *) ((CoerceToDomain *) node)->arg,
3999 return isSimpleNode((Node *) ((RelabelType *) node)->arg,
4002 return isSimpleNode((Node *) ((CoerceViaIO *) node)->arg,
4004 case T_ArrayCoerceExpr:
4005 return isSimpleNode((Node *) ((ArrayCoerceExpr *) node)->arg,
4007 case T_ConvertRowtypeExpr:
4008 return isSimpleNode((Node *) ((ConvertRowtypeExpr *) node)->arg,
4013 /* depends on parent node type; needs further checking */
4014 if (prettyFlags & PRETTYFLAG_PAREN && IsA(parentNode, OpExpr))
4017 const char *parentOp;
4020 bool is_lopriparent;
4021 bool is_hipriparent;
4023 op = get_simple_binary_op_name((OpExpr *) node);
4027 /* We know only the basic operators + - and * / % */
4028 is_lopriop = (strchr("+-", *op) != NULL);
4029 is_hipriop = (strchr("*/%", *op) != NULL);
4030 if (!(is_lopriop || is_hipriop))
4033 parentOp = get_simple_binary_op_name((OpExpr *) parentNode);
4037 is_lopriparent = (strchr("+-", *parentOp) != NULL);
4038 is_hipriparent = (strchr("*/%", *parentOp) != NULL);
4039 if (!(is_lopriparent || is_hipriparent))
4042 if (is_hipriop && is_lopriparent)
4043 return true; /* op binds tighter than parent */
4045 if (is_lopriop && is_hipriparent)
4049 * Operators are same priority --- can skip parens only if
4050 * we have (a - b) - c, not a - (b - c).
4052 if (node == (Node *) linitial(((OpExpr *) parentNode)->args))
4057 /* else do the same stuff as for T_SubLink et al. */
4064 case T_DistinctExpr:
4065 switch (nodeTag(parentNode))
4069 /* special handling for casts */
4070 CoercionForm type = ((FuncExpr *) parentNode)->funcformat;
4072 if (type == COERCE_EXPLICIT_CAST ||
4073 type == COERCE_IMPLICIT_CAST)
4075 return true; /* own parentheses */
4077 case T_BoolExpr: /* lower precedence */
4078 case T_ArrayRef: /* other separators */
4079 case T_ArrayExpr: /* other separators */
4080 case T_RowExpr: /* other separators */
4081 case T_CoalesceExpr: /* own parentheses */
4082 case T_MinMaxExpr: /* own parentheses */
4083 case T_XmlExpr: /* own parentheses */
4084 case T_NullIfExpr: /* other separators */
4085 case T_Aggref: /* own parentheses */
4086 case T_WindowFunc: /* own parentheses */
4087 case T_CaseExpr: /* other separators */
4094 switch (nodeTag(parentNode))
4097 if (prettyFlags & PRETTYFLAG_PAREN)
4100 BoolExprType parentType;
4102 type = ((BoolExpr *) node)->boolop;
4103 parentType = ((BoolExpr *) parentNode)->boolop;
4108 if (parentType == AND_EXPR || parentType == OR_EXPR)
4112 if (parentType == OR_EXPR)
4120 /* special handling for casts */
4121 CoercionForm type = ((FuncExpr *) parentNode)->funcformat;
4123 if (type == COERCE_EXPLICIT_CAST ||
4124 type == COERCE_IMPLICIT_CAST)
4126 return true; /* own parentheses */
4128 case T_ArrayRef: /* other separators */
4129 case T_ArrayExpr: /* other separators */
4130 case T_RowExpr: /* other separators */
4131 case T_CoalesceExpr: /* own parentheses */
4132 case T_MinMaxExpr: /* own parentheses */
4133 case T_XmlExpr: /* own parentheses */
4134 case T_NullIfExpr: /* other separators */
4135 case T_Aggref: /* own parentheses */
4136 case T_WindowFunc: /* own parentheses */
4137 case T_CaseExpr: /* other separators */
4146 /* those we don't know: in dubio complexo */
4152 * appendStringInfoSpaces - append spaces to buffer
4155 appendStringInfoSpaces(StringInfo buf, int count)
4158 appendStringInfoChar(buf, ' ');
4162 * appendContextKeyword - append a keyword to buffer
4164 * If prettyPrint is enabled, perform a line break, and adjust indentation.
4165 * Otherwise, just append the keyword.
4168 appendContextKeyword(deparse_context *context, const char *str,
4169 int indentBefore, int indentAfter, int indentPlus)
4171 if (PRETTY_INDENT(context))
4173 context->indentLevel += indentBefore;
4175 appendStringInfoChar(context->buf, '\n');
4176 appendStringInfoSpaces(context->buf,
4177 Max(context->indentLevel, 0) + indentPlus);
4178 appendStringInfoString(context->buf, str);
4180 context->indentLevel += indentAfter;
4181 if (context->indentLevel < 0)
4182 context->indentLevel = 0;
4185 appendStringInfoString(context->buf, str);
4189 * get_rule_expr_paren - deparse expr using get_rule_expr,
4190 * embracing the string with parentheses if necessary for prettyPrint.
4192 * Never embrace if prettyFlags=0, because it's done in the calling node.
4194 * Any node that does *not* embrace its argument node by sql syntax (with
4195 * parentheses, non-operator keywords like CASE/WHEN/ON, or comma etc) should
4196 * use get_rule_expr_paren instead of get_rule_expr so parentheses can be
4200 get_rule_expr_paren(Node *node, deparse_context *context,
4201 bool showimplicit, Node *parentNode)
4205 need_paren = PRETTY_PAREN(context) &&
4206 !isSimpleNode(node, parentNode, context->prettyFlags);
4209 appendStringInfoChar(context->buf, '(');
4211 get_rule_expr(node, context, showimplicit);
4214 appendStringInfoChar(context->buf, ')');
4219 * get_rule_expr - Parse back an expression
4221 * Note: showimplicit determines whether we display any implicit cast that
4222 * is present at the top of the expression tree. It is a passed argument,
4223 * not a field of the context struct, because we change the value as we
4224 * recurse down into the expression. In general we suppress implicit casts
4225 * when the result type is known with certainty (eg, the arguments of an
4226 * OR must be boolean). We display implicit casts for arguments of functions
4227 * and operators, since this is needed to be certain that the same function
4228 * or operator will be chosen when the expression is re-parsed.
4232 get_rule_expr(Node *node, deparse_context *context,
4235 StringInfo buf = context->buf;
4241 * Each level of get_rule_expr must emit an indivisible term
4242 * (parenthesized if necessary) to ensure result is reparsed into the same
4243 * expression tree. The only exception is that when the input is a List,
4244 * we emit the component items comma-separated with no surrounding
4245 * decoration; this is convenient for most callers.
4247 switch (nodeTag(node))
4250 (void) get_variable((Var *) node, 0, true, context);
4254 get_const_expr((Const *) node, context, 0);
4258 appendStringInfo(buf, "$%d", ((Param *) node)->paramid);
4262 get_agg_expr((Aggref *) node, context);
4266 get_windowfunc_expr((WindowFunc *) node, context);
4271 ArrayRef *aref = (ArrayRef *) node;
4275 * Parenthesize the argument unless it's a simple Var or a
4276 * FieldSelect. (In particular, if it's another ArrayRef, we
4277 * *must* parenthesize to avoid confusion.)
4279 need_parens = !IsA(aref->refexpr, Var) &&
4280 !IsA(aref->refexpr, FieldSelect);
4282 appendStringInfoChar(buf, '(');
4283 get_rule_expr((Node *) aref->refexpr, context, showimplicit);
4285 appendStringInfoChar(buf, ')');
4286 printSubscripts(aref, context);
4289 * Array assignment nodes should have been handled in
4290 * processIndirection().
4292 if (aref->refassgnexpr)
4293 elog(ERROR, "unexpected refassgnexpr");
4298 get_func_expr((FuncExpr *) node, context, showimplicit);
4302 get_oper_expr((OpExpr *) node, context);
4305 case T_DistinctExpr:
4307 DistinctExpr *expr = (DistinctExpr *) node;
4308 List *args = expr->args;
4309 Node *arg1 = (Node *) linitial(args);
4310 Node *arg2 = (Node *) lsecond(args);
4312 if (!PRETTY_PAREN(context))
4313 appendStringInfoChar(buf, '(');
4314 get_rule_expr_paren(arg1, context, true, node);
4315 appendStringInfo(buf, " IS DISTINCT FROM ");
4316 get_rule_expr_paren(arg2, context, true, node);
4317 if (!PRETTY_PAREN(context))
4318 appendStringInfoChar(buf, ')');
4322 case T_ScalarArrayOpExpr:
4324 ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
4325 List *args = expr->args;
4326 Node *arg1 = (Node *) linitial(args);
4327 Node *arg2 = (Node *) lsecond(args);
4329 if (!PRETTY_PAREN(context))
4330 appendStringInfoChar(buf, '(');
4331 get_rule_expr_paren(arg1, context, true, node);
4332 appendStringInfo(buf, " %s %s (",
4333 generate_operator_name(expr->opno,
4335 get_element_type(exprType(arg2))),
4336 expr->useOr ? "ANY" : "ALL");
4337 get_rule_expr_paren(arg2, context, true, node);
4338 appendStringInfoChar(buf, ')');
4339 if (!PRETTY_PAREN(context))
4340 appendStringInfoChar(buf, ')');
4346 BoolExpr *expr = (BoolExpr *) node;
4347 Node *first_arg = linitial(expr->args);
4348 ListCell *arg = lnext(list_head(expr->args));
4350 switch (expr->boolop)
4353 if (!PRETTY_PAREN(context))
4354 appendStringInfoChar(buf, '(');
4355 get_rule_expr_paren(first_arg, context,
4359 appendStringInfo(buf, " AND ");
4360 get_rule_expr_paren((Node *) lfirst(arg), context,
4364 if (!PRETTY_PAREN(context))
4365 appendStringInfoChar(buf, ')');
4369 if (!PRETTY_PAREN(context))
4370 appendStringInfoChar(buf, '(');
4371 get_rule_expr_paren(first_arg, context,
4375 appendStringInfo(buf, " OR ");
4376 get_rule_expr_paren((Node *) lfirst(arg), context,
4380 if (!PRETTY_PAREN(context))
4381 appendStringInfoChar(buf, ')');
4385 if (!PRETTY_PAREN(context))
4386 appendStringInfoChar(buf, '(');
4387 appendStringInfo(buf, "NOT ");
4388 get_rule_expr_paren(first_arg, context,
4390 if (!PRETTY_PAREN(context))
4391 appendStringInfoChar(buf, ')');
4395 elog(ERROR, "unrecognized boolop: %d",
4396 (int) expr->boolop);
4402 get_sublink_expr((SubLink *) node, context);
4408 * We cannot see an already-planned subplan in rule deparsing,
4409 * only while EXPLAINing a query plan. For now, just punt.
4411 if (((SubPlan *) node)->useHashTable)
4412 appendStringInfo(buf, "(hashed subplan)");
4414 appendStringInfo(buf, "(subplan)");
4418 case T_AlternativeSubPlan:
4419 /* As above, just punt */
4420 appendStringInfo(buf, "(alternative subplans)");
4425 FieldSelect *fselect = (FieldSelect *) node;
4426 Node *arg = (Node *) fselect->arg;
4427 int fno = fselect->fieldnum;
4428 const char *fieldname;
4432 * Parenthesize the argument unless it's an ArrayRef or
4433 * another FieldSelect. Note in particular that it would be
4434 * WRONG to not parenthesize a Var argument; simplicity is not
4435 * the issue here, having the right number of names is.
4437 need_parens = !IsA(arg, ArrayRef) &&!IsA(arg, FieldSelect);
4439 appendStringInfoChar(buf, '(');
4440 get_rule_expr(arg, context, true);
4442 appendStringInfoChar(buf, ')');
4445 * Get and print the field name.
4447 fieldname = get_name_for_var_field((Var *) arg, fno,
4449 appendStringInfo(buf, ".%s", quote_identifier(fieldname));
4456 * We shouldn't see FieldStore here; it should have been stripped
4457 * off by processIndirection().
4459 elog(ERROR, "unexpected FieldStore");
4464 RelabelType *relabel = (RelabelType *) node;
4465 Node *arg = (Node *) relabel->arg;
4467 if (relabel->relabelformat == COERCE_IMPLICIT_CAST &&
4470 /* don't show the implicit cast */
4471 get_rule_expr_paren(arg, context, false, node);
4475 get_coercion_expr(arg, context,
4476 relabel->resulttype,
4477 relabel->resulttypmod,
4485 CoerceViaIO *iocoerce = (CoerceViaIO *) node;
4486 Node *arg = (Node *) iocoerce->arg;
4488 if (iocoerce->coerceformat == COERCE_IMPLICIT_CAST &&
4491 /* don't show the implicit cast */
4492 get_rule_expr_paren(arg, context, false, node);
4496 get_coercion_expr(arg, context,
4497 iocoerce->resulttype,
4504 case T_ArrayCoerceExpr:
4506 ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;
4507 Node *arg = (Node *) acoerce->arg;
4509 if (acoerce->coerceformat == COERCE_IMPLICIT_CAST &&
4512 /* don't show the implicit cast */
4513 get_rule_expr_paren(arg, context, false, node);
4517 get_coercion_expr(arg, context,
4518 acoerce->resulttype,
4519 acoerce->resulttypmod,
4525 case T_ConvertRowtypeExpr:
4527 ConvertRowtypeExpr *convert = (ConvertRowtypeExpr *) node;
4528 Node *arg = (Node *) convert->arg;
4530 if (convert->convertformat == COERCE_IMPLICIT_CAST &&
4533 /* don't show the implicit cast */
4534 get_rule_expr_paren(arg, context, false, node);
4538 get_coercion_expr(arg, context,
4539 convert->resulttype, -1,
4547 CaseExpr *caseexpr = (CaseExpr *) node;
4550 appendContextKeyword(context, "CASE",
4551 0, PRETTYINDENT_VAR, 0);
4554 appendStringInfoChar(buf, ' ');
4555 get_rule_expr((Node *) caseexpr->arg, context, true);
4557 foreach(temp, caseexpr->args)
4559 CaseWhen *when = (CaseWhen *) lfirst(temp);
4560 Node *w = (Node *) when->expr;
4562 if (!PRETTY_INDENT(context))
4563 appendStringInfoChar(buf, ' ');
4564 appendContextKeyword(context, "WHEN ",
4569 * The parser should have produced WHEN clauses of the
4570 * form "CaseTestExpr = RHS"; we want to show just the
4571 * RHS. If the user wrote something silly like "CASE
4572 * boolexpr WHEN TRUE THEN ...", then the optimizer's
4573 * simplify_boolean_equality() may have reduced this
4574 * to just "CaseTestExpr" or "NOT CaseTestExpr", for
4575 * which we have to show "TRUE" or "FALSE". Also,
4576 * depending on context the original CaseTestExpr
4577 * might have been reduced to a Const (but we won't
4578 * see "WHEN Const"). We have also to consider the
4579 * possibility that an implicit coercion was inserted
4580 * between the CaseTestExpr and the operator.
4584 List *args = ((OpExpr *) w)->args;
4588 Assert(list_length(args) == 2);
4589 lhs = strip_implicit_coercions(linitial(args));
4590 Assert(IsA(lhs, CaseTestExpr) ||
4592 rhs = (Node *) lsecond(args);
4593 get_rule_expr(rhs, context, false);
4595 else if (IsA(strip_implicit_coercions(w),
4597 appendStringInfo(buf, "TRUE");
4598 else if (not_clause(w))
4600 Assert(IsA(strip_implicit_coercions((Node *) get_notclausearg((Expr *) w)),
4602 appendStringInfo(buf, "FALSE");
4605 elog(ERROR, "unexpected CASE WHEN clause: %d",
4609 get_rule_expr(w, context, false);
4610 appendStringInfo(buf, " THEN ");
4611 get_rule_expr((Node *) when->result, context, true);
4613 if (!PRETTY_INDENT(context))
4614 appendStringInfoChar(buf, ' ');
4615 appendContextKeyword(context, "ELSE ",
4617 get_rule_expr((Node *) caseexpr->defresult, context, true);
4618 if (!PRETTY_INDENT(context))
4619 appendStringInfoChar(buf, ' ');
4620 appendContextKeyword(context, "END",
4621 -PRETTYINDENT_VAR, 0, 0);
4627 ArrayExpr *arrayexpr = (ArrayExpr *) node;
4629 appendStringInfo(buf, "ARRAY[");
4630 get_rule_expr((Node *) arrayexpr->elements, context, true);
4631 appendStringInfoChar(buf, ']');
4633 * If the array isn't empty, we assume its elements are
4634 * coerced to the desired type. If it's empty, though, we
4635 * need an explicit coercion to the array type.
4637 if (arrayexpr->elements == NIL)
4638 appendStringInfo(buf, "::%s",
4639 format_type_with_typemod(arrayexpr->array_typeid, -1));
4645 RowExpr *rowexpr = (RowExpr *) node;
4646 TupleDesc tupdesc = NULL;
4652 * If it's a named type and not RECORD, we may have to skip
4653 * dropped columns and/or claim there are NULLs for added
4656 if (rowexpr->row_typeid != RECORDOID)
4658 tupdesc = lookup_rowtype_tupdesc(rowexpr->row_typeid, -1);
4659 Assert(list_length(rowexpr->args) <= tupdesc->natts);
4663 * SQL99 allows "ROW" to be omitted when there is more than
4664 * one column, but for simplicity we always print it.
4666 appendStringInfo(buf, "ROW(");
4669 foreach(arg, rowexpr->args)
4671 Node *e = (Node *) lfirst(arg);
4673 if (tupdesc == NULL ||
4674 !tupdesc->attrs[i]->attisdropped)
4676 appendStringInfoString(buf, sep);
4677 get_rule_expr(e, context, true);
4682 if (tupdesc != NULL)
4684 while (i < tupdesc->natts)
4686 if (!tupdesc->attrs[i]->attisdropped)
4688 appendStringInfoString(buf, sep);
4689 appendStringInfo(buf, "NULL");
4695 ReleaseTupleDesc(tupdesc);
4697 appendStringInfo(buf, ")");
4698 if (rowexpr->row_format == COERCE_EXPLICIT_CAST)
4699 appendStringInfo(buf, "::%s",
4700 format_type_with_typemod(rowexpr->row_typeid, -1));
4704 case T_RowCompareExpr:
4706 RowCompareExpr *rcexpr = (RowCompareExpr *) node;
4711 * SQL99 allows "ROW" to be omitted when there is more than
4712 * one column, but for simplicity we always print it.
4714 appendStringInfo(buf, "(ROW(");
4716 foreach(arg, rcexpr->largs)
4718 Node *e = (Node *) lfirst(arg);
4720 appendStringInfoString(buf, sep);
4721 get_rule_expr(e, context, true);
4726 * We assume that the name of the first-column operator will
4727 * do for all the rest too. This is definitely open to
4728 * failure, eg if some but not all operators were renamed
4729 * since the construct was parsed, but there seems no way to
4732 appendStringInfo(buf, ") %s ROW(",
4733 generate_operator_name(linitial_oid(rcexpr->opnos),
4734 exprType(linitial(rcexpr->largs)),
4735 exprType(linitial(rcexpr->rargs))));
4737 foreach(arg, rcexpr->rargs)
4739 Node *e = (Node *) lfirst(arg);
4741 appendStringInfoString(buf, sep);
4742 get_rule_expr(e, context, true);
4745 appendStringInfo(buf, "))");
4749 case T_CoalesceExpr:
4751 CoalesceExpr *coalesceexpr = (CoalesceExpr *) node;
4753 appendStringInfo(buf, "COALESCE(");
4754 get_rule_expr((Node *) coalesceexpr->args, context, true);
4755 appendStringInfoChar(buf, ')');
4761 MinMaxExpr *minmaxexpr = (MinMaxExpr *) node;
4763 switch (minmaxexpr->op)
4766 appendStringInfo(buf, "GREATEST(");
4769 appendStringInfo(buf, "LEAST(");
4772 get_rule_expr((Node *) minmaxexpr->args, context, true);
4773 appendStringInfoChar(buf, ')');
4779 XmlExpr *xexpr = (XmlExpr *) node;
4780 bool needcomma = false;
4788 appendStringInfoString(buf, "XMLCONCAT(");
4791 appendStringInfoString(buf, "XMLELEMENT(");
4794 appendStringInfoString(buf, "XMLFOREST(");
4797 appendStringInfoString(buf, "XMLPARSE(");
4800 appendStringInfoString(buf, "XMLPI(");
4803 appendStringInfoString(buf, "XMLROOT(");
4805 case IS_XMLSERIALIZE:
4806 appendStringInfoString(buf, "XMLSERIALIZE(");
4811 if (xexpr->op == IS_XMLPARSE || xexpr->op == IS_XMLSERIALIZE)
4813 if (xexpr->xmloption == XMLOPTION_DOCUMENT)
4814 appendStringInfoString(buf, "DOCUMENT ");
4816 appendStringInfoString(buf, "CONTENT ");
4820 appendStringInfo(buf, "NAME %s",
4821 quote_identifier(map_xml_name_to_sql_identifier(xexpr->name)));
4824 if (xexpr->named_args)
4826 if (xexpr->op != IS_XMLFOREST)
4829 appendStringInfoString(buf, ", ");
4830 appendStringInfoString(buf, "XMLATTRIBUTES(");
4833 forboth(arg, xexpr->named_args, narg, xexpr->arg_names)
4835 Node *e = (Node *) lfirst(arg);
4836 char *argname = strVal(lfirst(narg));
4839 appendStringInfoString(buf, ", ");
4840 get_rule_expr((Node *) e, context, true);
4841 appendStringInfo(buf, " AS %s",
4842 quote_identifier(map_xml_name_to_sql_identifier(argname)));
4845 if (xexpr->op != IS_XMLFOREST)
4846 appendStringInfoChar(buf, ')');
4851 appendStringInfoString(buf, ", ");
4858 case IS_XMLSERIALIZE:
4859 /* no extra decoration needed */
4860 get_rule_expr((Node *) xexpr->args, context, true);
4863 Assert(list_length(xexpr->args) == 2);
4865 get_rule_expr((Node *) linitial(xexpr->args),
4868 con = (Const *) lsecond(xexpr->args);
4869 Assert(IsA(con, Const));
4870 Assert(!con->constisnull);
4871 if (DatumGetBool(con->constvalue))
4872 appendStringInfoString(buf,
4873 " PRESERVE WHITESPACE");
4875 appendStringInfoString(buf,
4876 " STRIP WHITESPACE");
4879 Assert(list_length(xexpr->args) == 3);
4881 get_rule_expr((Node *) linitial(xexpr->args),
4884 appendStringInfoString(buf, ", VERSION ");
4885 con = (Const *) lsecond(xexpr->args);
4886 if (IsA(con, Const) &&
4888 appendStringInfoString(buf, "NO VALUE");
4890 get_rule_expr((Node *) con, context, false);
4892 con = (Const *) lthird(xexpr->args);
4893 Assert(IsA(con, Const));
4894 if (con->constisnull)
4895 /* suppress STANDALONE NO VALUE */ ;
4898 switch (DatumGetInt32(con->constvalue))
4900 case XML_STANDALONE_YES:
4901 appendStringInfoString(buf,
4902 ", STANDALONE YES");
4904 case XML_STANDALONE_NO:
4905 appendStringInfoString(buf,
4908 case XML_STANDALONE_NO_VALUE:
4909 appendStringInfoString(buf,
4910 ", STANDALONE NO VALUE");
4918 get_rule_expr_paren((Node *) xexpr->args, context, false, node);
4923 if (xexpr->op == IS_XMLSERIALIZE)
4924 appendStringInfo(buf, " AS %s", format_type_with_typemod(xexpr->type,
4926 if (xexpr->op == IS_DOCUMENT)
4927 appendStringInfoString(buf, " IS DOCUMENT");
4929 appendStringInfoChar(buf, ')');
4935 NullIfExpr *nullifexpr = (NullIfExpr *) node;
4937 appendStringInfo(buf, "NULLIF(");
4938 get_rule_expr((Node *) nullifexpr->args, context, true);
4939 appendStringInfoChar(buf, ')');
4945 NullTest *ntest = (NullTest *) node;
4947 if (!PRETTY_PAREN(context))
4948 appendStringInfoChar(buf, '(');
4949 get_rule_expr_paren((Node *) ntest->arg, context, true, node);
4950 switch (ntest->nulltesttype)
4953 appendStringInfo(buf, " IS NULL");
4956 appendStringInfo(buf, " IS NOT NULL");
4959 elog(ERROR, "unrecognized nulltesttype: %d",
4960 (int) ntest->nulltesttype);
4962 if (!PRETTY_PAREN(context))
4963 appendStringInfoChar(buf, ')');
4969 BooleanTest *btest = (BooleanTest *) node;
4971 if (!PRETTY_PAREN(context))
4972 appendStringInfoChar(buf, '(');
4973 get_rule_expr_paren((Node *) btest->arg, context, false, node);
4974 switch (btest->booltesttype)
4977 appendStringInfo(buf, " IS TRUE");
4980 appendStringInfo(buf, " IS NOT TRUE");
4983 appendStringInfo(buf, " IS FALSE");
4986 appendStringInfo(buf, " IS NOT FALSE");
4989 appendStringInfo(buf, " IS UNKNOWN");
4991 case IS_NOT_UNKNOWN:
4992 appendStringInfo(buf, " IS NOT UNKNOWN");
4995 elog(ERROR, "unrecognized booltesttype: %d",
4996 (int) btest->booltesttype);
4998 if (!PRETTY_PAREN(context))
4999 appendStringInfoChar(buf, ')');
5003 case T_CoerceToDomain:
5005 CoerceToDomain *ctest = (CoerceToDomain *) node;
5006 Node *arg = (Node *) ctest->arg;
5008 if (ctest->coercionformat == COERCE_IMPLICIT_CAST &&
5011 /* don't show the implicit cast */
5012 get_rule_expr(arg, context, false);
5016 get_coercion_expr(arg, context,
5018 ctest->resulttypmod,
5024 case T_CoerceToDomainValue:
5025 appendStringInfo(buf, "VALUE");
5028 case T_SetToDefault:
5029 appendStringInfo(buf, "DEFAULT");
5032 case T_CurrentOfExpr:
5034 CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
5036 if (cexpr->cursor_name)
5037 appendStringInfo(buf, "CURRENT OF %s",
5038 quote_identifier(cexpr->cursor_name));
5040 appendStringInfo(buf, "CURRENT OF $%d",
5041 cexpr->cursor_param);
5051 foreach(l, (List *) node)
5053 appendStringInfoString(buf, sep);
5054 get_rule_expr((Node *) lfirst(l), context, showimplicit);
5061 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
5068 * get_oper_expr - Parse back an OpExpr node
5071 get_oper_expr(OpExpr *expr, deparse_context *context)
5073 StringInfo buf = context->buf;
5074 Oid opno = expr->opno;
5075 List *args = expr->args;
5077 if (!PRETTY_PAREN(context))
5078 appendStringInfoChar(buf, '(');
5079 if (list_length(args) == 2)
5081 /* binary operator */
5082 Node *arg1 = (Node *) linitial(args);
5083 Node *arg2 = (Node *) lsecond(args);
5085 get_rule_expr_paren(arg1, context, true, (Node *) expr);
5086 appendStringInfo(buf, " %s ",
5087 generate_operator_name(opno,
5090 get_rule_expr_paren(arg2, context, true, (Node *) expr);
5094 /* unary operator --- but which side? */
5095 Node *arg = (Node *) linitial(args);
5097 Form_pg_operator optup;
5099 tp = SearchSysCache(OPEROID,
5100 ObjectIdGetDatum(opno),
5102 if (!HeapTupleIsValid(tp))
5103 elog(ERROR, "cache lookup failed for operator %u", opno);
5104 optup = (Form_pg_operator) GETSTRUCT(tp);
5105 switch (optup->oprkind)
5108 appendStringInfo(buf, "%s ",
5109 generate_operator_name(opno,
5112 get_rule_expr_paren(arg, context, true, (Node *) expr);
5115 get_rule_expr_paren(arg, context, true, (Node *) expr);
5116 appendStringInfo(buf, " %s",
5117 generate_operator_name(opno,
5122 elog(ERROR, "bogus oprkind: %d", optup->oprkind);
5124 ReleaseSysCache(tp);
5126 if (!PRETTY_PAREN(context))
5127 appendStringInfoChar(buf, ')');
5131 * get_func_expr - Parse back a FuncExpr node
5134 get_func_expr(FuncExpr *expr, deparse_context *context,
5137 StringInfo buf = context->buf;
5138 Oid funcoid = expr->funcid;
5139 Oid argtypes[FUNC_MAX_ARGS];
5145 * If the function call came from an implicit coercion, then just show the
5146 * first argument --- unless caller wants to see implicit coercions.
5148 if (expr->funcformat == COERCE_IMPLICIT_CAST && !showimplicit)
5150 get_rule_expr_paren((Node *) linitial(expr->args), context,
5151 false, (Node *) expr);
5156 * If the function call came from a cast, then show the first argument
5157 * plus an explicit cast operation.
5159 if (expr->funcformat == COERCE_EXPLICIT_CAST ||
5160 expr->funcformat == COERCE_IMPLICIT_CAST)
5162 Node *arg = linitial(expr->args);
5163 Oid rettype = expr->funcresulttype;
5164 int32 coercedTypmod;
5166 /* Get the typmod if this is a length-coercion function */
5167 (void) exprIsLengthCoercion((Node *) expr, &coercedTypmod);
5169 get_coercion_expr(arg, context,
5170 rettype, coercedTypmod,
5177 * Normal function: display as proname(args). First we need to extract
5178 * the argument datatypes.
5180 if (list_length(expr->args) > FUNC_MAX_ARGS)
5182 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
5183 errmsg("too many arguments")));
5185 foreach(l, expr->args)
5187 argtypes[nargs] = exprType((Node *) lfirst(l));
5191 appendStringInfo(buf, "%s(",
5192 generate_function_name(funcoid, nargs, argtypes,
5195 foreach(l, expr->args)
5198 appendStringInfoString(buf, ", ");
5199 if (is_variadic && lnext(l) == NULL)
5200 appendStringInfoString(buf, "VARIADIC ");
5201 get_rule_expr((Node *) lfirst(l), context, true);
5203 appendStringInfoChar(buf, ')');
5207 * get_agg_expr - Parse back an Aggref node
5210 get_agg_expr(Aggref *aggref, deparse_context *context)
5212 StringInfo buf = context->buf;
5213 Oid argtypes[FUNC_MAX_ARGS];
5217 if (list_length(aggref->args) > FUNC_MAX_ARGS)
5219 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
5220 errmsg("too many arguments")));
5222 foreach(l, aggref->args)
5224 argtypes[nargs] = exprType((Node *) lfirst(l));
5228 appendStringInfo(buf, "%s(%s",
5229 generate_function_name(aggref->aggfnoid,
5230 nargs, argtypes, NULL),
5231 aggref->aggdistinct ? "DISTINCT " : "");
5232 /* aggstar can be set only in zero-argument aggregates */
5233 if (aggref->aggstar)
5234 appendStringInfoChar(buf, '*');
5236 get_rule_expr((Node *) aggref->args, context, true);
5237 appendStringInfoChar(buf, ')');
5241 * get_windowfunc_expr - Parse back a WindowFunc node
5244 get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context)
5246 StringInfo buf = context->buf;
5247 Oid argtypes[FUNC_MAX_ARGS];
5251 if (list_length(wfunc->args) > FUNC_MAX_ARGS)
5253 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
5254 errmsg("too many arguments")));
5256 foreach(l, wfunc->args)
5258 argtypes[nargs] = exprType((Node *) lfirst(l));
5262 appendStringInfo(buf, "%s(%s",
5263 generate_function_name(wfunc->winfnoid,
5264 nargs, argtypes, NULL), "");
5265 /* winstar can be set only in zero-argument aggregates */
5267 appendStringInfoChar(buf, '*');
5269 get_rule_expr((Node *) wfunc->args, context, true);
5270 appendStringInfoString(buf, ") OVER ");
5272 foreach(l, context->windowClause)
5274 WindowClause *wc = (WindowClause *) lfirst(l);
5276 if (wc->winref == wfunc->winref)
5279 appendStringInfoString(buf, quote_identifier(wc->name));
5281 get_rule_windowspec(wc, context->windowTList, context);
5287 if (context->windowClause)
5288 elog(ERROR, "could not find window clause for winref %u",
5291 * In EXPLAIN, we don't have window context information available,
5292 * so we have to settle for this:
5294 appendStringInfoString(buf, "(?)");
5301 * Make a string representation of a value coerced to a specific type
5305 get_coercion_expr(Node *arg, deparse_context *context,
5306 Oid resulttype, int32 resulttypmod,
5309 StringInfo buf = context->buf;
5312 * Since parse_coerce.c doesn't immediately collapse application of
5313 * length-coercion functions to constants, what we'll typically see in
5314 * such cases is a Const with typmod -1 and a length-coercion function
5315 * right above it. Avoid generating redundant output. However, beware of
5316 * suppressing casts when the user actually wrote something like
5317 * 'foo'::text::char(3).
5319 if (arg && IsA(arg, Const) &&
5320 ((Const *) arg)->consttype == resulttype &&
5321 ((Const *) arg)->consttypmod == -1)
5323 /* Show the constant without normal ::typename decoration */
5324 get_const_expr((Const *) arg, context, -1);
5328 if (!PRETTY_PAREN(context))
5329 appendStringInfoChar(buf, '(');
5330 get_rule_expr_paren(arg, context, false, parentNode);
5331 if (!PRETTY_PAREN(context))
5332 appendStringInfoChar(buf, ')');
5334 appendStringInfo(buf, "::%s",
5335 format_type_with_typemod(resulttype, resulttypmod));
5341 * Make a string representation of a Const
5343 * showtype can be -1 to never show "::typename" decoration, or +1 to always
5344 * show it, or 0 to show it only if the constant wouldn't be assumed to be
5345 * the right type by default.
5349 get_const_expr(Const *constval, deparse_context *context, int showtype)
5351 StringInfo buf = context->buf;
5355 bool isfloat = false;
5358 if (constval->constisnull)
5361 * Always label the type of a NULL constant to prevent misdecisions
5362 * about type when reparsing.
5364 appendStringInfo(buf, "NULL");
5366 appendStringInfo(buf, "::%s",
5367 format_type_with_typemod(constval->consttype,
5368 constval->consttypmod));
5372 getTypeOutputInfo(constval->consttype,
5373 &typoutput, &typIsVarlena);
5375 extval = OidOutputFunctionCall(typoutput, constval->constvalue);
5377 switch (constval->consttype)
5388 * These types are printed without quotes unless they contain
5389 * values that aren't accepted by the scanner unquoted (e.g.,
5390 * 'NaN'). Note that strtod() and friends might accept NaN,
5391 * so we can't use that to test.
5393 * In reality we only need to defend against infinity and NaN,
5394 * so we need not get too crazy about pattern matching here.
5396 * There is a special-case gotcha: if the constant is signed,
5397 * we need to parenthesize it, else the parser might see a
5398 * leading plus/minus as binding less tightly than adjacent
5399 * operators --- particularly, the cast that we might attach
5402 if (strspn(extval, "0123456789+-eE.") == strlen(extval))
5404 if (extval[0] == '+' || extval[0] == '-')
5405 appendStringInfo(buf, "(%s)", extval);
5407 appendStringInfoString(buf, extval);
5408 if (strcspn(extval, "eE.") != strlen(extval))
5409 isfloat = true; /* it looks like a float */
5412 appendStringInfo(buf, "'%s'", extval);
5418 appendStringInfo(buf, "B'%s'", extval);
5422 if (strcmp(extval, "t") == 0)
5423 appendStringInfo(buf, "true");
5425 appendStringInfo(buf, "false");
5429 simple_quote_literal(buf, extval);
5439 * For showtype == 0, append ::typename unless the constant will be
5440 * implicitly typed as the right type when it is read in.
5442 * XXX this code has to be kept in sync with the behavior of the parser,
5443 * especially make_const.
5445 switch (constval->consttype)
5450 /* These types can be left unlabeled */
5456 * Float-looking constants will be typed as numeric, but if
5457 * there's a specific typmod we need to show it.
5459 needlabel = !isfloat || (constval->consttypmod >= 0);
5465 if (needlabel || showtype > 0)
5466 appendStringInfo(buf, "::%s",
5467 format_type_with_typemod(constval->consttype,
5468 constval->consttypmod));
5472 * simple_quote_literal - Format a string as a SQL literal, append to buf
5475 simple_quote_literal(StringInfo buf, const char *val)
5480 * We form the string literal according to the prevailing setting
5481 * of standard_conforming_strings; we never use E''. User is
5482 * responsible for making sure result is used correctly.
5484 appendStringInfoChar(buf, '\'');
5485 for (valptr = val; *valptr; valptr++)
5489 if (SQL_STR_DOUBLE(ch, !standard_conforming_strings))
5490 appendStringInfoChar(buf, ch);
5491 appendStringInfoChar(buf, ch);
5493 appendStringInfoChar(buf, '\'');
5498 * get_sublink_expr - Parse back a sublink
5502 get_sublink_expr(SubLink *sublink, deparse_context *context)
5504 StringInfo buf = context->buf;
5505 Query *query = (Query *) (sublink->subselect);
5506 char *opname = NULL;
5509 if (sublink->subLinkType == ARRAY_SUBLINK)
5510 appendStringInfo(buf, "ARRAY(");
5512 appendStringInfoChar(buf, '(');
5515 * Note that we print the name of only the first operator, when there are
5516 * multiple combining operators. This is an approximation that could go
5517 * wrong in various scenarios (operators in different schemas, renamed
5518 * operators, etc) but there is not a whole lot we can do about it, since
5519 * the syntax allows only one operator to be shown.
5521 if (sublink->testexpr)
5523 if (IsA(sublink->testexpr, OpExpr))
5525 /* single combining operator */
5526 OpExpr *opexpr = (OpExpr *) sublink->testexpr;
5528 get_rule_expr(linitial(opexpr->args), context, true);
5529 opname = generate_operator_name(opexpr->opno,
5530 exprType(linitial(opexpr->args)),
5531 exprType(lsecond(opexpr->args)));
5533 else if (IsA(sublink->testexpr, BoolExpr))
5535 /* multiple combining operators, = or <> cases */
5539 appendStringInfoChar(buf, '(');
5541 foreach(l, ((BoolExpr *) sublink->testexpr)->args)
5543 OpExpr *opexpr = (OpExpr *) lfirst(l);
5545 Assert(IsA(opexpr, OpExpr));
5546 appendStringInfoString(buf, sep);
5547 get_rule_expr(linitial(opexpr->args), context, true);
5549 opname = generate_operator_name(opexpr->opno,
5550 exprType(linitial(opexpr->args)),
5551 exprType(lsecond(opexpr->args)));
5554 appendStringInfoChar(buf, ')');
5556 else if (IsA(sublink->testexpr, RowCompareExpr))
5558 /* multiple combining operators, < <= > >= cases */
5559 RowCompareExpr *rcexpr = (RowCompareExpr *) sublink->testexpr;
5561 appendStringInfoChar(buf, '(');
5562 get_rule_expr((Node *) rcexpr->largs, context, true);
5563 opname = generate_operator_name(linitial_oid(rcexpr->opnos),
5564 exprType(linitial(rcexpr->largs)),
5565 exprType(linitial(rcexpr->rargs)));
5566 appendStringInfoChar(buf, ')');
5569 elog(ERROR, "unrecognized testexpr type: %d",
5570 (int) nodeTag(sublink->testexpr));
5575 switch (sublink->subLinkType)
5577 case EXISTS_SUBLINK:
5578 appendStringInfo(buf, "EXISTS ");
5582 if (strcmp(opname, "=") == 0) /* Represent = ANY as IN */
5583 appendStringInfo(buf, " IN ");
5585 appendStringInfo(buf, " %s ANY ", opname);
5589 appendStringInfo(buf, " %s ALL ", opname);
5592 case ROWCOMPARE_SUBLINK:
5593 appendStringInfo(buf, " %s ", opname);
5601 case CTE_SUBLINK: /* shouldn't occur in a SubLink */
5603 elog(ERROR, "unrecognized sublink type: %d",
5604 (int) sublink->subLinkType);
5609 appendStringInfoChar(buf, '(');
5611 get_query_def(query, buf, context->namespaces, NULL,
5612 context->prettyFlags, context->indentLevel);
5615 appendStringInfo(buf, "))");
5617 appendStringInfoChar(buf, ')');
5622 * get_from_clause - Parse back a FROM clause
5624 * "prefix" is the keyword that denotes the start of the list of FROM
5625 * elements. It is FROM when used to parse back SELECT and UPDATE, but
5626 * is USING when parsing back DELETE.
5630 get_from_clause(Query *query, const char *prefix, deparse_context *context)
5632 StringInfo buf = context->buf;
5637 * We use the query's jointree as a guide to what to print. However, we
5638 * must ignore auto-added RTEs that are marked not inFromCl. (These can
5639 * only appear at the top level of the jointree, so it's sufficient to
5640 * check here.) This check also ensures we ignore the rule pseudo-RTEs
5643 foreach(l, query->jointree->fromlist)
5645 Node *jtnode = (Node *) lfirst(l);
5647 if (IsA(jtnode, RangeTblRef))
5649 int varno = ((RangeTblRef *) jtnode)->rtindex;
5650 RangeTblEntry *rte = rt_fetch(varno, query->rtable);
5658 appendContextKeyword(context, prefix,
5659 -PRETTYINDENT_STD, PRETTYINDENT_STD, 2);
5663 appendStringInfoString(buf, ", ");
5665 get_from_clause_item(jtnode, query, context);
5670 get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
5672 StringInfo buf = context->buf;
5674 if (IsA(jtnode, RangeTblRef))
5676 int varno = ((RangeTblRef *) jtnode)->rtindex;
5677 RangeTblEntry *rte = rt_fetch(varno, query->rtable);
5678 bool gavealias = false;
5680 switch (rte->rtekind)
5683 /* Normal relation RTE */
5684 appendStringInfo(buf, "%s%s",
5686 generate_relation_name(rte->relid,
5687 context->namespaces));
5691 appendStringInfoChar(buf, '(');
5692 get_query_def(rte->subquery, buf, context->namespaces, NULL,
5693 context->prettyFlags, context->indentLevel);
5694 appendStringInfoChar(buf, ')');
5698 get_rule_expr(rte->funcexpr, context, true);
5701 /* Values list RTE */
5702 get_values_def(rte->values_lists, context);
5705 appendStringInfoString(buf, quote_identifier(rte->ctename));
5708 elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
5712 if (rte->alias != NULL)
5714 appendStringInfo(buf, " %s",
5715 quote_identifier(rte->alias->aliasname));
5718 else if (rte->rtekind == RTE_RELATION &&
5719 strcmp(rte->eref->aliasname, get_rel_name(rte->relid)) != 0)
5722 * Apparently the rel has been renamed since the rule was made.
5723 * Emit a fake alias clause so that variable references will still
5724 * work. This is not a 100% solution but should work in most
5725 * reasonable situations.
5727 appendStringInfo(buf, " %s",
5728 quote_identifier(rte->eref->aliasname));
5731 else if (rte->rtekind == RTE_FUNCTION)
5734 * For a function RTE, always give an alias. This covers possible
5735 * renaming of the function and/or instability of the
5736 * FigureColname rules for things that aren't simple functions.
5738 appendStringInfo(buf, " %s",
5739 quote_identifier(rte->eref->aliasname));
5743 if (rte->rtekind == RTE_FUNCTION)
5745 if (rte->funccoltypes != NIL)
5747 /* Function returning RECORD, reconstruct the columndefs */
5749 appendStringInfo(buf, " AS ");
5750 get_from_clause_coldeflist(rte->eref->colnames,
5752 rte->funccoltypmods,
5758 * For a function RTE, always emit a complete column alias
5759 * list; this is to protect against possible instability of
5760 * the default column names (eg, from altering parameter
5763 get_from_clause_alias(rte->eref, rte, context);
5769 * For non-function RTEs, just report whatever the user originally
5770 * gave as column aliases.
5772 get_from_clause_alias(rte->alias, rte, context);
5775 else if (IsA(jtnode, JoinExpr))
5777 JoinExpr *j = (JoinExpr *) jtnode;
5778 bool need_paren_on_right;
5780 need_paren_on_right = PRETTY_PAREN(context) &&
5781 !IsA(j->rarg, RangeTblRef) &&
5782 !(IsA(j->rarg, JoinExpr) &&((JoinExpr *) j->rarg)->alias != NULL);
5784 if (!PRETTY_PAREN(context) || j->alias != NULL)
5785 appendStringInfoChar(buf, '(');
5787 get_from_clause_item(j->larg, query, context);
5791 if (!PRETTY_INDENT(context))
5792 appendStringInfoChar(buf, ' ');
5793 switch (j->jointype)
5796 appendContextKeyword(context, "NATURAL JOIN ",
5798 PRETTYINDENT_JOIN, 0);
5801 appendContextKeyword(context, "NATURAL LEFT JOIN ",
5803 PRETTYINDENT_JOIN, 0);
5806 appendContextKeyword(context, "NATURAL FULL JOIN ",
5808 PRETTYINDENT_JOIN, 0);
5811 appendContextKeyword(context, "NATURAL RIGHT JOIN ",
5813 PRETTYINDENT_JOIN, 0);
5816 elog(ERROR, "unrecognized join type: %d",
5822 switch (j->jointype)
5826 appendContextKeyword(context, " JOIN ",
5828 PRETTYINDENT_JOIN, 2);
5830 appendContextKeyword(context, " CROSS JOIN ",
5832 PRETTYINDENT_JOIN, 1);
5835 appendContextKeyword(context, " LEFT JOIN ",
5837 PRETTYINDENT_JOIN, 2);
5840 appendContextKeyword(context, " FULL JOIN ",
5842 PRETTYINDENT_JOIN, 2);
5845 appendContextKeyword(context, " RIGHT JOIN ",
5847 PRETTYINDENT_JOIN, 2);
5850 elog(ERROR, "unrecognized join type: %d",
5855 if (need_paren_on_right)
5856 appendStringInfoChar(buf, '(');
5857 get_from_clause_item(j->rarg, query, context);
5858 if (need_paren_on_right)
5859 appendStringInfoChar(buf, ')');
5861 context->indentLevel -= PRETTYINDENT_JOIN_ON;
5869 appendStringInfo(buf, " USING (");
5870 foreach(col, j->using)
5872 if (col != list_head(j->using))
5873 appendStringInfo(buf, ", ");
5874 appendStringInfoString(buf,
5875 quote_identifier(strVal(lfirst(col))));
5877 appendStringInfoChar(buf, ')');
5881 appendStringInfo(buf, " ON ");
5882 if (!PRETTY_PAREN(context))
5883 appendStringInfoChar(buf, '(');
5884 get_rule_expr(j->quals, context, false);
5885 if (!PRETTY_PAREN(context))
5886 appendStringInfoChar(buf, ')');
5889 if (!PRETTY_PAREN(context) || j->alias != NULL)
5890 appendStringInfoChar(buf, ')');
5892 /* Yes, it's correct to put alias after the right paren ... */
5893 if (j->alias != NULL)
5895 appendStringInfo(buf, " %s",
5896 quote_identifier(j->alias->aliasname));
5897 get_from_clause_alias(j->alias,
5898 rt_fetch(j->rtindex, query->rtable),
5903 elog(ERROR, "unrecognized node type: %d",
5904 (int) nodeTag(jtnode));
5908 * get_from_clause_alias - reproduce column alias list
5910 * This is tricky because we must ignore dropped columns.
5913 get_from_clause_alias(Alias *alias, RangeTblEntry *rte,
5914 deparse_context *context)
5916 StringInfo buf = context->buf;
5921 if (alias == NULL || alias->colnames == NIL)
5922 return; /* definitely nothing to do */
5925 foreach(col, alias->colnames)
5928 if (get_rte_attribute_is_dropped(rte, attnum))
5932 appendStringInfoChar(buf, '(');
5936 appendStringInfo(buf, ", ");
5937 appendStringInfoString(buf,
5938 quote_identifier(strVal(lfirst(col))));
5941 appendStringInfoChar(buf, ')');
5945 * get_from_clause_coldeflist - reproduce FROM clause coldeflist
5947 * The coldeflist is appended immediately (no space) to buf. Caller is
5948 * responsible for ensuring that an alias or AS is present before it.
5951 get_from_clause_coldeflist(List *names, List *types, List *typmods,
5952 deparse_context *context)
5954 StringInfo buf = context->buf;
5960 appendStringInfoChar(buf, '(');
5962 l2 = list_head(types);
5963 l3 = list_head(typmods);
5966 char *attname = strVal(lfirst(l1));
5970 atttypid = lfirst_oid(l2);
5972 atttypmod = lfirst_int(l3);
5976 appendStringInfo(buf, ", ");
5977 appendStringInfo(buf, "%s %s",
5978 quote_identifier(attname),
5979 format_type_with_typemod(atttypid, atttypmod));
5983 appendStringInfoChar(buf, ')');
5987 * get_opclass_name - fetch name of an index operator class
5989 * The opclass name is appended (after a space) to buf.
5991 * Output is suppressed if the opclass is the default for the given
5992 * actual_datatype. (If you don't want this behavior, just pass
5993 * InvalidOid for actual_datatype.)
5996 get_opclass_name(Oid opclass, Oid actual_datatype,
6000 Form_pg_opclass opcrec;
6004 ht_opc = SearchSysCache(CLAOID,
6005 ObjectIdGetDatum(opclass),
6007 if (!HeapTupleIsValid(ht_opc))
6008 elog(ERROR, "cache lookup failed for opclass %u", opclass);
6009 opcrec = (Form_pg_opclass) GETSTRUCT(ht_opc);
6011 if (!OidIsValid(actual_datatype) ||
6012 GetDefaultOpClass(actual_datatype, opcrec->opcmethod) != opclass)
6014 /* Okay, we need the opclass name. Do we need to qualify it? */
6015 opcname = NameStr(opcrec->opcname);
6016 if (OpclassIsVisible(opclass))
6017 appendStringInfo(buf, " %s", quote_identifier(opcname));
6020 nspname = get_namespace_name(opcrec->opcnamespace);
6021 appendStringInfo(buf, " %s.%s",
6022 quote_identifier(nspname),
6023 quote_identifier(opcname));
6026 ReleaseSysCache(ht_opc);
6030 * processIndirection - take care of array and subfield assignment
6032 * We strip any top-level FieldStore or assignment ArrayRef nodes that
6033 * appear in the input, and return the subexpression that's to be assigned.
6034 * If printit is true, we also print out the appropriate decoration for the
6035 * base column name (that the caller just printed).
6038 processIndirection(Node *node, deparse_context *context, bool printit)
6040 StringInfo buf = context->buf;
6046 if (IsA(node, FieldStore))
6048 FieldStore *fstore = (FieldStore *) node;
6052 /* lookup tuple type */
6053 typrelid = get_typ_typrelid(fstore->resulttype);
6054 if (!OidIsValid(typrelid))
6055 elog(ERROR, "argument type %s of FieldStore is not a tuple type",
6056 format_type_be(fstore->resulttype));
6059 * Print the field name. Note we assume here that there's only
6060 * one field being assigned to. This is okay in stored rules but
6061 * could be wrong in executable target lists. Presently no
6062 * problem since explain.c doesn't print plan targetlists, but
6063 * someday may have to think of something ...
6065 fieldname = get_relid_attribute_name(typrelid,
6066 linitial_int(fstore->fieldnums));
6068 appendStringInfo(buf, ".%s", quote_identifier(fieldname));
6071 * We ignore arg since it should be an uninteresting reference to
6072 * the target column or subcolumn.
6074 node = (Node *) linitial(fstore->newvals);
6076 else if (IsA(node, ArrayRef))
6078 ArrayRef *aref = (ArrayRef *) node;
6080 if (aref->refassgnexpr == NULL)
6083 printSubscripts(aref, context);
6086 * We ignore refexpr since it should be an uninteresting reference
6087 * to the target column or subcolumn.
6089 node = (Node *) aref->refassgnexpr;
6099 printSubscripts(ArrayRef *aref, deparse_context *context)
6101 StringInfo buf = context->buf;
6102 ListCell *lowlist_item;
6103 ListCell *uplist_item;
6105 lowlist_item = list_head(aref->reflowerindexpr); /* could be NULL */
6106 foreach(uplist_item, aref->refupperindexpr)
6108 appendStringInfoChar(buf, '[');
6111 get_rule_expr((Node *) lfirst(lowlist_item), context, false);
6112 appendStringInfoChar(buf, ':');
6113 lowlist_item = lnext(lowlist_item);
6115 get_rule_expr((Node *) lfirst(uplist_item), context, false);
6116 appendStringInfoChar(buf, ']');
6121 * quote_identifier - Quote an identifier only if needed
6123 * When quotes are needed, we palloc the required space; slightly
6124 * space-wasteful but well worth it for notational simplicity.
6127 quote_identifier(const char *ident)
6130 * Can avoid quoting if ident starts with a lowercase letter or underscore
6131 * and contains only lowercase letters, digits, and underscores, *and* is
6132 * not any SQL keyword. Otherwise, supply quotes.
6141 * would like to use <ctype.h> macros here, but they might yield unwanted
6142 * locale-specific results...
6144 safe = ((ident[0] >= 'a' && ident[0] <= 'z') || ident[0] == '_');
6146 for (ptr = ident; *ptr; ptr++)
6150 if ((ch >= 'a' && ch <= 'z') ||
6151 (ch >= '0' && ch <= '9') ||
6167 * Check for keyword. We quote keywords except for unreserved ones.
6168 * (In some cases we could avoid quoting a col_name or type_func_name
6169 * keyword, but it seems much harder than it's worth to tell that.)
6171 * Note: ScanKeywordLookup() does case-insensitive comparison, but
6172 * that's fine, since we already know we have all-lower-case.
6174 const ScanKeyword *keyword = ScanKeywordLookup(ident);
6176 if (keyword != NULL && keyword->category != UNRESERVED_KEYWORD)
6181 return ident; /* no change needed */
6183 result = (char *) palloc(strlen(ident) + nquotes + 2 + 1);
6187 for (ptr = ident; *ptr; ptr++)
6202 * quote_qualified_identifier - Quote a possibly-qualified identifier
6204 * Return a name of the form namespace.ident, or just ident if namespace
6205 * is NULL, quoting each component if necessary. The result is palloc'd.
6208 quote_qualified_identifier(const char *namespace,
6213 initStringInfo(&buf);
6215 appendStringInfo(&buf, "%s.", quote_identifier(namespace));
6216 appendStringInfoString(&buf, quote_identifier(ident));
6221 * generate_relation_name
6222 * Compute the name to display for a relation specified by OID
6224 * The result includes all necessary quoting and schema-prefixing.
6226 * If namespaces isn't NIL, it must be a list of deparse_namespace nodes.
6227 * We will forcibly qualify the relation name if it equals any CTE name
6228 * visible in the namespace list.
6231 generate_relation_name(Oid relid, List *namespaces)
6234 Form_pg_class reltup;
6241 tp = SearchSysCache(RELOID,
6242 ObjectIdGetDatum(relid),
6244 if (!HeapTupleIsValid(tp))
6245 elog(ERROR, "cache lookup failed for relation %u", relid);
6246 reltup = (Form_pg_class) GETSTRUCT(tp);
6247 relname = NameStr(reltup->relname);
6249 /* Check for conflicting CTE name */
6251 foreach(nslist, namespaces)
6253 deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist);
6256 foreach(ctlist, dpns->ctes)
6258 CommonTableExpr *cte = (CommonTableExpr *) lfirst(ctlist);
6260 if (strcmp(cte->ctename, relname) == 0)
6270 /* Otherwise, qualify the name if not visible in search path */
6272 need_qual = !RelationIsVisible(relid);
6275 nspname = get_namespace_name(reltup->relnamespace);
6279 result = quote_qualified_identifier(nspname, relname);
6281 ReleaseSysCache(tp);
6287 * generate_function_name
6288 * Compute the name to display for a function specified by OID,
6289 * given that it is being called with the specified actual arg types.
6290 * (Arg types matter because of ambiguous-function resolution rules.)
6292 * The result includes all necessary quoting and schema-prefixing. We can
6293 * also pass back an indication of whether the function is variadic.
6296 generate_function_name(Oid funcid, int nargs, Oid *argtypes,
6300 Form_pg_proc procform;
6304 FuncDetailCode p_result;
6309 Oid *p_true_typeids;
6311 proctup = SearchSysCache(PROCOID,
6312 ObjectIdGetDatum(funcid),
6314 if (!HeapTupleIsValid(proctup))
6315 elog(ERROR, "cache lookup failed for function %u", funcid);
6316 procform = (Form_pg_proc) GETSTRUCT(proctup);
6317 proname = NameStr(procform->proname);
6320 * The idea here is to schema-qualify only if the parser would fail to
6321 * resolve the correct function given the unqualified func name with the
6322 * specified argtypes.
6324 p_result = func_get_detail(list_make1(makeString(proname)),
6325 NIL, nargs, argtypes, false, true,
6326 &p_funcid, &p_rettype,
6327 &p_retset, &p_nvargs, &p_true_typeids, NULL);
6328 if ((p_result == FUNCDETAIL_NORMAL ||
6329 p_result == FUNCDETAIL_AGGREGATE ||
6330 p_result == FUNCDETAIL_WINDOWFUNC) &&
6334 nspname = get_namespace_name(procform->pronamespace);
6336 result = quote_qualified_identifier(nspname, proname);
6338 /* Check variadic-ness if caller cares */
6341 /* "any" variadics are not treated as variadics for listing */
6342 if (OidIsValid(procform->provariadic) &&
6343 procform->provariadic != ANYOID)
6344 *is_variadic = true;
6346 *is_variadic = false;
6349 ReleaseSysCache(proctup);
6355 * generate_operator_name
6356 * Compute the name to display for an operator specified by OID,
6357 * given that it is being called with the specified actual arg types.
6358 * (Arg types matter because of ambiguous-operator resolution rules.
6359 * Pass InvalidOid for unused arg of a unary operator.)
6361 * The result includes all necessary quoting and schema-prefixing,
6362 * plus the OPERATOR() decoration needed to use a qualified operator name
6366 generate_operator_name(Oid operid, Oid arg1, Oid arg2)
6370 Form_pg_operator operform;
6375 initStringInfo(&buf);
6377 opertup = SearchSysCache(OPEROID,
6378 ObjectIdGetDatum(operid),
6380 if (!HeapTupleIsValid(opertup))
6381 elog(ERROR, "cache lookup failed for operator %u", operid);
6382 operform = (Form_pg_operator) GETSTRUCT(opertup);
6383 oprname = NameStr(operform->oprname);
6386 * The idea here is to schema-qualify only if the parser would fail to
6387 * resolve the correct operator given the unqualified op name with the
6388 * specified argtypes.
6390 switch (operform->oprkind)
6393 p_result = oper(NULL, list_make1(makeString(oprname)), arg1, arg2,
6397 p_result = left_oper(NULL, list_make1(makeString(oprname)), arg2,
6401 p_result = right_oper(NULL, list_make1(makeString(oprname)), arg1,
6405 elog(ERROR, "unrecognized oprkind: %d", operform->oprkind);
6406 p_result = NULL; /* keep compiler quiet */
6410 if (p_result != NULL && oprid(p_result) == operid)
6414 nspname = get_namespace_name(operform->oprnamespace);
6415 appendStringInfo(&buf, "OPERATOR(%s.", quote_identifier(nspname));
6418 appendStringInfoString(&buf, oprname);
6421 appendStringInfoChar(&buf, ')');
6423 if (p_result != NULL)
6424 ReleaseSysCache(p_result);
6426 ReleaseSysCache(opertup);
6432 * Given a C string, produce a TEXT datum.
6434 * We assume that the input was palloc'd and may be freed.
6437 string_to_text(char *str)
6441 result = cstring_to_text(str);
6447 * Generate a C string representing a relation's reloptions, or NULL if none.
6450 flatten_reloptions(Oid relid)
6452 char *result = NULL;
6457 tuple = SearchSysCache(RELOID,
6458 ObjectIdGetDatum(relid),
6460 if (!HeapTupleIsValid(tuple))
6461 elog(ERROR, "cache lookup failed for relation %u", relid);
6463 reloptions = SysCacheGetAttr(RELOID, tuple,
6464 Anum_pg_class_reloptions, &isnull);
6471 * We want to use array_to_text(reloptions, ', ') --- but
6472 * DirectFunctionCall2(array_to_text) does not work, because
6473 * array_to_text() relies on flinfo to be valid. So use
6476 sep = CStringGetTextDatum(", ");
6477 txt = OidFunctionCall2(F_ARRAY_TO_TEXT, reloptions, sep);
6478 result = TextDatumGetCString(txt);
6481 ReleaseSysCache(tuple);