1 /*-------------------------------------------------------------------------
4 * Functions to convert stored expressions/querytrees back to
7 * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
12 * src/backend/utils/adt/ruleutils.c
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/keywords.h"
43 #include "parser/parse_func.h"
44 #include "parser/parse_oper.h"
45 #include "parser/parser.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 * When deparsing plan trees, there is always just a single item in the
106 * deparse_namespace list (since a plan tree never contains Vars with
107 * varlevelsup > 0). We store the PlanState node that is the immediate
108 * parent of the expression to be deparsed, as well as a list of that
109 * PlanState's ancestors. In addition, we store the outer and inner
110 * subplan nodes, whose targetlists are used to resolve OUTER and INNER Vars.
111 * (Note: these could be derived on-the-fly from the planstate instead.)
115 List *rtable; /* List of RangeTblEntry nodes */
116 List *ctes; /* List of CommonTableExpr nodes */
117 /* Remaining fields are used only when deparsing a Plan tree: */
118 PlanState *planstate; /* immediate parent of current expression */
119 List *ancestors; /* ancestors of planstate */
120 PlanState *outer_planstate; /* OUTER subplan state, or NULL if none */
121 PlanState *inner_planstate; /* INNER subplan state, or NULL if none */
122 Plan *outer_plan; /* OUTER subplan, or NULL if none */
123 Plan *inner_plan; /* INNER subplan, or NULL if none */
131 static SPIPlanPtr plan_getrulebyoid = NULL;
132 static const char *query_getrulebyoid = "SELECT * FROM pg_catalog.pg_rewrite WHERE oid = $1";
133 static SPIPlanPtr plan_getviewrule = NULL;
134 static const char *query_getviewrule = "SELECT * FROM pg_catalog.pg_rewrite WHERE ev_class = $1 AND rulename = $2";
137 bool quote_all_identifiers = false;
143 * Most of these functions used to use fixed-size buffers to build their
144 * results. Now, they take an (already initialized) StringInfo object
145 * as a parameter, and append their text output to its contents.
148 static char *deparse_expression_pretty(Node *expr, List *dpcontext,
149 bool forceprefix, bool showimplicit,
150 int prettyFlags, int startIndent);
151 static char *pg_get_viewdef_worker(Oid viewoid, int prettyFlags);
152 static char *pg_get_triggerdef_worker(Oid trigid, bool pretty);
153 static void decompile_column_index_array(Datum column_index_array, Oid relId,
155 static char *pg_get_ruledef_worker(Oid ruleoid, int prettyFlags);
156 static char *pg_get_indexdef_worker(Oid indexrelid, int colno,
157 const Oid *excludeOps,
158 bool attrsOnly, bool showTblSpc,
160 static char *pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
162 static text *pg_get_expr_worker(text *expr, Oid relid, const char *relname,
164 static int print_function_arguments(StringInfo buf, HeapTuple proctup,
165 bool print_table_args, bool print_defaults);
166 static void print_function_rettype(StringInfo buf, HeapTuple proctup);
167 static void set_deparse_planstate(deparse_namespace *dpns, PlanState *ps);
168 static void push_child_plan(deparse_namespace *dpns, PlanState *ps,
169 deparse_namespace *save_dpns);
170 static void pop_child_plan(deparse_namespace *dpns,
171 deparse_namespace *save_dpns);
172 static void push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell,
173 deparse_namespace *save_dpns);
174 static void pop_ancestor_plan(deparse_namespace *dpns,
175 deparse_namespace *save_dpns);
176 static void make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
178 static void make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
180 static void get_query_def(Query *query, StringInfo buf, List *parentnamespace,
181 TupleDesc resultDesc, int prettyFlags, int startIndent);
182 static void get_values_def(List *values_lists, deparse_context *context);
183 static void get_with_clause(Query *query, deparse_context *context);
184 static void get_select_query_def(Query *query, deparse_context *context,
185 TupleDesc resultDesc);
186 static void get_insert_query_def(Query *query, deparse_context *context);
187 static void get_update_query_def(Query *query, deparse_context *context);
188 static void get_delete_query_def(Query *query, deparse_context *context);
189 static void get_utility_query_def(Query *query, deparse_context *context);
190 static void get_basic_select_query(Query *query, deparse_context *context,
191 TupleDesc resultDesc);
192 static void get_target_list(List *targetList, deparse_context *context,
193 TupleDesc resultDesc);
194 static void get_setop_query(Node *setOp, Query *query,
195 deparse_context *context,
196 TupleDesc resultDesc);
197 static Node *get_rule_sortgroupclause(SortGroupClause *srt, List *tlist,
199 deparse_context *context);
200 static void get_rule_orderby(List *orderList, List *targetList,
201 bool force_colno, deparse_context *context);
202 static void get_rule_windowclause(Query *query, deparse_context *context);
203 static void get_rule_windowspec(WindowClause *wc, List *targetList,
204 deparse_context *context);
205 static char *get_variable(Var *var, int levelsup, bool showstar,
206 deparse_context *context);
207 static RangeTblEntry *find_rte_by_refname(const char *refname,
208 deparse_context *context);
209 static void get_parameter(Param *param, deparse_context *context);
210 static void print_parameter_expr(Node *expr, ListCell *ancestor_cell,
211 deparse_namespace *dpns, deparse_context *context);
212 static const char *get_simple_binary_op_name(OpExpr *expr);
213 static bool isSimpleNode(Node *node, Node *parentNode, int prettyFlags);
214 static void appendContextKeyword(deparse_context *context, const char *str,
215 int indentBefore, int indentAfter, int indentPlus);
216 static void get_rule_expr(Node *node, deparse_context *context,
218 static void get_oper_expr(OpExpr *expr, deparse_context *context);
219 static void get_func_expr(FuncExpr *expr, deparse_context *context,
221 static void get_agg_expr(Aggref *aggref, deparse_context *context);
222 static void get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context);
223 static void get_coercion_expr(Node *arg, deparse_context *context,
224 Oid resulttype, int32 resulttypmod,
226 static void get_const_expr(Const *constval, deparse_context *context,
228 static void simple_quote_literal(StringInfo buf, const char *val);
229 static void get_sublink_expr(SubLink *sublink, deparse_context *context);
230 static void get_from_clause(Query *query, const char *prefix,
231 deparse_context *context);
232 static void get_from_clause_item(Node *jtnode, Query *query,
233 deparse_context *context);
234 static void get_from_clause_alias(Alias *alias, RangeTblEntry *rte,
235 deparse_context *context);
236 static void get_from_clause_coldeflist(List *names, List *types, List *typmods,
237 deparse_context *context);
238 static void get_opclass_name(Oid opclass, Oid actual_datatype,
240 static Node *processIndirection(Node *node, deparse_context *context,
242 static void printSubscripts(ArrayRef *aref, deparse_context *context);
243 static char *generate_relation_name(Oid relid, List *namespaces);
244 static char *generate_function_name(Oid funcid, int nargs, List *argnames,
245 Oid *argtypes, bool *is_variadic);
246 static char *generate_operator_name(Oid operid, Oid arg1, Oid arg2);
247 static text *string_to_text(char *str);
248 static char *flatten_reloptions(Oid relid);
250 #define only_marker(rte) ((rte)->inh ? "" : "ONLY ")
254 * get_ruledef - Do it all and return a text
255 * that could be used as a statement
256 * to recreate the rule
260 pg_get_ruledef(PG_FUNCTION_ARGS)
262 Oid ruleoid = PG_GETARG_OID(0);
264 PG_RETURN_TEXT_P(string_to_text(pg_get_ruledef_worker(ruleoid, 0)));
269 pg_get_ruledef_ext(PG_FUNCTION_ARGS)
271 Oid ruleoid = PG_GETARG_OID(0);
272 bool pretty = PG_GETARG_BOOL(1);
275 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
276 PG_RETURN_TEXT_P(string_to_text(pg_get_ruledef_worker(ruleoid, prettyFlags)));
281 pg_get_ruledef_worker(Oid ruleoid, int prettyFlags)
291 * Do this first so that string is alloc'd in outer context not SPI's.
293 initStringInfo(&buf);
296 * Connect to SPI manager
298 if (SPI_connect() != SPI_OK_CONNECT)
299 elog(ERROR, "SPI_connect failed");
302 * On the first call prepare the plan to lookup pg_rewrite. We read
303 * pg_rewrite over the SPI manager instead of using the syscache to be
304 * checked for read access on pg_rewrite.
306 if (plan_getrulebyoid == NULL)
311 argtypes[0] = OIDOID;
312 plan = SPI_prepare(query_getrulebyoid, 1, argtypes);
314 elog(ERROR, "SPI_prepare failed for \"%s\"", query_getrulebyoid);
315 plan_getrulebyoid = SPI_saveplan(plan);
319 * Get the pg_rewrite tuple for this rule
321 args[0] = ObjectIdGetDatum(ruleoid);
323 spirc = SPI_execute_plan(plan_getrulebyoid, args, nulls, true, 1);
324 if (spirc != SPI_OK_SELECT)
325 elog(ERROR, "failed to get pg_rewrite tuple for rule %u", ruleoid);
326 if (SPI_processed != 1)
327 appendStringInfo(&buf, "-");
331 * Get the rule's definition and put it into executor's memory
333 ruletup = SPI_tuptable->vals[0];
334 rulettc = SPI_tuptable->tupdesc;
335 make_ruledef(&buf, ruletup, rulettc, prettyFlags);
339 * Disconnect from SPI manager
341 if (SPI_finish() != SPI_OK_FINISH)
342 elog(ERROR, "SPI_finish failed");
349 * get_viewdef - Mainly the same thing, but we
350 * only return the SELECT part of a view
354 pg_get_viewdef(PG_FUNCTION_ARGS)
357 Oid viewoid = PG_GETARG_OID(0);
359 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, 0)));
364 pg_get_viewdef_ext(PG_FUNCTION_ARGS)
367 Oid viewoid = PG_GETARG_OID(0);
368 bool pretty = PG_GETARG_BOOL(1);
371 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
372 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, prettyFlags)));
376 pg_get_viewdef_name(PG_FUNCTION_ARGS)
378 /* By qualified name */
379 text *viewname = PG_GETARG_TEXT_P(0);
383 viewrel = makeRangeVarFromNameList(textToQualifiedNameList(viewname));
384 viewoid = RangeVarGetRelid(viewrel, false);
386 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, 0)));
391 pg_get_viewdef_name_ext(PG_FUNCTION_ARGS)
393 /* By qualified name */
394 text *viewname = PG_GETARG_TEXT_P(0);
395 bool pretty = PG_GETARG_BOOL(1);
400 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
401 viewrel = makeRangeVarFromNameList(textToQualifiedNameList(viewname));
402 viewoid = RangeVarGetRelid(viewrel, false);
404 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, prettyFlags)));
408 * Common code for by-OID and by-name variants of pg_get_viewdef
411 pg_get_viewdef_worker(Oid viewoid, int prettyFlags)
421 * Do this first so that string is alloc'd in outer context not SPI's.
423 initStringInfo(&buf);
426 * Connect to SPI manager
428 if (SPI_connect() != SPI_OK_CONNECT)
429 elog(ERROR, "SPI_connect failed");
432 * On the first call prepare the plan to lookup pg_rewrite. We read
433 * pg_rewrite over the SPI manager instead of using the syscache to be
434 * checked for read access on pg_rewrite.
436 if (plan_getviewrule == NULL)
441 argtypes[0] = OIDOID;
442 argtypes[1] = NAMEOID;
443 plan = SPI_prepare(query_getviewrule, 2, argtypes);
445 elog(ERROR, "SPI_prepare failed for \"%s\"", query_getviewrule);
446 plan_getviewrule = SPI_saveplan(plan);
450 * Get the pg_rewrite tuple for the view's SELECT rule
452 args[0] = ObjectIdGetDatum(viewoid);
453 args[1] = PointerGetDatum(ViewSelectRuleName);
456 spirc = SPI_execute_plan(plan_getviewrule, args, nulls, true, 2);
457 if (spirc != SPI_OK_SELECT)
458 elog(ERROR, "failed to get pg_rewrite tuple for view %u", viewoid);
459 if (SPI_processed != 1)
460 appendStringInfo(&buf, "Not a view");
464 * Get the rule's definition and put it into executor's memory
466 ruletup = SPI_tuptable->vals[0];
467 rulettc = SPI_tuptable->tupdesc;
468 make_viewdef(&buf, ruletup, rulettc, prettyFlags);
472 * Disconnect from SPI manager
474 if (SPI_finish() != SPI_OK_FINISH)
475 elog(ERROR, "SPI_finish failed");
481 * get_triggerdef - Get the definition of a trigger
485 pg_get_triggerdef(PG_FUNCTION_ARGS)
487 Oid trigid = PG_GETARG_OID(0);
489 PG_RETURN_TEXT_P(string_to_text(pg_get_triggerdef_worker(trigid, false)));
493 pg_get_triggerdef_ext(PG_FUNCTION_ARGS)
495 Oid trigid = PG_GETARG_OID(0);
496 bool pretty = PG_GETARG_BOOL(1);
498 PG_RETURN_TEXT_P(string_to_text(pg_get_triggerdef_worker(trigid, pretty)));
502 pg_get_triggerdef_worker(Oid trigid, bool pretty)
505 Form_pg_trigger trigrec;
516 * Fetch the pg_trigger tuple by the Oid of the trigger
518 tgrel = heap_open(TriggerRelationId, AccessShareLock);
520 ScanKeyInit(&skey[0],
521 ObjectIdAttributeNumber,
522 BTEqualStrategyNumber, F_OIDEQ,
523 ObjectIdGetDatum(trigid));
525 tgscan = systable_beginscan(tgrel, TriggerOidIndexId, true,
526 SnapshotNow, 1, skey);
528 ht_trig = systable_getnext(tgscan);
530 if (!HeapTupleIsValid(ht_trig))
531 elog(ERROR, "could not find tuple for trigger %u", trigid);
533 trigrec = (Form_pg_trigger) GETSTRUCT(ht_trig);
536 * Start the trigger definition. Note that the trigger's name should never
537 * be schema-qualified, but the trigger rel's name may be.
539 initStringInfo(&buf);
541 tgname = NameStr(trigrec->tgname);
542 appendStringInfo(&buf, "CREATE %sTRIGGER %s ",
543 OidIsValid(trigrec->tgconstraint) ? "CONSTRAINT " : "",
544 quote_identifier(tgname));
546 if (TRIGGER_FOR_BEFORE(trigrec->tgtype))
547 appendStringInfo(&buf, "BEFORE");
548 else if (TRIGGER_FOR_AFTER(trigrec->tgtype))
549 appendStringInfo(&buf, "AFTER");
550 else if (TRIGGER_FOR_INSTEAD(trigrec->tgtype))
551 appendStringInfo(&buf, "INSTEAD OF");
553 elog(ERROR, "unexpected tgtype value: %d", trigrec->tgtype);
555 if (TRIGGER_FOR_INSERT(trigrec->tgtype))
557 appendStringInfo(&buf, " INSERT");
560 if (TRIGGER_FOR_DELETE(trigrec->tgtype))
563 appendStringInfo(&buf, " OR DELETE");
565 appendStringInfo(&buf, " DELETE");
568 if (TRIGGER_FOR_UPDATE(trigrec->tgtype))
571 appendStringInfo(&buf, " OR UPDATE");
573 appendStringInfo(&buf, " UPDATE");
575 /* tgattr is first var-width field, so OK to access directly */
576 if (trigrec->tgattr.dim1 > 0)
580 appendStringInfoString(&buf, " OF ");
581 for (i = 0; i < trigrec->tgattr.dim1; i++)
586 appendStringInfoString(&buf, ", ");
587 attname = get_relid_attribute_name(trigrec->tgrelid,
588 trigrec->tgattr.values[i]);
589 appendStringInfoString(&buf, quote_identifier(attname));
593 if (TRIGGER_FOR_TRUNCATE(trigrec->tgtype))
596 appendStringInfo(&buf, " OR TRUNCATE");
598 appendStringInfo(&buf, " TRUNCATE");
601 appendStringInfo(&buf, " ON %s ",
602 generate_relation_name(trigrec->tgrelid, NIL));
604 if (OidIsValid(trigrec->tgconstraint))
606 if (OidIsValid(trigrec->tgconstrrelid))
607 appendStringInfo(&buf, "FROM %s ",
608 generate_relation_name(trigrec->tgconstrrelid, NIL));
609 if (!trigrec->tgdeferrable)
610 appendStringInfo(&buf, "NOT ");
611 appendStringInfo(&buf, "DEFERRABLE INITIALLY ");
612 if (trigrec->tginitdeferred)
613 appendStringInfo(&buf, "DEFERRED ");
615 appendStringInfo(&buf, "IMMEDIATE ");
618 if (TRIGGER_FOR_ROW(trigrec->tgtype))
619 appendStringInfo(&buf, "FOR EACH ROW ");
621 appendStringInfo(&buf, "FOR EACH STATEMENT ");
623 /* If the trigger has a WHEN qualification, add that */
624 value = fastgetattr(ht_trig, Anum_pg_trigger_tgqual,
625 tgrel->rd_att, &isnull);
629 deparse_context context;
630 deparse_namespace dpns;
631 RangeTblEntry *oldrte;
632 RangeTblEntry *newrte;
634 appendStringInfoString(&buf, "WHEN (");
636 qual = stringToNode(TextDatumGetCString(value));
638 /* Build minimal OLD and NEW RTEs for the rel */
639 oldrte = makeNode(RangeTblEntry);
640 oldrte->rtekind = RTE_RELATION;
641 oldrte->relid = trigrec->tgrelid;
642 oldrte->eref = makeAlias("old", NIL);
644 oldrte->inFromCl = true;
646 newrte = makeNode(RangeTblEntry);
647 newrte->rtekind = RTE_RELATION;
648 newrte->relid = trigrec->tgrelid;
649 newrte->eref = makeAlias("new", NIL);
651 newrte->inFromCl = true;
653 /* Build two-element rtable */
654 memset(&dpns, 0, sizeof(dpns));
655 dpns.rtable = list_make2(oldrte, newrte);
658 /* Set up context with one-deep namespace stack */
660 context.namespaces = list_make1(&dpns);
661 context.windowClause = NIL;
662 context.windowTList = NIL;
663 context.varprefix = true;
664 context.prettyFlags = pretty ? PRETTYFLAG_PAREN : 0;
665 context.indentLevel = PRETTYINDENT_STD;
667 get_rule_expr(qual, &context, false);
669 appendStringInfo(&buf, ") ");
672 appendStringInfo(&buf, "EXECUTE PROCEDURE %s(",
673 generate_function_name(trigrec->tgfoid, 0,
676 if (trigrec->tgnargs > 0)
681 value = fastgetattr(ht_trig, Anum_pg_trigger_tgargs,
682 tgrel->rd_att, &isnull);
684 elog(ERROR, "tgargs is null for trigger %u", trigid);
685 p = (char *) VARDATA(DatumGetByteaP(value));
686 for (i = 0; i < trigrec->tgnargs; i++)
689 appendStringInfo(&buf, ", ");
690 simple_quote_literal(&buf, p);
691 /* advance p to next string embedded in tgargs */
698 /* We deliberately do not put semi-colon at end */
699 appendStringInfo(&buf, ")");
702 systable_endscan(tgscan);
704 heap_close(tgrel, AccessShareLock);
710 * get_indexdef - Get the definition of an index
712 * In the extended version, there is a colno argument as well as pretty bool.
713 * if colno == 0, we want a complete index definition.
714 * if colno > 0, we only want the Nth index key's variable or expression.
716 * Note that the SQL-function versions of this omit any info about the
717 * index tablespace; this is intentional because pg_dump wants it that way.
718 * However pg_get_indexdef_string() includes index tablespace if not default.
722 pg_get_indexdef(PG_FUNCTION_ARGS)
724 Oid indexrelid = PG_GETARG_OID(0);
726 PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, 0,
732 pg_get_indexdef_ext(PG_FUNCTION_ARGS)
734 Oid indexrelid = PG_GETARG_OID(0);
735 int32 colno = PG_GETARG_INT32(1);
736 bool pretty = PG_GETARG_BOOL(2);
739 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
740 PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, colno,
747 /* Internal version that returns a palloc'd C string */
749 pg_get_indexdef_string(Oid indexrelid)
751 return pg_get_indexdef_worker(indexrelid, 0, NULL, false, true, 0);
754 /* Internal version that just reports the column definitions */
756 pg_get_indexdef_columns(Oid indexrelid, bool pretty)
760 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
761 return pg_get_indexdef_worker(indexrelid, 0, NULL, true, false, prettyFlags);
765 * Internal workhorse to decompile an index definition.
767 * This is now used for exclusion constraints as well: if excludeOps is not
768 * NULL then it points to an array of exclusion operator OIDs.
771 pg_get_indexdef_worker(Oid indexrelid, int colno,
772 const Oid *excludeOps,
773 bool attrsOnly, bool showTblSpc,
776 /* might want a separate isConstraint parameter later */
777 bool isConstraint = (excludeOps != NULL);
781 Form_pg_index idxrec;
782 Form_pg_class idxrelrec;
785 ListCell *indexpr_item;
791 Datum indoptionDatum;
794 int2vector *indoption;
800 * Fetch the pg_index tuple by the Oid of the index
802 ht_idx = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexrelid));
803 if (!HeapTupleIsValid(ht_idx))
804 elog(ERROR, "cache lookup failed for index %u", indexrelid);
805 idxrec = (Form_pg_index) GETSTRUCT(ht_idx);
807 indrelid = idxrec->indrelid;
808 Assert(indexrelid == idxrec->indexrelid);
810 /* Must get indclass and indoption the hard way */
811 indclassDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
812 Anum_pg_index_indclass, &isnull);
814 indclass = (oidvector *) DatumGetPointer(indclassDatum);
815 indoptionDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
816 Anum_pg_index_indoption, &isnull);
818 indoption = (int2vector *) DatumGetPointer(indoptionDatum);
821 * Fetch the pg_class tuple of the index relation
823 ht_idxrel = SearchSysCache1(RELOID, ObjectIdGetDatum(indexrelid));
824 if (!HeapTupleIsValid(ht_idxrel))
825 elog(ERROR, "cache lookup failed for relation %u", indexrelid);
826 idxrelrec = (Form_pg_class) GETSTRUCT(ht_idxrel);
829 * Fetch the pg_am tuple of the index' access method
831 ht_am = SearchSysCache1(AMOID, ObjectIdGetDatum(idxrelrec->relam));
832 if (!HeapTupleIsValid(ht_am))
833 elog(ERROR, "cache lookup failed for access method %u",
835 amrec = (Form_pg_am) GETSTRUCT(ht_am);
838 * Get the index expressions, if any. (NOTE: we do not use the relcache
839 * versions of the expressions and predicate, because we want to display
840 * non-const-folded expressions.)
842 if (!heap_attisnull(ht_idx, Anum_pg_index_indexprs))
848 exprsDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
849 Anum_pg_index_indexprs, &isnull);
851 exprsString = TextDatumGetCString(exprsDatum);
852 indexprs = (List *) stringToNode(exprsString);
858 indexpr_item = list_head(indexprs);
860 context = deparse_context_for(get_rel_name(indrelid), indrelid);
863 * Start the index definition. Note that the index's name should never be
864 * schema-qualified, but the indexed rel's name may be.
866 initStringInfo(&buf);
871 appendStringInfo(&buf, "CREATE %sINDEX %s ON %s USING %s (",
872 idxrec->indisunique ? "UNIQUE " : "",
873 quote_identifier(NameStr(idxrelrec->relname)),
874 generate_relation_name(indrelid, NIL),
875 quote_identifier(NameStr(amrec->amname)));
876 else /* currently, must be EXCLUDE constraint */
877 appendStringInfo(&buf, "EXCLUDE USING %s (",
878 quote_identifier(NameStr(amrec->amname)));
882 * Report the indexed attributes
885 for (keyno = 0; keyno < idxrec->indnatts; keyno++)
887 AttrNumber attnum = idxrec->indkey.values[keyno];
888 int16 opt = indoption->values[keyno];
891 appendStringInfoString(&buf, sep);
896 /* Simple index column */
899 attname = get_relid_attribute_name(indrelid, attnum);
900 if (!colno || colno == keyno + 1)
901 appendStringInfoString(&buf, quote_identifier(attname));
902 keycoltype = get_atttype(indrelid, attnum);
906 /* expressional index */
909 if (indexpr_item == NULL)
910 elog(ERROR, "too few entries in indexprs list");
911 indexkey = (Node *) lfirst(indexpr_item);
912 indexpr_item = lnext(indexpr_item);
914 str = deparse_expression_pretty(indexkey, context, false, false,
916 if (!colno || colno == keyno + 1)
918 /* Need parens if it's not a bare function call */
919 if (indexkey && IsA(indexkey, FuncExpr) &&
920 ((FuncExpr *) indexkey)->funcformat == COERCE_EXPLICIT_CALL)
921 appendStringInfoString(&buf, str);
923 appendStringInfo(&buf, "(%s)", str);
925 keycoltype = exprType(indexkey);
928 if (!attrsOnly && (!colno || colno == keyno + 1))
930 /* Add the operator class name, if not default */
931 get_opclass_name(indclass->values[keyno], keycoltype, &buf);
933 /* Add options if relevant */
934 if (amrec->amcanorder)
936 /* if it supports sort ordering, report DESC and NULLS opts */
937 if (opt & INDOPTION_DESC)
939 appendStringInfo(&buf, " DESC");
940 /* NULLS FIRST is the default in this case */
941 if (!(opt & INDOPTION_NULLS_FIRST))
942 appendStringInfo(&buf, " NULLS LAST");
946 if (opt & INDOPTION_NULLS_FIRST)
947 appendStringInfo(&buf, " NULLS FIRST");
951 /* Add the exclusion operator if relevant */
952 if (excludeOps != NULL)
953 appendStringInfo(&buf, " WITH %s",
954 generate_operator_name(excludeOps[keyno],
962 appendStringInfoChar(&buf, ')');
965 * If it has options, append "WITH (options)"
967 str = flatten_reloptions(indexrelid);
970 appendStringInfo(&buf, " WITH (%s)", str);
975 * If it's in a nondefault tablespace, say so, but only if requested
981 tblspc = get_rel_tablespace(indexrelid);
982 if (OidIsValid(tblspc))
985 appendStringInfoString(&buf, " USING INDEX");
986 appendStringInfo(&buf, " TABLESPACE %s",
987 quote_identifier(get_tablespace_name(tblspc)));
992 * If it's a partial index, decompile and append the predicate
994 if (!heap_attisnull(ht_idx, Anum_pg_index_indpred))
1001 /* Convert text string to node tree */
1002 predDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
1003 Anum_pg_index_indpred, &isnull);
1005 predString = TextDatumGetCString(predDatum);
1006 node = (Node *) stringToNode(predString);
1010 str = deparse_expression_pretty(node, context, false, false,
1013 appendStringInfo(&buf, " WHERE (%s)", str);
1015 appendStringInfo(&buf, " WHERE %s", str);
1020 ReleaseSysCache(ht_idx);
1021 ReleaseSysCache(ht_idxrel);
1022 ReleaseSysCache(ht_am);
1029 * pg_get_constraintdef
1031 * Returns the definition for the constraint, ie, everything that needs to
1032 * appear after "ALTER TABLE ... ADD CONSTRAINT <constraintname>".
1035 pg_get_constraintdef(PG_FUNCTION_ARGS)
1037 Oid constraintId = PG_GETARG_OID(0);
1039 PG_RETURN_TEXT_P(string_to_text(pg_get_constraintdef_worker(constraintId,
1044 pg_get_constraintdef_ext(PG_FUNCTION_ARGS)
1046 Oid constraintId = PG_GETARG_OID(0);
1047 bool pretty = PG_GETARG_BOOL(1);
1050 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
1051 PG_RETURN_TEXT_P(string_to_text(pg_get_constraintdef_worker(constraintId,
1052 false, prettyFlags)));
1055 /* Internal version that returns a palloc'd C string */
1057 pg_get_constraintdef_string(Oid constraintId)
1059 return pg_get_constraintdef_worker(constraintId, true, 0);
1063 pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
1067 Form_pg_constraint conForm;
1070 tup = SearchSysCache1(CONSTROID, ObjectIdGetDatum(constraintId));
1071 if (!HeapTupleIsValid(tup)) /* should not happen */
1072 elog(ERROR, "cache lookup failed for constraint %u", constraintId);
1073 conForm = (Form_pg_constraint) GETSTRUCT(tup);
1075 initStringInfo(&buf);
1077 if (fullCommand && OidIsValid(conForm->conrelid))
1079 appendStringInfo(&buf, "ALTER TABLE ONLY %s ADD CONSTRAINT %s ",
1080 generate_relation_name(conForm->conrelid, NIL),
1081 quote_identifier(NameStr(conForm->conname)));
1084 switch (conForm->contype)
1086 case CONSTRAINT_FOREIGN:
1092 /* Start off the constraint definition */
1093 appendStringInfo(&buf, "FOREIGN KEY (");
1095 /* Fetch and build referencing-column list */
1096 val = SysCacheGetAttr(CONSTROID, tup,
1097 Anum_pg_constraint_conkey, &isnull);
1099 elog(ERROR, "null conkey for constraint %u",
1102 decompile_column_index_array(val, conForm->conrelid, &buf);
1104 /* add foreign relation name */
1105 appendStringInfo(&buf, ") REFERENCES %s(",
1106 generate_relation_name(conForm->confrelid,
1109 /* Fetch and build referenced-column list */
1110 val = SysCacheGetAttr(CONSTROID, tup,
1111 Anum_pg_constraint_confkey, &isnull);
1113 elog(ERROR, "null confkey for constraint %u",
1116 decompile_column_index_array(val, conForm->confrelid, &buf);
1118 appendStringInfo(&buf, ")");
1120 /* Add match type */
1121 switch (conForm->confmatchtype)
1123 case FKCONSTR_MATCH_FULL:
1124 string = " MATCH FULL";
1126 case FKCONSTR_MATCH_PARTIAL:
1127 string = " MATCH PARTIAL";
1129 case FKCONSTR_MATCH_UNSPECIFIED:
1133 elog(ERROR, "unrecognized confmatchtype: %d",
1134 conForm->confmatchtype);
1135 string = ""; /* keep compiler quiet */
1138 appendStringInfoString(&buf, string);
1140 /* Add ON UPDATE and ON DELETE clauses, if needed */
1141 switch (conForm->confupdtype)
1143 case FKCONSTR_ACTION_NOACTION:
1144 string = NULL; /* suppress default */
1146 case FKCONSTR_ACTION_RESTRICT:
1147 string = "RESTRICT";
1149 case FKCONSTR_ACTION_CASCADE:
1152 case FKCONSTR_ACTION_SETNULL:
1153 string = "SET NULL";
1155 case FKCONSTR_ACTION_SETDEFAULT:
1156 string = "SET DEFAULT";
1159 elog(ERROR, "unrecognized confupdtype: %d",
1160 conForm->confupdtype);
1161 string = NULL; /* keep compiler quiet */
1165 appendStringInfo(&buf, " ON UPDATE %s", string);
1167 switch (conForm->confdeltype)
1169 case FKCONSTR_ACTION_NOACTION:
1170 string = NULL; /* suppress default */
1172 case FKCONSTR_ACTION_RESTRICT:
1173 string = "RESTRICT";
1175 case FKCONSTR_ACTION_CASCADE:
1178 case FKCONSTR_ACTION_SETNULL:
1179 string = "SET NULL";
1181 case FKCONSTR_ACTION_SETDEFAULT:
1182 string = "SET DEFAULT";
1185 elog(ERROR, "unrecognized confdeltype: %d",
1186 conForm->confdeltype);
1187 string = NULL; /* keep compiler quiet */
1191 appendStringInfo(&buf, " ON DELETE %s", string);
1195 case CONSTRAINT_PRIMARY:
1196 case CONSTRAINT_UNIQUE:
1202 /* Start off the constraint definition */
1203 if (conForm->contype == CONSTRAINT_PRIMARY)
1204 appendStringInfo(&buf, "PRIMARY KEY (");
1206 appendStringInfo(&buf, "UNIQUE (");
1208 /* Fetch and build target column list */
1209 val = SysCacheGetAttr(CONSTROID, tup,
1210 Anum_pg_constraint_conkey, &isnull);
1212 elog(ERROR, "null conkey for constraint %u",
1215 decompile_column_index_array(val, conForm->conrelid, &buf);
1217 appendStringInfo(&buf, ")");
1219 indexId = get_constraint_index(constraintId);
1221 /* XXX why do we only print these bits if fullCommand? */
1222 if (fullCommand && OidIsValid(indexId))
1224 char *options = flatten_reloptions(indexId);
1229 appendStringInfo(&buf, " WITH (%s)", options);
1233 tblspc = get_rel_tablespace(indexId);
1234 if (OidIsValid(tblspc))
1235 appendStringInfo(&buf, " USING INDEX TABLESPACE %s",
1236 quote_identifier(get_tablespace_name(tblspc)));
1241 case CONSTRAINT_CHECK:
1250 /* Fetch constraint expression in parsetree form */
1251 val = SysCacheGetAttr(CONSTROID, tup,
1252 Anum_pg_constraint_conbin, &isnull);
1254 elog(ERROR, "null conbin for constraint %u",
1257 conbin = TextDatumGetCString(val);
1258 expr = stringToNode(conbin);
1260 /* Set up deparsing context for Var nodes in constraint */
1261 if (conForm->conrelid != InvalidOid)
1263 /* relation constraint */
1264 context = deparse_context_for(get_rel_name(conForm->conrelid),
1269 /* domain constraint --- can't have Vars */
1273 consrc = deparse_expression_pretty(expr, context, false, false,
1277 * Now emit the constraint definition. There are cases where
1278 * the constraint expression will be fully parenthesized and
1279 * we don't need the outer parens ... but there are other
1280 * cases where we do need 'em. Be conservative for now.
1282 * Note that simply checking for leading '(' and trailing ')'
1283 * would NOT be good enough, consider "(x > 0) AND (y > 0)".
1285 appendStringInfo(&buf, "CHECK (%s)", consrc);
1289 case CONSTRAINT_TRIGGER:
1292 * There isn't an ALTER TABLE syntax for creating a user-defined
1293 * constraint trigger, but it seems better to print something than
1294 * throw an error; if we throw error then this function couldn't
1295 * safely be applied to all rows of pg_constraint.
1297 appendStringInfo(&buf, "TRIGGER");
1299 case CONSTRAINT_EXCLUSION:
1301 Oid indexOid = conForm->conindid;
1309 /* Extract operator OIDs from the pg_constraint tuple */
1310 val = SysCacheGetAttr(CONSTROID, tup,
1311 Anum_pg_constraint_conexclop,
1314 elog(ERROR, "null conexclop for constraint %u",
1317 deconstruct_array(DatumGetArrayTypeP(val),
1318 OIDOID, sizeof(Oid), true, 'i',
1319 &elems, NULL, &nElems);
1321 operators = (Oid *) palloc(nElems * sizeof(Oid));
1322 for (i = 0; i < nElems; i++)
1323 operators[i] = DatumGetObjectId(elems[i]);
1325 /* pg_get_indexdef_worker does the rest */
1326 /* suppress tablespace because pg_dump wants it that way */
1327 appendStringInfoString(&buf,
1328 pg_get_indexdef_worker(indexOid,
1337 elog(ERROR, "invalid constraint type \"%c\"", conForm->contype);
1341 if (conForm->condeferrable)
1342 appendStringInfo(&buf, " DEFERRABLE");
1343 if (conForm->condeferred)
1344 appendStringInfo(&buf, " INITIALLY DEFERRED");
1347 ReleaseSysCache(tup);
1354 * Convert an int16[] Datum into a comma-separated list of column names
1355 * for the indicated relation; append the list to buf.
1358 decompile_column_index_array(Datum column_index_array, Oid relId,
1365 /* Extract data from array of int16 */
1366 deconstruct_array(DatumGetArrayTypeP(column_index_array),
1367 INT2OID, 2, true, 's',
1368 &keys, NULL, &nKeys);
1370 for (j = 0; j < nKeys; j++)
1374 colName = get_relid_attribute_name(relId, DatumGetInt16(keys[j]));
1377 appendStringInfoString(buf, quote_identifier(colName));
1379 appendStringInfo(buf, ", %s", quote_identifier(colName));
1385 * get_expr - Decompile an expression tree
1387 * Input: an expression tree in nodeToString form, and a relation OID
1389 * Output: reverse-listed expression
1391 * Currently, the expression can only refer to a single relation, namely
1392 * the one specified by the second parameter. This is sufficient for
1393 * partial indexes, column default expressions, etc. We also support
1394 * Var-free expressions, for which the OID can be InvalidOid.
1398 pg_get_expr(PG_FUNCTION_ARGS)
1400 text *expr = PG_GETARG_TEXT_P(0);
1401 Oid relid = PG_GETARG_OID(1);
1404 if (OidIsValid(relid))
1406 /* Get the name for the relation */
1407 relname = get_rel_name(relid);
1410 * If the OID isn't actually valid, don't throw an error, just return
1411 * NULL. This is a bit questionable, but it's what we've done
1412 * historically, and it can help avoid unwanted failures when
1413 * examining catalog entries for just-deleted relations.
1415 if (relname == NULL)
1421 PG_RETURN_TEXT_P(pg_get_expr_worker(expr, relid, relname, 0));
1425 pg_get_expr_ext(PG_FUNCTION_ARGS)
1427 text *expr = PG_GETARG_TEXT_P(0);
1428 Oid relid = PG_GETARG_OID(1);
1429 bool pretty = PG_GETARG_BOOL(2);
1433 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
1435 if (OidIsValid(relid))
1437 /* Get the name for the relation */
1438 relname = get_rel_name(relid);
1439 /* See notes above */
1440 if (relname == NULL)
1446 PG_RETURN_TEXT_P(pg_get_expr_worker(expr, relid, relname, prettyFlags));
1450 pg_get_expr_worker(text *expr, Oid relid, const char *relname, int prettyFlags)
1457 /* Convert input TEXT object to C string */
1458 exprstr = text_to_cstring(expr);
1460 /* Convert expression to node tree */
1461 node = (Node *) stringToNode(exprstr);
1465 /* Prepare deparse context if needed */
1466 if (OidIsValid(relid))
1467 context = deparse_context_for(relname, relid);
1472 str = deparse_expression_pretty(node, context, false, false,
1475 return string_to_text(str);
1480 * get_userbyid - Get a user name by roleid and
1481 * fallback to 'unknown (OID=n)'
1485 pg_get_userbyid(PG_FUNCTION_ARGS)
1487 Oid roleid = PG_GETARG_OID(0);
1490 Form_pg_authid role_rec;
1493 * Allocate space for the result
1495 result = (Name) palloc(NAMEDATALEN);
1496 memset(NameStr(*result), 0, NAMEDATALEN);
1499 * Get the pg_authid entry and print the result
1501 roletup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
1502 if (HeapTupleIsValid(roletup))
1504 role_rec = (Form_pg_authid) GETSTRUCT(roletup);
1505 StrNCpy(NameStr(*result), NameStr(role_rec->rolname), NAMEDATALEN);
1506 ReleaseSysCache(roletup);
1509 sprintf(NameStr(*result), "unknown (OID=%u)", roleid);
1511 PG_RETURN_NAME(result);
1516 * pg_get_serial_sequence
1517 * Get the name of the sequence used by a serial column,
1518 * formatted suitably for passing to setval, nextval or currval.
1519 * First parameter is not treated as double-quoted, second parameter
1520 * is --- see documentation for reason.
1523 pg_get_serial_sequence(PG_FUNCTION_ARGS)
1525 text *tablename = PG_GETARG_TEXT_P(0);
1526 text *columnname = PG_GETARG_TEXT_PP(1);
1531 Oid sequenceId = InvalidOid;
1537 /* Get the OID of the table */
1538 tablerv = makeRangeVarFromNameList(textToQualifiedNameList(tablename));
1539 tableOid = RangeVarGetRelid(tablerv, false);
1541 /* Get the number of the column */
1542 column = text_to_cstring(columnname);
1544 attnum = get_attnum(tableOid, column);
1545 if (attnum == InvalidAttrNumber)
1547 (errcode(ERRCODE_UNDEFINED_COLUMN),
1548 errmsg("column \"%s\" of relation \"%s\" does not exist",
1549 column, tablerv->relname)));
1551 /* Search the dependency table for the dependent sequence */
1552 depRel = heap_open(DependRelationId, AccessShareLock);
1554 ScanKeyInit(&key[0],
1555 Anum_pg_depend_refclassid,
1556 BTEqualStrategyNumber, F_OIDEQ,
1557 ObjectIdGetDatum(RelationRelationId));
1558 ScanKeyInit(&key[1],
1559 Anum_pg_depend_refobjid,
1560 BTEqualStrategyNumber, F_OIDEQ,
1561 ObjectIdGetDatum(tableOid));
1562 ScanKeyInit(&key[2],
1563 Anum_pg_depend_refobjsubid,
1564 BTEqualStrategyNumber, F_INT4EQ,
1565 Int32GetDatum(attnum));
1567 scan = systable_beginscan(depRel, DependReferenceIndexId, true,
1568 SnapshotNow, 3, key);
1570 while (HeapTupleIsValid(tup = systable_getnext(scan)))
1572 Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
1575 * We assume any auto dependency of a sequence on a column must be
1576 * what we are looking for. (We need the relkind test because indexes
1577 * can also have auto dependencies on columns.)
1579 if (deprec->classid == RelationRelationId &&
1580 deprec->objsubid == 0 &&
1581 deprec->deptype == DEPENDENCY_AUTO &&
1582 get_rel_relkind(deprec->objid) == RELKIND_SEQUENCE)
1584 sequenceId = deprec->objid;
1589 systable_endscan(scan);
1590 heap_close(depRel, AccessShareLock);
1592 if (OidIsValid(sequenceId))
1595 Form_pg_class classtuple;
1599 /* Get the sequence's pg_class entry */
1600 classtup = SearchSysCache1(RELOID, ObjectIdGetDatum(sequenceId));
1601 if (!HeapTupleIsValid(classtup))
1602 elog(ERROR, "cache lookup failed for relation %u", sequenceId);
1603 classtuple = (Form_pg_class) GETSTRUCT(classtup);
1605 /* Get the namespace */
1606 nspname = get_namespace_name(classtuple->relnamespace);
1608 elog(ERROR, "cache lookup failed for namespace %u",
1609 classtuple->relnamespace);
1611 /* And construct the result string */
1612 result = quote_qualified_identifier(nspname,
1613 NameStr(classtuple->relname));
1615 ReleaseSysCache(classtup);
1617 PG_RETURN_TEXT_P(string_to_text(result));
1625 * pg_get_functiondef
1626 * Returns the complete "CREATE OR REPLACE FUNCTION ..." statement for
1627 * the specified function.
1629 * Note: if you change the output format of this function, be careful not
1630 * to break psql's rules (in \ef and \sf) for identifying the start of the
1631 * function body. To wit: the function body starts on a line that begins
1632 * with "AS ", and no preceding line will look like that.
1635 pg_get_functiondef(PG_FUNCTION_ARGS)
1637 Oid funcid = PG_GETARG_OID(0);
1643 Form_pg_language lang;
1652 initStringInfo(&buf);
1654 /* Look up the function */
1655 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1656 if (!HeapTupleIsValid(proctup))
1657 elog(ERROR, "cache lookup failed for function %u", funcid);
1658 proc = (Form_pg_proc) GETSTRUCT(proctup);
1659 name = NameStr(proc->proname);
1663 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1664 errmsg("\"%s\" is an aggregate function", name)));
1666 /* Need its pg_language tuple for the language name */
1667 langtup = SearchSysCache1(LANGOID, ObjectIdGetDatum(proc->prolang));
1668 if (!HeapTupleIsValid(langtup))
1669 elog(ERROR, "cache lookup failed for language %u", proc->prolang);
1670 lang = (Form_pg_language) GETSTRUCT(langtup);
1673 * We always qualify the function name, to ensure the right function gets
1676 nsp = get_namespace_name(proc->pronamespace);
1677 appendStringInfo(&buf, "CREATE OR REPLACE FUNCTION %s(",
1678 quote_qualified_identifier(nsp, name));
1679 (void) print_function_arguments(&buf, proctup, false, true);
1680 appendStringInfoString(&buf, ")\n RETURNS ");
1681 print_function_rettype(&buf, proctup);
1682 appendStringInfo(&buf, "\n LANGUAGE %s\n",
1683 quote_identifier(NameStr(lang->lanname)));
1685 /* Emit some miscellaneous options on one line */
1688 if (proc->proiswindow)
1689 appendStringInfoString(&buf, " WINDOW");
1690 switch (proc->provolatile)
1692 case PROVOLATILE_IMMUTABLE:
1693 appendStringInfoString(&buf, " IMMUTABLE");
1695 case PROVOLATILE_STABLE:
1696 appendStringInfoString(&buf, " STABLE");
1698 case PROVOLATILE_VOLATILE:
1701 if (proc->proisstrict)
1702 appendStringInfoString(&buf, " STRICT");
1703 if (proc->prosecdef)
1704 appendStringInfoString(&buf, " SECURITY DEFINER");
1706 /* This code for the default cost and rows should match functioncmds.c */
1707 if (proc->prolang == INTERNALlanguageId ||
1708 proc->prolang == ClanguageId)
1712 if (proc->procost != procost)
1713 appendStringInfo(&buf, " COST %g", proc->procost);
1715 if (proc->prorows > 0 && proc->prorows != 1000)
1716 appendStringInfo(&buf, " ROWS %g", proc->prorows);
1718 if (oldlen != buf.len)
1719 appendStringInfoChar(&buf, '\n');
1721 /* Emit any proconfig options, one per line */
1722 tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_proconfig, &isnull);
1725 ArrayType *a = DatumGetArrayTypeP(tmp);
1728 Assert(ARR_ELEMTYPE(a) == TEXTOID);
1729 Assert(ARR_NDIM(a) == 1);
1730 Assert(ARR_LBOUND(a)[0] == 1);
1732 for (i = 1; i <= ARR_DIMS(a)[0]; i++)
1736 d = array_ref(a, 1, &i,
1737 -1 /* varlenarray */ ,
1738 -1 /* TEXT's typlen */ ,
1739 false /* TEXT's typbyval */ ,
1740 'i' /* TEXT's typalign */ ,
1744 char *configitem = TextDatumGetCString(d);
1747 pos = strchr(configitem, '=');
1752 appendStringInfo(&buf, " SET %s TO ",
1753 quote_identifier(configitem));
1756 * Some GUC variable names are 'LIST' type and hence must not
1759 if (pg_strcasecmp(configitem, "DateStyle") == 0
1760 || pg_strcasecmp(configitem, "search_path") == 0)
1761 appendStringInfoString(&buf, pos);
1763 simple_quote_literal(&buf, pos);
1764 appendStringInfoChar(&buf, '\n');
1769 /* And finally the function definition ... */
1770 appendStringInfoString(&buf, "AS ");
1772 tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_probin, &isnull);
1775 simple_quote_literal(&buf, TextDatumGetCString(tmp));
1776 appendStringInfoString(&buf, ", "); /* assume prosrc isn't null */
1779 tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_prosrc, &isnull);
1781 elog(ERROR, "null prosrc");
1782 prosrc = TextDatumGetCString(tmp);
1785 * We always use dollar quoting. Figure out a suitable delimiter.
1787 * Since the user is likely to be editing the function body string, we
1788 * shouldn't use a short delimiter that he might easily create a conflict
1789 * with. Hence prefer "$function$", but extend if needed.
1791 initStringInfo(&dq);
1792 appendStringInfoString(&dq, "$function");
1793 while (strstr(prosrc, dq.data) != NULL)
1794 appendStringInfoChar(&dq, 'x');
1795 appendStringInfoChar(&dq, '$');
1797 appendStringInfoString(&buf, dq.data);
1798 appendStringInfoString(&buf, prosrc);
1799 appendStringInfoString(&buf, dq.data);
1801 appendStringInfoString(&buf, "\n");
1803 ReleaseSysCache(langtup);
1804 ReleaseSysCache(proctup);
1806 PG_RETURN_TEXT_P(string_to_text(buf.data));
1810 * pg_get_function_arguments
1811 * Get a nicely-formatted list of arguments for a function.
1812 * This is everything that would go between the parentheses in
1816 pg_get_function_arguments(PG_FUNCTION_ARGS)
1818 Oid funcid = PG_GETARG_OID(0);
1822 initStringInfo(&buf);
1824 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1825 if (!HeapTupleIsValid(proctup))
1826 elog(ERROR, "cache lookup failed for function %u", funcid);
1828 (void) print_function_arguments(&buf, proctup, false, true);
1830 ReleaseSysCache(proctup);
1832 PG_RETURN_TEXT_P(string_to_text(buf.data));
1836 * pg_get_function_identity_arguments
1837 * Get a formatted list of arguments for a function.
1838 * This is everything that would go between the parentheses in
1839 * ALTER FUNCTION, etc. In particular, don't print defaults.
1842 pg_get_function_identity_arguments(PG_FUNCTION_ARGS)
1844 Oid funcid = PG_GETARG_OID(0);
1848 initStringInfo(&buf);
1850 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1851 if (!HeapTupleIsValid(proctup))
1852 elog(ERROR, "cache lookup failed for function %u", funcid);
1854 (void) print_function_arguments(&buf, proctup, false, false);
1856 ReleaseSysCache(proctup);
1858 PG_RETURN_TEXT_P(string_to_text(buf.data));
1862 * pg_get_function_result
1863 * Get a nicely-formatted version of the result type of a function.
1864 * This is what would appear after RETURNS in CREATE FUNCTION.
1867 pg_get_function_result(PG_FUNCTION_ARGS)
1869 Oid funcid = PG_GETARG_OID(0);
1873 initStringInfo(&buf);
1875 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1876 if (!HeapTupleIsValid(proctup))
1877 elog(ERROR, "cache lookup failed for function %u", funcid);
1879 print_function_rettype(&buf, proctup);
1881 ReleaseSysCache(proctup);
1883 PG_RETURN_TEXT_P(string_to_text(buf.data));
1887 * Guts of pg_get_function_result: append the function's return type
1888 * to the specified buffer.
1891 print_function_rettype(StringInfo buf, HeapTuple proctup)
1893 Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(proctup);
1895 StringInfoData rbuf;
1897 initStringInfo(&rbuf);
1899 if (proc->proretset)
1901 /* It might be a table function; try to print the arguments */
1902 appendStringInfoString(&rbuf, "TABLE(");
1903 ntabargs = print_function_arguments(&rbuf, proctup, true, false);
1905 appendStringInfoString(&rbuf, ")");
1907 resetStringInfo(&rbuf);
1912 /* Not a table function, so do the normal thing */
1913 if (proc->proretset)
1914 appendStringInfoString(&rbuf, "SETOF ");
1915 appendStringInfoString(&rbuf, format_type_be(proc->prorettype));
1918 appendStringInfoString(buf, rbuf.data);
1922 * Common code for pg_get_function_arguments and pg_get_function_result:
1923 * append the desired subset of arguments to buf. We print only TABLE
1924 * arguments when print_table_args is true, and all the others when it's false.
1925 * We print argument defaults only if print_defaults is true.
1926 * Function return value is the number of arguments printed.
1929 print_function_arguments(StringInfo buf, HeapTuple proctup,
1930 bool print_table_args, bool print_defaults)
1932 Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(proctup);
1940 ListCell *nextargdefault = NULL;
1943 numargs = get_func_arg_info(proctup,
1944 &argtypes, &argnames, &argmodes);
1946 nlackdefaults = numargs;
1947 if (print_defaults && proc->pronargdefaults > 0)
1949 Datum proargdefaults;
1952 proargdefaults = SysCacheGetAttr(PROCOID, proctup,
1953 Anum_pg_proc_proargdefaults,
1960 str = TextDatumGetCString(proargdefaults);
1961 argdefaults = (List *) stringToNode(str);
1962 Assert(IsA(argdefaults, List));
1964 nextargdefault = list_head(argdefaults);
1965 /* nlackdefaults counts only *input* arguments lacking defaults */
1966 nlackdefaults = proc->pronargs - list_length(argdefaults);
1972 for (i = 0; i < numargs; i++)
1974 Oid argtype = argtypes[i];
1975 char *argname = argnames ? argnames[i] : NULL;
1976 char argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
1977 const char *modename;
1986 case PROARGMODE_INOUT:
1987 modename = "INOUT ";
1990 case PROARGMODE_OUT:
1994 case PROARGMODE_VARIADIC:
1995 modename = "VARIADIC ";
1998 case PROARGMODE_TABLE:
2003 elog(ERROR, "invalid parameter mode '%c'", argmode);
2004 modename = NULL; /* keep compiler quiet */
2009 inputargno++; /* this is a 1-based counter */
2011 if (print_table_args != (argmode == PROARGMODE_TABLE))
2015 appendStringInfoString(buf, ", ");
2016 appendStringInfoString(buf, modename);
2017 if (argname && argname[0])
2018 appendStringInfo(buf, "%s ", quote_identifier(argname));
2019 appendStringInfoString(buf, format_type_be(argtype));
2020 if (print_defaults && isinput && inputargno > nlackdefaults)
2024 Assert(nextargdefault != NULL);
2025 expr = (Node *) lfirst(nextargdefault);
2026 nextargdefault = lnext(nextargdefault);
2028 appendStringInfo(buf, " DEFAULT %s",
2029 deparse_expression(expr, NIL, false, false));
2039 * deparse_expression - General utility for deparsing expressions
2041 * calls deparse_expression_pretty with all prettyPrinting disabled
2044 deparse_expression(Node *expr, List *dpcontext,
2045 bool forceprefix, bool showimplicit)
2047 return deparse_expression_pretty(expr, dpcontext, forceprefix,
2048 showimplicit, 0, 0);
2052 * deparse_expression_pretty - General utility for deparsing expressions
2054 * expr is the node tree to be deparsed. It must be a transformed expression
2055 * tree (ie, not the raw output of gram.y).
2057 * dpcontext is a list of deparse_namespace nodes representing the context
2058 * for interpreting Vars in the node tree.
2060 * forceprefix is TRUE to force all Vars to be prefixed with their table names.
2062 * showimplicit is TRUE to force all implicit casts to be shown explicitly.
2064 * tries to pretty up the output according to prettyFlags and startIndent.
2066 * The result is a palloc'd string.
2070 deparse_expression_pretty(Node *expr, List *dpcontext,
2071 bool forceprefix, bool showimplicit,
2072 int prettyFlags, int startIndent)
2075 deparse_context context;
2077 initStringInfo(&buf);
2079 context.namespaces = dpcontext;
2080 context.windowClause = NIL;
2081 context.windowTList = NIL;
2082 context.varprefix = forceprefix;
2083 context.prettyFlags = prettyFlags;
2084 context.indentLevel = startIndent;
2086 get_rule_expr(expr, &context, showimplicit);
2092 * deparse_context_for - Build deparse context for a single relation
2094 * Given the reference name (alias) and OID of a relation, build deparsing
2095 * context for an expression referencing only that relation (as varno 1,
2096 * varlevelsup 0). This is sufficient for many uses of deparse_expression.
2100 deparse_context_for(const char *aliasname, Oid relid)
2102 deparse_namespace *dpns;
2105 dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
2107 /* Build a minimal RTE for the rel */
2108 rte = makeNode(RangeTblEntry);
2109 rte->rtekind = RTE_RELATION;
2111 rte->eref = makeAlias(aliasname, NIL);
2113 rte->inFromCl = true;
2115 /* Build one-element rtable */
2116 dpns->rtable = list_make1(rte);
2119 /* Return a one-deep namespace stack */
2120 return list_make1(dpns);
2124 * deparse_context_for_planstate - Build deparse context for a plan
2126 * When deparsing an expression in a Plan tree, we might have to resolve
2127 * OUTER or INNER references. To do this, the caller must provide the
2128 * parent PlanState node. Then OUTER and INNER references can be resolved
2129 * by drilling down into the left and right child plans.
2131 * Note: planstate really ought to be declared as "PlanState *", but we use
2132 * "Node *" to avoid having to include execnodes.h in builtins.h.
2134 * The ancestors list is a list of the PlanState's parent PlanStates, the
2135 * most-closely-nested first. This is needed to resolve PARAM_EXEC Params.
2136 * Note we assume that all the PlanStates share the same rtable.
2138 * The plan's rangetable list must also be passed. We actually prefer to use
2139 * the rangetable to resolve simple Vars, but the plan inputs are necessary
2140 * for Vars that reference expressions computed in subplan target lists.
2143 deparse_context_for_planstate(Node *planstate, List *ancestors,
2146 deparse_namespace *dpns;
2148 dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
2150 /* Initialize fields that stay the same across the whole plan tree */
2151 dpns->rtable = rtable;
2154 /* Set our attention on the specific plan node passed in */
2155 set_deparse_planstate(dpns, (PlanState *) planstate);
2156 dpns->ancestors = ancestors;
2158 /* Return a one-deep namespace stack */
2159 return list_make1(dpns);
2163 * set_deparse_planstate: set up deparse_namespace to parse subexpressions
2164 * of a given PlanState node
2166 * This sets the planstate, outer_planstate, inner_planstate, outer_plan, and
2167 * inner_plan fields. Caller is responsible for adjusting the ancestors list
2168 * if necessary. Note that the rtable and ctes fields do not need to change
2169 * when shifting attention to different plan nodes in a single plan tree.
2172 set_deparse_planstate(deparse_namespace *dpns, PlanState *ps)
2174 dpns->planstate = ps;
2177 * We special-case Append and MergeAppend to pretend that the first child
2178 * plan is the OUTER referent; we have to interpret OUTER Vars in their
2179 * tlists according to one of the children, and the first one is the most
2180 * natural choice. Likewise special-case ModifyTable to pretend that the
2181 * first child plan is the OUTER referent; this is to support RETURNING
2182 * lists containing references to non-target relations.
2184 if (IsA(ps, AppendState))
2185 dpns->outer_planstate = ((AppendState *) ps)->appendplans[0];
2186 else if (IsA(ps, MergeAppendState))
2187 dpns->outer_planstate = ((MergeAppendState *) ps)->mergeplans[0];
2188 else if (IsA(ps, ModifyTableState))
2189 dpns->outer_planstate = ((ModifyTableState *) ps)->mt_plans[0];
2191 dpns->outer_planstate = outerPlanState(ps);
2193 if (dpns->outer_planstate)
2194 dpns->outer_plan = dpns->outer_planstate->plan;
2196 dpns->outer_plan = NULL;
2199 * For a SubqueryScan, pretend the subplan is INNER referent. (We don't
2200 * use OUTER because that could someday conflict with the normal meaning.)
2201 * Likewise, for a CteScan, pretend the subquery's plan is INNER referent.
2203 if (IsA(ps, SubqueryScanState))
2204 dpns->inner_planstate = ((SubqueryScanState *) ps)->subplan;
2205 else if (IsA(ps, CteScanState))
2206 dpns->inner_planstate = ((CteScanState *) ps)->cteplanstate;
2208 dpns->inner_planstate = innerPlanState(ps);
2210 if (dpns->inner_planstate)
2211 dpns->inner_plan = dpns->inner_planstate->plan;
2213 dpns->inner_plan = NULL;
2217 * push_child_plan: temporarily transfer deparsing attention to a child plan
2219 * When expanding an OUTER or INNER reference, we must adjust the deparse
2220 * context in case the referenced expression itself uses OUTER/INNER. We
2221 * modify the top stack entry in-place to avoid affecting levelsup issues
2222 * (although in a Plan tree there really shouldn't be any).
2224 * Caller must provide a local deparse_namespace variable to save the
2225 * previous state for pop_child_plan.
2228 push_child_plan(deparse_namespace *dpns, PlanState *ps,
2229 deparse_namespace *save_dpns)
2231 /* Save state for restoration later */
2235 * Currently we don't bother to adjust the ancestors list, because an
2236 * OUTER or INNER reference really shouldn't contain any Params that
2237 * would be set by the parent node itself. If we did want to adjust it,
2238 * lcons'ing dpns->planstate onto dpns->ancestors would be the appropriate
2239 * thing --- and pop_child_plan would need to undo the change to the list.
2242 /* Set attention on selected child */
2243 set_deparse_planstate(dpns, ps);
2247 * pop_child_plan: undo the effects of push_child_plan
2250 pop_child_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
2252 /* Restore fields changed by push_child_plan */
2257 * push_ancestor_plan: temporarily transfer deparsing attention to an
2260 * When expanding a Param reference, we must adjust the deparse context
2261 * to match the plan node that contains the expression being printed;
2262 * otherwise we'd fail if that expression itself contains a Param or
2263 * OUTER/INNER variables.
2265 * The target ancestor is conveniently identified by the ListCell holding it
2266 * in dpns->ancestors.
2268 * Caller must provide a local deparse_namespace variable to save the
2269 * previous state for pop_ancestor_plan.
2272 push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell,
2273 deparse_namespace *save_dpns)
2275 PlanState *ps = (PlanState *) lfirst(ancestor_cell);
2278 /* Save state for restoration later */
2281 /* Build a new ancestor list with just this node's ancestors */
2283 while ((ancestor_cell = lnext(ancestor_cell)) != NULL)
2284 ancestors = lappend(ancestors, lfirst(ancestor_cell));
2285 dpns->ancestors = ancestors;
2287 /* Set attention on selected ancestor */
2288 set_deparse_planstate(dpns, ps);
2292 * pop_ancestor_plan: undo the effects of push_ancestor_plan
2295 pop_ancestor_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
2297 /* Free the ancestor list made in push_ancestor_plan */
2298 list_free(dpns->ancestors);
2300 /* Restore fields changed by push_ancestor_plan */
2306 * make_ruledef - reconstruct the CREATE RULE command
2307 * for a given pg_rewrite tuple
2311 make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
2321 List *actions = NIL;
2327 * Get the attribute values from the rules tuple
2329 fno = SPI_fnumber(rulettc, "rulename");
2330 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
2332 rulename = NameStr(*(DatumGetName(dat)));
2334 fno = SPI_fnumber(rulettc, "ev_type");
2335 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
2337 ev_type = DatumGetChar(dat);
2339 fno = SPI_fnumber(rulettc, "ev_class");
2340 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
2342 ev_class = DatumGetObjectId(dat);
2344 fno = SPI_fnumber(rulettc, "ev_attr");
2345 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
2347 ev_attr = DatumGetInt16(dat);
2349 fno = SPI_fnumber(rulettc, "is_instead");
2350 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
2352 is_instead = DatumGetBool(dat);
2354 /* these could be nulls */
2355 fno = SPI_fnumber(rulettc, "ev_qual");
2356 ev_qual = SPI_getvalue(ruletup, rulettc, fno);
2358 fno = SPI_fnumber(rulettc, "ev_action");
2359 ev_action = SPI_getvalue(ruletup, rulettc, fno);
2360 if (ev_action != NULL)
2361 actions = (List *) stringToNode(ev_action);
2364 * Build the rules definition text
2366 appendStringInfo(buf, "CREATE RULE %s AS",
2367 quote_identifier(rulename));
2369 if (prettyFlags & PRETTYFLAG_INDENT)
2370 appendStringInfoString(buf, "\n ON ");
2372 appendStringInfoString(buf, " ON ");
2374 /* The event the rule is fired for */
2378 appendStringInfo(buf, "SELECT");
2382 appendStringInfo(buf, "UPDATE");
2386 appendStringInfo(buf, "INSERT");
2390 appendStringInfo(buf, "DELETE");
2395 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2396 errmsg("rule \"%s\" has unsupported event type %d",
2397 rulename, ev_type)));
2401 /* The relation the rule is fired on */
2402 appendStringInfo(buf, " TO %s", generate_relation_name(ev_class, NIL));
2404 appendStringInfo(buf, ".%s",
2405 quote_identifier(get_relid_attribute_name(ev_class,
2408 /* If the rule has an event qualification, add it */
2409 if (ev_qual == NULL)
2411 if (strlen(ev_qual) > 0 && strcmp(ev_qual, "<>") != 0)
2415 deparse_context context;
2416 deparse_namespace dpns;
2418 if (prettyFlags & PRETTYFLAG_INDENT)
2419 appendStringInfoString(buf, "\n ");
2420 appendStringInfo(buf, " WHERE ");
2422 qual = stringToNode(ev_qual);
2425 * We need to make a context for recognizing any Vars in the qual
2426 * (which can only be references to OLD and NEW). Use the rtable of
2427 * the first query in the action list for this purpose.
2429 query = (Query *) linitial(actions);
2432 * If the action is INSERT...SELECT, OLD/NEW have been pushed down
2433 * into the SELECT, and that's what we need to look at. (Ugly kluge
2434 * ... try to fix this when we redesign querytrees.)
2436 query = getInsertSelectQuery(query, NULL);
2438 /* Must acquire locks right away; see notes in get_query_def() */
2439 AcquireRewriteLocks(query, false);
2442 context.namespaces = list_make1(&dpns);
2443 context.windowClause = NIL;
2444 context.windowTList = NIL;
2445 context.varprefix = (list_length(query->rtable) != 1);
2446 context.prettyFlags = prettyFlags;
2447 context.indentLevel = PRETTYINDENT_STD;
2449 memset(&dpns, 0, sizeof(dpns));
2450 dpns.rtable = query->rtable;
2451 dpns.ctes = query->cteList;
2453 get_rule_expr(qual, &context, false);
2456 appendStringInfo(buf, " DO ");
2458 /* The INSTEAD keyword (if so) */
2460 appendStringInfo(buf, "INSTEAD ");
2462 /* Finally the rules actions */
2463 if (list_length(actions) > 1)
2468 appendStringInfo(buf, "(");
2469 foreach(action, actions)
2471 query = (Query *) lfirst(action);
2472 get_query_def(query, buf, NIL, NULL, prettyFlags, 0);
2474 appendStringInfo(buf, ";\n");
2476 appendStringInfo(buf, "; ");
2478 appendStringInfo(buf, ");");
2480 else if (list_length(actions) == 0)
2482 appendStringInfo(buf, "NOTHING;");
2488 query = (Query *) linitial(actions);
2489 get_query_def(query, buf, NIL, NULL, prettyFlags, 0);
2490 appendStringInfo(buf, ";");
2496 * make_viewdef - reconstruct the SELECT part of a
2501 make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
2511 List *actions = NIL;
2512 Relation ev_relation;
2517 * Get the attribute values from the rules tuple
2519 fno = SPI_fnumber(rulettc, "ev_type");
2520 ev_type = (char) SPI_getbinval(ruletup, rulettc, fno, &isnull);
2522 fno = SPI_fnumber(rulettc, "ev_class");
2523 ev_class = (Oid) SPI_getbinval(ruletup, rulettc, fno, &isnull);
2525 fno = SPI_fnumber(rulettc, "ev_attr");
2526 ev_attr = (int2) SPI_getbinval(ruletup, rulettc, fno, &isnull);
2528 fno = SPI_fnumber(rulettc, "is_instead");
2529 is_instead = (bool) SPI_getbinval(ruletup, rulettc, fno, &isnull);
2531 fno = SPI_fnumber(rulettc, "ev_qual");
2532 ev_qual = SPI_getvalue(ruletup, rulettc, fno);
2534 fno = SPI_fnumber(rulettc, "ev_action");
2535 ev_action = SPI_getvalue(ruletup, rulettc, fno);
2536 if (ev_action != NULL)
2537 actions = (List *) stringToNode(ev_action);
2539 if (list_length(actions) != 1)
2541 appendStringInfo(buf, "Not a view");
2545 query = (Query *) linitial(actions);
2547 if (ev_type != '1' || ev_attr >= 0 || !is_instead ||
2548 strcmp(ev_qual, "<>") != 0 || query->commandType != CMD_SELECT)
2550 appendStringInfo(buf, "Not a view");
2554 ev_relation = heap_open(ev_class, AccessShareLock);
2556 get_query_def(query, buf, NIL, RelationGetDescr(ev_relation),
2558 appendStringInfo(buf, ";");
2560 heap_close(ev_relation, AccessShareLock);
2565 * get_query_def - Parse back one query parsetree
2567 * If resultDesc is not NULL, then it is the output tuple descriptor for
2568 * the view represented by a SELECT query.
2572 get_query_def(Query *query, StringInfo buf, List *parentnamespace,
2573 TupleDesc resultDesc, int prettyFlags, int startIndent)
2575 deparse_context context;
2576 deparse_namespace dpns;
2579 * Before we begin to examine the query, acquire locks on referenced
2580 * relations, and fix up deleted columns in JOIN RTEs. This ensures
2581 * consistent results. Note we assume it's OK to scribble on the passed
2584 AcquireRewriteLocks(query, false);
2587 context.namespaces = lcons(&dpns, list_copy(parentnamespace));
2588 context.windowClause = NIL;
2589 context.windowTList = NIL;
2590 context.varprefix = (parentnamespace != NIL ||
2591 list_length(query->rtable) != 1);
2592 context.prettyFlags = prettyFlags;
2593 context.indentLevel = startIndent;
2595 memset(&dpns, 0, sizeof(dpns));
2596 dpns.rtable = query->rtable;
2597 dpns.ctes = query->cteList;
2599 switch (query->commandType)
2602 get_select_query_def(query, &context, resultDesc);
2606 get_update_query_def(query, &context);
2610 get_insert_query_def(query, &context);
2614 get_delete_query_def(query, &context);
2618 appendStringInfo(buf, "NOTHING");
2622 get_utility_query_def(query, &context);
2626 elog(ERROR, "unrecognized query command type: %d",
2627 query->commandType);
2633 * get_values_def - Parse back a VALUES list
2637 get_values_def(List *values_lists, deparse_context *context)
2639 StringInfo buf = context->buf;
2640 bool first_list = true;
2643 appendStringInfoString(buf, "VALUES ");
2645 foreach(vtl, values_lists)
2647 List *sublist = (List *) lfirst(vtl);
2648 bool first_col = true;
2654 appendStringInfoString(buf, ", ");
2656 appendStringInfoChar(buf, '(');
2657 foreach(lc, sublist)
2659 Node *col = (Node *) lfirst(lc);
2664 appendStringInfoChar(buf, ',');
2667 * Strip any top-level nodes representing indirection assignments,
2668 * then print the result.
2670 get_rule_expr(processIndirection(col, context, false),
2673 appendStringInfoChar(buf, ')');
2678 * get_with_clause - Parse back a WITH clause
2682 get_with_clause(Query *query, deparse_context *context)
2684 StringInfo buf = context->buf;
2688 if (query->cteList == NIL)
2691 if (PRETTY_INDENT(context))
2693 context->indentLevel += PRETTYINDENT_STD;
2694 appendStringInfoChar(buf, ' ');
2697 if (query->hasRecursive)
2698 sep = "WITH RECURSIVE ";
2701 foreach(l, query->cteList)
2703 CommonTableExpr *cte = (CommonTableExpr *) lfirst(l);
2705 appendStringInfoString(buf, sep);
2706 appendStringInfoString(buf, quote_identifier(cte->ctename));
2707 if (cte->aliascolnames)
2712 appendStringInfoChar(buf, '(');
2713 foreach(col, cte->aliascolnames)
2718 appendStringInfoString(buf, ", ");
2719 appendStringInfoString(buf,
2720 quote_identifier(strVal(lfirst(col))));
2722 appendStringInfoChar(buf, ')');
2724 appendStringInfoString(buf, " AS (");
2725 if (PRETTY_INDENT(context))
2726 appendContextKeyword(context, "", 0, 0, 0);
2727 get_query_def((Query *) cte->ctequery, buf, context->namespaces, NULL,
2728 context->prettyFlags, context->indentLevel);
2729 if (PRETTY_INDENT(context))
2730 appendContextKeyword(context, "", 0, 0, 0);
2731 appendStringInfoChar(buf, ')');
2735 if (PRETTY_INDENT(context))
2737 context->indentLevel -= PRETTYINDENT_STD;
2738 appendContextKeyword(context, "", 0, 0, 0);
2741 appendStringInfoChar(buf, ' ');
2745 * get_select_query_def - Parse back a SELECT parsetree
2749 get_select_query_def(Query *query, deparse_context *context,
2750 TupleDesc resultDesc)
2752 StringInfo buf = context->buf;
2753 List *save_windowclause;
2754 List *save_windowtlist;
2758 /* Insert the WITH clause if given */
2759 get_with_clause(query, context);
2761 /* Set up context for possible window functions */
2762 save_windowclause = context->windowClause;
2763 context->windowClause = query->windowClause;
2764 save_windowtlist = context->windowTList;
2765 context->windowTList = query->targetList;
2768 * If the Query node has a setOperations tree, then it's the top level of
2769 * a UNION/INTERSECT/EXCEPT query; only the WITH, ORDER BY and LIMIT
2770 * fields are interesting in the top query itself.
2772 if (query->setOperations)
2774 get_setop_query(query->setOperations, query, context, resultDesc);
2775 /* ORDER BY clauses must be simple in this case */
2780 get_basic_select_query(query, context, resultDesc);
2781 force_colno = false;
2784 /* Add the ORDER BY clause if given */
2785 if (query->sortClause != NIL)
2787 appendContextKeyword(context, " ORDER BY ",
2788 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2789 get_rule_orderby(query->sortClause, query->targetList,
2790 force_colno, context);
2793 /* Add the LIMIT clause if given */
2794 if (query->limitOffset != NULL)
2796 appendContextKeyword(context, " OFFSET ",
2797 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2798 get_rule_expr(query->limitOffset, context, false);
2800 if (query->limitCount != NULL)
2802 appendContextKeyword(context, " LIMIT ",
2803 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2804 if (IsA(query->limitCount, Const) &&
2805 ((Const *) query->limitCount)->constisnull)
2806 appendStringInfo(buf, "ALL");
2808 get_rule_expr(query->limitCount, context, false);
2811 /* Add FOR UPDATE/SHARE clauses if present */
2812 if (query->hasForUpdate)
2814 foreach(l, query->rowMarks)
2816 RowMarkClause *rc = (RowMarkClause *) lfirst(l);
2817 RangeTblEntry *rte = rt_fetch(rc->rti, query->rtable);
2819 /* don't print implicit clauses */
2824 appendContextKeyword(context, " FOR UPDATE",
2825 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2827 appendContextKeyword(context, " FOR SHARE",
2828 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2829 appendStringInfo(buf, " OF %s",
2830 quote_identifier(rte->eref->aliasname));
2832 appendStringInfo(buf, " NOWAIT");
2836 context->windowClause = save_windowclause;
2837 context->windowTList = save_windowtlist;
2841 get_basic_select_query(Query *query, deparse_context *context,
2842 TupleDesc resultDesc)
2844 StringInfo buf = context->buf;
2848 if (PRETTY_INDENT(context))
2850 context->indentLevel += PRETTYINDENT_STD;
2851 appendStringInfoChar(buf, ' ');
2855 * If the query looks like SELECT * FROM (VALUES ...), then print just the
2856 * VALUES part. This reverses what transformValuesClause() did at parse
2857 * time. If the jointree contains just a single VALUES RTE, we assume
2858 * this case applies (without looking at the targetlist...)
2860 if (list_length(query->jointree->fromlist) == 1)
2862 RangeTblRef *rtr = (RangeTblRef *) linitial(query->jointree->fromlist);
2864 if (IsA(rtr, RangeTblRef))
2866 RangeTblEntry *rte = rt_fetch(rtr->rtindex, query->rtable);
2868 if (rte->rtekind == RTE_VALUES)
2870 get_values_def(rte->values_lists, context);
2877 * Build up the query string - first we say SELECT
2879 appendStringInfo(buf, "SELECT");
2881 /* Add the DISTINCT clause if given */
2882 if (query->distinctClause != NIL)
2884 if (query->hasDistinctOn)
2886 appendStringInfo(buf, " DISTINCT ON (");
2888 foreach(l, query->distinctClause)
2890 SortGroupClause *srt = (SortGroupClause *) lfirst(l);
2892 appendStringInfoString(buf, sep);
2893 get_rule_sortgroupclause(srt, query->targetList,
2897 appendStringInfo(buf, ")");
2900 appendStringInfo(buf, " DISTINCT");
2903 /* Then we tell what to select (the targetlist) */
2904 get_target_list(query->targetList, context, resultDesc);
2906 /* Add the FROM clause if needed */
2907 get_from_clause(query, " FROM ", context);
2909 /* Add the WHERE clause if given */
2910 if (query->jointree->quals != NULL)
2912 appendContextKeyword(context, " WHERE ",
2913 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2914 get_rule_expr(query->jointree->quals, context, false);
2917 /* Add the GROUP BY clause if given */
2918 if (query->groupClause != NULL)
2920 appendContextKeyword(context, " GROUP BY ",
2921 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2923 foreach(l, query->groupClause)
2925 SortGroupClause *grp = (SortGroupClause *) lfirst(l);
2927 appendStringInfoString(buf, sep);
2928 get_rule_sortgroupclause(grp, query->targetList,
2934 /* Add the HAVING clause if given */
2935 if (query->havingQual != NULL)
2937 appendContextKeyword(context, " HAVING ",
2938 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2939 get_rule_expr(query->havingQual, context, false);
2942 /* Add the WINDOW clause if needed */
2943 if (query->windowClause != NIL)
2944 get_rule_windowclause(query, context);
2948 * get_target_list - Parse back a SELECT target list
2950 * This is also used for RETURNING lists in INSERT/UPDATE/DELETE.
2954 get_target_list(List *targetList, deparse_context *context,
2955 TupleDesc resultDesc)
2957 StringInfo buf = context->buf;
2964 foreach(l, targetList)
2966 TargetEntry *tle = (TargetEntry *) lfirst(l);
2971 continue; /* ignore junk entries */
2973 appendStringInfoString(buf, sep);
2978 * We special-case Var nodes rather than using get_rule_expr. This is
2979 * needed because get_rule_expr will display a whole-row Var as
2980 * "foo.*", which is the preferred notation in most contexts, but at
2981 * the top level of a SELECT list it's not right (the parser will
2982 * expand that notation into multiple columns, yielding behavior
2983 * different from a whole-row Var). We want just "foo", instead.
2985 if (tle->expr && IsA(tle->expr, Var))
2987 attname = get_variable((Var *) tle->expr, 0, false, context);
2991 get_rule_expr((Node *) tle->expr, context, true);
2992 /* We'll show the AS name unless it's this: */
2993 attname = "?column?";
2997 * Figure out what the result column should be called. In the context
2998 * of a view, use the view's tuple descriptor (so as to pick up the
2999 * effects of any column RENAME that's been done on the view).
3000 * Otherwise, just use what we can find in the TLE.
3002 if (resultDesc && colno <= resultDesc->natts)
3003 colname = NameStr(resultDesc->attrs[colno - 1]->attname);
3005 colname = tle->resname;
3007 /* Show AS unless the column's name is correct as-is */
3008 if (colname) /* resname could be NULL */
3010 if (attname == NULL || strcmp(attname, colname) != 0)
3011 appendStringInfo(buf, " AS %s", quote_identifier(colname));
3017 get_setop_query(Node *setOp, Query *query, deparse_context *context,
3018 TupleDesc resultDesc)
3020 StringInfo buf = context->buf;
3023 if (IsA(setOp, RangeTblRef))
3025 RangeTblRef *rtr = (RangeTblRef *) setOp;
3026 RangeTblEntry *rte = rt_fetch(rtr->rtindex, query->rtable);
3027 Query *subquery = rte->subquery;
3029 Assert(subquery != NULL);
3030 Assert(subquery->setOperations == NULL);
3031 /* Need parens if WITH, ORDER BY, FOR UPDATE, or LIMIT; see gram.y */
3032 need_paren = (subquery->cteList ||
3033 subquery->sortClause ||
3034 subquery->rowMarks ||
3035 subquery->limitOffset ||
3036 subquery->limitCount);
3038 appendStringInfoChar(buf, '(');
3039 get_query_def(subquery, buf, context->namespaces, resultDesc,
3040 context->prettyFlags, context->indentLevel);
3042 appendStringInfoChar(buf, ')');
3044 else if (IsA(setOp, SetOperationStmt))
3046 SetOperationStmt *op = (SetOperationStmt *) setOp;
3048 if (PRETTY_INDENT(context))
3050 context->indentLevel += PRETTYINDENT_STD;
3051 appendStringInfoSpaces(buf, PRETTYINDENT_STD);
3055 * We force parens whenever nesting two SetOperationStmts. There are
3056 * some cases in which parens are needed around a leaf query too, but
3057 * those are more easily handled at the next level down (see code
3060 need_paren = !IsA(op->larg, RangeTblRef);
3063 appendStringInfoChar(buf, '(');
3064 get_setop_query(op->larg, query, context, resultDesc);
3066 appendStringInfoChar(buf, ')');
3068 if (!PRETTY_INDENT(context))
3069 appendStringInfoChar(buf, ' ');
3073 appendContextKeyword(context, "UNION ",
3074 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
3076 case SETOP_INTERSECT:
3077 appendContextKeyword(context, "INTERSECT ",
3078 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
3081 appendContextKeyword(context, "EXCEPT ",
3082 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
3085 elog(ERROR, "unrecognized set op: %d",
3089 appendStringInfo(buf, "ALL ");
3091 if (PRETTY_INDENT(context))
3092 appendContextKeyword(context, "", 0, 0, 0);
3094 need_paren = !IsA(op->rarg, RangeTblRef);
3097 appendStringInfoChar(buf, '(');
3098 get_setop_query(op->rarg, query, context, resultDesc);
3100 appendStringInfoChar(buf, ')');
3102 if (PRETTY_INDENT(context))
3103 context->indentLevel -= PRETTYINDENT_STD;
3107 elog(ERROR, "unrecognized node type: %d",
3108 (int) nodeTag(setOp));
3113 * Display a sort/group clause.
3115 * Also returns the expression tree, so caller need not find it again.
3118 get_rule_sortgroupclause(SortGroupClause *srt, List *tlist, bool force_colno,
3119 deparse_context *context)
3121 StringInfo buf = context->buf;
3125 tle = get_sortgroupclause_tle(srt, tlist);
3126 expr = (Node *) tle->expr;
3129 * Use column-number form if requested by caller. Otherwise, if
3130 * expression is a constant, force it to be dumped with an explicit cast
3131 * as decoration --- this is because a simple integer constant is
3132 * ambiguous (and will be misinterpreted by findTargetlistEntry()) if we
3133 * dump it without any decoration. Otherwise, just dump the expression
3138 Assert(!tle->resjunk);
3139 appendStringInfo(buf, "%d", tle->resno);
3141 else if (expr && IsA(expr, Const))
3142 get_const_expr((Const *) expr, context, 1);
3144 get_rule_expr(expr, context, true);
3150 * Display an ORDER BY list.
3153 get_rule_orderby(List *orderList, List *targetList,
3154 bool force_colno, deparse_context *context)
3156 StringInfo buf = context->buf;
3161 foreach(l, orderList)
3163 SortGroupClause *srt = (SortGroupClause *) lfirst(l);
3166 TypeCacheEntry *typentry;
3168 appendStringInfoString(buf, sep);
3169 sortexpr = get_rule_sortgroupclause(srt, targetList,
3170 force_colno, context);
3171 sortcoltype = exprType(sortexpr);
3172 /* See whether operator is default < or > for datatype */
3173 typentry = lookup_type_cache(sortcoltype,
3174 TYPECACHE_LT_OPR | TYPECACHE_GT_OPR);
3175 if (srt->sortop == typentry->lt_opr)
3177 /* ASC is default, so emit nothing for it */
3178 if (srt->nulls_first)
3179 appendStringInfo(buf, " NULLS FIRST");
3181 else if (srt->sortop == typentry->gt_opr)
3183 appendStringInfo(buf, " DESC");
3184 /* DESC defaults to NULLS FIRST */
3185 if (!srt->nulls_first)
3186 appendStringInfo(buf, " NULLS LAST");
3190 appendStringInfo(buf, " USING %s",
3191 generate_operator_name(srt->sortop,
3194 /* be specific to eliminate ambiguity */
3195 if (srt->nulls_first)
3196 appendStringInfo(buf, " NULLS FIRST");
3198 appendStringInfo(buf, " NULLS LAST");
3205 * Display a WINDOW clause.
3207 * Note that the windowClause list might contain only anonymous window
3208 * specifications, in which case we should print nothing here.
3211 get_rule_windowclause(Query *query, deparse_context *context)
3213 StringInfo buf = context->buf;
3218 foreach(l, query->windowClause)
3220 WindowClause *wc = (WindowClause *) lfirst(l);
3222 if (wc->name == NULL)
3223 continue; /* ignore anonymous windows */
3226 appendContextKeyword(context, " WINDOW ",
3227 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
3229 appendStringInfoString(buf, sep);
3231 appendStringInfo(buf, "%s AS ", quote_identifier(wc->name));
3233 get_rule_windowspec(wc, query->targetList, context);
3240 * Display a window definition
3243 get_rule_windowspec(WindowClause *wc, List *targetList,
3244 deparse_context *context)
3246 StringInfo buf = context->buf;
3247 bool needspace = false;
3251 appendStringInfoChar(buf, '(');
3254 appendStringInfoString(buf, quote_identifier(wc->refname));
3257 /* partition clauses are always inherited, so only print if no refname */
3258 if (wc->partitionClause && !wc->refname)
3261 appendStringInfoChar(buf, ' ');
3262 appendStringInfoString(buf, "PARTITION BY ");
3264 foreach(l, wc->partitionClause)
3266 SortGroupClause *grp = (SortGroupClause *) lfirst(l);
3268 appendStringInfoString(buf, sep);
3269 get_rule_sortgroupclause(grp, targetList,
3275 /* print ordering clause only if not inherited */
3276 if (wc->orderClause && !wc->copiedOrder)
3279 appendStringInfoChar(buf, ' ');
3280 appendStringInfoString(buf, "ORDER BY ");
3281 get_rule_orderby(wc->orderClause, targetList, false, context);
3284 /* framing clause is never inherited, so print unless it's default */
3285 if (wc->frameOptions & FRAMEOPTION_NONDEFAULT)
3288 appendStringInfoChar(buf, ' ');
3289 if (wc->frameOptions & FRAMEOPTION_RANGE)
3290 appendStringInfoString(buf, "RANGE ");
3291 else if (wc->frameOptions & FRAMEOPTION_ROWS)
3292 appendStringInfoString(buf, "ROWS ");
3295 if (wc->frameOptions & FRAMEOPTION_BETWEEN)
3296 appendStringInfoString(buf, "BETWEEN ");
3297 if (wc->frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING)
3298 appendStringInfoString(buf, "UNBOUNDED PRECEDING ");
3299 else if (wc->frameOptions & FRAMEOPTION_START_CURRENT_ROW)
3300 appendStringInfoString(buf, "CURRENT ROW ");
3301 else if (wc->frameOptions & FRAMEOPTION_START_VALUE)
3303 get_rule_expr(wc->startOffset, context, false);
3304 if (wc->frameOptions & FRAMEOPTION_START_VALUE_PRECEDING)
3305 appendStringInfoString(buf, " PRECEDING ");
3306 else if (wc->frameOptions & FRAMEOPTION_START_VALUE_FOLLOWING)
3307 appendStringInfoString(buf, " FOLLOWING ");
3313 if (wc->frameOptions & FRAMEOPTION_BETWEEN)
3315 appendStringInfoString(buf, "AND ");
3316 if (wc->frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING)
3317 appendStringInfoString(buf, "UNBOUNDED FOLLOWING ");
3318 else if (wc->frameOptions & FRAMEOPTION_END_CURRENT_ROW)
3319 appendStringInfoString(buf, "CURRENT ROW ");
3320 else if (wc->frameOptions & FRAMEOPTION_END_VALUE)
3322 get_rule_expr(wc->endOffset, context, false);
3323 if (wc->frameOptions & FRAMEOPTION_END_VALUE_PRECEDING)
3324 appendStringInfoString(buf, " PRECEDING ");
3325 else if (wc->frameOptions & FRAMEOPTION_END_VALUE_FOLLOWING)
3326 appendStringInfoString(buf, " FOLLOWING ");
3333 /* we will now have a trailing space; remove it */
3336 appendStringInfoChar(buf, ')');
3340 * get_insert_query_def - Parse back an INSERT parsetree
3344 get_insert_query_def(Query *query, deparse_context *context)
3346 StringInfo buf = context->buf;
3347 RangeTblEntry *select_rte = NULL;
3348 RangeTblEntry *values_rte = NULL;
3351 ListCell *values_cell;
3353 List *strippedexprs;
3356 * If it's an INSERT ... SELECT or VALUES (...), (...), ... there will be
3357 * a single RTE for the SELECT or VALUES.
3359 foreach(l, query->rtable)
3361 rte = (RangeTblEntry *) lfirst(l);
3363 if (rte->rtekind == RTE_SUBQUERY)
3366 elog(ERROR, "too many subquery RTEs in INSERT");
3370 if (rte->rtekind == RTE_VALUES)
3373 elog(ERROR, "too many values RTEs in INSERT");
3377 if (select_rte && values_rte)
3378 elog(ERROR, "both subquery and values RTEs in INSERT");
3381 * Start the query with INSERT INTO relname
3383 rte = rt_fetch(query->resultRelation, query->rtable);
3384 Assert(rte->rtekind == RTE_RELATION);
3386 if (PRETTY_INDENT(context))
3388 context->indentLevel += PRETTYINDENT_STD;
3389 appendStringInfoChar(buf, ' ');
3391 appendStringInfo(buf, "INSERT INTO %s (",
3392 generate_relation_name(rte->relid, NIL));
3395 * Add the insert-column-names list. To handle indirection properly, we
3396 * need to look for indirection nodes in the top targetlist (if it's
3397 * INSERT ... SELECT or INSERT ... single VALUES), or in the first
3398 * expression list of the VALUES RTE (if it's INSERT ... multi VALUES). We
3399 * assume that all the expression lists will have similar indirection in
3403 values_cell = list_head((List *) linitial(values_rte->values_lists));
3406 strippedexprs = NIL;
3408 foreach(l, query->targetList)
3410 TargetEntry *tle = (TargetEntry *) lfirst(l);
3413 continue; /* ignore junk entries */
3415 appendStringInfoString(buf, sep);
3419 * Put out name of target column; look in the catalogs, not at
3420 * tle->resname, since resname will fail to track RENAME.
3422 appendStringInfoString(buf,
3423 quote_identifier(get_relid_attribute_name(rte->relid,
3427 * Print any indirection needed (subfields or subscripts), and strip
3428 * off the top-level nodes representing the indirection assignments.
3432 /* we discard the stripped expression in this case */
3433 processIndirection((Node *) lfirst(values_cell), context, true);
3434 values_cell = lnext(values_cell);
3438 /* we keep a list of the stripped expressions in this case */
3439 strippedexprs = lappend(strippedexprs,
3440 processIndirection((Node *) tle->expr,
3444 appendStringInfo(buf, ") ");
3448 /* Add the SELECT */
3449 get_query_def(select_rte->subquery, buf, NIL, NULL,
3450 context->prettyFlags, context->indentLevel);
3452 else if (values_rte)
3454 /* A WITH clause is possible here */
3455 get_with_clause(query, context);
3456 /* Add the multi-VALUES expression lists */
3457 get_values_def(values_rte->values_lists, context);
3461 /* A WITH clause is possible here */
3462 get_with_clause(query, context);
3463 /* Add the single-VALUES expression list */
3464 appendContextKeyword(context, "VALUES (",
3465 -PRETTYINDENT_STD, PRETTYINDENT_STD, 2);
3466 get_rule_expr((Node *) strippedexprs, context, false);
3467 appendStringInfoChar(buf, ')');
3470 /* Add RETURNING if present */
3471 if (query->returningList)
3473 appendContextKeyword(context, " RETURNING",
3474 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
3475 get_target_list(query->returningList, context, NULL);
3481 * get_update_query_def - Parse back an UPDATE parsetree
3485 get_update_query_def(Query *query, deparse_context *context)
3487 StringInfo buf = context->buf;
3493 * Start the query with UPDATE relname SET
3495 rte = rt_fetch(query->resultRelation, query->rtable);
3496 Assert(rte->rtekind == RTE_RELATION);
3497 if (PRETTY_INDENT(context))
3499 appendStringInfoChar(buf, ' ');
3500 context->indentLevel += PRETTYINDENT_STD;
3502 appendStringInfo(buf, "UPDATE %s%s",
3504 generate_relation_name(rte->relid, NIL));
3505 if (rte->alias != NULL)
3506 appendStringInfo(buf, " %s",
3507 quote_identifier(rte->alias->aliasname));
3508 appendStringInfoString(buf, " SET ");
3510 /* Add the comma separated list of 'attname = value' */
3512 foreach(l, query->targetList)
3514 TargetEntry *tle = (TargetEntry *) lfirst(l);
3518 continue; /* ignore junk entries */
3520 appendStringInfoString(buf, sep);
3524 * Put out name of target column; look in the catalogs, not at
3525 * tle->resname, since resname will fail to track RENAME.
3527 appendStringInfoString(buf,
3528 quote_identifier(get_relid_attribute_name(rte->relid,
3532 * Print any indirection needed (subfields or subscripts), and strip
3533 * off the top-level nodes representing the indirection assignments.
3535 expr = processIndirection((Node *) tle->expr, context, true);
3537 appendStringInfo(buf, " = ");
3539 get_rule_expr(expr, context, false);
3542 /* Add the FROM clause if needed */
3543 get_from_clause(query, " FROM ", context);
3545 /* Add a WHERE clause if given */
3546 if (query->jointree->quals != NULL)
3548 appendContextKeyword(context, " WHERE ",
3549 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
3550 get_rule_expr(query->jointree->quals, context, false);
3553 /* Add RETURNING if present */
3554 if (query->returningList)
3556 appendContextKeyword(context, " RETURNING",
3557 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
3558 get_target_list(query->returningList, context, NULL);
3564 * get_delete_query_def - Parse back a DELETE parsetree
3568 get_delete_query_def(Query *query, deparse_context *context)
3570 StringInfo buf = context->buf;
3574 * Start the query with DELETE FROM relname
3576 rte = rt_fetch(query->resultRelation, query->rtable);
3577 Assert(rte->rtekind == RTE_RELATION);
3578 if (PRETTY_INDENT(context))
3580 appendStringInfoChar(buf, ' ');
3581 context->indentLevel += PRETTYINDENT_STD;
3583 appendStringInfo(buf, "DELETE FROM %s%s",
3585 generate_relation_name(rte->relid, NIL));
3586 if (rte->alias != NULL)
3587 appendStringInfo(buf, " %s",
3588 quote_identifier(rte->alias->aliasname));
3590 /* Add the USING clause if given */
3591 get_from_clause(query, " USING ", context);
3593 /* Add a WHERE clause if given */
3594 if (query->jointree->quals != NULL)
3596 appendContextKeyword(context, " WHERE ",
3597 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
3598 get_rule_expr(query->jointree->quals, context, false);
3601 /* Add RETURNING if present */
3602 if (query->returningList)
3604 appendContextKeyword(context, " RETURNING",
3605 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
3606 get_target_list(query->returningList, context, NULL);
3612 * get_utility_query_def - Parse back a UTILITY parsetree
3616 get_utility_query_def(Query *query, deparse_context *context)
3618 StringInfo buf = context->buf;
3620 if (query->utilityStmt && IsA(query->utilityStmt, NotifyStmt))
3622 NotifyStmt *stmt = (NotifyStmt *) query->utilityStmt;
3624 appendContextKeyword(context, "",
3625 0, PRETTYINDENT_STD, 1);
3626 appendStringInfo(buf, "NOTIFY %s",
3627 quote_identifier(stmt->conditionname));
3630 appendStringInfoString(buf, ", ");
3631 simple_quote_literal(buf, stmt->payload);
3636 /* Currently only NOTIFY utility commands can appear in rules */
3637 elog(ERROR, "unexpected utility statement type");
3643 * Display a Var appropriately.
3645 * In some cases (currently only when recursing into an unnamed join)
3646 * the Var's varlevelsup has to be interpreted with respect to a context
3647 * above the current one; levelsup indicates the offset.
3649 * If showstar is TRUE, whole-row Vars are displayed as "foo.*";
3650 * if FALSE, merely as "foo".
3652 * Returns the attname of the Var, or NULL if not determinable.
3655 get_variable(Var *var, int levelsup, bool showstar, deparse_context *context)
3657 StringInfo buf = context->buf;
3661 deparse_namespace *dpns;
3666 /* Find appropriate nesting depth */
3667 netlevelsup = var->varlevelsup + levelsup;
3668 if (netlevelsup >= list_length(context->namespaces))
3669 elog(ERROR, "bogus varlevelsup: %d offset %d",
3670 var->varlevelsup, levelsup);
3671 dpns = (deparse_namespace *) list_nth(context->namespaces,
3675 * Try to find the relevant RTE in this rtable. In a plan tree, it's
3676 * likely that varno is OUTER or INNER, in which case we must dig down
3677 * into the subplans.
3679 if (var->varno >= 1 && var->varno <= list_length(dpns->rtable))
3681 rte = rt_fetch(var->varno, dpns->rtable);
3682 attnum = var->varattno;
3684 else if (var->varno == OUTER && dpns->outer_plan)
3687 deparse_namespace save_dpns;
3689 tle = get_tle_by_resno(dpns->outer_plan->targetlist, var->varattno);
3691 elog(ERROR, "bogus varattno for OUTER var: %d", var->varattno);
3693 Assert(netlevelsup == 0);
3694 push_child_plan(dpns, dpns->outer_planstate, &save_dpns);
3697 * Force parentheses because our caller probably assumed a Var is a
3698 * simple expression.
3700 if (!IsA(tle->expr, Var))
3701 appendStringInfoChar(buf, '(');
3702 get_rule_expr((Node *) tle->expr, context, true);
3703 if (!IsA(tle->expr, Var))
3704 appendStringInfoChar(buf, ')');
3706 pop_child_plan(dpns, &save_dpns);
3709 else if (var->varno == INNER && dpns->inner_plan)
3712 deparse_namespace save_dpns;
3714 tle = get_tle_by_resno(dpns->inner_plan->targetlist, var->varattno);
3716 elog(ERROR, "bogus varattno for INNER var: %d", var->varattno);
3718 Assert(netlevelsup == 0);
3719 push_child_plan(dpns, dpns->inner_planstate, &save_dpns);
3722 * Force parentheses because our caller probably assumed a Var is a
3723 * simple expression.
3725 if (!IsA(tle->expr, Var))
3726 appendStringInfoChar(buf, '(');
3727 get_rule_expr((Node *) tle->expr, context, true);
3728 if (!IsA(tle->expr, Var))
3729 appendStringInfoChar(buf, ')');
3731 pop_child_plan(dpns, &save_dpns);
3736 elog(ERROR, "bogus varno: %d", var->varno);
3737 return NULL; /* keep compiler quiet */
3741 * The planner will sometimes emit Vars referencing resjunk elements of a
3742 * subquery's target list (this is currently only possible if it chooses
3743 * to generate a "physical tlist" for a SubqueryScan or CteScan node).
3744 * Although we prefer to print subquery-referencing Vars using the
3745 * subquery's alias, that's not possible for resjunk items since they have
3746 * no alias. So in that case, drill down to the subplan and print the
3747 * contents of the referenced tlist item. This works because in a plan
3748 * tree, such Vars can only occur in a SubqueryScan or CteScan node,
3749 * and we'll have set dpns->inner_plan to reference the child plan node.
3751 if ((rte->rtekind == RTE_SUBQUERY || rte->rtekind == RTE_CTE) &&
3752 attnum > list_length(rte->eref->colnames) &&
3756 deparse_namespace save_dpns;
3758 tle = get_tle_by_resno(dpns->inner_plan->targetlist, var->varattno);
3760 elog(ERROR, "bogus varattno for subquery var: %d", var->varattno);
3762 Assert(netlevelsup == 0);
3763 push_child_plan(dpns, dpns->inner_planstate, &save_dpns);
3766 * Force parentheses because our caller probably assumed a Var is a
3767 * simple expression.
3769 if (!IsA(tle->expr, Var))
3770 appendStringInfoChar(buf, '(');
3771 get_rule_expr((Node *) tle->expr, context, true);
3772 if (!IsA(tle->expr, Var))
3773 appendStringInfoChar(buf, ')');
3775 pop_child_plan(dpns, &save_dpns);
3779 /* Identify names to use */
3780 schemaname = NULL; /* default assumptions */
3781 refname = rte->eref->aliasname;
3783 /* Exceptions occur only if the RTE is alias-less */
3784 if (rte->alias == NULL)
3786 if (rte->rtekind == RTE_RELATION)
3789 * It's possible that use of the bare refname would find another
3790 * more-closely-nested RTE, or be ambiguous, in which case we need
3791 * to specify the schemaname to avoid these errors.
3793 if (find_rte_by_refname(rte->eref->aliasname, context) != rte)
3794 schemaname = get_namespace_name(get_rel_namespace(rte->relid));
3796 else if (rte->rtekind == RTE_JOIN)
3799 * If it's an unnamed join, look at the expansion of the alias
3800 * variable. If it's a simple reference to one of the input vars
3801 * then recursively print the name of that var, instead. (This
3802 * allows correct decompiling of cases where there are identically
3803 * named columns on both sides of the join.) When it's not a
3804 * simple reference, we have to just print the unqualified
3805 * variable name (this can only happen with columns that were
3806 * merged by USING or NATURAL clauses).
3808 * This wouldn't work in decompiling plan trees, because we don't
3809 * store joinaliasvars lists after planning; but a plan tree
3810 * should never contain a join alias variable.
3812 if (rte->joinaliasvars == NIL)
3813 elog(ERROR, "cannot decompile join alias var in plan tree");
3818 aliasvar = (Var *) list_nth(rte->joinaliasvars, attnum - 1);
3819 if (IsA(aliasvar, Var))
3821 return get_variable(aliasvar, var->varlevelsup + levelsup,
3825 /* Unnamed join has neither schemaname nor refname */
3830 if (attnum == InvalidAttrNumber)
3833 attname = get_rte_attribute_name(rte, attnum);
3835 if (refname && (context->varprefix || attname == NULL))
3838 appendStringInfo(buf, "%s.",
3839 quote_identifier(schemaname));
3840 appendStringInfoString(buf, quote_identifier(refname));
3841 if (attname || showstar)
3842 appendStringInfoChar(buf, '.');
3845 appendStringInfoString(buf, quote_identifier(attname));
3847 appendStringInfoChar(buf, '*');
3854 * Get the name of a field of an expression of composite type.
3856 * This is fairly straightforward except for the case of a Var of type RECORD.
3857 * Since no actual table or view column is allowed to have type RECORD, such
3858 * a Var must refer to a JOIN or FUNCTION RTE or to a subquery output. We
3859 * drill down to find the ultimate defining expression and attempt to infer
3860 * the field name from it. We ereport if we can't determine the name.
3862 * levelsup is an extra offset to interpret the Var's varlevelsup correctly.
3865 get_name_for_var_field(Var *var, int fieldno,
3866 int levelsup, deparse_context *context)
3871 deparse_namespace *dpns;
3872 TupleDesc tupleDesc;
3876 * If it's a RowExpr that was expanded from a whole-row Var, use the
3877 * column names attached to it.
3879 if (IsA(var, RowExpr))
3881 RowExpr *r = (RowExpr *) var;
3883 if (fieldno > 0 && fieldno <= list_length(r->colnames))
3884 return strVal(list_nth(r->colnames, fieldno - 1));
3888 * If it's a Var of type RECORD, we have to find what the Var refers to;
3889 * if not, we can use get_expr_result_type. If that fails, we try
3890 * lookup_rowtype_tupdesc, which will probably fail too, but will ereport
3891 * an acceptable message.
3893 if (!IsA(var, Var) ||
3894 var->vartype != RECORDOID)
3896 if (get_expr_result_type((Node *) var, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
3897 tupleDesc = lookup_rowtype_tupdesc_copy(exprType((Node *) var),
3898 exprTypmod((Node *) var));
3900 /* Got the tupdesc, so we can extract the field name */
3901 Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
3902 return NameStr(tupleDesc->attrs[fieldno - 1]->attname);
3905 /* Find appropriate nesting depth */
3906 netlevelsup = var->varlevelsup + levelsup;
3907 if (netlevelsup >= list_length(context->namespaces))
3908 elog(ERROR, "bogus varlevelsup: %d offset %d",
3909 var->varlevelsup, levelsup);
3910 dpns = (deparse_namespace *) list_nth(context->namespaces,
3914 * Try to find the relevant RTE in this rtable. In a plan tree, it's
3915 * likely that varno is OUTER or INNER, in which case we must dig down
3916 * into the subplans.
3918 if (var->varno >= 1 && var->varno <= list_length(dpns->rtable))
3920 rte = rt_fetch(var->varno, dpns->rtable);
3921 attnum = var->varattno;
3923 else if (var->varno == OUTER && dpns->outer_plan)
3926 deparse_namespace save_dpns;
3929 tle = get_tle_by_resno(dpns->outer_plan->targetlist, var->varattno);
3931 elog(ERROR, "bogus varattno for OUTER var: %d", var->varattno);
3933 Assert(netlevelsup == 0);
3934 push_child_plan(dpns, dpns->outer_planstate, &save_dpns);
3936 result = get_name_for_var_field((Var *) tle->expr, fieldno,
3939 pop_child_plan(dpns, &save_dpns);
3942 else if (var->varno == INNER && dpns->inner_plan)
3945 deparse_namespace save_dpns;
3948 tle = get_tle_by_resno(dpns->inner_plan->targetlist, var->varattno);
3950 elog(ERROR, "bogus varattno for INNER var: %d", var->varattno);
3952 Assert(netlevelsup == 0);
3953 push_child_plan(dpns, dpns->inner_planstate, &save_dpns);
3955 result = get_name_for_var_field((Var *) tle->expr, fieldno,
3958 pop_child_plan(dpns, &save_dpns);
3963 elog(ERROR, "bogus varno: %d", var->varno);
3964 return NULL; /* keep compiler quiet */
3967 if (attnum == InvalidAttrNumber)
3969 /* Var is whole-row reference to RTE, so select the right field */
3970 return get_rte_attribute_name(rte, fieldno);
3974 * This part has essentially the same logic as the parser's
3975 * expandRecordVariable() function, but we are dealing with a different
3976 * representation of the input context, and we only need one field name
3977 * not a TupleDesc. Also, we need special cases for finding subquery and
3978 * CTE subplans when deparsing Plan trees.
3980 expr = (Node *) var; /* default if we can't drill down */
3982 switch (rte->rtekind)
3989 * This case should not occur: a column of a table or values list
3990 * shouldn't have type RECORD. Fall through and fail (most
3991 * likely) at the bottom.
3995 /* Subselect-in-FROM: examine sub-select's output expr */
3999 TargetEntry *ste = get_tle_by_resno(rte->subquery->targetList,
4002 if (ste == NULL || ste->resjunk)
4003 elog(ERROR, "subquery %s does not have attribute %d",
4004 rte->eref->aliasname, attnum);
4005 expr = (Node *) ste->expr;
4009 * Recurse into the sub-select to see what its Var
4010 * refers to. We have to build an additional level of
4011 * namespace to keep in step with varlevelsup in the
4014 deparse_namespace mydpns;
4017 memset(&mydpns, 0, sizeof(mydpns));
4018 mydpns.rtable = rte->subquery->rtable;
4019 mydpns.ctes = rte->subquery->cteList;
4021 context->namespaces = lcons(&mydpns,
4022 context->namespaces);
4024 result = get_name_for_var_field((Var *) expr, fieldno,
4027 context->namespaces =
4028 list_delete_first(context->namespaces);
4032 /* else fall through to inspect the expression */
4037 * We're deparsing a Plan tree so we don't have complete
4038 * RTE entries (in particular, rte->subquery is NULL). But
4039 * the only place we'd see a Var directly referencing a
4040 * SUBQUERY RTE is in a SubqueryScan plan node, and we can
4041 * look into the child plan's tlist instead.
4044 deparse_namespace save_dpns;
4047 if (!dpns->inner_plan)
4048 elog(ERROR, "failed to find plan for subquery %s",
4049 rte->eref->aliasname);
4050 tle = get_tle_by_resno(dpns->inner_plan->targetlist,
4053 elog(ERROR, "bogus varattno for subquery var: %d",
4055 Assert(netlevelsup == 0);
4056 push_child_plan(dpns, dpns->inner_planstate, &save_dpns);
4058 result = get_name_for_var_field((Var *) tle->expr, fieldno,
4061 pop_child_plan(dpns, &save_dpns);
4067 /* Join RTE --- recursively inspect the alias variable */
4068 if (rte->joinaliasvars == NIL)
4069 elog(ERROR, "cannot decompile join alias var in plan tree");
4070 Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars));
4071 expr = (Node *) list_nth(rte->joinaliasvars, attnum - 1);
4073 return get_name_for_var_field((Var *) expr, fieldno,
4074 var->varlevelsup + levelsup,
4076 /* else fall through to inspect the expression */
4081 * We couldn't get here unless a function is declared with one of
4082 * its result columns as RECORD, which is not allowed.
4086 /* CTE reference: examine subquery's output expr */
4088 CommonTableExpr *cte = NULL;
4093 * Try to find the referenced CTE using the namespace stack.
4095 ctelevelsup = rte->ctelevelsup + netlevelsup;
4096 if (ctelevelsup >= list_length(context->namespaces))
4100 deparse_namespace *ctedpns;
4102 ctedpns = (deparse_namespace *)
4103 list_nth(context->namespaces, ctelevelsup);
4104 foreach(lc, ctedpns->ctes)
4106 cte = (CommonTableExpr *) lfirst(lc);
4107 if (strcmp(cte->ctename, rte->ctename) == 0)
4113 Query *ctequery = (Query *) cte->ctequery;
4114 TargetEntry *ste = get_tle_by_resno(ctequery->targetList,
4117 if (ste == NULL || ste->resjunk)
4118 elog(ERROR, "subquery %s does not have attribute %d",
4119 rte->eref->aliasname, attnum);
4120 expr = (Node *) ste->expr;
4124 * Recurse into the CTE to see what its Var refers to.
4125 * We have to build an additional level of namespace
4126 * to keep in step with varlevelsup in the CTE.
4127 * Furthermore it could be an outer CTE, so we may
4128 * have to delete some levels of namespace.
4130 List *save_nslist = context->namespaces;
4132 deparse_namespace mydpns;
4135 memset(&mydpns, 0, sizeof(mydpns));
4136 mydpns.rtable = ctequery->rtable;
4137 mydpns.ctes = ctequery->cteList;
4139 new_nslist = list_copy_tail(context->namespaces,
4141 context->namespaces = lcons(&mydpns, new_nslist);
4143 result = get_name_for_var_field((Var *) expr, fieldno,
4146 context->namespaces = save_nslist;
4150 /* else fall through to inspect the expression */
4155 * We're deparsing a Plan tree so we don't have a CTE
4156 * list. But the only place we'd see a Var directly
4157 * referencing a CTE RTE is in a CteScan plan node, and we
4158 * can look into the subplan's tlist instead.
4161 deparse_namespace save_dpns;
4164 if (!dpns->inner_plan)
4165 elog(ERROR, "failed to find plan for CTE %s",
4166 rte->eref->aliasname);
4167 tle = get_tle_by_resno(dpns->inner_plan->targetlist,
4170 elog(ERROR, "bogus varattno for subquery var: %d",
4172 Assert(netlevelsup == 0);
4173 push_child_plan(dpns, dpns->inner_planstate, &save_dpns);
4175 result = get_name_for_var_field((Var *) tle->expr, fieldno,
4178 pop_child_plan(dpns, &save_dpns);
4186 * We now have an expression we can't expand any more, so see if
4187 * get_expr_result_type() can do anything with it. If not, pass to
4188 * lookup_rowtype_tupdesc() which will probably fail, but will give an
4189 * appropriate error message while failing.
4191 if (get_expr_result_type(expr, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
4192 tupleDesc = lookup_rowtype_tupdesc_copy(exprType(expr),
4195 /* Got the tupdesc, so we can extract the field name */
4196 Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
4197 return NameStr(tupleDesc->attrs[fieldno - 1]->attname);
4202 * find_rte_by_refname - look up an RTE by refname in a deparse context
4204 * Returns NULL if there is no matching RTE or the refname is ambiguous.
4206 * NOTE: this code is not really correct since it does not take account of
4207 * the fact that not all the RTEs in a rangetable may be visible from the
4208 * point where a Var reference appears. For the purposes we need, however,
4209 * the only consequence of a false match is that we might stick a schema
4210 * qualifier on a Var that doesn't really need it. So it seems close
4213 static RangeTblEntry *
4214 find_rte_by_refname(const char *refname, deparse_context *context)
4216 RangeTblEntry *result = NULL;
4219 foreach(nslist, context->namespaces)
4221 deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist);
4224 foreach(rtlist, dpns->rtable)
4226 RangeTblEntry *rte = (RangeTblEntry *) lfirst(rtlist);
4228 if (strcmp(rte->eref->aliasname, refname) == 0)
4231 return NULL; /* it's ambiguous */
4242 * Display a Param appropriately.
4245 get_parameter(Param *param, deparse_context *context)
4248 * If it's a PARAM_EXEC parameter, try to locate the expression from
4249 * which the parameter was computed. This will necessarily be in some
4250 * ancestor of the current expression's PlanState. Note that failing
4251 * to find a referent isn't an error, since the Param might well be a
4252 * subplan output rather than an input.
4254 if (param->paramkind == PARAM_EXEC)
4256 deparse_namespace *dpns;
4257 PlanState *child_ps;
4258 bool in_same_plan_level;
4261 dpns = (deparse_namespace *) linitial(context->namespaces);
4262 child_ps = dpns->planstate;
4263 in_same_plan_level = true;
4265 foreach(lc, dpns->ancestors)
4267 PlanState *ps = (PlanState *) lfirst(lc);
4271 * NestLoops transmit params to their inner child only; also,
4272 * once we've crawled up out of a subplan, this couldn't
4273 * possibly be the right match.
4275 if (IsA(ps, NestLoopState) &&
4276 child_ps == innerPlanState(ps) &&
4279 NestLoop *nl = (NestLoop *) ps->plan;
4281 foreach(lc2, nl->nestParams)
4283 NestLoopParam *nlp = (NestLoopParam *) lfirst(lc2);
4285 if (nlp->paramno == param->paramid)
4287 /* Found a match, so print it */
4288 print_parameter_expr((Node *) nlp->paramval, lc,
4296 * Check to see if we're crawling up from a subplan.
4298 foreach(lc2, ps->subPlan)
4300 SubPlanState *sstate = (SubPlanState *) lfirst(lc2);
4301 SubPlan *subplan = (SubPlan *) sstate->xprstate.expr;
4305 if (child_ps != sstate->planstate)
4308 /* Matched subplan, so check its arguments */
4309 forboth(lc3, subplan->parParam, lc4, subplan->args)
4311 int paramid = lfirst_int(lc3);
4312 Node *arg = (Node *) lfirst(lc4);
4314 if (paramid == param->paramid)
4316 /* Found a match, so print it */
4317 print_parameter_expr(arg, lc, dpns, context);
4322 /* Keep looking, but we are emerging from a subplan. */
4323 in_same_plan_level = false;
4328 * Likewise check to see if we're emerging from an initplan.
4329 * Initplans never have any parParams, so no need to search that
4330 * list, but we need to know if we should reset
4331 * in_same_plan_level.
4333 foreach(lc2, ps->initPlan)
4335 SubPlanState *sstate = (SubPlanState *) lfirst(lc2);
4337 if (child_ps != sstate->planstate)
4340 /* No parameters to be had here. */
4341 Assert(((SubPlan *) sstate->xprstate.expr)->parParam == NIL);
4343 /* Keep looking, but we are emerging from an initplan. */
4344 in_same_plan_level = false;
4348 /* No luck, crawl up to next ancestor */
4354 * Not PARAM_EXEC, or couldn't find referent: just print $N.
4356 appendStringInfo(context->buf, "$%d", param->paramid);
4359 /* Print a parameter reference expression found by get_parameter */
4361 print_parameter_expr(Node *expr, ListCell *ancestor_cell,
4362 deparse_namespace *dpns, deparse_context *context)
4364 deparse_namespace save_dpns;
4365 bool save_varprefix;
4367 /* Switch attention to the ancestor plan node */
4368 push_ancestor_plan(dpns, ancestor_cell, &save_dpns);
4371 * Force prefixing of Vars, since they won't belong to the relation being
4372 * scanned in the original plan node.
4374 save_varprefix = context->varprefix;
4375 context->varprefix = true;
4378 * We don't need to add parentheses because a Param's expansion is
4379 * (currently) always a Var or Aggref.
4381 Assert(IsA(expr, Var) || IsA(expr, Aggref));
4383 get_rule_expr(expr, context, false);
4385 context->varprefix = save_varprefix;
4387 pop_ancestor_plan(dpns, &save_dpns);
4391 * get_simple_binary_op_name
4393 * helper function for isSimpleNode
4394 * will return single char binary operator name, or NULL if it's not
4397 get_simple_binary_op_name(OpExpr *expr)
4399 List *args = expr->args;
4401 if (list_length(args) == 2)
4403 /* binary operator */
4404 Node *arg1 = (Node *) linitial(args);
4405 Node *arg2 = (Node *) lsecond(args);
4408 op = generate_operator_name(expr->opno, exprType(arg1), exprType(arg2));
4409 if (strlen(op) == 1)
4417 * isSimpleNode - check if given node is simple (doesn't need parenthesizing)
4419 * true : simple in the context of parent node's type
4420 * false : not simple
4423 isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
4428 switch (nodeTag(node))
4433 case T_CoerceToDomainValue:
4434 case T_SetToDefault:
4435 case T_CurrentOfExpr:
4436 /* single words: always simple */
4442 case T_CoalesceExpr:
4449 /* function-like: name(..) or name[..] */
4452 /* CASE keywords act as parentheses */
4459 * appears simple since . has top precedence, unless parent is
4460 * T_FieldSelect itself!
4462 return (IsA(parentNode, FieldSelect) ? false : true);
4467 * treat like FieldSelect (probably doesn't matter)
4469 return (IsA(parentNode, FieldStore) ? false : true);
4471 case T_CoerceToDomain:
4472 /* maybe simple, check args */
4473 return isSimpleNode((Node *) ((CoerceToDomain *) node)->arg,
4476 return isSimpleNode((Node *) ((RelabelType *) node)->arg,
4479 return isSimpleNode((Node *) ((CoerceViaIO *) node)->arg,
4481 case T_ArrayCoerceExpr:
4482 return isSimpleNode((Node *) ((ArrayCoerceExpr *) node)->arg,
4484 case T_ConvertRowtypeExpr:
4485 return isSimpleNode((Node *) ((ConvertRowtypeExpr *) node)->arg,
4490 /* depends on parent node type; needs further checking */
4491 if (prettyFlags & PRETTYFLAG_PAREN && IsA(parentNode, OpExpr))
4494 const char *parentOp;
4497 bool is_lopriparent;
4498 bool is_hipriparent;
4500 op = get_simple_binary_op_name((OpExpr *) node);
4504 /* We know only the basic operators + - and * / % */
4505 is_lopriop = (strchr("+-", *op) != NULL);
4506 is_hipriop = (strchr("*/%", *op) != NULL);
4507 if (!(is_lopriop || is_hipriop))
4510 parentOp = get_simple_binary_op_name((OpExpr *) parentNode);
4514 is_lopriparent = (strchr("+-", *parentOp) != NULL);
4515 is_hipriparent = (strchr("*/%", *parentOp) != NULL);
4516 if (!(is_lopriparent || is_hipriparent))
4519 if (is_hipriop && is_lopriparent)
4520 return true; /* op binds tighter than parent */
4522 if (is_lopriop && is_hipriparent)
4526 * Operators are same priority --- can skip parens only if
4527 * we have (a - b) - c, not a - (b - c).
4529 if (node == (Node *) linitial(((OpExpr *) parentNode)->args))
4534 /* else do the same stuff as for T_SubLink et al. */
4541 case T_DistinctExpr:
4542 switch (nodeTag(parentNode))
4546 /* special handling for casts */
4547 CoercionForm type = ((FuncExpr *) parentNode)->funcformat;
4549 if (type == COERCE_EXPLICIT_CAST ||
4550 type == COERCE_IMPLICIT_CAST)
4552 return true; /* own parentheses */
4554 case T_BoolExpr: /* lower precedence */
4555 case T_ArrayRef: /* other separators */
4556 case T_ArrayExpr: /* other separators */
4557 case T_RowExpr: /* other separators */
4558 case T_CoalesceExpr: /* own parentheses */
4559 case T_MinMaxExpr: /* own parentheses */
4560 case T_XmlExpr: /* own parentheses */
4561 case T_NullIfExpr: /* other separators */
4562 case T_Aggref: /* own parentheses */
4563 case T_WindowFunc: /* own parentheses */
4564 case T_CaseExpr: /* other separators */
4571 switch (nodeTag(parentNode))
4574 if (prettyFlags & PRETTYFLAG_PAREN)
4577 BoolExprType parentType;
4579 type = ((BoolExpr *) node)->boolop;
4580 parentType = ((BoolExpr *) parentNode)->boolop;
4585 if (parentType == AND_EXPR || parentType == OR_EXPR)
4589 if (parentType == OR_EXPR)
4597 /* special handling for casts */
4598 CoercionForm type = ((FuncExpr *) parentNode)->funcformat;
4600 if (type == COERCE_EXPLICIT_CAST ||
4601 type == COERCE_IMPLICIT_CAST)
4603 return true; /* own parentheses */
4605 case T_ArrayRef: /* other separators */
4606 case T_ArrayExpr: /* other separators */
4607 case T_RowExpr: /* other separators */
4608 case T_CoalesceExpr: /* own parentheses */
4609 case T_MinMaxExpr: /* own parentheses */
4610 case T_XmlExpr: /* own parentheses */
4611 case T_NullIfExpr: /* other separators */
4612 case T_Aggref: /* own parentheses */
4613 case T_WindowFunc: /* own parentheses */
4614 case T_CaseExpr: /* other separators */
4623 /* those we don't know: in dubio complexo */
4629 * appendContextKeyword - append a keyword to buffer
4631 * If prettyPrint is enabled, perform a line break, and adjust indentation.
4632 * Otherwise, just append the keyword.
4635 appendContextKeyword(deparse_context *context, const char *str,
4636 int indentBefore, int indentAfter, int indentPlus)
4638 if (PRETTY_INDENT(context))
4640 context->indentLevel += indentBefore;
4642 appendStringInfoChar(context->buf, '\n');
4643 appendStringInfoSpaces(context->buf,
4644 Max(context->indentLevel, 0) + indentPlus);
4645 appendStringInfoString(context->buf, str);
4647 context->indentLevel += indentAfter;
4648 if (context->indentLevel < 0)
4649 context->indentLevel = 0;
4652 appendStringInfoString(context->buf, str);
4656 * get_rule_expr_paren - deparse expr using get_rule_expr,
4657 * embracing the string with parentheses if necessary for prettyPrint.
4659 * Never embrace if prettyFlags=0, because it's done in the calling node.
4661 * Any node that does *not* embrace its argument node by sql syntax (with
4662 * parentheses, non-operator keywords like CASE/WHEN/ON, or comma etc) should
4663 * use get_rule_expr_paren instead of get_rule_expr so parentheses can be
4667 get_rule_expr_paren(Node *node, deparse_context *context,
4668 bool showimplicit, Node *parentNode)
4672 need_paren = PRETTY_PAREN(context) &&
4673 !isSimpleNode(node, parentNode, context->prettyFlags);
4676 appendStringInfoChar(context->buf, '(');
4678 get_rule_expr(node, context, showimplicit);
4681 appendStringInfoChar(context->buf, ')');
4686 * get_rule_expr - Parse back an expression
4688 * Note: showimplicit determines whether we display any implicit cast that
4689 * is present at the top of the expression tree. It is a passed argument,
4690 * not a field of the context struct, because we change the value as we
4691 * recurse down into the expression. In general we suppress implicit casts
4692 * when the result type is known with certainty (eg, the arguments of an
4693 * OR must be boolean). We display implicit casts for arguments of functions
4694 * and operators, since this is needed to be certain that the same function
4695 * or operator will be chosen when the expression is re-parsed.
4699 get_rule_expr(Node *node, deparse_context *context,
4702 StringInfo buf = context->buf;
4708 * Each level of get_rule_expr must emit an indivisible term
4709 * (parenthesized if necessary) to ensure result is reparsed into the same
4710 * expression tree. The only exception is that when the input is a List,
4711 * we emit the component items comma-separated with no surrounding
4712 * decoration; this is convenient for most callers.
4714 switch (nodeTag(node))
4717 (void) get_variable((Var *) node, 0, true, context);
4721 get_const_expr((Const *) node, context, 0);
4725 get_parameter((Param *) node, context);
4729 get_agg_expr((Aggref *) node, context);
4733 get_windowfunc_expr((WindowFunc *) node, context);
4738 ArrayRef *aref = (ArrayRef *) node;
4742 * If the argument is a CaseTestExpr, we must be inside a
4743 * FieldStore, ie, we are assigning to an element of an array
4744 * within a composite column. Since we already punted on
4745 * displaying the FieldStore's target information, just punt
4746 * here too, and display only the assignment source
4749 if (IsA(aref->refexpr, CaseTestExpr))
4751 Assert(aref->refassgnexpr);
4752 get_rule_expr((Node *) aref->refassgnexpr,
4753 context, showimplicit);
4758 * Parenthesize the argument unless it's a simple Var or a
4759 * FieldSelect. (In particular, if it's another ArrayRef, we
4760 * *must* parenthesize to avoid confusion.)
4762 need_parens = !IsA(aref->refexpr, Var) &&
4763 !IsA(aref->refexpr, FieldSelect);
4765 appendStringInfoChar(buf, '(');
4766 get_rule_expr((Node *) aref->refexpr, context, showimplicit);
4768 appendStringInfoChar(buf, ')');
4771 * If there's a refassgnexpr, we want to print the node in the
4772 * format "array[subscripts] := refassgnexpr". This is not
4773 * legal SQL, so decompilation of INSERT or UPDATE statements
4774 * should always use processIndirection as part of the
4775 * statement-level syntax. We should only see this when
4776 * EXPLAIN tries to print the targetlist of a plan resulting
4777 * from such a statement.
4779 if (aref->refassgnexpr)
4784 * Use processIndirection to print this node's subscripts
4785 * as well as any additional field selections or
4786 * subscripting in immediate descendants. It returns the
4787 * RHS expr that is actually being "assigned".
4789 refassgnexpr = processIndirection(node, context, true);
4790 appendStringInfoString(buf, " := ");
4791 get_rule_expr(refassgnexpr, context, showimplicit);
4795 /* Just an ordinary array fetch, so print subscripts */
4796 printSubscripts(aref, context);
4802 get_func_expr((FuncExpr *) node, context, showimplicit);
4805 case T_NamedArgExpr:
4807 NamedArgExpr *na = (NamedArgExpr *) node;
4809 appendStringInfo(buf, "%s := ", quote_identifier(na->name));
4810 get_rule_expr((Node *) na->arg, context, showimplicit);
4815 get_oper_expr((OpExpr *) node, context);
4818 case T_DistinctExpr:
4820 DistinctExpr *expr = (DistinctExpr *) node;
4821 List *args = expr->args;
4822 Node *arg1 = (Node *) linitial(args);
4823 Node *arg2 = (Node *) lsecond(args);
4825 if (!PRETTY_PAREN(context))
4826 appendStringInfoChar(buf, '(');
4827 get_rule_expr_paren(arg1, context, true, node);
4828 appendStringInfo(buf, " IS DISTINCT FROM ");
4829 get_rule_expr_paren(arg2, context, true, node);
4830 if (!PRETTY_PAREN(context))
4831 appendStringInfoChar(buf, ')');
4835 case T_ScalarArrayOpExpr:
4837 ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
4838 List *args = expr->args;
4839 Node *arg1 = (Node *) linitial(args);
4840 Node *arg2 = (Node *) lsecond(args);
4842 if (!PRETTY_PAREN(context))
4843 appendStringInfoChar(buf, '(');
4844 get_rule_expr_paren(arg1, context, true, node);
4845 appendStringInfo(buf, " %s %s (",
4846 generate_operator_name(expr->opno,
4848 get_element_type(exprType(arg2))),
4849 expr->useOr ? "ANY" : "ALL");
4850 get_rule_expr_paren(arg2, context, true, node);
4851 appendStringInfoChar(buf, ')');
4852 if (!PRETTY_PAREN(context))
4853 appendStringInfoChar(buf, ')');
4859 BoolExpr *expr = (BoolExpr *) node;
4860 Node *first_arg = linitial(expr->args);
4861 ListCell *arg = lnext(list_head(expr->args));
4863 switch (expr->boolop)
4866 if (!PRETTY_PAREN(context))
4867 appendStringInfoChar(buf, '(');
4868 get_rule_expr_paren(first_arg, context,
4872 appendStringInfo(buf, " AND ");
4873 get_rule_expr_paren((Node *) lfirst(arg), context,
4877 if (!PRETTY_PAREN(context))
4878 appendStringInfoChar(buf, ')');
4882 if (!PRETTY_PAREN(context))
4883 appendStringInfoChar(buf, '(');
4884 get_rule_expr_paren(first_arg, context,
4888 appendStringInfo(buf, " OR ");
4889 get_rule_expr_paren((Node *) lfirst(arg), context,
4893 if (!PRETTY_PAREN(context))
4894 appendStringInfoChar(buf, ')');
4898 if (!PRETTY_PAREN(context))
4899 appendStringInfoChar(buf, '(');
4900 appendStringInfo(buf, "NOT ");
4901 get_rule_expr_paren(first_arg, context,
4903 if (!PRETTY_PAREN(context))
4904 appendStringInfoChar(buf, ')');
4908 elog(ERROR, "unrecognized boolop: %d",
4909 (int) expr->boolop);
4915 get_sublink_expr((SubLink *) node, context);
4920 SubPlan *subplan = (SubPlan *) node;
4923 * We cannot see an already-planned subplan in rule deparsing,
4924 * only while EXPLAINing a query plan. We don't try to
4925 * reconstruct the original SQL, just reference the subplan
4926 * that appears elsewhere in EXPLAIN's result.
4928 if (subplan->useHashTable)
4929 appendStringInfo(buf, "(hashed %s)", subplan->plan_name);
4931 appendStringInfo(buf, "(%s)", subplan->plan_name);
4935 case T_AlternativeSubPlan:
4937 AlternativeSubPlan *asplan = (AlternativeSubPlan *) node;
4940 /* As above, this can only happen during EXPLAIN */
4941 appendStringInfo(buf, "(alternatives: ");
4942 foreach(lc, asplan->subplans)
4944 SubPlan *splan = (SubPlan *) lfirst(lc);
4946 Assert(IsA(splan, SubPlan));
4947 if (splan->useHashTable)
4948 appendStringInfo(buf, "hashed %s", splan->plan_name);
4950 appendStringInfo(buf, "%s", splan->plan_name);
4952 appendStringInfo(buf, " or ");
4954 appendStringInfo(buf, ")");
4960 FieldSelect *fselect = (FieldSelect *) node;
4961 Node *arg = (Node *) fselect->arg;
4962 int fno = fselect->fieldnum;
4963 const char *fieldname;
4967 * Parenthesize the argument unless it's an ArrayRef or
4968 * another FieldSelect. Note in particular that it would be
4969 * WRONG to not parenthesize a Var argument; simplicity is not
4970 * the issue here, having the right number of names is.
4972 need_parens = !IsA(arg, ArrayRef) &&!IsA(arg, FieldSelect);
4974 appendStringInfoChar(buf, '(');
4975 get_rule_expr(arg, context, true);
4977 appendStringInfoChar(buf, ')');
4980 * Get and print the field name.
4982 fieldname = get_name_for_var_field((Var *) arg, fno,
4984 appendStringInfo(buf, ".%s", quote_identifier(fieldname));
4990 FieldStore *fstore = (FieldStore *) node;
4994 * There is no good way to represent a FieldStore as real SQL,
4995 * so decompilation of INSERT or UPDATE statements should
4996 * always use processIndirection as part of the
4997 * statement-level syntax. We should only get here when
4998 * EXPLAIN tries to print the targetlist of a plan resulting
4999 * from such a statement. The plan case is even harder than
5000 * ordinary rules would be, because the planner tries to
5001 * collapse multiple assignments to the same field or subfield
5002 * into one FieldStore; so we can see a list of target fields
5003 * not just one, and the arguments could be FieldStores
5004 * themselves. We don't bother to try to print the target
5005 * field names; we just print the source arguments, with a
5006 * ROW() around them if there's more than one. This isn't
5007 * terribly complete, but it's probably good enough for
5008 * EXPLAIN's purposes; especially since anything more would be
5009 * either hopelessly confusing or an even poorer
5010 * representation of what the plan is actually doing.
5012 need_parens = (list_length(fstore->newvals) != 1);
5014 appendStringInfoString(buf, "ROW(");
5015 get_rule_expr((Node *) fstore->newvals, context, showimplicit);
5017 appendStringInfoChar(buf, ')');
5023 RelabelType *relabel = (RelabelType *) node;
5024 Node *arg = (Node *) relabel->arg;
5026 if (relabel->relabelformat == COERCE_IMPLICIT_CAST &&
5029 /* don't show the implicit cast */
5030 get_rule_expr_paren(arg, context, false, node);
5034 get_coercion_expr(arg, context,
5035 relabel->resulttype,
5036 relabel->resulttypmod,
5044 CoerceViaIO *iocoerce = (CoerceViaIO *) node;
5045 Node *arg = (Node *) iocoerce->arg;
5047 if (iocoerce->coerceformat == COERCE_IMPLICIT_CAST &&
5050 /* don't show the implicit cast */
5051 get_rule_expr_paren(arg, context, false, node);
5055 get_coercion_expr(arg, context,
5056 iocoerce->resulttype,
5063 case T_ArrayCoerceExpr:
5065 ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;
5066 Node *arg = (Node *) acoerce->arg;
5068 if (acoerce->coerceformat == COERCE_IMPLICIT_CAST &&
5071 /* don't show the implicit cast */
5072 get_rule_expr_paren(arg, context, false, node);
5076 get_coercion_expr(arg, context,
5077 acoerce->resulttype,
5078 acoerce->resulttypmod,
5084 case T_ConvertRowtypeExpr:
5086 ConvertRowtypeExpr *convert = (ConvertRowtypeExpr *) node;
5087 Node *arg = (Node *) convert->arg;
5089 if (convert->convertformat == COERCE_IMPLICIT_CAST &&
5092 /* don't show the implicit cast */
5093 get_rule_expr_paren(arg, context, false, node);
5097 get_coercion_expr(arg, context,
5098 convert->resulttype, -1,
5106 CaseExpr *caseexpr = (CaseExpr *) node;
5109 appendContextKeyword(context, "CASE",
5110 0, PRETTYINDENT_VAR, 0);
5113 appendStringInfoChar(buf, ' ');
5114 get_rule_expr((Node *) caseexpr->arg, context, true);
5116 foreach(temp, caseexpr->args)
5118 CaseWhen *when = (CaseWhen *) lfirst(temp);
5119 Node *w = (Node *) when->expr;
5121 if (!PRETTY_INDENT(context))
5122 appendStringInfoChar(buf, ' ');
5123 appendContextKeyword(context, "WHEN ",
5128 * The parser should have produced WHEN clauses of the
5129 * form "CaseTestExpr = RHS"; we want to show just the
5130 * RHS. If the user wrote something silly like "CASE
5131 * boolexpr WHEN TRUE THEN ...", then the optimizer's
5132 * simplify_boolean_equality() may have reduced this
5133 * to just "CaseTestExpr" or "NOT CaseTestExpr", for
5134 * which we have to show "TRUE" or "FALSE". Also,
5135 * depending on context the original CaseTestExpr
5136 * might have been reduced to a Const (but we won't
5137 * see "WHEN Const"). We have also to consider the
5138 * possibility that an implicit coercion was inserted
5139 * between the CaseTestExpr and the operator.
5143 List *args = ((OpExpr *) w)->args;
5147 Assert(list_length(args) == 2);
5148 lhs = strip_implicit_coercions(linitial(args));
5149 Assert(IsA(lhs, CaseTestExpr) ||
5151 rhs = (Node *) lsecond(args);
5152 get_rule_expr(rhs, context, false);
5154 else if (IsA(strip_implicit_coercions(w),
5156 appendStringInfo(buf, "TRUE");
5157 else if (not_clause(w))
5159 Assert(IsA(strip_implicit_coercions((Node *) get_notclausearg((Expr *) w)),
5161 appendStringInfo(buf, "FALSE");
5164 elog(ERROR, "unexpected CASE WHEN clause: %d",
5168 get_rule_expr(w, context, false);
5169 appendStringInfo(buf, " THEN ");
5170 get_rule_expr((Node *) when->result, context, true);
5172 if (!PRETTY_INDENT(context))
5173 appendStringInfoChar(buf, ' ');
5174 appendContextKeyword(context, "ELSE ",
5176 get_rule_expr((Node *) caseexpr->defresult, context, true);
5177 if (!PRETTY_INDENT(context))
5178 appendStringInfoChar(buf, ' ');
5179 appendContextKeyword(context, "END",
5180 -PRETTYINDENT_VAR, 0, 0);
5186 ArrayExpr *arrayexpr = (ArrayExpr *) node;
5188 appendStringInfo(buf, "ARRAY[");
5189 get_rule_expr((Node *) arrayexpr->elements, context, true);
5190 appendStringInfoChar(buf, ']');
5193 * If the array isn't empty, we assume its elements are
5194 * coerced to the desired type. If it's empty, though, we
5195 * need an explicit coercion to the array type.
5197 if (arrayexpr->elements == NIL)
5198 appendStringInfo(buf, "::%s",
5199 format_type_with_typemod(arrayexpr->array_typeid, -1));
5205 RowExpr *rowexpr = (RowExpr *) node;
5206 TupleDesc tupdesc = NULL;
5212 * If it's a named type and not RECORD, we may have to skip
5213 * dropped columns and/or claim there are NULLs for added
5216 if (rowexpr->row_typeid != RECORDOID)
5218 tupdesc = lookup_rowtype_tupdesc(rowexpr->row_typeid, -1);
5219 Assert(list_length(rowexpr->args) <= tupdesc->natts);
5223 * SQL99 allows "ROW" to be omitted when there is more than
5224 * one column, but for simplicity we always print it.
5226 appendStringInfo(buf, "ROW(");
5229 foreach(arg, rowexpr->args)
5231 Node *e = (Node *) lfirst(arg);
5233 if (tupdesc == NULL ||
5234 !tupdesc->attrs[i]->attisdropped)
5236 appendStringInfoString(buf, sep);
5237 get_rule_expr(e, context, true);
5242 if (tupdesc != NULL)
5244 while (i < tupdesc->natts)
5246 if (!tupdesc->attrs[i]->attisdropped)
5248 appendStringInfoString(buf, sep);
5249 appendStringInfo(buf, "NULL");
5255 ReleaseTupleDesc(tupdesc);
5257 appendStringInfo(buf, ")");
5258 if (rowexpr->row_format == COERCE_EXPLICIT_CAST)
5259 appendStringInfo(buf, "::%s",
5260 format_type_with_typemod(rowexpr->row_typeid, -1));
5264 case T_RowCompareExpr:
5266 RowCompareExpr *rcexpr = (RowCompareExpr *) node;
5271 * SQL99 allows "ROW" to be omitted when there is more than
5272 * one column, but for simplicity we always print it.
5274 appendStringInfo(buf, "(ROW(");
5276 foreach(arg, rcexpr->largs)
5278 Node *e = (Node *) lfirst(arg);
5280 appendStringInfoString(buf, sep);
5281 get_rule_expr(e, context, true);
5286 * We assume that the name of the first-column operator will
5287 * do for all the rest too. This is definitely open to
5288 * failure, eg if some but not all operators were renamed
5289 * since the construct was parsed, but there seems no way to
5292 appendStringInfo(buf, ") %s ROW(",
5293 generate_operator_name(linitial_oid(rcexpr->opnos),
5294 exprType(linitial(rcexpr->largs)),
5295 exprType(linitial(rcexpr->rargs))));
5297 foreach(arg, rcexpr->rargs)
5299 Node *e = (Node *) lfirst(arg);
5301 appendStringInfoString(buf, sep);
5302 get_rule_expr(e, context, true);
5305 appendStringInfo(buf, "))");
5309 case T_CoalesceExpr:
5311 CoalesceExpr *coalesceexpr = (CoalesceExpr *) node;
5313 appendStringInfo(buf, "COALESCE(");
5314 get_rule_expr((Node *) coalesceexpr->args, context, true);
5315 appendStringInfoChar(buf, ')');
5321 MinMaxExpr *minmaxexpr = (MinMaxExpr *) node;
5323 switch (minmaxexpr->op)
5326 appendStringInfo(buf, "GREATEST(");
5329 appendStringInfo(buf, "LEAST(");
5332 get_rule_expr((Node *) minmaxexpr->args, context, true);
5333 appendStringInfoChar(buf, ')');
5339 XmlExpr *xexpr = (XmlExpr *) node;
5340 bool needcomma = false;
5348 appendStringInfoString(buf, "XMLCONCAT(");
5351 appendStringInfoString(buf, "XMLELEMENT(");
5354 appendStringInfoString(buf, "XMLFOREST(");
5357 appendStringInfoString(buf, "XMLPARSE(");
5360 appendStringInfoString(buf, "XMLPI(");
5363 appendStringInfoString(buf, "XMLROOT(");
5365 case IS_XMLSERIALIZE:
5366 appendStringInfoString(buf, "XMLSERIALIZE(");
5371 if (xexpr->op == IS_XMLPARSE || xexpr->op == IS_XMLSERIALIZE)
5373 if (xexpr->xmloption == XMLOPTION_DOCUMENT)
5374 appendStringInfoString(buf, "DOCUMENT ");
5376 appendStringInfoString(buf, "CONTENT ");
5380 appendStringInfo(buf, "NAME %s",
5381 quote_identifier(map_xml_name_to_sql_identifier(xexpr->name)));
5384 if (xexpr->named_args)
5386 if (xexpr->op != IS_XMLFOREST)
5389 appendStringInfoString(buf, ", ");
5390 appendStringInfoString(buf, "XMLATTRIBUTES(");
5393 forboth(arg, xexpr->named_args, narg, xexpr->arg_names)
5395 Node *e = (Node *) lfirst(arg);
5396 char *argname = strVal(lfirst(narg));
5399 appendStringInfoString(buf, ", ");
5400 get_rule_expr((Node *) e, context, true);
5401 appendStringInfo(buf, " AS %s",
5402 quote_identifier(map_xml_name_to_sql_identifier(argname)));
5405 if (xexpr->op != IS_XMLFOREST)
5406 appendStringInfoChar(buf, ')');
5411 appendStringInfoString(buf, ", ");
5418 case IS_XMLSERIALIZE:
5419 /* no extra decoration needed */
5420 get_rule_expr((Node *) xexpr->args, context, true);
5423 Assert(list_length(xexpr->args) == 2);
5425 get_rule_expr((Node *) linitial(xexpr->args),
5428 con = (Const *) lsecond(xexpr->args);
5429 Assert(IsA(con, Const));
5430 Assert(!con->constisnull);
5431 if (DatumGetBool(con->constvalue))
5432 appendStringInfoString(buf,
5433 " PRESERVE WHITESPACE");
5435 appendStringInfoString(buf,
5436 " STRIP WHITESPACE");
5439 Assert(list_length(xexpr->args) == 3);
5441 get_rule_expr((Node *) linitial(xexpr->args),
5444 appendStringInfoString(buf, ", VERSION ");
5445 con = (Const *) lsecond(xexpr->args);
5446 if (IsA(con, Const) &&
5448 appendStringInfoString(buf, "NO VALUE");
5450 get_rule_expr((Node *) con, context, false);
5452 con = (Const *) lthird(xexpr->args);
5453 Assert(IsA(con, Const));
5454 if (con->constisnull)
5455 /* suppress STANDALONE NO VALUE */ ;
5458 switch (DatumGetInt32(con->constvalue))
5460 case XML_STANDALONE_YES:
5461 appendStringInfoString(buf,
5462 ", STANDALONE YES");
5464 case XML_STANDALONE_NO:
5465 appendStringInfoString(buf,
5468 case XML_STANDALONE_NO_VALUE:
5469 appendStringInfoString(buf,
5470 ", STANDALONE NO VALUE");
5478 get_rule_expr_paren((Node *) xexpr->args, context, false, node);
5483 if (xexpr->op == IS_XMLSERIALIZE)
5484 appendStringInfo(buf, " AS %s", format_type_with_typemod(xexpr->type,
5486 if (xexpr->op == IS_DOCUMENT)
5487 appendStringInfoString(buf, " IS DOCUMENT");
5489 appendStringInfoChar(buf, ')');
5495 NullIfExpr *nullifexpr = (NullIfExpr *) node;
5497 appendStringInfo(buf, "NULLIF(");
5498 get_rule_expr((Node *) nullifexpr->args, context, true);
5499 appendStringInfoChar(buf, ')');
5505 NullTest *ntest = (NullTest *) node;
5507 if (!PRETTY_PAREN(context))
5508 appendStringInfoChar(buf, '(');
5509 get_rule_expr_paren((Node *) ntest->arg, context, true, node);
5510 switch (ntest->nulltesttype)
5513 appendStringInfo(buf, " IS NULL");
5516 appendStringInfo(buf, " IS NOT NULL");
5519 elog(ERROR, "unrecognized nulltesttype: %d",
5520 (int) ntest->nulltesttype);
5522 if (!PRETTY_PAREN(context))
5523 appendStringInfoChar(buf, ')');
5529 BooleanTest *btest = (BooleanTest *) node;
5531 if (!PRETTY_PAREN(context))
5532 appendStringInfoChar(buf, '(');
5533 get_rule_expr_paren((Node *) btest->arg, context, false, node);
5534 switch (btest->booltesttype)
5537 appendStringInfo(buf, " IS TRUE");
5540 appendStringInfo(buf, " IS NOT TRUE");
5543 appendStringInfo(buf, " IS FALSE");
5546 appendStringInfo(buf, " IS NOT FALSE");
5549 appendStringInfo(buf, " IS UNKNOWN");
5551 case IS_NOT_UNKNOWN:
5552 appendStringInfo(buf, " IS NOT UNKNOWN");
5555 elog(ERROR, "unrecognized booltesttype: %d",
5556 (int) btest->booltesttype);
5558 if (!PRETTY_PAREN(context))
5559 appendStringInfoChar(buf, ')');
5563 case T_CoerceToDomain:
5565 CoerceToDomain *ctest = (CoerceToDomain *) node;
5566 Node *arg = (Node *) ctest->arg;
5568 if (ctest->coercionformat == COERCE_IMPLICIT_CAST &&
5571 /* don't show the implicit cast */
5572 get_rule_expr(arg, context, false);
5576 get_coercion_expr(arg, context,
5578 ctest->resulttypmod,
5584 case T_CoerceToDomainValue:
5585 appendStringInfo(buf, "VALUE");
5588 case T_SetToDefault:
5589 appendStringInfo(buf, "DEFAULT");
5592 case T_CurrentOfExpr:
5594 CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
5596 if (cexpr->cursor_name)
5597 appendStringInfo(buf, "CURRENT OF %s",
5598 quote_identifier(cexpr->cursor_name));
5600 appendStringInfo(buf, "CURRENT OF $%d",
5601 cexpr->cursor_param);
5611 foreach(l, (List *) node)
5613 appendStringInfoString(buf, sep);
5614 get_rule_expr((Node *) lfirst(l), context, showimplicit);
5621 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
5628 * get_oper_expr - Parse back an OpExpr node
5631 get_oper_expr(OpExpr *expr, deparse_context *context)
5633 StringInfo buf = context->buf;
5634 Oid opno = expr->opno;
5635 List *args = expr->args;
5637 if (!PRETTY_PAREN(context))
5638 appendStringInfoChar(buf, '(');
5639 if (list_length(args) == 2)
5641 /* binary operator */
5642 Node *arg1 = (Node *) linitial(args);
5643 Node *arg2 = (Node *) lsecond(args);
5645 get_rule_expr_paren(arg1, context, true, (Node *) expr);
5646 appendStringInfo(buf, " %s ",
5647 generate_operator_name(opno,
5650 get_rule_expr_paren(arg2, context, true, (Node *) expr);
5654 /* unary operator --- but which side? */
5655 Node *arg = (Node *) linitial(args);
5657 Form_pg_operator optup;
5659 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
5660 if (!HeapTupleIsValid(tp))
5661 elog(ERROR, "cache lookup failed for operator %u", opno);
5662 optup = (Form_pg_operator) GETSTRUCT(tp);
5663 switch (optup->oprkind)
5666 appendStringInfo(buf, "%s ",
5667 generate_operator_name(opno,
5670 get_rule_expr_paren(arg, context, true, (Node *) expr);
5673 get_rule_expr_paren(arg, context, true, (Node *) expr);
5674 appendStringInfo(buf, " %s",
5675 generate_operator_name(opno,
5680 elog(ERROR, "bogus oprkind: %d", optup->oprkind);
5682 ReleaseSysCache(tp);
5684 if (!PRETTY_PAREN(context))
5685 appendStringInfoChar(buf, ')');
5689 * get_func_expr - Parse back a FuncExpr node
5692 get_func_expr(FuncExpr *expr, deparse_context *context,
5695 StringInfo buf = context->buf;
5696 Oid funcoid = expr->funcid;
5697 Oid argtypes[FUNC_MAX_ARGS];
5704 * If the function call came from an implicit coercion, then just show the
5705 * first argument --- unless caller wants to see implicit coercions.
5707 if (expr->funcformat == COERCE_IMPLICIT_CAST && !showimplicit)
5709 get_rule_expr_paren((Node *) linitial(expr->args), context,
5710 false, (Node *) expr);
5715 * If the function call came from a cast, then show the first argument
5716 * plus an explicit cast operation.
5718 if (expr->funcformat == COERCE_EXPLICIT_CAST ||
5719 expr->funcformat == COERCE_IMPLICIT_CAST)
5721 Node *arg = linitial(expr->args);
5722 Oid rettype = expr->funcresulttype;
5723 int32 coercedTypmod;
5725 /* Get the typmod if this is a length-coercion function */
5726 (void) exprIsLengthCoercion((Node *) expr, &coercedTypmod);
5728 get_coercion_expr(arg, context,
5729 rettype, coercedTypmod,
5736 * Normal function: display as proname(args). First we need to extract
5737 * the argument datatypes.
5739 if (list_length(expr->args) > FUNC_MAX_ARGS)
5741 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
5742 errmsg("too many arguments")));
5745 foreach(l, expr->args)
5747 Node *arg = (Node *) lfirst(l);
5749 if (IsA(arg, NamedArgExpr))
5750 argnames = lappend(argnames, ((NamedArgExpr *) arg)->name);
5751 argtypes[nargs] = exprType(arg);
5755 appendStringInfo(buf, "%s(",
5756 generate_function_name(funcoid, nargs,
5760 foreach(l, expr->args)
5763 appendStringInfoString(buf, ", ");
5764 if (is_variadic && lnext(l) == NULL)
5765 appendStringInfoString(buf, "VARIADIC ");
5766 get_rule_expr((Node *) lfirst(l), context, true);
5768 appendStringInfoChar(buf, ')');
5772 * get_agg_expr - Parse back an Aggref node
5775 get_agg_expr(Aggref *aggref, deparse_context *context)
5777 StringInfo buf = context->buf;
5778 Oid argtypes[FUNC_MAX_ARGS];
5783 /* Extract the regular arguments, ignoring resjunk stuff for the moment */
5786 foreach(l, aggref->args)
5788 TargetEntry *tle = (TargetEntry *) lfirst(l);
5789 Node *arg = (Node *) tle->expr;
5791 Assert(!IsA(arg, NamedArgExpr));
5794 if (nargs >= FUNC_MAX_ARGS) /* paranoia */
5796 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
5797 errmsg("too many arguments")));
5798 argtypes[nargs] = exprType(arg);
5799 arglist = lappend(arglist, arg);
5803 appendStringInfo(buf, "%s(%s",
5804 generate_function_name(aggref->aggfnoid, nargs,
5805 NIL, argtypes, NULL),
5806 (aggref->aggdistinct != NIL) ? "DISTINCT " : "");
5807 /* aggstar can be set only in zero-argument aggregates */
5808 if (aggref->aggstar)
5809 appendStringInfoChar(buf, '*');
5811 get_rule_expr((Node *) arglist, context, true);
5812 if (aggref->aggorder != NIL)
5814 appendStringInfoString(buf, " ORDER BY ");
5815 get_rule_orderby(aggref->aggorder, aggref->args, false, context);
5817 appendStringInfoChar(buf, ')');
5821 * get_windowfunc_expr - Parse back a WindowFunc node
5824 get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context)
5826 StringInfo buf = context->buf;
5827 Oid argtypes[FUNC_MAX_ARGS];
5831 if (list_length(wfunc->args) > FUNC_MAX_ARGS)
5833 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
5834 errmsg("too many arguments")));
5836 foreach(l, wfunc->args)
5838 Node *arg = (Node *) lfirst(l);
5840 Assert(!IsA(arg, NamedArgExpr));
5841 argtypes[nargs] = exprType(arg);
5845 appendStringInfo(buf, "%s(",
5846 generate_function_name(wfunc->winfnoid, nargs,
5847 NIL, argtypes, NULL));
5848 /* winstar can be set only in zero-argument aggregates */
5850 appendStringInfoChar(buf, '*');
5852 get_rule_expr((Node *) wfunc->args, context, true);
5853 appendStringInfoString(buf, ") OVER ");
5855 foreach(l, context->windowClause)
5857 WindowClause *wc = (WindowClause *) lfirst(l);
5859 if (wc->winref == wfunc->winref)
5862 appendStringInfoString(buf, quote_identifier(wc->name));
5864 get_rule_windowspec(wc, context->windowTList, context);
5870 if (context->windowClause)
5871 elog(ERROR, "could not find window clause for winref %u",
5875 * In EXPLAIN, we don't have window context information available, so
5876 * we have to settle for this:
5878 appendStringInfoString(buf, "(?)");
5885 * Make a string representation of a value coerced to a specific type
5889 get_coercion_expr(Node *arg, deparse_context *context,
5890 Oid resulttype, int32 resulttypmod,
5893 StringInfo buf = context->buf;
5896 * Since parse_coerce.c doesn't immediately collapse application of
5897 * length-coercion functions to constants, what we'll typically see in
5898 * such cases is a Const with typmod -1 and a length-coercion function
5899 * right above it. Avoid generating redundant output. However, beware of
5900 * suppressing casts when the user actually wrote something like
5901 * 'foo'::text::char(3).
5903 if (arg && IsA(arg, Const) &&
5904 ((Const *) arg)->consttype == resulttype &&
5905 ((Const *) arg)->consttypmod == -1)
5907 /* Show the constant without normal ::typename decoration */
5908 get_const_expr((Const *) arg, context, -1);
5912 if (!PRETTY_PAREN(context))
5913 appendStringInfoChar(buf, '(');
5914 get_rule_expr_paren(arg, context, false, parentNode);
5915 if (!PRETTY_PAREN(context))
5916 appendStringInfoChar(buf, ')');
5918 appendStringInfo(buf, "::%s",
5919 format_type_with_typemod(resulttype, resulttypmod));
5925 * Make a string representation of a Const
5927 * showtype can be -1 to never show "::typename" decoration, or +1 to always
5928 * show it, or 0 to show it only if the constant wouldn't be assumed to be
5929 * the right type by default.
5933 get_const_expr(Const *constval, deparse_context *context, int showtype)
5935 StringInfo buf = context->buf;
5939 bool isfloat = false;
5942 if (constval->constisnull)
5945 * Always label the type of a NULL constant to prevent misdecisions
5946 * about type when reparsing.
5948 appendStringInfo(buf, "NULL");
5950 appendStringInfo(buf, "::%s",
5951 format_type_with_typemod(constval->consttype,
5952 constval->consttypmod));
5956 getTypeOutputInfo(constval->consttype,
5957 &typoutput, &typIsVarlena);
5959 extval = OidOutputFunctionCall(typoutput, constval->constvalue);
5961 switch (constval->consttype)
5972 * These types are printed without quotes unless they contain
5973 * values that aren't accepted by the scanner unquoted (e.g.,
5974 * 'NaN'). Note that strtod() and friends might accept NaN,
5975 * so we can't use that to test.
5977 * In reality we only need to defend against infinity and NaN,
5978 * so we need not get too crazy about pattern matching here.
5980 * There is a special-case gotcha: if the constant is signed,
5981 * we need to parenthesize it, else the parser might see a
5982 * leading plus/minus as binding less tightly than adjacent
5983 * operators --- particularly, the cast that we might attach
5986 if (strspn(extval, "0123456789+-eE.") == strlen(extval))
5988 if (extval[0] == '+' || extval[0] == '-')
5989 appendStringInfo(buf, "(%s)", extval);
5991 appendStringInfoString(buf, extval);
5992 if (strcspn(extval, "eE.") != strlen(extval))
5993 isfloat = true; /* it looks like a float */
5996 appendStringInfo(buf, "'%s'", extval);
6002 appendStringInfo(buf, "B'%s'", extval);
6006 if (strcmp(extval, "t") == 0)
6007 appendStringInfo(buf, "true");
6009 appendStringInfo(buf, "false");
6013 simple_quote_literal(buf, extval);
6023 * For showtype == 0, append ::typename unless the constant will be
6024 * implicitly typed as the right type when it is read in.
6026 * XXX this code has to be kept in sync with the behavior of the parser,
6027 * especially make_const.
6029 switch (constval->consttype)
6034 /* These types can be left unlabeled */
6040 * Float-looking constants will be typed as numeric, but if
6041 * there's a specific typmod we need to show it.
6043 needlabel = !isfloat || (constval->consttypmod >= 0);
6049 if (needlabel || showtype > 0)
6050 appendStringInfo(buf, "::%s",
6051 format_type_with_typemod(constval->consttype,
6052 constval->consttypmod));
6056 * simple_quote_literal - Format a string as a SQL literal, append to buf
6059 simple_quote_literal(StringInfo buf, const char *val)
6064 * We form the string literal according to the prevailing setting of
6065 * standard_conforming_strings; we never use E''. User is responsible for
6066 * making sure result is used correctly.
6068 appendStringInfoChar(buf, '\'');
6069 for (valptr = val; *valptr; valptr++)
6073 if (SQL_STR_DOUBLE(ch, !standard_conforming_strings))
6074 appendStringInfoChar(buf, ch);
6075 appendStringInfoChar(buf, ch);
6077 appendStringInfoChar(buf, '\'');
6082 * get_sublink_expr - Parse back a sublink
6086 get_sublink_expr(SubLink *sublink, deparse_context *context)
6088 StringInfo buf = context->buf;
6089 Query *query = (Query *) (sublink->subselect);
6090 char *opname = NULL;
6093 if (sublink->subLinkType == ARRAY_SUBLINK)
6094 appendStringInfo(buf, "ARRAY(");
6096 appendStringInfoChar(buf, '(');
6099 * Note that we print the name of only the first operator, when there are
6100 * multiple combining operators. This is an approximation that could go
6101 * wrong in various scenarios (operators in different schemas, renamed
6102 * operators, etc) but there is not a whole lot we can do about it, since
6103 * the syntax allows only one operator to be shown.
6105 if (sublink->testexpr)
6107 if (IsA(sublink->testexpr, OpExpr))
6109 /* single combining operator */
6110 OpExpr *opexpr = (OpExpr *) sublink->testexpr;
6112 get_rule_expr(linitial(opexpr->args), context, true);
6113 opname = generate_operator_name(opexpr->opno,
6114 exprType(linitial(opexpr->args)),
6115 exprType(lsecond(opexpr->args)));
6117 else if (IsA(sublink->testexpr, BoolExpr))
6119 /* multiple combining operators, = or <> cases */
6123 appendStringInfoChar(buf, '(');
6125 foreach(l, ((BoolExpr *) sublink->testexpr)->args)
6127 OpExpr *opexpr = (OpExpr *) lfirst(l);
6129 Assert(IsA(opexpr, OpExpr));
6130 appendStringInfoString(buf, sep);
6131 get_rule_expr(linitial(opexpr->args), context, true);
6133 opname = generate_operator_name(opexpr->opno,
6134 exprType(linitial(opexpr->args)),
6135 exprType(lsecond(opexpr->args)));
6138 appendStringInfoChar(buf, ')');
6140 else if (IsA(sublink->testexpr, RowCompareExpr))
6142 /* multiple combining operators, < <= > >= cases */
6143 RowCompareExpr *rcexpr = (RowCompareExpr *) sublink->testexpr;
6145 appendStringInfoChar(buf, '(');
6146 get_rule_expr((Node *) rcexpr->largs, context, true);
6147 opname = generate_operator_name(linitial_oid(rcexpr->opnos),
6148 exprType(linitial(rcexpr->largs)),
6149 exprType(linitial(rcexpr->rargs)));
6150 appendStringInfoChar(buf, ')');
6153 elog(ERROR, "unrecognized testexpr type: %d",
6154 (int) nodeTag(sublink->testexpr));
6159 switch (sublink->subLinkType)
6161 case EXISTS_SUBLINK:
6162 appendStringInfo(buf, "EXISTS ");
6166 if (strcmp(opname, "=") == 0) /* Represent = ANY as IN */
6167 appendStringInfo(buf, " IN ");
6169 appendStringInfo(buf, " %s ANY ", opname);
6173 appendStringInfo(buf, " %s ALL ", opname);
6176 case ROWCOMPARE_SUBLINK:
6177 appendStringInfo(buf, " %s ", opname);
6185 case CTE_SUBLINK: /* shouldn't occur in a SubLink */
6187 elog(ERROR, "unrecognized sublink type: %d",
6188 (int) sublink->subLinkType);
6193 appendStringInfoChar(buf, '(');
6195 get_query_def(query, buf, context->namespaces, NULL,
6196 context->prettyFlags, context->indentLevel);
6199 appendStringInfo(buf, "))");
6201 appendStringInfoChar(buf, ')');
6206 * get_from_clause - Parse back a FROM clause
6208 * "prefix" is the keyword that denotes the start of the list of FROM
6209 * elements. It is FROM when used to parse back SELECT and UPDATE, but
6210 * is USING when parsing back DELETE.
6214 get_from_clause(Query *query, const char *prefix, deparse_context *context)
6216 StringInfo buf = context->buf;
6221 * We use the query's jointree as a guide to what to print. However, we
6222 * must ignore auto-added RTEs that are marked not inFromCl. (These can
6223 * only appear at the top level of the jointree, so it's sufficient to
6224 * check here.) This check also ensures we ignore the rule pseudo-RTEs
6227 foreach(l, query->jointree->fromlist)
6229 Node *jtnode = (Node *) lfirst(l);
6231 if (IsA(jtnode, RangeTblRef))
6233 int varno = ((RangeTblRef *) jtnode)->rtindex;
6234 RangeTblEntry *rte = rt_fetch(varno, query->rtable);
6242 appendContextKeyword(context, prefix,
6243 -PRETTYINDENT_STD, PRETTYINDENT_STD, 2);
6247 appendStringInfoString(buf, ", ");
6249 get_from_clause_item(jtnode, query, context);
6254 get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
6256 StringInfo buf = context->buf;
6258 if (IsA(jtnode, RangeTblRef))
6260 int varno = ((RangeTblRef *) jtnode)->rtindex;
6261 RangeTblEntry *rte = rt_fetch(varno, query->rtable);
6262 bool gavealias = false;
6264 switch (rte->rtekind)
6267 /* Normal relation RTE */
6268 appendStringInfo(buf, "%s%s",
6270 generate_relation_name(rte->relid,
6271 context->namespaces));
6275 appendStringInfoChar(buf, '(');
6276 get_query_def(rte->subquery, buf, context->namespaces, NULL,
6277 context->prettyFlags, context->indentLevel);
6278 appendStringInfoChar(buf, ')');
6282 get_rule_expr(rte->funcexpr, context, true);
6285 /* Values list RTE */
6286 get_values_def(rte->values_lists, context);
6289 appendStringInfoString(buf, quote_identifier(rte->ctename));
6292 elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
6296 if (rte->alias != NULL)
6298 appendStringInfo(buf, " %s",
6299 quote_identifier(rte->alias->aliasname));
6302 else if (rte->rtekind == RTE_RELATION &&
6303 strcmp(rte->eref->aliasname, get_rel_name(rte->relid)) != 0)
6306 * Apparently the rel has been renamed since the rule was made.
6307 * Emit a fake alias clause so that variable references will still
6308 * work. This is not a 100% solution but should work in most
6309 * reasonable situations.
6311 appendStringInfo(buf, " %s",
6312 quote_identifier(rte->eref->aliasname));
6315 else if (rte->rtekind == RTE_FUNCTION)
6318 * For a function RTE, always give an alias. This covers possible
6319 * renaming of the function and/or instability of the
6320 * FigureColname rules for things that aren't simple functions.
6322 appendStringInfo(buf, " %s",
6323 quote_identifier(rte->eref->aliasname));
6327 if (rte->rtekind == RTE_FUNCTION)
6329 if (rte->funccoltypes != NIL)
6331 /* Function returning RECORD, reconstruct the columndefs */
6333 appendStringInfo(buf, " AS ");
6334 get_from_clause_coldeflist(rte->eref->colnames,
6336 rte->funccoltypmods,
6342 * For a function RTE, always emit a complete column alias
6343 * list; this is to protect against possible instability of
6344 * the default column names (eg, from altering parameter
6347 get_from_clause_alias(rte->eref, rte, context);
6353 * For non-function RTEs, just report whatever the user originally
6354 * gave as column aliases.
6356 get_from_clause_alias(rte->alias, rte, context);
6359 else if (IsA(jtnode, JoinExpr))
6361 JoinExpr *j = (JoinExpr *) jtnode;
6362 bool need_paren_on_right;
6364 need_paren_on_right = PRETTY_PAREN(context) &&
6365 !IsA(j->rarg, RangeTblRef) &&
6366 !(IsA(j->rarg, JoinExpr) &&((JoinExpr *) j->rarg)->alias != NULL);
6368 if (!PRETTY_PAREN(context) || j->alias != NULL)
6369 appendStringInfoChar(buf, '(');
6371 get_from_clause_item(j->larg, query, context);
6375 if (!PRETTY_INDENT(context))
6376 appendStringInfoChar(buf, ' ');
6377 switch (j->jointype)
6380 appendContextKeyword(context, "NATURAL JOIN ",
6382 PRETTYINDENT_JOIN, 0);
6385 appendContextKeyword(context, "NATURAL LEFT JOIN ",
6387 PRETTYINDENT_JOIN, 0);
6390 appendContextKeyword(context, "NATURAL FULL JOIN ",
6392 PRETTYINDENT_JOIN, 0);
6395 appendContextKeyword(context, "NATURAL RIGHT JOIN ",
6397 PRETTYINDENT_JOIN, 0);
6400 elog(ERROR, "unrecognized join type: %d",
6406 switch (j->jointype)
6410 appendContextKeyword(context, " JOIN ",
6412 PRETTYINDENT_JOIN, 2);
6414 appendContextKeyword(context, " CROSS JOIN ",
6416 PRETTYINDENT_JOIN, 1);
6419 appendContextKeyword(context, " LEFT JOIN ",
6421 PRETTYINDENT_JOIN, 2);
6424 appendContextKeyword(context, " FULL JOIN ",
6426 PRETTYINDENT_JOIN, 2);
6429 appendContextKeyword(context, " RIGHT JOIN ",
6431 PRETTYINDENT_JOIN, 2);
6434 elog(ERROR, "unrecognized join type: %d",
6439 if (need_paren_on_right)
6440 appendStringInfoChar(buf, '(');
6441 get_from_clause_item(j->rarg, query, context);
6442 if (need_paren_on_right)
6443 appendStringInfoChar(buf, ')');
6445 context->indentLevel -= PRETTYINDENT_JOIN_ON;
6453 appendStringInfo(buf, " USING (");
6454 foreach(col, j->usingClause)
6456 if (col != list_head(j->usingClause))
6457 appendStringInfo(buf, ", ");
6458 appendStringInfoString(buf,
6459 quote_identifier(strVal(lfirst(col))));
6461 appendStringInfoChar(buf, ')');
6465 appendStringInfo(buf, " ON ");
6466 if (!PRETTY_PAREN(context))
6467 appendStringInfoChar(buf, '(');
6468 get_rule_expr(j->quals, context, false);
6469 if (!PRETTY_PAREN(context))
6470 appendStringInfoChar(buf, ')');
6473 if (!PRETTY_PAREN(context) || j->alias != NULL)
6474 appendStringInfoChar(buf, ')');
6476 /* Yes, it's correct to put alias after the right paren ... */
6477 if (j->alias != NULL)
6479 appendStringInfo(buf, " %s",
6480 quote_identifier(j->alias->aliasname));
6481 get_from_clause_alias(j->alias,
6482 rt_fetch(j->rtindex, query->rtable),
6487 elog(ERROR, "unrecognized node type: %d",
6488 (int) nodeTag(jtnode));
6492 * get_from_clause_alias - reproduce column alias list
6494 * This is tricky because we must ignore dropped columns.
6497 get_from_clause_alias(Alias *alias, RangeTblEntry *rte,
6498 deparse_context *context)
6500 StringInfo buf = context->buf;
6505 if (alias == NULL || alias->colnames == NIL)
6506 return; /* definitely nothing to do */
6509 foreach(col, alias->colnames)
6512 if (get_rte_attribute_is_dropped(rte, attnum))
6516 appendStringInfoChar(buf, '(');
6520 appendStringInfo(buf, ", ");
6521 appendStringInfoString(buf,
6522 quote_identifier(strVal(lfirst(col))));
6525 appendStringInfoChar(buf, ')');
6529 * get_from_clause_coldeflist - reproduce FROM clause coldeflist
6531 * The coldeflist is appended immediately (no space) to buf. Caller is
6532 * responsible for ensuring that an alias or AS is present before it.
6535 get_from_clause_coldeflist(List *names, List *types, List *typmods,
6536 deparse_context *context)
6538 StringInfo buf = context->buf;
6544 appendStringInfoChar(buf, '(');
6546 l2 = list_head(types);
6547 l3 = list_head(typmods);
6550 char *attname = strVal(lfirst(l1));
6554 atttypid = lfirst_oid(l2);
6556 atttypmod = lfirst_int(l3);
6560 appendStringInfo(buf, ", ");
6561 appendStringInfo(buf, "%s %s",
6562 quote_identifier(attname),
6563 format_type_with_typemod(atttypid, atttypmod));
6567 appendStringInfoChar(buf, ')');
6571 * get_opclass_name - fetch name of an index operator class
6573 * The opclass name is appended (after a space) to buf.
6575 * Output is suppressed if the opclass is the default for the given
6576 * actual_datatype. (If you don't want this behavior, just pass
6577 * InvalidOid for actual_datatype.)
6580 get_opclass_name(Oid opclass, Oid actual_datatype,
6584 Form_pg_opclass opcrec;
6588 ht_opc = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
6589 if (!HeapTupleIsValid(ht_opc))
6590 elog(ERROR, "cache lookup failed for opclass %u", opclass);
6591 opcrec = (Form_pg_opclass) GETSTRUCT(ht_opc);
6593 if (!OidIsValid(actual_datatype) ||
6594 GetDefaultOpClass(actual_datatype, opcrec->opcmethod) != opclass)
6596 /* Okay, we need the opclass name. Do we need to qualify it? */
6597 opcname = NameStr(opcrec->opcname);
6598 if (OpclassIsVisible(opclass))
6599 appendStringInfo(buf, " %s", quote_identifier(opcname));
6602 nspname = get_namespace_name(opcrec->opcnamespace);
6603 appendStringInfo(buf, " %s.%s",
6604 quote_identifier(nspname),
6605 quote_identifier(opcname));
6608 ReleaseSysCache(ht_opc);
6612 * processIndirection - take care of array and subfield assignment
6614 * We strip any top-level FieldStore or assignment ArrayRef nodes that
6615 * appear in the input, and return the subexpression that's to be assigned.
6616 * If printit is true, we also print out the appropriate decoration for the
6617 * base column name (that the caller just printed).
6620 processIndirection(Node *node, deparse_context *context, bool printit)
6622 StringInfo buf = context->buf;
6628 if (IsA(node, FieldStore))
6630 FieldStore *fstore = (FieldStore *) node;
6634 /* lookup tuple type */
6635 typrelid = get_typ_typrelid(fstore->resulttype);
6636 if (!OidIsValid(typrelid))
6637 elog(ERROR, "argument type %s of FieldStore is not a tuple type",
6638 format_type_be(fstore->resulttype));
6641 * Print the field name. There should only be one target field in
6642 * stored rules. There could be more than that in executable
6643 * target lists, but this function cannot be used for that case.
6645 Assert(list_length(fstore->fieldnums) == 1);
6646 fieldname = get_relid_attribute_name(typrelid,
6647 linitial_int(fstore->fieldnums));
6649 appendStringInfo(buf, ".%s", quote_identifier(fieldname));
6652 * We ignore arg since it should be an uninteresting reference to
6653 * the target column or subcolumn.
6655 node = (Node *) linitial(fstore->newvals);
6657 else if (IsA(node, ArrayRef))
6659 ArrayRef *aref = (ArrayRef *) node;
6661 if (aref->refassgnexpr == NULL)
6664 printSubscripts(aref, context);
6667 * We ignore refexpr since it should be an uninteresting reference
6668 * to the target column or subcolumn.
6670 node = (Node *) aref->refassgnexpr;
6680 printSubscripts(ArrayRef *aref, deparse_context *context)
6682 StringInfo buf = context->buf;
6683 ListCell *lowlist_item;
6684 ListCell *uplist_item;
6686 lowlist_item = list_head(aref->reflowerindexpr); /* could be NULL */
6687 foreach(uplist_item, aref->refupperindexpr)
6689 appendStringInfoChar(buf, '[');
6692 get_rule_expr((Node *) lfirst(lowlist_item), context, false);
6693 appendStringInfoChar(buf, ':');
6694 lowlist_item = lnext(lowlist_item);
6696 get_rule_expr((Node *) lfirst(uplist_item), context, false);
6697 appendStringInfoChar(buf, ']');
6702 * quote_identifier - Quote an identifier only if needed
6704 * When quotes are needed, we palloc the required space; slightly
6705 * space-wasteful but well worth it for notational simplicity.
6708 quote_identifier(const char *ident)
6711 * Can avoid quoting if ident starts with a lowercase letter or underscore
6712 * and contains only lowercase letters, digits, and underscores, *and* is
6713 * not any SQL keyword. Otherwise, supply quotes.
6722 * would like to use <ctype.h> macros here, but they might yield unwanted
6723 * locale-specific results...
6725 safe = ((ident[0] >= 'a' && ident[0] <= 'z') || ident[0] == '_');
6727 for (ptr = ident; *ptr; ptr++)
6731 if ((ch >= 'a' && ch <= 'z') ||
6732 (ch >= '0' && ch <= '9') ||
6745 if (quote_all_identifiers)
6751 * Check for keyword. We quote keywords except for unreserved ones.
6752 * (In some cases we could avoid quoting a col_name or type_func_name
6753 * keyword, but it seems much harder than it's worth to tell that.)
6755 * Note: ScanKeywordLookup() does case-insensitive comparison, but
6756 * that's fine, since we already know we have all-lower-case.
6758 const ScanKeyword *keyword = ScanKeywordLookup(ident,
6762 if (keyword != NULL && keyword->category != UNRESERVED_KEYWORD)
6767 return ident; /* no change needed */
6769 result = (char *) palloc(strlen(ident) + nquotes + 2 + 1);
6773 for (ptr = ident; *ptr; ptr++)
6788 * quote_qualified_identifier - Quote a possibly-qualified identifier
6790 * Return a name of the form qualifier.ident, or just ident if qualifier
6791 * is NULL, quoting each component if necessary. The result is palloc'd.
6794 quote_qualified_identifier(const char *qualifier,
6799 initStringInfo(&buf);
6801 appendStringInfo(&buf, "%s.", quote_identifier(qualifier));
6802 appendStringInfoString(&buf, quote_identifier(ident));
6807 * generate_relation_name
6808 * Compute the name to display for a relation specified by OID
6810 * The result includes all necessary quoting and schema-prefixing.
6812 * If namespaces isn't NIL, it must be a list of deparse_namespace nodes.
6813 * We will forcibly qualify the relation name if it equals any CTE name
6814 * visible in the namespace list.
6817 generate_relation_name(Oid relid, List *namespaces)
6820 Form_pg_class reltup;
6827 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
6828 if (!HeapTupleIsValid(tp))
6829 elog(ERROR, "cache lookup failed for relation %u", relid);
6830 reltup = (Form_pg_class) GETSTRUCT(tp);
6831 relname = NameStr(reltup->relname);
6833 /* Check for conflicting CTE name */
6835 foreach(nslist, namespaces)
6837 deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist);
6840 foreach(ctlist, dpns->ctes)
6842 CommonTableExpr *cte = (CommonTableExpr *) lfirst(ctlist);
6844 if (strcmp(cte->ctename, relname) == 0)
6854 /* Otherwise, qualify the name if not visible in search path */
6856 need_qual = !RelationIsVisible(relid);
6859 nspname = get_namespace_name(reltup->relnamespace);
6863 result = quote_qualified_identifier(nspname, relname);
6865 ReleaseSysCache(tp);
6871 * generate_function_name
6872 * Compute the name to display for a function specified by OID,
6873 * given that it is being called with the specified actual arg names and
6874 * types. (Those matter because of ambiguous-function resolution rules.)
6876 * The result includes all necessary quoting and schema-prefixing. We can
6877 * also pass back an indication of whether the function is variadic.
6880 generate_function_name(Oid funcid, int nargs, List *argnames,
6881 Oid *argtypes, bool *is_variadic)
6884 Form_pg_proc procform;
6888 FuncDetailCode p_result;
6893 Oid *p_true_typeids;
6895 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
6896 if (!HeapTupleIsValid(proctup))
6897 elog(ERROR, "cache lookup failed for function %u", funcid);
6898 procform = (Form_pg_proc) GETSTRUCT(proctup);
6899 proname = NameStr(procform->proname);
6902 * The idea here is to schema-qualify only if the parser would fail to
6903 * resolve the correct function given the unqualified func name with the
6904 * specified argtypes. If the function is variadic, we should presume
6905 * that VARIADIC will be included in the call.
6907 p_result = func_get_detail(list_make1(makeString(proname)),
6908 NIL, argnames, nargs, argtypes,
6909 !OidIsValid(procform->provariadic), true,
6910 &p_funcid, &p_rettype,
6911 &p_retset, &p_nvargs, &p_true_typeids, NULL);
6912 if ((p_result == FUNCDETAIL_NORMAL ||
6913 p_result == FUNCDETAIL_AGGREGATE ||
6914 p_result == FUNCDETAIL_WINDOWFUNC) &&
6918 nspname = get_namespace_name(procform->pronamespace);
6920 result = quote_qualified_identifier(nspname, proname);
6922 /* Check variadic-ness if caller cares */
6925 /* "any" variadics are not treated as variadics for listing */
6926 if (OidIsValid(procform->provariadic) &&
6927 procform->provariadic != ANYOID)
6928 *is_variadic = true;
6930 *is_variadic = false;
6933 ReleaseSysCache(proctup);
6939 * generate_operator_name
6940 * Compute the name to display for an operator specified by OID,
6941 * given that it is being called with the specified actual arg types.
6942 * (Arg types matter because of ambiguous-operator resolution rules.
6943 * Pass InvalidOid for unused arg of a unary operator.)
6945 * The result includes all necessary quoting and schema-prefixing,
6946 * plus the OPERATOR() decoration needed to use a qualified operator name
6950 generate_operator_name(Oid operid, Oid arg1, Oid arg2)
6954 Form_pg_operator operform;
6959 initStringInfo(&buf);
6961 opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operid));
6962 if (!HeapTupleIsValid(opertup))
6963 elog(ERROR, "cache lookup failed for operator %u", operid);
6964 operform = (Form_pg_operator) GETSTRUCT(opertup);
6965 oprname = NameStr(operform->oprname);
6968 * The idea here is to schema-qualify only if the parser would fail to
6969 * resolve the correct operator given the unqualified op name with the
6970 * specified argtypes.
6972 switch (operform->oprkind)
6975 p_result = oper(NULL, list_make1(makeString(oprname)), arg1, arg2,
6979 p_result = left_oper(NULL, list_make1(makeString(oprname)), arg2,
6983 p_result = right_oper(NULL, list_make1(makeString(oprname)), arg1,
6987 elog(ERROR, "unrecognized oprkind: %d", operform->oprkind);
6988 p_result = NULL; /* keep compiler quiet */
6992 if (p_result != NULL && oprid(p_result) == operid)
6996 nspname = get_namespace_name(operform->oprnamespace);
6997 appendStringInfo(&buf, "OPERATOR(%s.", quote_identifier(nspname));
7000 appendStringInfoString(&buf, oprname);
7003 appendStringInfoChar(&buf, ')');
7005 if (p_result != NULL)
7006 ReleaseSysCache(p_result);
7008 ReleaseSysCache(opertup);
7014 * Given a C string, produce a TEXT datum.
7016 * We assume that the input was palloc'd and may be freed.
7019 string_to_text(char *str)
7023 result = cstring_to_text(str);
7029 * Generate a C string representing a relation's reloptions, or NULL if none.
7032 flatten_reloptions(Oid relid)
7034 char *result = NULL;
7039 tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
7040 if (!HeapTupleIsValid(tuple))
7041 elog(ERROR, "cache lookup failed for relation %u", relid);
7043 reloptions = SysCacheGetAttr(RELOID, tuple,
7044 Anum_pg_class_reloptions, &isnull);
7051 * We want to use array_to_text(reloptions, ', ') --- but
7052 * DirectFunctionCall2(array_to_text) does not work, because
7053 * array_to_text() relies on flinfo to be valid. So use
7056 sep = CStringGetTextDatum(", ");
7057 txt = OidFunctionCall2(F_ARRAY_TO_TEXT, reloptions, sep);
7058 result = TextDatumGetCString(txt);
7061 ReleaseSysCache(tuple);