1 /*-------------------------------------------------------------------------
4 * Functions to convert stored expressions/querytrees back to
7 * Portions Copyright (c) 1996-2011, 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_collation.h"
27 #include "catalog/pg_constraint.h"
28 #include "catalog/pg_depend.h"
29 #include "catalog/pg_language.h"
30 #include "catalog/pg_opclass.h"
31 #include "catalog/pg_operator.h"
32 #include "catalog/pg_proc.h"
33 #include "catalog/pg_trigger.h"
34 #include "catalog/pg_type.h"
35 #include "commands/defrem.h"
36 #include "commands/tablespace.h"
37 #include "executor/spi.h"
39 #include "nodes/makefuncs.h"
40 #include "nodes/nodeFuncs.h"
41 #include "optimizer/clauses.h"
42 #include "optimizer/tlist.h"
43 #include "parser/keywords.h"
44 #include "parser/parse_func.h"
45 #include "parser/parse_oper.h"
46 #include "parser/parser.h"
47 #include "parser/parsetree.h"
48 #include "rewrite/rewriteHandler.h"
49 #include "rewrite/rewriteManip.h"
50 #include "rewrite/rewriteSupport.h"
51 #include "utils/array.h"
52 #include "utils/builtins.h"
53 #include "utils/fmgroids.h"
54 #include "utils/lsyscache.h"
55 #include "utils/tqual.h"
56 #include "utils/syscache.h"
57 #include "utils/typcache.h"
58 #include "utils/xml.h"
62 * Pretty formatting constants
67 #define PRETTYINDENT_STD 8
68 #define PRETTYINDENT_JOIN 13
69 #define PRETTYINDENT_JOIN_ON (PRETTYINDENT_JOIN-PRETTYINDENT_STD)
70 #define PRETTYINDENT_VAR 4
73 #define PRETTYFLAG_PAREN 1
74 #define PRETTYFLAG_INDENT 2
76 /* macro to test if pretty action needed */
77 #define PRETTY_PAREN(context) ((context)->prettyFlags & PRETTYFLAG_PAREN)
78 #define PRETTY_INDENT(context) ((context)->prettyFlags & PRETTYFLAG_INDENT)
86 /* Context info needed for invoking a recursive querytree display routine */
89 StringInfo buf; /* output buffer to append to */
90 List *namespaces; /* List of deparse_namespace nodes */
91 List *windowClause; /* Current query level's WINDOW clause */
92 List *windowTList; /* targetlist for resolving WINDOW clause */
93 int prettyFlags; /* enabling of pretty-print functions */
94 int indentLevel; /* current indent level for prettyprint */
95 bool varprefix; /* TRUE to print prefixes on Vars */
99 * Each level of query context around a subtree needs a level of Var namespace.
100 * A Var having varlevelsup=N refers to the N'th item (counting from 0) in
101 * the current context's namespaces list.
103 * The rangetable is the list of actual RTEs from the query tree, and the
104 * cte list is the list of actual CTEs.
106 * When deparsing plan trees, there is always just a single item in the
107 * deparse_namespace list (since a plan tree never contains Vars with
108 * varlevelsup > 0). We store the PlanState node that is the immediate
109 * parent of the expression to be deparsed, as well as a list of that
110 * PlanState's ancestors. In addition, we store the outer and inner
111 * subplan nodes, whose targetlists are used to resolve OUTER and INNER Vars.
112 * (Note: these could be derived on-the-fly from the planstate instead.)
116 List *rtable; /* List of RangeTblEntry nodes */
117 List *ctes; /* List of CommonTableExpr nodes */
118 /* Remaining fields are used only when deparsing a Plan tree: */
119 PlanState *planstate; /* immediate parent of current expression */
120 List *ancestors; /* ancestors of planstate */
121 PlanState *outer_planstate; /* OUTER subplan state, or NULL if none */
122 PlanState *inner_planstate; /* INNER subplan state, or NULL if none */
123 Plan *outer_plan; /* OUTER subplan, or NULL if none */
124 Plan *inner_plan; /* INNER subplan, or NULL if none */
132 static SPIPlanPtr plan_getrulebyoid = NULL;
133 static const char *query_getrulebyoid = "SELECT * FROM pg_catalog.pg_rewrite WHERE oid = $1";
134 static SPIPlanPtr plan_getviewrule = NULL;
135 static const char *query_getviewrule = "SELECT * FROM pg_catalog.pg_rewrite WHERE ev_class = $1 AND rulename = $2";
138 bool quote_all_identifiers = false;
144 * Most of these functions used to use fixed-size buffers to build their
145 * results. Now, they take an (already initialized) StringInfo object
146 * as a parameter, and append their text output to its contents.
149 static char *deparse_expression_pretty(Node *expr, List *dpcontext,
150 bool forceprefix, bool showimplicit,
151 int prettyFlags, int startIndent);
152 static char *pg_get_viewdef_worker(Oid viewoid, int prettyFlags);
153 static char *pg_get_triggerdef_worker(Oid trigid, bool pretty);
154 static void decompile_column_index_array(Datum column_index_array, Oid relId,
156 static char *pg_get_ruledef_worker(Oid ruleoid, int prettyFlags);
157 static char *pg_get_indexdef_worker(Oid indexrelid, int colno,
158 const Oid *excludeOps,
159 bool attrsOnly, bool showTblSpc,
161 static char *pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
163 static text *pg_get_expr_worker(text *expr, Oid relid, const char *relname,
165 static int print_function_arguments(StringInfo buf, HeapTuple proctup,
166 bool print_table_args, bool print_defaults);
167 static void print_function_rettype(StringInfo buf, HeapTuple proctup);
168 static void set_deparse_planstate(deparse_namespace *dpns, PlanState *ps);
169 static void push_child_plan(deparse_namespace *dpns, PlanState *ps,
170 deparse_namespace *save_dpns);
171 static void pop_child_plan(deparse_namespace *dpns,
172 deparse_namespace *save_dpns);
173 static void push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell,
174 deparse_namespace *save_dpns);
175 static void pop_ancestor_plan(deparse_namespace *dpns,
176 deparse_namespace *save_dpns);
177 static void make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
179 static void make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
181 static void get_query_def(Query *query, StringInfo buf, List *parentnamespace,
182 TupleDesc resultDesc, int prettyFlags, int startIndent);
183 static void get_values_def(List *values_lists, deparse_context *context);
184 static void get_with_clause(Query *query, deparse_context *context);
185 static void get_select_query_def(Query *query, deparse_context *context,
186 TupleDesc resultDesc);
187 static void get_insert_query_def(Query *query, deparse_context *context);
188 static void get_update_query_def(Query *query, deparse_context *context);
189 static void get_delete_query_def(Query *query, deparse_context *context);
190 static void get_utility_query_def(Query *query, deparse_context *context);
191 static void get_basic_select_query(Query *query, deparse_context *context,
192 TupleDesc resultDesc);
193 static void get_target_list(List *targetList, deparse_context *context,
194 TupleDesc resultDesc);
195 static void get_setop_query(Node *setOp, Query *query,
196 deparse_context *context,
197 TupleDesc resultDesc);
198 static Node *get_rule_sortgroupclause(SortGroupClause *srt, List *tlist,
200 deparse_context *context);
201 static void get_rule_orderby(List *orderList, List *targetList,
202 bool force_colno, deparse_context *context);
203 static void get_rule_windowclause(Query *query, deparse_context *context);
204 static void get_rule_windowspec(WindowClause *wc, List *targetList,
205 deparse_context *context);
206 static char *get_variable(Var *var, int levelsup, bool showstar,
207 deparse_context *context);
208 static RangeTblEntry *find_rte_by_refname(const char *refname,
209 deparse_context *context);
210 static void get_parameter(Param *param, deparse_context *context);
211 static void print_parameter_expr(Node *expr, ListCell *ancestor_cell,
212 deparse_namespace *dpns, deparse_context *context);
213 static const char *get_simple_binary_op_name(OpExpr *expr);
214 static bool isSimpleNode(Node *node, Node *parentNode, int prettyFlags);
215 static void appendContextKeyword(deparse_context *context, const char *str,
216 int indentBefore, int indentAfter, int indentPlus);
217 static void get_rule_expr(Node *node, deparse_context *context,
219 static void get_oper_expr(OpExpr *expr, deparse_context *context);
220 static void get_func_expr(FuncExpr *expr, deparse_context *context,
222 static void get_agg_expr(Aggref *aggref, deparse_context *context);
223 static void get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context);
224 static void get_coercion_expr(Node *arg, deparse_context *context,
225 Oid resulttype, int32 resulttypmod,
227 static void get_const_expr(Const *constval, deparse_context *context,
229 static void get_const_collation(Const *constval, deparse_context *context);
230 static void simple_quote_literal(StringInfo buf, const char *val);
231 static void get_sublink_expr(SubLink *sublink, deparse_context *context);
232 static void get_from_clause(Query *query, const char *prefix,
233 deparse_context *context);
234 static void get_from_clause_item(Node *jtnode, Query *query,
235 deparse_context *context);
236 static void get_from_clause_alias(Alias *alias, RangeTblEntry *rte,
237 deparse_context *context);
238 static void get_from_clause_coldeflist(List *names,
239 List *types, List *typmods, List *collations,
240 deparse_context *context);
241 static void get_opclass_name(Oid opclass, Oid actual_datatype,
243 static Node *processIndirection(Node *node, deparse_context *context,
245 static void printSubscripts(ArrayRef *aref, deparse_context *context);
246 static char *get_relation_name(Oid relid);
247 static char *generate_relation_name(Oid relid, List *namespaces);
248 static char *generate_function_name(Oid funcid, int nargs, List *argnames,
249 Oid *argtypes, bool *is_variadic);
250 static char *generate_operator_name(Oid operid, Oid arg1, Oid arg2);
251 static text *string_to_text(char *str);
252 static char *flatten_reloptions(Oid relid);
254 #define only_marker(rte) ((rte)->inh ? "" : "ONLY ")
258 * get_ruledef - Do it all and return a text
259 * that could be used as a statement
260 * to recreate the rule
264 pg_get_ruledef(PG_FUNCTION_ARGS)
266 Oid ruleoid = PG_GETARG_OID(0);
268 PG_RETURN_TEXT_P(string_to_text(pg_get_ruledef_worker(ruleoid, 0)));
273 pg_get_ruledef_ext(PG_FUNCTION_ARGS)
275 Oid ruleoid = PG_GETARG_OID(0);
276 bool pretty = PG_GETARG_BOOL(1);
279 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
280 PG_RETURN_TEXT_P(string_to_text(pg_get_ruledef_worker(ruleoid, prettyFlags)));
285 pg_get_ruledef_worker(Oid ruleoid, int prettyFlags)
295 * Do this first so that string is alloc'd in outer context not SPI's.
297 initStringInfo(&buf);
300 * Connect to SPI manager
302 if (SPI_connect() != SPI_OK_CONNECT)
303 elog(ERROR, "SPI_connect failed");
306 * On the first call prepare the plan to lookup pg_rewrite. We read
307 * pg_rewrite over the SPI manager instead of using the syscache to be
308 * checked for read access on pg_rewrite.
310 if (plan_getrulebyoid == NULL)
315 argtypes[0] = OIDOID;
316 plan = SPI_prepare(query_getrulebyoid, 1, argtypes);
318 elog(ERROR, "SPI_prepare failed for \"%s\"", query_getrulebyoid);
319 plan_getrulebyoid = SPI_saveplan(plan);
323 * Get the pg_rewrite tuple for this rule
325 args[0] = ObjectIdGetDatum(ruleoid);
327 spirc = SPI_execute_plan(plan_getrulebyoid, args, nulls, true, 1);
328 if (spirc != SPI_OK_SELECT)
329 elog(ERROR, "failed to get pg_rewrite tuple for rule %u", ruleoid);
330 if (SPI_processed != 1)
331 appendStringInfo(&buf, "-");
335 * Get the rule's definition and put it into executor's memory
337 ruletup = SPI_tuptable->vals[0];
338 rulettc = SPI_tuptable->tupdesc;
339 make_ruledef(&buf, ruletup, rulettc, prettyFlags);
343 * Disconnect from SPI manager
345 if (SPI_finish() != SPI_OK_FINISH)
346 elog(ERROR, "SPI_finish failed");
353 * get_viewdef - Mainly the same thing, but we
354 * only return the SELECT part of a view
358 pg_get_viewdef(PG_FUNCTION_ARGS)
361 Oid viewoid = PG_GETARG_OID(0);
363 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, 0)));
368 pg_get_viewdef_ext(PG_FUNCTION_ARGS)
371 Oid viewoid = PG_GETARG_OID(0);
372 bool pretty = PG_GETARG_BOOL(1);
375 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
376 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, prettyFlags)));
380 pg_get_viewdef_name(PG_FUNCTION_ARGS)
382 /* By qualified name */
383 text *viewname = PG_GETARG_TEXT_P(0);
387 viewrel = makeRangeVarFromNameList(textToQualifiedNameList(viewname));
388 viewoid = RangeVarGetRelid(viewrel, false);
390 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, 0)));
395 pg_get_viewdef_name_ext(PG_FUNCTION_ARGS)
397 /* By qualified name */
398 text *viewname = PG_GETARG_TEXT_P(0);
399 bool pretty = PG_GETARG_BOOL(1);
404 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
405 viewrel = makeRangeVarFromNameList(textToQualifiedNameList(viewname));
406 viewoid = RangeVarGetRelid(viewrel, false);
408 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, prettyFlags)));
412 * Common code for by-OID and by-name variants of pg_get_viewdef
415 pg_get_viewdef_worker(Oid viewoid, int prettyFlags)
425 * Do this first so that string is alloc'd in outer context not SPI's.
427 initStringInfo(&buf);
430 * Connect to SPI manager
432 if (SPI_connect() != SPI_OK_CONNECT)
433 elog(ERROR, "SPI_connect failed");
436 * On the first call prepare the plan to lookup pg_rewrite. We read
437 * pg_rewrite over the SPI manager instead of using the syscache to be
438 * checked for read access on pg_rewrite.
440 if (plan_getviewrule == NULL)
445 argtypes[0] = OIDOID;
446 argtypes[1] = NAMEOID;
447 plan = SPI_prepare(query_getviewrule, 2, argtypes);
449 elog(ERROR, "SPI_prepare failed for \"%s\"", query_getviewrule);
450 plan_getviewrule = SPI_saveplan(plan);
454 * Get the pg_rewrite tuple for the view's SELECT rule
456 args[0] = ObjectIdGetDatum(viewoid);
457 args[1] = PointerGetDatum(ViewSelectRuleName);
460 spirc = SPI_execute_plan(plan_getviewrule, args, nulls, true, 2);
461 if (spirc != SPI_OK_SELECT)
462 elog(ERROR, "failed to get pg_rewrite tuple for view %u", viewoid);
463 if (SPI_processed != 1)
464 appendStringInfo(&buf, "Not a view");
468 * Get the rule's definition and put it into executor's memory
470 ruletup = SPI_tuptable->vals[0];
471 rulettc = SPI_tuptable->tupdesc;
472 make_viewdef(&buf, ruletup, rulettc, prettyFlags);
476 * Disconnect from SPI manager
478 if (SPI_finish() != SPI_OK_FINISH)
479 elog(ERROR, "SPI_finish failed");
485 * get_triggerdef - Get the definition of a trigger
489 pg_get_triggerdef(PG_FUNCTION_ARGS)
491 Oid trigid = PG_GETARG_OID(0);
493 PG_RETURN_TEXT_P(string_to_text(pg_get_triggerdef_worker(trigid, false)));
497 pg_get_triggerdef_ext(PG_FUNCTION_ARGS)
499 Oid trigid = PG_GETARG_OID(0);
500 bool pretty = PG_GETARG_BOOL(1);
502 PG_RETURN_TEXT_P(string_to_text(pg_get_triggerdef_worker(trigid, pretty)));
506 pg_get_triggerdef_worker(Oid trigid, bool pretty)
509 Form_pg_trigger trigrec;
520 * Fetch the pg_trigger tuple by the Oid of the trigger
522 tgrel = heap_open(TriggerRelationId, AccessShareLock);
524 ScanKeyInit(&skey[0],
525 ObjectIdAttributeNumber,
526 BTEqualStrategyNumber, F_OIDEQ,
527 ObjectIdGetDatum(trigid));
529 tgscan = systable_beginscan(tgrel, TriggerOidIndexId, true,
530 SnapshotNow, 1, skey);
532 ht_trig = systable_getnext(tgscan);
534 if (!HeapTupleIsValid(ht_trig))
535 elog(ERROR, "could not find tuple for trigger %u", trigid);
537 trigrec = (Form_pg_trigger) GETSTRUCT(ht_trig);
540 * Start the trigger definition. Note that the trigger's name should never
541 * be schema-qualified, but the trigger rel's name may be.
543 initStringInfo(&buf);
545 tgname = NameStr(trigrec->tgname);
546 appendStringInfo(&buf, "CREATE %sTRIGGER %s ",
547 OidIsValid(trigrec->tgconstraint) ? "CONSTRAINT " : "",
548 quote_identifier(tgname));
550 if (TRIGGER_FOR_BEFORE(trigrec->tgtype))
551 appendStringInfo(&buf, "BEFORE");
552 else if (TRIGGER_FOR_AFTER(trigrec->tgtype))
553 appendStringInfo(&buf, "AFTER");
554 else if (TRIGGER_FOR_INSTEAD(trigrec->tgtype))
555 appendStringInfo(&buf, "INSTEAD OF");
557 elog(ERROR, "unexpected tgtype value: %d", trigrec->tgtype);
559 if (TRIGGER_FOR_INSERT(trigrec->tgtype))
561 appendStringInfo(&buf, " INSERT");
564 if (TRIGGER_FOR_DELETE(trigrec->tgtype))
567 appendStringInfo(&buf, " OR DELETE");
569 appendStringInfo(&buf, " DELETE");
572 if (TRIGGER_FOR_UPDATE(trigrec->tgtype))
575 appendStringInfo(&buf, " OR UPDATE");
577 appendStringInfo(&buf, " UPDATE");
579 /* tgattr is first var-width field, so OK to access directly */
580 if (trigrec->tgattr.dim1 > 0)
584 appendStringInfoString(&buf, " OF ");
585 for (i = 0; i < trigrec->tgattr.dim1; i++)
590 appendStringInfoString(&buf, ", ");
591 attname = get_relid_attribute_name(trigrec->tgrelid,
592 trigrec->tgattr.values[i]);
593 appendStringInfoString(&buf, quote_identifier(attname));
597 if (TRIGGER_FOR_TRUNCATE(trigrec->tgtype))
600 appendStringInfo(&buf, " OR TRUNCATE");
602 appendStringInfo(&buf, " TRUNCATE");
605 appendStringInfo(&buf, " ON %s ",
606 generate_relation_name(trigrec->tgrelid, NIL));
608 if (OidIsValid(trigrec->tgconstraint))
610 if (OidIsValid(trigrec->tgconstrrelid))
611 appendStringInfo(&buf, "FROM %s ",
612 generate_relation_name(trigrec->tgconstrrelid, NIL));
613 if (!trigrec->tgdeferrable)
614 appendStringInfo(&buf, "NOT ");
615 appendStringInfo(&buf, "DEFERRABLE INITIALLY ");
616 if (trigrec->tginitdeferred)
617 appendStringInfo(&buf, "DEFERRED ");
619 appendStringInfo(&buf, "IMMEDIATE ");
622 if (TRIGGER_FOR_ROW(trigrec->tgtype))
623 appendStringInfo(&buf, "FOR EACH ROW ");
625 appendStringInfo(&buf, "FOR EACH STATEMENT ");
627 /* If the trigger has a WHEN qualification, add that */
628 value = fastgetattr(ht_trig, Anum_pg_trigger_tgqual,
629 tgrel->rd_att, &isnull);
634 deparse_context context;
635 deparse_namespace dpns;
636 RangeTblEntry *oldrte;
637 RangeTblEntry *newrte;
639 appendStringInfoString(&buf, "WHEN (");
641 qual = stringToNode(TextDatumGetCString(value));
643 relkind = get_rel_relkind(trigrec->tgrelid);
645 /* Build minimal OLD and NEW RTEs for the rel */
646 oldrte = makeNode(RangeTblEntry);
647 oldrte->rtekind = RTE_RELATION;
648 oldrte->relid = trigrec->tgrelid;
649 oldrte->relkind = relkind;
650 oldrte->eref = makeAlias("old", NIL);
652 oldrte->inFromCl = true;
654 newrte = makeNode(RangeTblEntry);
655 newrte->rtekind = RTE_RELATION;
656 newrte->relid = trigrec->tgrelid;
657 newrte->relkind = relkind;
658 newrte->eref = makeAlias("new", NIL);
660 newrte->inFromCl = true;
662 /* Build two-element rtable */
663 memset(&dpns, 0, sizeof(dpns));
664 dpns.rtable = list_make2(oldrte, newrte);
667 /* Set up context with one-deep namespace stack */
669 context.namespaces = list_make1(&dpns);
670 context.windowClause = NIL;
671 context.windowTList = NIL;
672 context.varprefix = true;
673 context.prettyFlags = pretty ? PRETTYFLAG_PAREN : 0;
674 context.indentLevel = PRETTYINDENT_STD;
676 get_rule_expr(qual, &context, false);
678 appendStringInfo(&buf, ") ");
681 appendStringInfo(&buf, "EXECUTE PROCEDURE %s(",
682 generate_function_name(trigrec->tgfoid, 0,
685 if (trigrec->tgnargs > 0)
690 value = fastgetattr(ht_trig, Anum_pg_trigger_tgargs,
691 tgrel->rd_att, &isnull);
693 elog(ERROR, "tgargs is null for trigger %u", trigid);
694 p = (char *) VARDATA(DatumGetByteaP(value));
695 for (i = 0; i < trigrec->tgnargs; i++)
698 appendStringInfo(&buf, ", ");
699 simple_quote_literal(&buf, p);
700 /* advance p to next string embedded in tgargs */
707 /* We deliberately do not put semi-colon at end */
708 appendStringInfo(&buf, ")");
711 systable_endscan(tgscan);
713 heap_close(tgrel, AccessShareLock);
719 * get_indexdef - Get the definition of an index
721 * In the extended version, there is a colno argument as well as pretty bool.
722 * if colno == 0, we want a complete index definition.
723 * if colno > 0, we only want the Nth index key's variable or expression.
725 * Note that the SQL-function versions of this omit any info about the
726 * index tablespace; this is intentional because pg_dump wants it that way.
727 * However pg_get_indexdef_string() includes index tablespace if not default.
731 pg_get_indexdef(PG_FUNCTION_ARGS)
733 Oid indexrelid = PG_GETARG_OID(0);
735 PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, 0,
741 pg_get_indexdef_ext(PG_FUNCTION_ARGS)
743 Oid indexrelid = PG_GETARG_OID(0);
744 int32 colno = PG_GETARG_INT32(1);
745 bool pretty = PG_GETARG_BOOL(2);
748 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
749 PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, colno,
756 /* Internal version that returns a palloc'd C string */
758 pg_get_indexdef_string(Oid indexrelid)
760 return pg_get_indexdef_worker(indexrelid, 0, NULL, false, true, 0);
763 /* Internal version that just reports the column definitions */
765 pg_get_indexdef_columns(Oid indexrelid, bool pretty)
769 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
770 return pg_get_indexdef_worker(indexrelid, 0, NULL, true, false, prettyFlags);
774 * Internal workhorse to decompile an index definition.
776 * This is now used for exclusion constraints as well: if excludeOps is not
777 * NULL then it points to an array of exclusion operator OIDs.
780 pg_get_indexdef_worker(Oid indexrelid, int colno,
781 const Oid *excludeOps,
782 bool attrsOnly, bool showTblSpc,
785 /* might want a separate isConstraint parameter later */
786 bool isConstraint = (excludeOps != NULL);
790 Form_pg_index idxrec;
791 Form_pg_class idxrelrec;
794 ListCell *indexpr_item;
800 Datum indoptionDatum;
802 oidvector *indcollation;
804 int2vector *indoption;
810 * Fetch the pg_index tuple by the Oid of the index
812 ht_idx = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexrelid));
813 if (!HeapTupleIsValid(ht_idx))
814 elog(ERROR, "cache lookup failed for index %u", indexrelid);
815 idxrec = (Form_pg_index) GETSTRUCT(ht_idx);
817 indrelid = idxrec->indrelid;
818 Assert(indexrelid == idxrec->indexrelid);
820 /* Must get indcollation, indclass, and indoption the hard way */
821 indcollDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
822 Anum_pg_index_indcollation, &isnull);
824 indcollation = (oidvector *) DatumGetPointer(indcollDatum);
826 indclassDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
827 Anum_pg_index_indclass, &isnull);
829 indclass = (oidvector *) DatumGetPointer(indclassDatum);
831 indoptionDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
832 Anum_pg_index_indoption, &isnull);
834 indoption = (int2vector *) DatumGetPointer(indoptionDatum);
837 * Fetch the pg_class tuple of the index relation
839 ht_idxrel = SearchSysCache1(RELOID, ObjectIdGetDatum(indexrelid));
840 if (!HeapTupleIsValid(ht_idxrel))
841 elog(ERROR, "cache lookup failed for relation %u", indexrelid);
842 idxrelrec = (Form_pg_class) GETSTRUCT(ht_idxrel);
845 * Fetch the pg_am tuple of the index' access method
847 ht_am = SearchSysCache1(AMOID, ObjectIdGetDatum(idxrelrec->relam));
848 if (!HeapTupleIsValid(ht_am))
849 elog(ERROR, "cache lookup failed for access method %u",
851 amrec = (Form_pg_am) GETSTRUCT(ht_am);
854 * Get the index expressions, if any. (NOTE: we do not use the relcache
855 * versions of the expressions and predicate, because we want to display
856 * non-const-folded expressions.)
858 if (!heap_attisnull(ht_idx, Anum_pg_index_indexprs))
864 exprsDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
865 Anum_pg_index_indexprs, &isnull);
867 exprsString = TextDatumGetCString(exprsDatum);
868 indexprs = (List *) stringToNode(exprsString);
874 indexpr_item = list_head(indexprs);
876 context = deparse_context_for(get_relation_name(indrelid), indrelid);
879 * Start the index definition. Note that the index's name should never be
880 * schema-qualified, but the indexed rel's name may be.
882 initStringInfo(&buf);
887 appendStringInfo(&buf, "CREATE %sINDEX %s ON %s USING %s (",
888 idxrec->indisunique ? "UNIQUE " : "",
889 quote_identifier(NameStr(idxrelrec->relname)),
890 generate_relation_name(indrelid, NIL),
891 quote_identifier(NameStr(amrec->amname)));
892 else /* currently, must be EXCLUDE constraint */
893 appendStringInfo(&buf, "EXCLUDE USING %s (",
894 quote_identifier(NameStr(amrec->amname)));
898 * Report the indexed attributes
901 for (keyno = 0; keyno < idxrec->indnatts; keyno++)
903 AttrNumber attnum = idxrec->indkey.values[keyno];
904 int16 opt = indoption->values[keyno];
909 appendStringInfoString(&buf, sep);
914 /* Simple index column */
918 attname = get_relid_attribute_name(indrelid, attnum);
919 if (!colno || colno == keyno + 1)
920 appendStringInfoString(&buf, quote_identifier(attname));
921 get_atttypetypmodcoll(indrelid, attnum,
922 &keycoltype, &keycoltypmod,
927 /* expressional index */
930 if (indexpr_item == NULL)
931 elog(ERROR, "too few entries in indexprs list");
932 indexkey = (Node *) lfirst(indexpr_item);
933 indexpr_item = lnext(indexpr_item);
935 str = deparse_expression_pretty(indexkey, context, false, false,
937 if (!colno || colno == keyno + 1)
939 /* Need parens if it's not a bare function call */
940 if (indexkey && IsA(indexkey, FuncExpr) &&
941 ((FuncExpr *) indexkey)->funcformat == COERCE_EXPLICIT_CALL)
942 appendStringInfoString(&buf, str);
944 appendStringInfo(&buf, "(%s)", str);
946 keycoltype = exprType(indexkey);
947 keycolcollation = exprCollation(indexkey);
950 if (!attrsOnly && (!colno || colno == keyno + 1))
954 /* Add collation, if not default for column */
955 indcoll = indcollation->values[keyno];
956 if (OidIsValid(indcoll) && indcoll != keycolcollation)
957 appendStringInfo(&buf, " COLLATE %s",
958 generate_collation_name((indcoll)));
960 /* Add the operator class name, if not default */
961 get_opclass_name(indclass->values[keyno], keycoltype, &buf);
963 /* Add options if relevant */
964 if (amrec->amcanorder)
966 /* if it supports sort ordering, report DESC and NULLS opts */
967 if (opt & INDOPTION_DESC)
969 appendStringInfo(&buf, " DESC");
970 /* NULLS FIRST is the default in this case */
971 if (!(opt & INDOPTION_NULLS_FIRST))
972 appendStringInfo(&buf, " NULLS LAST");
976 if (opt & INDOPTION_NULLS_FIRST)
977 appendStringInfo(&buf, " NULLS FIRST");
981 /* Add the exclusion operator if relevant */
982 if (excludeOps != NULL)
983 appendStringInfo(&buf, " WITH %s",
984 generate_operator_name(excludeOps[keyno],
992 appendStringInfoChar(&buf, ')');
995 * If it has options, append "WITH (options)"
997 str = flatten_reloptions(indexrelid);
1000 appendStringInfo(&buf, " WITH (%s)", str);
1005 * If it's in a nondefault tablespace, say so, but only if requested
1011 tblspc = get_rel_tablespace(indexrelid);
1012 if (OidIsValid(tblspc))
1015 appendStringInfoString(&buf, " USING INDEX");
1016 appendStringInfo(&buf, " TABLESPACE %s",
1017 quote_identifier(get_tablespace_name(tblspc)));
1022 * If it's a partial index, decompile and append the predicate
1024 if (!heap_attisnull(ht_idx, Anum_pg_index_indpred))
1031 /* Convert text string to node tree */
1032 predDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
1033 Anum_pg_index_indpred, &isnull);
1035 predString = TextDatumGetCString(predDatum);
1036 node = (Node *) stringToNode(predString);
1040 str = deparse_expression_pretty(node, context, false, false,
1043 appendStringInfo(&buf, " WHERE (%s)", str);
1045 appendStringInfo(&buf, " WHERE %s", str);
1050 ReleaseSysCache(ht_idx);
1051 ReleaseSysCache(ht_idxrel);
1052 ReleaseSysCache(ht_am);
1059 * pg_get_constraintdef
1061 * Returns the definition for the constraint, ie, everything that needs to
1062 * appear after "ALTER TABLE ... ADD CONSTRAINT <constraintname>".
1065 pg_get_constraintdef(PG_FUNCTION_ARGS)
1067 Oid constraintId = PG_GETARG_OID(0);
1069 PG_RETURN_TEXT_P(string_to_text(pg_get_constraintdef_worker(constraintId,
1074 pg_get_constraintdef_ext(PG_FUNCTION_ARGS)
1076 Oid constraintId = PG_GETARG_OID(0);
1077 bool pretty = PG_GETARG_BOOL(1);
1080 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
1081 PG_RETURN_TEXT_P(string_to_text(pg_get_constraintdef_worker(constraintId,
1082 false, prettyFlags)));
1085 /* Internal version that returns a palloc'd C string */
1087 pg_get_constraintdef_string(Oid constraintId)
1089 return pg_get_constraintdef_worker(constraintId, true, 0);
1093 pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
1097 Form_pg_constraint conForm;
1100 tup = SearchSysCache1(CONSTROID, ObjectIdGetDatum(constraintId));
1101 if (!HeapTupleIsValid(tup)) /* should not happen */
1102 elog(ERROR, "cache lookup failed for constraint %u", constraintId);
1103 conForm = (Form_pg_constraint) GETSTRUCT(tup);
1105 initStringInfo(&buf);
1107 if (fullCommand && OidIsValid(conForm->conrelid))
1109 appendStringInfo(&buf, "ALTER TABLE ONLY %s ADD CONSTRAINT %s ",
1110 generate_relation_name(conForm->conrelid, NIL),
1111 quote_identifier(NameStr(conForm->conname)));
1114 switch (conForm->contype)
1116 case CONSTRAINT_FOREIGN:
1122 /* Start off the constraint definition */
1123 appendStringInfo(&buf, "FOREIGN KEY (");
1125 /* Fetch and build referencing-column list */
1126 val = SysCacheGetAttr(CONSTROID, tup,
1127 Anum_pg_constraint_conkey, &isnull);
1129 elog(ERROR, "null conkey for constraint %u",
1132 decompile_column_index_array(val, conForm->conrelid, &buf);
1134 /* add foreign relation name */
1135 appendStringInfo(&buf, ") REFERENCES %s(",
1136 generate_relation_name(conForm->confrelid,
1139 /* Fetch and build referenced-column list */
1140 val = SysCacheGetAttr(CONSTROID, tup,
1141 Anum_pg_constraint_confkey, &isnull);
1143 elog(ERROR, "null confkey for constraint %u",
1146 decompile_column_index_array(val, conForm->confrelid, &buf);
1148 appendStringInfo(&buf, ")");
1150 /* Add match type */
1151 switch (conForm->confmatchtype)
1153 case FKCONSTR_MATCH_FULL:
1154 string = " MATCH FULL";
1156 case FKCONSTR_MATCH_PARTIAL:
1157 string = " MATCH PARTIAL";
1159 case FKCONSTR_MATCH_UNSPECIFIED:
1163 elog(ERROR, "unrecognized confmatchtype: %d",
1164 conForm->confmatchtype);
1165 string = ""; /* keep compiler quiet */
1168 appendStringInfoString(&buf, string);
1170 /* Add ON UPDATE and ON DELETE clauses, if needed */
1171 switch (conForm->confupdtype)
1173 case FKCONSTR_ACTION_NOACTION:
1174 string = NULL; /* suppress default */
1176 case FKCONSTR_ACTION_RESTRICT:
1177 string = "RESTRICT";
1179 case FKCONSTR_ACTION_CASCADE:
1182 case FKCONSTR_ACTION_SETNULL:
1183 string = "SET NULL";
1185 case FKCONSTR_ACTION_SETDEFAULT:
1186 string = "SET DEFAULT";
1189 elog(ERROR, "unrecognized confupdtype: %d",
1190 conForm->confupdtype);
1191 string = NULL; /* keep compiler quiet */
1195 appendStringInfo(&buf, " ON UPDATE %s", string);
1197 switch (conForm->confdeltype)
1199 case FKCONSTR_ACTION_NOACTION:
1200 string = NULL; /* suppress default */
1202 case FKCONSTR_ACTION_RESTRICT:
1203 string = "RESTRICT";
1205 case FKCONSTR_ACTION_CASCADE:
1208 case FKCONSTR_ACTION_SETNULL:
1209 string = "SET NULL";
1211 case FKCONSTR_ACTION_SETDEFAULT:
1212 string = "SET DEFAULT";
1215 elog(ERROR, "unrecognized confdeltype: %d",
1216 conForm->confdeltype);
1217 string = NULL; /* keep compiler quiet */
1221 appendStringInfo(&buf, " ON DELETE %s", string);
1225 case CONSTRAINT_PRIMARY:
1226 case CONSTRAINT_UNIQUE:
1232 /* Start off the constraint definition */
1233 if (conForm->contype == CONSTRAINT_PRIMARY)
1234 appendStringInfo(&buf, "PRIMARY KEY (");
1236 appendStringInfo(&buf, "UNIQUE (");
1238 /* Fetch and build target column list */
1239 val = SysCacheGetAttr(CONSTROID, tup,
1240 Anum_pg_constraint_conkey, &isnull);
1242 elog(ERROR, "null conkey for constraint %u",
1245 decompile_column_index_array(val, conForm->conrelid, &buf);
1247 appendStringInfo(&buf, ")");
1249 indexId = get_constraint_index(constraintId);
1251 /* XXX why do we only print these bits if fullCommand? */
1252 if (fullCommand && OidIsValid(indexId))
1254 char *options = flatten_reloptions(indexId);
1259 appendStringInfo(&buf, " WITH (%s)", options);
1263 tblspc = get_rel_tablespace(indexId);
1264 if (OidIsValid(tblspc))
1265 appendStringInfo(&buf, " USING INDEX TABLESPACE %s",
1266 quote_identifier(get_tablespace_name(tblspc)));
1271 case CONSTRAINT_CHECK:
1280 /* Fetch constraint expression in parsetree form */
1281 val = SysCacheGetAttr(CONSTROID, tup,
1282 Anum_pg_constraint_conbin, &isnull);
1284 elog(ERROR, "null conbin for constraint %u",
1287 conbin = TextDatumGetCString(val);
1288 expr = stringToNode(conbin);
1290 /* Set up deparsing context for Var nodes in constraint */
1291 if (conForm->conrelid != InvalidOid)
1293 /* relation constraint */
1294 context = deparse_context_for(get_relation_name(conForm->conrelid),
1299 /* domain constraint --- can't have Vars */
1303 consrc = deparse_expression_pretty(expr, context, false, false,
1307 * Now emit the constraint definition. There are cases where
1308 * the constraint expression will be fully parenthesized and
1309 * we don't need the outer parens ... but there are other
1310 * cases where we do need 'em. Be conservative for now.
1312 * Note that simply checking for leading '(' and trailing ')'
1313 * would NOT be good enough, consider "(x > 0) AND (y > 0)".
1315 appendStringInfo(&buf, "CHECK (%s)", consrc);
1319 case CONSTRAINT_TRIGGER:
1322 * There isn't an ALTER TABLE syntax for creating a user-defined
1323 * constraint trigger, but it seems better to print something than
1324 * throw an error; if we throw error then this function couldn't
1325 * safely be applied to all rows of pg_constraint.
1327 appendStringInfo(&buf, "TRIGGER");
1329 case CONSTRAINT_EXCLUSION:
1331 Oid indexOid = conForm->conindid;
1339 /* Extract operator OIDs from the pg_constraint tuple */
1340 val = SysCacheGetAttr(CONSTROID, tup,
1341 Anum_pg_constraint_conexclop,
1344 elog(ERROR, "null conexclop for constraint %u",
1347 deconstruct_array(DatumGetArrayTypeP(val),
1348 OIDOID, sizeof(Oid), true, 'i',
1349 &elems, NULL, &nElems);
1351 operators = (Oid *) palloc(nElems * sizeof(Oid));
1352 for (i = 0; i < nElems; i++)
1353 operators[i] = DatumGetObjectId(elems[i]);
1355 /* pg_get_indexdef_worker does the rest */
1356 /* suppress tablespace because pg_dump wants it that way */
1357 appendStringInfoString(&buf,
1358 pg_get_indexdef_worker(indexOid,
1367 elog(ERROR, "invalid constraint type \"%c\"", conForm->contype);
1371 if (conForm->condeferrable)
1372 appendStringInfo(&buf, " DEFERRABLE");
1373 if (conForm->condeferred)
1374 appendStringInfo(&buf, " INITIALLY DEFERRED");
1376 if (!conForm->convalidated)
1377 appendStringInfoString(&buf, " NOT VALID");
1380 ReleaseSysCache(tup);
1387 * Convert an int16[] Datum into a comma-separated list of column names
1388 * for the indicated relation; append the list to buf.
1391 decompile_column_index_array(Datum column_index_array, Oid relId,
1398 /* Extract data from array of int16 */
1399 deconstruct_array(DatumGetArrayTypeP(column_index_array),
1400 INT2OID, 2, true, 's',
1401 &keys, NULL, &nKeys);
1403 for (j = 0; j < nKeys; j++)
1407 colName = get_relid_attribute_name(relId, DatumGetInt16(keys[j]));
1410 appendStringInfoString(buf, quote_identifier(colName));
1412 appendStringInfo(buf, ", %s", quote_identifier(colName));
1418 * get_expr - Decompile an expression tree
1420 * Input: an expression tree in nodeToString form, and a relation OID
1422 * Output: reverse-listed expression
1424 * Currently, the expression can only refer to a single relation, namely
1425 * the one specified by the second parameter. This is sufficient for
1426 * partial indexes, column default expressions, etc. We also support
1427 * Var-free expressions, for which the OID can be InvalidOid.
1431 pg_get_expr(PG_FUNCTION_ARGS)
1433 text *expr = PG_GETARG_TEXT_P(0);
1434 Oid relid = PG_GETARG_OID(1);
1437 if (OidIsValid(relid))
1439 /* Get the name for the relation */
1440 relname = get_rel_name(relid);
1443 * If the OID isn't actually valid, don't throw an error, just return
1444 * NULL. This is a bit questionable, but it's what we've done
1445 * historically, and it can help avoid unwanted failures when
1446 * examining catalog entries for just-deleted relations.
1448 if (relname == NULL)
1454 PG_RETURN_TEXT_P(pg_get_expr_worker(expr, relid, relname, 0));
1458 pg_get_expr_ext(PG_FUNCTION_ARGS)
1460 text *expr = PG_GETARG_TEXT_P(0);
1461 Oid relid = PG_GETARG_OID(1);
1462 bool pretty = PG_GETARG_BOOL(2);
1466 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
1468 if (OidIsValid(relid))
1470 /* Get the name for the relation */
1471 relname = get_rel_name(relid);
1472 /* See notes above */
1473 if (relname == NULL)
1479 PG_RETURN_TEXT_P(pg_get_expr_worker(expr, relid, relname, prettyFlags));
1483 pg_get_expr_worker(text *expr, Oid relid, const char *relname, int prettyFlags)
1490 /* Convert input TEXT object to C string */
1491 exprstr = text_to_cstring(expr);
1493 /* Convert expression to node tree */
1494 node = (Node *) stringToNode(exprstr);
1498 /* Prepare deparse context if needed */
1499 if (OidIsValid(relid))
1500 context = deparse_context_for(relname, relid);
1505 str = deparse_expression_pretty(node, context, false, false,
1508 return string_to_text(str);
1513 * get_userbyid - Get a user name by roleid and
1514 * fallback to 'unknown (OID=n)'
1518 pg_get_userbyid(PG_FUNCTION_ARGS)
1520 Oid roleid = PG_GETARG_OID(0);
1523 Form_pg_authid role_rec;
1526 * Allocate space for the result
1528 result = (Name) palloc(NAMEDATALEN);
1529 memset(NameStr(*result), 0, NAMEDATALEN);
1532 * Get the pg_authid entry and print the result
1534 roletup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
1535 if (HeapTupleIsValid(roletup))
1537 role_rec = (Form_pg_authid) GETSTRUCT(roletup);
1538 StrNCpy(NameStr(*result), NameStr(role_rec->rolname), NAMEDATALEN);
1539 ReleaseSysCache(roletup);
1542 sprintf(NameStr(*result), "unknown (OID=%u)", roleid);
1544 PG_RETURN_NAME(result);
1549 * pg_get_serial_sequence
1550 * Get the name of the sequence used by a serial column,
1551 * formatted suitably for passing to setval, nextval or currval.
1552 * First parameter is not treated as double-quoted, second parameter
1553 * is --- see documentation for reason.
1556 pg_get_serial_sequence(PG_FUNCTION_ARGS)
1558 text *tablename = PG_GETARG_TEXT_P(0);
1559 text *columnname = PG_GETARG_TEXT_PP(1);
1564 Oid sequenceId = InvalidOid;
1570 /* Get the OID of the table */
1571 tablerv = makeRangeVarFromNameList(textToQualifiedNameList(tablename));
1572 tableOid = RangeVarGetRelid(tablerv, false);
1574 /* Get the number of the column */
1575 column = text_to_cstring(columnname);
1577 attnum = get_attnum(tableOid, column);
1578 if (attnum == InvalidAttrNumber)
1580 (errcode(ERRCODE_UNDEFINED_COLUMN),
1581 errmsg("column \"%s\" of relation \"%s\" does not exist",
1582 column, tablerv->relname)));
1584 /* Search the dependency table for the dependent sequence */
1585 depRel = heap_open(DependRelationId, AccessShareLock);
1587 ScanKeyInit(&key[0],
1588 Anum_pg_depend_refclassid,
1589 BTEqualStrategyNumber, F_OIDEQ,
1590 ObjectIdGetDatum(RelationRelationId));
1591 ScanKeyInit(&key[1],
1592 Anum_pg_depend_refobjid,
1593 BTEqualStrategyNumber, F_OIDEQ,
1594 ObjectIdGetDatum(tableOid));
1595 ScanKeyInit(&key[2],
1596 Anum_pg_depend_refobjsubid,
1597 BTEqualStrategyNumber, F_INT4EQ,
1598 Int32GetDatum(attnum));
1600 scan = systable_beginscan(depRel, DependReferenceIndexId, true,
1601 SnapshotNow, 3, key);
1603 while (HeapTupleIsValid(tup = systable_getnext(scan)))
1605 Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
1608 * We assume any auto dependency of a sequence on a column must be
1609 * what we are looking for. (We need the relkind test because indexes
1610 * can also have auto dependencies on columns.)
1612 if (deprec->classid == RelationRelationId &&
1613 deprec->objsubid == 0 &&
1614 deprec->deptype == DEPENDENCY_AUTO &&
1615 get_rel_relkind(deprec->objid) == RELKIND_SEQUENCE)
1617 sequenceId = deprec->objid;
1622 systable_endscan(scan);
1623 heap_close(depRel, AccessShareLock);
1625 if (OidIsValid(sequenceId))
1628 Form_pg_class classtuple;
1632 /* Get the sequence's pg_class entry */
1633 classtup = SearchSysCache1(RELOID, ObjectIdGetDatum(sequenceId));
1634 if (!HeapTupleIsValid(classtup))
1635 elog(ERROR, "cache lookup failed for relation %u", sequenceId);
1636 classtuple = (Form_pg_class) GETSTRUCT(classtup);
1638 /* Get the namespace */
1639 nspname = get_namespace_name(classtuple->relnamespace);
1641 elog(ERROR, "cache lookup failed for namespace %u",
1642 classtuple->relnamespace);
1644 /* And construct the result string */
1645 result = quote_qualified_identifier(nspname,
1646 NameStr(classtuple->relname));
1648 ReleaseSysCache(classtup);
1650 PG_RETURN_TEXT_P(string_to_text(result));
1658 * pg_get_functiondef
1659 * Returns the complete "CREATE OR REPLACE FUNCTION ..." statement for
1660 * the specified function.
1662 * Note: if you change the output format of this function, be careful not
1663 * to break psql's rules (in \ef and \sf) for identifying the start of the
1664 * function body. To wit: the function body starts on a line that begins
1665 * with "AS ", and no preceding line will look like that.
1668 pg_get_functiondef(PG_FUNCTION_ARGS)
1670 Oid funcid = PG_GETARG_OID(0);
1676 Form_pg_language lang;
1685 initStringInfo(&buf);
1687 /* Look up the function */
1688 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1689 if (!HeapTupleIsValid(proctup))
1690 elog(ERROR, "cache lookup failed for function %u", funcid);
1691 proc = (Form_pg_proc) GETSTRUCT(proctup);
1692 name = NameStr(proc->proname);
1696 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1697 errmsg("\"%s\" is an aggregate function", name)));
1699 /* Need its pg_language tuple for the language name */
1700 langtup = SearchSysCache1(LANGOID, ObjectIdGetDatum(proc->prolang));
1701 if (!HeapTupleIsValid(langtup))
1702 elog(ERROR, "cache lookup failed for language %u", proc->prolang);
1703 lang = (Form_pg_language) GETSTRUCT(langtup);
1706 * We always qualify the function name, to ensure the right function gets
1709 nsp = get_namespace_name(proc->pronamespace);
1710 appendStringInfo(&buf, "CREATE OR REPLACE FUNCTION %s(",
1711 quote_qualified_identifier(nsp, name));
1712 (void) print_function_arguments(&buf, proctup, false, true);
1713 appendStringInfoString(&buf, ")\n RETURNS ");
1714 print_function_rettype(&buf, proctup);
1715 appendStringInfo(&buf, "\n LANGUAGE %s\n",
1716 quote_identifier(NameStr(lang->lanname)));
1718 /* Emit some miscellaneous options on one line */
1721 if (proc->proiswindow)
1722 appendStringInfoString(&buf, " WINDOW");
1723 switch (proc->provolatile)
1725 case PROVOLATILE_IMMUTABLE:
1726 appendStringInfoString(&buf, " IMMUTABLE");
1728 case PROVOLATILE_STABLE:
1729 appendStringInfoString(&buf, " STABLE");
1731 case PROVOLATILE_VOLATILE:
1734 if (proc->proisstrict)
1735 appendStringInfoString(&buf, " STRICT");
1736 if (proc->prosecdef)
1737 appendStringInfoString(&buf, " SECURITY DEFINER");
1739 /* This code for the default cost and rows should match functioncmds.c */
1740 if (proc->prolang == INTERNALlanguageId ||
1741 proc->prolang == ClanguageId)
1745 if (proc->procost != procost)
1746 appendStringInfo(&buf, " COST %g", proc->procost);
1748 if (proc->prorows > 0 && proc->prorows != 1000)
1749 appendStringInfo(&buf, " ROWS %g", proc->prorows);
1751 if (oldlen != buf.len)
1752 appendStringInfoChar(&buf, '\n');
1754 /* Emit any proconfig options, one per line */
1755 tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_proconfig, &isnull);
1758 ArrayType *a = DatumGetArrayTypeP(tmp);
1761 Assert(ARR_ELEMTYPE(a) == TEXTOID);
1762 Assert(ARR_NDIM(a) == 1);
1763 Assert(ARR_LBOUND(a)[0] == 1);
1765 for (i = 1; i <= ARR_DIMS(a)[0]; i++)
1769 d = array_ref(a, 1, &i,
1770 -1 /* varlenarray */ ,
1771 -1 /* TEXT's typlen */ ,
1772 false /* TEXT's typbyval */ ,
1773 'i' /* TEXT's typalign */ ,
1777 char *configitem = TextDatumGetCString(d);
1780 pos = strchr(configitem, '=');
1785 appendStringInfo(&buf, " SET %s TO ",
1786 quote_identifier(configitem));
1789 * Some GUC variable names are 'LIST' type and hence must not
1792 if (pg_strcasecmp(configitem, "DateStyle") == 0
1793 || pg_strcasecmp(configitem, "search_path") == 0)
1794 appendStringInfoString(&buf, pos);
1796 simple_quote_literal(&buf, pos);
1797 appendStringInfoChar(&buf, '\n');
1802 /* And finally the function definition ... */
1803 appendStringInfoString(&buf, "AS ");
1805 tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_probin, &isnull);
1808 simple_quote_literal(&buf, TextDatumGetCString(tmp));
1809 appendStringInfoString(&buf, ", "); /* assume prosrc isn't null */
1812 tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_prosrc, &isnull);
1814 elog(ERROR, "null prosrc");
1815 prosrc = TextDatumGetCString(tmp);
1818 * We always use dollar quoting. Figure out a suitable delimiter.
1820 * Since the user is likely to be editing the function body string, we
1821 * shouldn't use a short delimiter that he might easily create a conflict
1822 * with. Hence prefer "$function$", but extend if needed.
1824 initStringInfo(&dq);
1825 appendStringInfoString(&dq, "$function");
1826 while (strstr(prosrc, dq.data) != NULL)
1827 appendStringInfoChar(&dq, 'x');
1828 appendStringInfoChar(&dq, '$');
1830 appendStringInfoString(&buf, dq.data);
1831 appendStringInfoString(&buf, prosrc);
1832 appendStringInfoString(&buf, dq.data);
1834 appendStringInfoString(&buf, "\n");
1836 ReleaseSysCache(langtup);
1837 ReleaseSysCache(proctup);
1839 PG_RETURN_TEXT_P(string_to_text(buf.data));
1843 * pg_get_function_arguments
1844 * Get a nicely-formatted list of arguments for a function.
1845 * This is everything that would go between the parentheses in
1849 pg_get_function_arguments(PG_FUNCTION_ARGS)
1851 Oid funcid = PG_GETARG_OID(0);
1855 initStringInfo(&buf);
1857 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1858 if (!HeapTupleIsValid(proctup))
1859 elog(ERROR, "cache lookup failed for function %u", funcid);
1861 (void) print_function_arguments(&buf, proctup, false, true);
1863 ReleaseSysCache(proctup);
1865 PG_RETURN_TEXT_P(string_to_text(buf.data));
1869 * pg_get_function_identity_arguments
1870 * Get a formatted list of arguments for a function.
1871 * This is everything that would go between the parentheses in
1872 * ALTER FUNCTION, etc. In particular, don't print defaults.
1875 pg_get_function_identity_arguments(PG_FUNCTION_ARGS)
1877 Oid funcid = PG_GETARG_OID(0);
1881 initStringInfo(&buf);
1883 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1884 if (!HeapTupleIsValid(proctup))
1885 elog(ERROR, "cache lookup failed for function %u", funcid);
1887 (void) print_function_arguments(&buf, proctup, false, false);
1889 ReleaseSysCache(proctup);
1891 PG_RETURN_TEXT_P(string_to_text(buf.data));
1895 * pg_get_function_result
1896 * Get a nicely-formatted version of the result type of a function.
1897 * This is what would appear after RETURNS in CREATE FUNCTION.
1900 pg_get_function_result(PG_FUNCTION_ARGS)
1902 Oid funcid = PG_GETARG_OID(0);
1906 initStringInfo(&buf);
1908 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1909 if (!HeapTupleIsValid(proctup))
1910 elog(ERROR, "cache lookup failed for function %u", funcid);
1912 print_function_rettype(&buf, proctup);
1914 ReleaseSysCache(proctup);
1916 PG_RETURN_TEXT_P(string_to_text(buf.data));
1920 * Guts of pg_get_function_result: append the function's return type
1921 * to the specified buffer.
1924 print_function_rettype(StringInfo buf, HeapTuple proctup)
1926 Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(proctup);
1928 StringInfoData rbuf;
1930 initStringInfo(&rbuf);
1932 if (proc->proretset)
1934 /* It might be a table function; try to print the arguments */
1935 appendStringInfoString(&rbuf, "TABLE(");
1936 ntabargs = print_function_arguments(&rbuf, proctup, true, false);
1938 appendStringInfoString(&rbuf, ")");
1940 resetStringInfo(&rbuf);
1945 /* Not a table function, so do the normal thing */
1946 if (proc->proretset)
1947 appendStringInfoString(&rbuf, "SETOF ");
1948 appendStringInfoString(&rbuf, format_type_be(proc->prorettype));
1951 appendStringInfoString(buf, rbuf.data);
1955 * Common code for pg_get_function_arguments and pg_get_function_result:
1956 * append the desired subset of arguments to buf. We print only TABLE
1957 * arguments when print_table_args is true, and all the others when it's false.
1958 * We print argument defaults only if print_defaults is true.
1959 * Function return value is the number of arguments printed.
1962 print_function_arguments(StringInfo buf, HeapTuple proctup,
1963 bool print_table_args, bool print_defaults)
1965 Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(proctup);
1973 ListCell *nextargdefault = NULL;
1976 numargs = get_func_arg_info(proctup,
1977 &argtypes, &argnames, &argmodes);
1979 nlackdefaults = numargs;
1980 if (print_defaults && proc->pronargdefaults > 0)
1982 Datum proargdefaults;
1985 proargdefaults = SysCacheGetAttr(PROCOID, proctup,
1986 Anum_pg_proc_proargdefaults,
1993 str = TextDatumGetCString(proargdefaults);
1994 argdefaults = (List *) stringToNode(str);
1995 Assert(IsA(argdefaults, List));
1997 nextargdefault = list_head(argdefaults);
1998 /* nlackdefaults counts only *input* arguments lacking defaults */
1999 nlackdefaults = proc->pronargs - list_length(argdefaults);
2005 for (i = 0; i < numargs; i++)
2007 Oid argtype = argtypes[i];
2008 char *argname = argnames ? argnames[i] : NULL;
2009 char argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
2010 const char *modename;
2019 case PROARGMODE_INOUT:
2020 modename = "INOUT ";
2023 case PROARGMODE_OUT:
2027 case PROARGMODE_VARIADIC:
2028 modename = "VARIADIC ";
2031 case PROARGMODE_TABLE:
2036 elog(ERROR, "invalid parameter mode '%c'", argmode);
2037 modename = NULL; /* keep compiler quiet */
2042 inputargno++; /* this is a 1-based counter */
2044 if (print_table_args != (argmode == PROARGMODE_TABLE))
2048 appendStringInfoString(buf, ", ");
2049 appendStringInfoString(buf, modename);
2050 if (argname && argname[0])
2051 appendStringInfo(buf, "%s ", quote_identifier(argname));
2052 appendStringInfoString(buf, format_type_be(argtype));
2053 if (print_defaults && isinput && inputargno > nlackdefaults)
2057 Assert(nextargdefault != NULL);
2058 expr = (Node *) lfirst(nextargdefault);
2059 nextargdefault = lnext(nextargdefault);
2061 appendStringInfo(buf, " DEFAULT %s",
2062 deparse_expression(expr, NIL, false, false));
2072 * deparse_expression - General utility for deparsing expressions
2074 * calls deparse_expression_pretty with all prettyPrinting disabled
2077 deparse_expression(Node *expr, List *dpcontext,
2078 bool forceprefix, bool showimplicit)
2080 return deparse_expression_pretty(expr, dpcontext, forceprefix,
2081 showimplicit, 0, 0);
2085 * deparse_expression_pretty - General utility for deparsing expressions
2087 * expr is the node tree to be deparsed. It must be a transformed expression
2088 * tree (ie, not the raw output of gram.y).
2090 * dpcontext is a list of deparse_namespace nodes representing the context
2091 * for interpreting Vars in the node tree.
2093 * forceprefix is TRUE to force all Vars to be prefixed with their table names.
2095 * showimplicit is TRUE to force all implicit casts to be shown explicitly.
2097 * tries to pretty up the output according to prettyFlags and startIndent.
2099 * The result is a palloc'd string.
2103 deparse_expression_pretty(Node *expr, List *dpcontext,
2104 bool forceprefix, bool showimplicit,
2105 int prettyFlags, int startIndent)
2108 deparse_context context;
2110 initStringInfo(&buf);
2112 context.namespaces = dpcontext;
2113 context.windowClause = NIL;
2114 context.windowTList = NIL;
2115 context.varprefix = forceprefix;
2116 context.prettyFlags = prettyFlags;
2117 context.indentLevel = startIndent;
2119 get_rule_expr(expr, &context, showimplicit);
2125 * deparse_context_for - Build deparse context for a single relation
2127 * Given the reference name (alias) and OID of a relation, build deparsing
2128 * context for an expression referencing only that relation (as varno 1,
2129 * varlevelsup 0). This is sufficient for many uses of deparse_expression.
2133 deparse_context_for(const char *aliasname, Oid relid)
2135 deparse_namespace *dpns;
2138 dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
2140 /* Build a minimal RTE for the rel */
2141 rte = makeNode(RangeTblEntry);
2142 rte->rtekind = RTE_RELATION;
2144 rte->relkind = RELKIND_RELATION; /* no need for exactness here */
2145 rte->eref = makeAlias(aliasname, NIL);
2147 rte->inFromCl = true;
2149 /* Build one-element rtable */
2150 dpns->rtable = list_make1(rte);
2153 /* Return a one-deep namespace stack */
2154 return list_make1(dpns);
2158 * deparse_context_for_planstate - Build deparse context for a plan
2160 * When deparsing an expression in a Plan tree, we might have to resolve
2161 * OUTER or INNER references. To do this, the caller must provide the
2162 * parent PlanState node. Then OUTER and INNER references can be resolved
2163 * by drilling down into the left and right child plans.
2165 * Note: planstate really ought to be declared as "PlanState *", but we use
2166 * "Node *" to avoid having to include execnodes.h in builtins.h.
2168 * The ancestors list is a list of the PlanState's parent PlanStates, the
2169 * most-closely-nested first. This is needed to resolve PARAM_EXEC Params.
2170 * Note we assume that all the PlanStates share the same rtable.
2172 * The plan's rangetable list must also be passed. We actually prefer to use
2173 * the rangetable to resolve simple Vars, but the plan inputs are necessary
2174 * for Vars that reference expressions computed in subplan target lists.
2177 deparse_context_for_planstate(Node *planstate, List *ancestors,
2180 deparse_namespace *dpns;
2182 dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace));
2184 /* Initialize fields that stay the same across the whole plan tree */
2185 dpns->rtable = rtable;
2188 /* Set our attention on the specific plan node passed in */
2189 set_deparse_planstate(dpns, (PlanState *) planstate);
2190 dpns->ancestors = ancestors;
2192 /* Return a one-deep namespace stack */
2193 return list_make1(dpns);
2197 * set_deparse_planstate: set up deparse_namespace to parse subexpressions
2198 * of a given PlanState node
2200 * This sets the planstate, outer_planstate, inner_planstate, outer_plan, and
2201 * inner_plan fields. Caller is responsible for adjusting the ancestors list
2202 * if necessary. Note that the rtable and ctes fields do not need to change
2203 * when shifting attention to different plan nodes in a single plan tree.
2206 set_deparse_planstate(deparse_namespace *dpns, PlanState *ps)
2208 dpns->planstate = ps;
2211 * We special-case Append and MergeAppend to pretend that the first child
2212 * plan is the OUTER referent; we have to interpret OUTER Vars in their
2213 * tlists according to one of the children, and the first one is the most
2214 * natural choice. Likewise special-case ModifyTable to pretend that the
2215 * first child plan is the OUTER referent; this is to support RETURNING
2216 * lists containing references to non-target relations.
2218 if (IsA(ps, AppendState))
2219 dpns->outer_planstate = ((AppendState *) ps)->appendplans[0];
2220 else if (IsA(ps, MergeAppendState))
2221 dpns->outer_planstate = ((MergeAppendState *) ps)->mergeplans[0];
2222 else if (IsA(ps, ModifyTableState))
2223 dpns->outer_planstate = ((ModifyTableState *) ps)->mt_plans[0];
2225 dpns->outer_planstate = outerPlanState(ps);
2227 if (dpns->outer_planstate)
2228 dpns->outer_plan = dpns->outer_planstate->plan;
2230 dpns->outer_plan = NULL;
2233 * For a SubqueryScan, pretend the subplan is INNER referent. (We don't
2234 * use OUTER because that could someday conflict with the normal meaning.)
2235 * Likewise, for a CteScan, pretend the subquery's plan is INNER referent.
2237 if (IsA(ps, SubqueryScanState))
2238 dpns->inner_planstate = ((SubqueryScanState *) ps)->subplan;
2239 else if (IsA(ps, CteScanState))
2240 dpns->inner_planstate = ((CteScanState *) ps)->cteplanstate;
2242 dpns->inner_planstate = innerPlanState(ps);
2244 if (dpns->inner_planstate)
2245 dpns->inner_plan = dpns->inner_planstate->plan;
2247 dpns->inner_plan = NULL;
2251 * push_child_plan: temporarily transfer deparsing attention to a child plan
2253 * When expanding an OUTER or INNER reference, we must adjust the deparse
2254 * context in case the referenced expression itself uses OUTER/INNER. We
2255 * modify the top stack entry in-place to avoid affecting levelsup issues
2256 * (although in a Plan tree there really shouldn't be any).
2258 * Caller must provide a local deparse_namespace variable to save the
2259 * previous state for pop_child_plan.
2262 push_child_plan(deparse_namespace *dpns, PlanState *ps,
2263 deparse_namespace *save_dpns)
2265 /* Save state for restoration later */
2269 * Currently we don't bother to adjust the ancestors list, because an
2270 * OUTER or INNER reference really shouldn't contain any Params that would
2271 * be set by the parent node itself. If we did want to adjust it,
2272 * lcons'ing dpns->planstate onto dpns->ancestors would be the appropriate
2273 * thing --- and pop_child_plan would need to undo the change to the list.
2276 /* Set attention on selected child */
2277 set_deparse_planstate(dpns, ps);
2281 * pop_child_plan: undo the effects of push_child_plan
2284 pop_child_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
2286 /* Restore fields changed by push_child_plan */
2291 * push_ancestor_plan: temporarily transfer deparsing attention to an
2294 * When expanding a Param reference, we must adjust the deparse context
2295 * to match the plan node that contains the expression being printed;
2296 * otherwise we'd fail if that expression itself contains a Param or
2297 * OUTER/INNER variables.
2299 * The target ancestor is conveniently identified by the ListCell holding it
2300 * in dpns->ancestors.
2302 * Caller must provide a local deparse_namespace variable to save the
2303 * previous state for pop_ancestor_plan.
2306 push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell,
2307 deparse_namespace *save_dpns)
2309 PlanState *ps = (PlanState *) lfirst(ancestor_cell);
2312 /* Save state for restoration later */
2315 /* Build a new ancestor list with just this node's ancestors */
2317 while ((ancestor_cell = lnext(ancestor_cell)) != NULL)
2318 ancestors = lappend(ancestors, lfirst(ancestor_cell));
2319 dpns->ancestors = ancestors;
2321 /* Set attention on selected ancestor */
2322 set_deparse_planstate(dpns, ps);
2326 * pop_ancestor_plan: undo the effects of push_ancestor_plan
2329 pop_ancestor_plan(deparse_namespace *dpns, deparse_namespace *save_dpns)
2331 /* Free the ancestor list made in push_ancestor_plan */
2332 list_free(dpns->ancestors);
2334 /* Restore fields changed by push_ancestor_plan */
2340 * make_ruledef - reconstruct the CREATE RULE command
2341 * for a given pg_rewrite tuple
2345 make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
2355 List *actions = NIL;
2361 * Get the attribute values from the rules tuple
2363 fno = SPI_fnumber(rulettc, "rulename");
2364 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
2366 rulename = NameStr(*(DatumGetName(dat)));
2368 fno = SPI_fnumber(rulettc, "ev_type");
2369 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
2371 ev_type = DatumGetChar(dat);
2373 fno = SPI_fnumber(rulettc, "ev_class");
2374 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
2376 ev_class = DatumGetObjectId(dat);
2378 fno = SPI_fnumber(rulettc, "ev_attr");
2379 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
2381 ev_attr = DatumGetInt16(dat);
2383 fno = SPI_fnumber(rulettc, "is_instead");
2384 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
2386 is_instead = DatumGetBool(dat);
2388 /* these could be nulls */
2389 fno = SPI_fnumber(rulettc, "ev_qual");
2390 ev_qual = SPI_getvalue(ruletup, rulettc, fno);
2392 fno = SPI_fnumber(rulettc, "ev_action");
2393 ev_action = SPI_getvalue(ruletup, rulettc, fno);
2394 if (ev_action != NULL)
2395 actions = (List *) stringToNode(ev_action);
2398 * Build the rules definition text
2400 appendStringInfo(buf, "CREATE RULE %s AS",
2401 quote_identifier(rulename));
2403 if (prettyFlags & PRETTYFLAG_INDENT)
2404 appendStringInfoString(buf, "\n ON ");
2406 appendStringInfoString(buf, " ON ");
2408 /* The event the rule is fired for */
2412 appendStringInfo(buf, "SELECT");
2416 appendStringInfo(buf, "UPDATE");
2420 appendStringInfo(buf, "INSERT");
2424 appendStringInfo(buf, "DELETE");
2429 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2430 errmsg("rule \"%s\" has unsupported event type %d",
2431 rulename, ev_type)));
2435 /* The relation the rule is fired on */
2436 appendStringInfo(buf, " TO %s", generate_relation_name(ev_class, NIL));
2438 appendStringInfo(buf, ".%s",
2439 quote_identifier(get_relid_attribute_name(ev_class,
2442 /* If the rule has an event qualification, add it */
2443 if (ev_qual == NULL)
2445 if (strlen(ev_qual) > 0 && strcmp(ev_qual, "<>") != 0)
2449 deparse_context context;
2450 deparse_namespace dpns;
2452 if (prettyFlags & PRETTYFLAG_INDENT)
2453 appendStringInfoString(buf, "\n ");
2454 appendStringInfo(buf, " WHERE ");
2456 qual = stringToNode(ev_qual);
2459 * We need to make a context for recognizing any Vars in the qual
2460 * (which can only be references to OLD and NEW). Use the rtable of
2461 * the first query in the action list for this purpose.
2463 query = (Query *) linitial(actions);
2466 * If the action is INSERT...SELECT, OLD/NEW have been pushed down
2467 * into the SELECT, and that's what we need to look at. (Ugly kluge
2468 * ... try to fix this when we redesign querytrees.)
2470 query = getInsertSelectQuery(query, NULL);
2472 /* Must acquire locks right away; see notes in get_query_def() */
2473 AcquireRewriteLocks(query, false);
2476 context.namespaces = list_make1(&dpns);
2477 context.windowClause = NIL;
2478 context.windowTList = NIL;
2479 context.varprefix = (list_length(query->rtable) != 1);
2480 context.prettyFlags = prettyFlags;
2481 context.indentLevel = PRETTYINDENT_STD;
2483 memset(&dpns, 0, sizeof(dpns));
2484 dpns.rtable = query->rtable;
2485 dpns.ctes = query->cteList;
2487 get_rule_expr(qual, &context, false);
2490 appendStringInfo(buf, " DO ");
2492 /* The INSTEAD keyword (if so) */
2494 appendStringInfo(buf, "INSTEAD ");
2496 /* Finally the rules actions */
2497 if (list_length(actions) > 1)
2502 appendStringInfo(buf, "(");
2503 foreach(action, actions)
2505 query = (Query *) lfirst(action);
2506 get_query_def(query, buf, NIL, NULL, prettyFlags, 0);
2508 appendStringInfo(buf, ";\n");
2510 appendStringInfo(buf, "; ");
2512 appendStringInfo(buf, ");");
2514 else if (list_length(actions) == 0)
2516 appendStringInfo(buf, "NOTHING;");
2522 query = (Query *) linitial(actions);
2523 get_query_def(query, buf, NIL, NULL, prettyFlags, 0);
2524 appendStringInfo(buf, ";");
2530 * make_viewdef - reconstruct the SELECT part of a
2535 make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
2545 List *actions = NIL;
2546 Relation ev_relation;
2551 * Get the attribute values from the rules tuple
2553 fno = SPI_fnumber(rulettc, "ev_type");
2554 ev_type = (char) SPI_getbinval(ruletup, rulettc, fno, &isnull);
2556 fno = SPI_fnumber(rulettc, "ev_class");
2557 ev_class = (Oid) SPI_getbinval(ruletup, rulettc, fno, &isnull);
2559 fno = SPI_fnumber(rulettc, "ev_attr");
2560 ev_attr = (int2) SPI_getbinval(ruletup, rulettc, fno, &isnull);
2562 fno = SPI_fnumber(rulettc, "is_instead");
2563 is_instead = (bool) SPI_getbinval(ruletup, rulettc, fno, &isnull);
2565 fno = SPI_fnumber(rulettc, "ev_qual");
2566 ev_qual = SPI_getvalue(ruletup, rulettc, fno);
2568 fno = SPI_fnumber(rulettc, "ev_action");
2569 ev_action = SPI_getvalue(ruletup, rulettc, fno);
2570 if (ev_action != NULL)
2571 actions = (List *) stringToNode(ev_action);
2573 if (list_length(actions) != 1)
2575 appendStringInfo(buf, "Not a view");
2579 query = (Query *) linitial(actions);
2581 if (ev_type != '1' || ev_attr >= 0 || !is_instead ||
2582 strcmp(ev_qual, "<>") != 0 || query->commandType != CMD_SELECT)
2584 appendStringInfo(buf, "Not a view");
2588 ev_relation = heap_open(ev_class, AccessShareLock);
2590 get_query_def(query, buf, NIL, RelationGetDescr(ev_relation),
2592 appendStringInfo(buf, ";");
2594 heap_close(ev_relation, AccessShareLock);
2599 * get_query_def - Parse back one query parsetree
2601 * If resultDesc is not NULL, then it is the output tuple descriptor for
2602 * the view represented by a SELECT query.
2606 get_query_def(Query *query, StringInfo buf, List *parentnamespace,
2607 TupleDesc resultDesc, int prettyFlags, int startIndent)
2609 deparse_context context;
2610 deparse_namespace dpns;
2613 * Before we begin to examine the query, acquire locks on referenced
2614 * relations, and fix up deleted columns in JOIN RTEs. This ensures
2615 * consistent results. Note we assume it's OK to scribble on the passed
2618 AcquireRewriteLocks(query, false);
2621 context.namespaces = lcons(&dpns, list_copy(parentnamespace));
2622 context.windowClause = NIL;
2623 context.windowTList = NIL;
2624 context.varprefix = (parentnamespace != NIL ||
2625 list_length(query->rtable) != 1);
2626 context.prettyFlags = prettyFlags;
2627 context.indentLevel = startIndent;
2629 memset(&dpns, 0, sizeof(dpns));
2630 dpns.rtable = query->rtable;
2631 dpns.ctes = query->cteList;
2633 switch (query->commandType)
2636 get_select_query_def(query, &context, resultDesc);
2640 get_update_query_def(query, &context);
2644 get_insert_query_def(query, &context);
2648 get_delete_query_def(query, &context);
2652 appendStringInfo(buf, "NOTHING");
2656 get_utility_query_def(query, &context);
2660 elog(ERROR, "unrecognized query command type: %d",
2661 query->commandType);
2667 * get_values_def - Parse back a VALUES list
2671 get_values_def(List *values_lists, deparse_context *context)
2673 StringInfo buf = context->buf;
2674 bool first_list = true;
2677 appendStringInfoString(buf, "VALUES ");
2679 foreach(vtl, values_lists)
2681 List *sublist = (List *) lfirst(vtl);
2682 bool first_col = true;
2688 appendStringInfoString(buf, ", ");
2690 appendStringInfoChar(buf, '(');
2691 foreach(lc, sublist)
2693 Node *col = (Node *) lfirst(lc);
2698 appendStringInfoChar(buf, ',');
2701 * Strip any top-level nodes representing indirection assignments,
2702 * then print the result.
2704 get_rule_expr(processIndirection(col, context, false),
2707 appendStringInfoChar(buf, ')');
2712 * get_with_clause - Parse back a WITH clause
2716 get_with_clause(Query *query, deparse_context *context)
2718 StringInfo buf = context->buf;
2722 if (query->cteList == NIL)
2725 if (PRETTY_INDENT(context))
2727 context->indentLevel += PRETTYINDENT_STD;
2728 appendStringInfoChar(buf, ' ');
2731 if (query->hasRecursive)
2732 sep = "WITH RECURSIVE ";
2735 foreach(l, query->cteList)
2737 CommonTableExpr *cte = (CommonTableExpr *) lfirst(l);
2739 appendStringInfoString(buf, sep);
2740 appendStringInfoString(buf, quote_identifier(cte->ctename));
2741 if (cte->aliascolnames)
2746 appendStringInfoChar(buf, '(');
2747 foreach(col, cte->aliascolnames)
2752 appendStringInfoString(buf, ", ");
2753 appendStringInfoString(buf,
2754 quote_identifier(strVal(lfirst(col))));
2756 appendStringInfoChar(buf, ')');
2758 appendStringInfoString(buf, " AS (");
2759 if (PRETTY_INDENT(context))
2760 appendContextKeyword(context, "", 0, 0, 0);
2761 get_query_def((Query *) cte->ctequery, buf, context->namespaces, NULL,
2762 context->prettyFlags, context->indentLevel);
2763 if (PRETTY_INDENT(context))
2764 appendContextKeyword(context, "", 0, 0, 0);
2765 appendStringInfoChar(buf, ')');
2769 if (PRETTY_INDENT(context))
2771 context->indentLevel -= PRETTYINDENT_STD;
2772 appendContextKeyword(context, "", 0, 0, 0);
2775 appendStringInfoChar(buf, ' ');
2779 * get_select_query_def - Parse back a SELECT parsetree
2783 get_select_query_def(Query *query, deparse_context *context,
2784 TupleDesc resultDesc)
2786 StringInfo buf = context->buf;
2787 List *save_windowclause;
2788 List *save_windowtlist;
2792 /* Insert the WITH clause if given */
2793 get_with_clause(query, context);
2795 /* Set up context for possible window functions */
2796 save_windowclause = context->windowClause;
2797 context->windowClause = query->windowClause;
2798 save_windowtlist = context->windowTList;
2799 context->windowTList = query->targetList;
2802 * If the Query node has a setOperations tree, then it's the top level of
2803 * a UNION/INTERSECT/EXCEPT query; only the WITH, ORDER BY and LIMIT
2804 * fields are interesting in the top query itself.
2806 if (query->setOperations)
2808 get_setop_query(query->setOperations, query, context, resultDesc);
2809 /* ORDER BY clauses must be simple in this case */
2814 get_basic_select_query(query, context, resultDesc);
2815 force_colno = false;
2818 /* Add the ORDER BY clause if given */
2819 if (query->sortClause != NIL)
2821 appendContextKeyword(context, " ORDER BY ",
2822 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2823 get_rule_orderby(query->sortClause, query->targetList,
2824 force_colno, context);
2827 /* Add the LIMIT clause if given */
2828 if (query->limitOffset != NULL)
2830 appendContextKeyword(context, " OFFSET ",
2831 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2832 get_rule_expr(query->limitOffset, context, false);
2834 if (query->limitCount != NULL)
2836 appendContextKeyword(context, " LIMIT ",
2837 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2838 if (IsA(query->limitCount, Const) &&
2839 ((Const *) query->limitCount)->constisnull)
2840 appendStringInfo(buf, "ALL");
2842 get_rule_expr(query->limitCount, context, false);
2845 /* Add FOR UPDATE/SHARE clauses if present */
2846 if (query->hasForUpdate)
2848 foreach(l, query->rowMarks)
2850 RowMarkClause *rc = (RowMarkClause *) lfirst(l);
2851 RangeTblEntry *rte = rt_fetch(rc->rti, query->rtable);
2853 /* don't print implicit clauses */
2858 appendContextKeyword(context, " FOR UPDATE",
2859 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2861 appendContextKeyword(context, " FOR SHARE",
2862 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2863 appendStringInfo(buf, " OF %s",
2864 quote_identifier(rte->eref->aliasname));
2866 appendStringInfo(buf, " NOWAIT");
2870 context->windowClause = save_windowclause;
2871 context->windowTList = save_windowtlist;
2875 get_basic_select_query(Query *query, deparse_context *context,
2876 TupleDesc resultDesc)
2878 StringInfo buf = context->buf;
2882 if (PRETTY_INDENT(context))
2884 context->indentLevel += PRETTYINDENT_STD;
2885 appendStringInfoChar(buf, ' ');
2889 * If the query looks like SELECT * FROM (VALUES ...), then print just the
2890 * VALUES part. This reverses what transformValuesClause() did at parse
2891 * time. If the jointree contains just a single VALUES RTE, we assume
2892 * this case applies (without looking at the targetlist...)
2894 if (list_length(query->jointree->fromlist) == 1)
2896 RangeTblRef *rtr = (RangeTblRef *) linitial(query->jointree->fromlist);
2898 if (IsA(rtr, RangeTblRef))
2900 RangeTblEntry *rte = rt_fetch(rtr->rtindex, query->rtable);
2902 if (rte->rtekind == RTE_VALUES)
2904 get_values_def(rte->values_lists, context);
2911 * Build up the query string - first we say SELECT
2913 appendStringInfo(buf, "SELECT");
2915 /* Add the DISTINCT clause if given */
2916 if (query->distinctClause != NIL)
2918 if (query->hasDistinctOn)
2920 appendStringInfo(buf, " DISTINCT ON (");
2922 foreach(l, query->distinctClause)
2924 SortGroupClause *srt = (SortGroupClause *) lfirst(l);
2926 appendStringInfoString(buf, sep);
2927 get_rule_sortgroupclause(srt, query->targetList,
2931 appendStringInfo(buf, ")");
2934 appendStringInfo(buf, " DISTINCT");
2937 /* Then we tell what to select (the targetlist) */
2938 get_target_list(query->targetList, context, resultDesc);
2940 /* Add the FROM clause if needed */
2941 get_from_clause(query, " FROM ", context);
2943 /* Add the WHERE clause if given */
2944 if (query->jointree->quals != NULL)
2946 appendContextKeyword(context, " WHERE ",
2947 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2948 get_rule_expr(query->jointree->quals, context, false);
2951 /* Add the GROUP BY clause if given */
2952 if (query->groupClause != NULL)
2954 appendContextKeyword(context, " GROUP BY ",
2955 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2957 foreach(l, query->groupClause)
2959 SortGroupClause *grp = (SortGroupClause *) lfirst(l);
2961 appendStringInfoString(buf, sep);
2962 get_rule_sortgroupclause(grp, query->targetList,
2968 /* Add the HAVING clause if given */
2969 if (query->havingQual != NULL)
2971 appendContextKeyword(context, " HAVING ",
2972 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2973 get_rule_expr(query->havingQual, context, false);
2976 /* Add the WINDOW clause if needed */
2977 if (query->windowClause != NIL)
2978 get_rule_windowclause(query, context);
2982 * get_target_list - Parse back a SELECT target list
2984 * This is also used for RETURNING lists in INSERT/UPDATE/DELETE.
2988 get_target_list(List *targetList, deparse_context *context,
2989 TupleDesc resultDesc)
2991 StringInfo buf = context->buf;
2998 foreach(l, targetList)
3000 TargetEntry *tle = (TargetEntry *) lfirst(l);
3005 continue; /* ignore junk entries */
3007 appendStringInfoString(buf, sep);
3012 * We special-case Var nodes rather than using get_rule_expr. This is
3013 * needed because get_rule_expr will display a whole-row Var as
3014 * "foo.*", which is the preferred notation in most contexts, but at
3015 * the top level of a SELECT list it's not right (the parser will
3016 * expand that notation into multiple columns, yielding behavior
3017 * different from a whole-row Var). We want just "foo", instead.
3019 if (tle->expr && IsA(tle->expr, Var))
3021 attname = get_variable((Var *) tle->expr, 0, false, context);
3025 get_rule_expr((Node *) tle->expr, context, true);
3026 /* We'll show the AS name unless it's this: */
3027 attname = "?column?";
3031 * Figure out what the result column should be called. In the context
3032 * of a view, use the view's tuple descriptor (so as to pick up the
3033 * effects of any column RENAME that's been done on the view).
3034 * Otherwise, just use what we can find in the TLE.
3036 if (resultDesc && colno <= resultDesc->natts)
3037 colname = NameStr(resultDesc->attrs[colno - 1]->attname);
3039 colname = tle->resname;
3041 /* Show AS unless the column's name is correct as-is */
3042 if (colname) /* resname could be NULL */
3044 if (attname == NULL || strcmp(attname, colname) != 0)
3045 appendStringInfo(buf, " AS %s", quote_identifier(colname));
3051 get_setop_query(Node *setOp, Query *query, deparse_context *context,
3052 TupleDesc resultDesc)
3054 StringInfo buf = context->buf;
3057 if (IsA(setOp, RangeTblRef))
3059 RangeTblRef *rtr = (RangeTblRef *) setOp;
3060 RangeTblEntry *rte = rt_fetch(rtr->rtindex, query->rtable);
3061 Query *subquery = rte->subquery;
3063 Assert(subquery != NULL);
3064 Assert(subquery->setOperations == NULL);
3065 /* Need parens if WITH, ORDER BY, FOR UPDATE, or LIMIT; see gram.y */
3066 need_paren = (subquery->cteList ||
3067 subquery->sortClause ||
3068 subquery->rowMarks ||
3069 subquery->limitOffset ||
3070 subquery->limitCount);
3072 appendStringInfoChar(buf, '(');
3073 get_query_def(subquery, buf, context->namespaces, resultDesc,
3074 context->prettyFlags, context->indentLevel);
3076 appendStringInfoChar(buf, ')');
3078 else if (IsA(setOp, SetOperationStmt))
3080 SetOperationStmt *op = (SetOperationStmt *) setOp;
3082 if (PRETTY_INDENT(context))
3084 context->indentLevel += PRETTYINDENT_STD;
3085 appendStringInfoSpaces(buf, PRETTYINDENT_STD);
3089 * We force parens whenever nesting two SetOperationStmts. There are
3090 * some cases in which parens are needed around a leaf query too, but
3091 * those are more easily handled at the next level down (see code
3094 need_paren = !IsA(op->larg, RangeTblRef);
3097 appendStringInfoChar(buf, '(');
3098 get_setop_query(op->larg, query, context, resultDesc);
3100 appendStringInfoChar(buf, ')');
3102 if (!PRETTY_INDENT(context))
3103 appendStringInfoChar(buf, ' ');
3107 appendContextKeyword(context, "UNION ",
3108 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
3110 case SETOP_INTERSECT:
3111 appendContextKeyword(context, "INTERSECT ",
3112 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
3115 appendContextKeyword(context, "EXCEPT ",
3116 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
3119 elog(ERROR, "unrecognized set op: %d",
3123 appendStringInfo(buf, "ALL ");
3125 if (PRETTY_INDENT(context))
3126 appendContextKeyword(context, "", 0, 0, 0);
3128 need_paren = !IsA(op->rarg, RangeTblRef);
3131 appendStringInfoChar(buf, '(');
3132 get_setop_query(op->rarg, query, context, resultDesc);
3134 appendStringInfoChar(buf, ')');
3136 if (PRETTY_INDENT(context))
3137 context->indentLevel -= PRETTYINDENT_STD;
3141 elog(ERROR, "unrecognized node type: %d",
3142 (int) nodeTag(setOp));
3147 * Display a sort/group clause.
3149 * Also returns the expression tree, so caller need not find it again.
3152 get_rule_sortgroupclause(SortGroupClause *srt, List *tlist, bool force_colno,
3153 deparse_context *context)
3155 StringInfo buf = context->buf;
3159 tle = get_sortgroupclause_tle(srt, tlist);
3160 expr = (Node *) tle->expr;
3163 * Use column-number form if requested by caller. Otherwise, if
3164 * expression is a constant, force it to be dumped with an explicit cast
3165 * as decoration --- this is because a simple integer constant is
3166 * ambiguous (and will be misinterpreted by findTargetlistEntry()) if we
3167 * dump it without any decoration. Otherwise, just dump the expression
3172 Assert(!tle->resjunk);
3173 appendStringInfo(buf, "%d", tle->resno);
3175 else if (expr && IsA(expr, Const))
3176 get_const_expr((Const *) expr, context, 1);
3178 get_rule_expr(expr, context, true);
3184 * Display an ORDER BY list.
3187 get_rule_orderby(List *orderList, List *targetList,
3188 bool force_colno, deparse_context *context)
3190 StringInfo buf = context->buf;
3195 foreach(l, orderList)
3197 SortGroupClause *srt = (SortGroupClause *) lfirst(l);
3200 TypeCacheEntry *typentry;
3202 appendStringInfoString(buf, sep);
3203 sortexpr = get_rule_sortgroupclause(srt, targetList,
3204 force_colno, context);
3205 sortcoltype = exprType(sortexpr);
3206 /* See whether operator is default < or > for datatype */
3207 typentry = lookup_type_cache(sortcoltype,
3208 TYPECACHE_LT_OPR | TYPECACHE_GT_OPR);
3209 if (srt->sortop == typentry->lt_opr)
3211 /* ASC is default, so emit nothing for it */
3212 if (srt->nulls_first)
3213 appendStringInfo(buf, " NULLS FIRST");
3215 else if (srt->sortop == typentry->gt_opr)
3217 appendStringInfo(buf, " DESC");
3218 /* DESC defaults to NULLS FIRST */
3219 if (!srt->nulls_first)
3220 appendStringInfo(buf, " NULLS LAST");
3224 appendStringInfo(buf, " USING %s",
3225 generate_operator_name(srt->sortop,
3228 /* be specific to eliminate ambiguity */
3229 if (srt->nulls_first)
3230 appendStringInfo(buf, " NULLS FIRST");
3232 appendStringInfo(buf, " NULLS LAST");
3239 * Display a WINDOW clause.
3241 * Note that the windowClause list might contain only anonymous window
3242 * specifications, in which case we should print nothing here.
3245 get_rule_windowclause(Query *query, deparse_context *context)
3247 StringInfo buf = context->buf;
3252 foreach(l, query->windowClause)
3254 WindowClause *wc = (WindowClause *) lfirst(l);
3256 if (wc->name == NULL)
3257 continue; /* ignore anonymous windows */
3260 appendContextKeyword(context, " WINDOW ",
3261 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
3263 appendStringInfoString(buf, sep);
3265 appendStringInfo(buf, "%s AS ", quote_identifier(wc->name));
3267 get_rule_windowspec(wc, query->targetList, context);
3274 * Display a window definition
3277 get_rule_windowspec(WindowClause *wc, List *targetList,
3278 deparse_context *context)
3280 StringInfo buf = context->buf;
3281 bool needspace = false;
3285 appendStringInfoChar(buf, '(');
3288 appendStringInfoString(buf, quote_identifier(wc->refname));
3291 /* partition clauses are always inherited, so only print if no refname */
3292 if (wc->partitionClause && !wc->refname)
3295 appendStringInfoChar(buf, ' ');
3296 appendStringInfoString(buf, "PARTITION BY ");
3298 foreach(l, wc->partitionClause)
3300 SortGroupClause *grp = (SortGroupClause *) lfirst(l);
3302 appendStringInfoString(buf, sep);
3303 get_rule_sortgroupclause(grp, targetList,
3309 /* print ordering clause only if not inherited */
3310 if (wc->orderClause && !wc->copiedOrder)
3313 appendStringInfoChar(buf, ' ');
3314 appendStringInfoString(buf, "ORDER BY ");
3315 get_rule_orderby(wc->orderClause, targetList, false, context);
3318 /* framing clause is never inherited, so print unless it's default */
3319 if (wc->frameOptions & FRAMEOPTION_NONDEFAULT)
3322 appendStringInfoChar(buf, ' ');
3323 if (wc->frameOptions & FRAMEOPTION_RANGE)
3324 appendStringInfoString(buf, "RANGE ");
3325 else if (wc->frameOptions & FRAMEOPTION_ROWS)
3326 appendStringInfoString(buf, "ROWS ");
3329 if (wc->frameOptions & FRAMEOPTION_BETWEEN)
3330 appendStringInfoString(buf, "BETWEEN ");
3331 if (wc->frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING)
3332 appendStringInfoString(buf, "UNBOUNDED PRECEDING ");
3333 else if (wc->frameOptions & FRAMEOPTION_START_CURRENT_ROW)
3334 appendStringInfoString(buf, "CURRENT ROW ");
3335 else if (wc->frameOptions & FRAMEOPTION_START_VALUE)
3337 get_rule_expr(wc->startOffset, context, false);
3338 if (wc->frameOptions & FRAMEOPTION_START_VALUE_PRECEDING)
3339 appendStringInfoString(buf, " PRECEDING ");
3340 else if (wc->frameOptions & FRAMEOPTION_START_VALUE_FOLLOWING)
3341 appendStringInfoString(buf, " FOLLOWING ");
3347 if (wc->frameOptions & FRAMEOPTION_BETWEEN)
3349 appendStringInfoString(buf, "AND ");
3350 if (wc->frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING)
3351 appendStringInfoString(buf, "UNBOUNDED FOLLOWING ");
3352 else if (wc->frameOptions & FRAMEOPTION_END_CURRENT_ROW)
3353 appendStringInfoString(buf, "CURRENT ROW ");
3354 else if (wc->frameOptions & FRAMEOPTION_END_VALUE)
3356 get_rule_expr(wc->endOffset, context, false);
3357 if (wc->frameOptions & FRAMEOPTION_END_VALUE_PRECEDING)
3358 appendStringInfoString(buf, " PRECEDING ");
3359 else if (wc->frameOptions & FRAMEOPTION_END_VALUE_FOLLOWING)
3360 appendStringInfoString(buf, " FOLLOWING ");
3367 /* we will now have a trailing space; remove it */
3370 appendStringInfoChar(buf, ')');
3374 * get_insert_query_def - Parse back an INSERT parsetree
3378 get_insert_query_def(Query *query, deparse_context *context)
3380 StringInfo buf = context->buf;
3381 RangeTblEntry *select_rte = NULL;
3382 RangeTblEntry *values_rte = NULL;
3385 ListCell *values_cell;
3387 List *strippedexprs;
3389 /* Insert the WITH clause if given */
3390 get_with_clause(query, context);
3393 * If it's an INSERT ... SELECT or VALUES (...), (...), ... there will be
3394 * a single RTE for the SELECT or VALUES.
3396 foreach(l, query->rtable)
3398 rte = (RangeTblEntry *) lfirst(l);
3400 if (rte->rtekind == RTE_SUBQUERY)
3403 elog(ERROR, "too many subquery RTEs in INSERT");
3407 if (rte->rtekind == RTE_VALUES)
3410 elog(ERROR, "too many values RTEs in INSERT");
3414 if (select_rte && values_rte)
3415 elog(ERROR, "both subquery and values RTEs in INSERT");
3418 * Start the query with INSERT INTO relname
3420 rte = rt_fetch(query->resultRelation, query->rtable);
3421 Assert(rte->rtekind == RTE_RELATION);
3423 if (PRETTY_INDENT(context))
3425 context->indentLevel += PRETTYINDENT_STD;
3426 appendStringInfoChar(buf, ' ');
3428 appendStringInfo(buf, "INSERT INTO %s (",
3429 generate_relation_name(rte->relid, NIL));
3432 * Add the insert-column-names list. To handle indirection properly, we
3433 * need to look for indirection nodes in the top targetlist (if it's
3434 * INSERT ... SELECT or INSERT ... single VALUES), or in the first
3435 * expression list of the VALUES RTE (if it's INSERT ... multi VALUES). We
3436 * assume that all the expression lists will have similar indirection in
3440 values_cell = list_head((List *) linitial(values_rte->values_lists));
3443 strippedexprs = NIL;
3445 foreach(l, query->targetList)
3447 TargetEntry *tle = (TargetEntry *) lfirst(l);
3450 continue; /* ignore junk entries */
3452 appendStringInfoString(buf, sep);
3456 * Put out name of target column; look in the catalogs, not at
3457 * tle->resname, since resname will fail to track RENAME.
3459 appendStringInfoString(buf,
3460 quote_identifier(get_relid_attribute_name(rte->relid,
3464 * Print any indirection needed (subfields or subscripts), and strip
3465 * off the top-level nodes representing the indirection assignments.
3469 /* we discard the stripped expression in this case */
3470 processIndirection((Node *) lfirst(values_cell), context, true);
3471 values_cell = lnext(values_cell);
3475 /* we keep a list of the stripped expressions in this case */
3476 strippedexprs = lappend(strippedexprs,
3477 processIndirection((Node *) tle->expr,
3481 appendStringInfo(buf, ") ");
3485 /* Add the SELECT */
3486 get_query_def(select_rte->subquery, buf, NIL, NULL,
3487 context->prettyFlags, context->indentLevel);
3489 else if (values_rte)
3491 /* Add the multi-VALUES expression lists */
3492 get_values_def(values_rte->values_lists, context);
3496 /* Add the single-VALUES expression list */
3497 appendContextKeyword(context, "VALUES (",
3498 -PRETTYINDENT_STD, PRETTYINDENT_STD, 2);
3499 get_rule_expr((Node *) strippedexprs, context, false);
3500 appendStringInfoChar(buf, ')');
3503 /* Add RETURNING if present */
3504 if (query->returningList)
3506 appendContextKeyword(context, " RETURNING",
3507 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
3508 get_target_list(query->returningList, context, NULL);
3514 * get_update_query_def - Parse back an UPDATE parsetree
3518 get_update_query_def(Query *query, deparse_context *context)
3520 StringInfo buf = context->buf;
3525 /* Insert the WITH clause if given */
3526 get_with_clause(query, context);
3529 * Start the query with UPDATE relname SET
3531 rte = rt_fetch(query->resultRelation, query->rtable);
3532 Assert(rte->rtekind == RTE_RELATION);
3533 if (PRETTY_INDENT(context))
3535 appendStringInfoChar(buf, ' ');
3536 context->indentLevel += PRETTYINDENT_STD;
3538 appendStringInfo(buf, "UPDATE %s%s",
3540 generate_relation_name(rte->relid, NIL));
3541 if (rte->alias != NULL)
3542 appendStringInfo(buf, " %s",
3543 quote_identifier(rte->alias->aliasname));
3544 appendStringInfoString(buf, " SET ");
3546 /* Add the comma separated list of 'attname = value' */
3548 foreach(l, query->targetList)
3550 TargetEntry *tle = (TargetEntry *) lfirst(l);
3554 continue; /* ignore junk entries */
3556 appendStringInfoString(buf, sep);
3560 * Put out name of target column; look in the catalogs, not at
3561 * tle->resname, since resname will fail to track RENAME.
3563 appendStringInfoString(buf,
3564 quote_identifier(get_relid_attribute_name(rte->relid,
3568 * Print any indirection needed (subfields or subscripts), and strip
3569 * off the top-level nodes representing the indirection assignments.
3571 expr = processIndirection((Node *) tle->expr, context, true);
3573 appendStringInfo(buf, " = ");
3575 get_rule_expr(expr, context, false);
3578 /* Add the FROM clause if needed */
3579 get_from_clause(query, " FROM ", context);
3581 /* Add a WHERE clause if given */
3582 if (query->jointree->quals != NULL)
3584 appendContextKeyword(context, " WHERE ",
3585 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
3586 get_rule_expr(query->jointree->quals, context, false);
3589 /* Add RETURNING if present */
3590 if (query->returningList)
3592 appendContextKeyword(context, " RETURNING",
3593 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
3594 get_target_list(query->returningList, context, NULL);
3600 * get_delete_query_def - Parse back a DELETE parsetree
3604 get_delete_query_def(Query *query, deparse_context *context)
3606 StringInfo buf = context->buf;
3609 /* Insert the WITH clause if given */
3610 get_with_clause(query, context);
3613 * Start the query with DELETE FROM relname
3615 rte = rt_fetch(query->resultRelation, query->rtable);
3616 Assert(rte->rtekind == RTE_RELATION);
3617 if (PRETTY_INDENT(context))
3619 appendStringInfoChar(buf, ' ');
3620 context->indentLevel += PRETTYINDENT_STD;
3622 appendStringInfo(buf, "DELETE FROM %s%s",
3624 generate_relation_name(rte->relid, NIL));
3625 if (rte->alias != NULL)
3626 appendStringInfo(buf, " %s",
3627 quote_identifier(rte->alias->aliasname));
3629 /* Add the USING clause if given */
3630 get_from_clause(query, " USING ", context);
3632 /* Add a WHERE clause if given */
3633 if (query->jointree->quals != NULL)
3635 appendContextKeyword(context, " WHERE ",
3636 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
3637 get_rule_expr(query->jointree->quals, context, false);
3640 /* Add RETURNING if present */
3641 if (query->returningList)
3643 appendContextKeyword(context, " RETURNING",
3644 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
3645 get_target_list(query->returningList, context, NULL);
3651 * get_utility_query_def - Parse back a UTILITY parsetree
3655 get_utility_query_def(Query *query, deparse_context *context)
3657 StringInfo buf = context->buf;
3659 if (query->utilityStmt && IsA(query->utilityStmt, NotifyStmt))
3661 NotifyStmt *stmt = (NotifyStmt *) query->utilityStmt;
3663 appendContextKeyword(context, "",
3664 0, PRETTYINDENT_STD, 1);
3665 appendStringInfo(buf, "NOTIFY %s",
3666 quote_identifier(stmt->conditionname));
3669 appendStringInfoString(buf, ", ");
3670 simple_quote_literal(buf, stmt->payload);
3675 /* Currently only NOTIFY utility commands can appear in rules */
3676 elog(ERROR, "unexpected utility statement type");
3682 * Display a Var appropriately.
3684 * In some cases (currently only when recursing into an unnamed join)
3685 * the Var's varlevelsup has to be interpreted with respect to a context
3686 * above the current one; levelsup indicates the offset.
3688 * If showstar is TRUE, whole-row Vars are displayed as "foo.*";
3689 * if FALSE, merely as "foo".
3691 * Returns the attname of the Var, or NULL if not determinable.
3694 get_variable(Var *var, int levelsup, bool showstar, deparse_context *context)
3696 StringInfo buf = context->buf;
3700 deparse_namespace *dpns;
3705 /* Find appropriate nesting depth */
3706 netlevelsup = var->varlevelsup + levelsup;
3707 if (netlevelsup >= list_length(context->namespaces))
3708 elog(ERROR, "bogus varlevelsup: %d offset %d",
3709 var->varlevelsup, levelsup);
3710 dpns = (deparse_namespace *) list_nth(context->namespaces,
3714 * Try to find the relevant RTE in this rtable. In a plan tree, it's
3715 * likely that varno is OUTER or INNER, in which case we must dig down
3716 * into the subplans.
3718 if (var->varno >= 1 && var->varno <= list_length(dpns->rtable))
3720 rte = rt_fetch(var->varno, dpns->rtable);
3721 attnum = var->varattno;
3723 else if (var->varno == OUTER && dpns->outer_plan)
3726 deparse_namespace save_dpns;
3728 tle = get_tle_by_resno(dpns->outer_plan->targetlist, var->varattno);
3730 elog(ERROR, "bogus varattno for OUTER var: %d", var->varattno);
3732 Assert(netlevelsup == 0);
3733 push_child_plan(dpns, dpns->outer_planstate, &save_dpns);
3736 * Force parentheses because our caller probably assumed a Var is a
3737 * simple expression.
3739 if (!IsA(tle->expr, Var))
3740 appendStringInfoChar(buf, '(');
3741 get_rule_expr((Node *) tle->expr, context, true);
3742 if (!IsA(tle->expr, Var))
3743 appendStringInfoChar(buf, ')');
3745 pop_child_plan(dpns, &save_dpns);
3748 else if (var->varno == INNER && dpns->inner_plan)
3751 deparse_namespace save_dpns;
3753 tle = get_tle_by_resno(dpns->inner_plan->targetlist, var->varattno);
3755 elog(ERROR, "bogus varattno for INNER var: %d", var->varattno);
3757 Assert(netlevelsup == 0);
3758 push_child_plan(dpns, dpns->inner_planstate, &save_dpns);
3761 * Force parentheses because our caller probably assumed a Var is a
3762 * simple expression.
3764 if (!IsA(tle->expr, Var))
3765 appendStringInfoChar(buf, '(');
3766 get_rule_expr((Node *) tle->expr, context, true);
3767 if (!IsA(tle->expr, Var))
3768 appendStringInfoChar(buf, ')');
3770 pop_child_plan(dpns, &save_dpns);
3775 elog(ERROR, "bogus varno: %d", var->varno);
3776 return NULL; /* keep compiler quiet */
3780 * The planner will sometimes emit Vars referencing resjunk elements of a
3781 * subquery's target list (this is currently only possible if it chooses
3782 * to generate a "physical tlist" for a SubqueryScan or CteScan node).
3783 * Although we prefer to print subquery-referencing Vars using the
3784 * subquery's alias, that's not possible for resjunk items since they have
3785 * no alias. So in that case, drill down to the subplan and print the
3786 * contents of the referenced tlist item. This works because in a plan
3787 * tree, such Vars can only occur in a SubqueryScan or CteScan node, and
3788 * we'll have set dpns->inner_plan to reference the child plan node.
3790 if ((rte->rtekind == RTE_SUBQUERY || rte->rtekind == RTE_CTE) &&
3791 attnum > list_length(rte->eref->colnames) &&
3795 deparse_namespace save_dpns;
3797 tle = get_tle_by_resno(dpns->inner_plan->targetlist, var->varattno);
3799 elog(ERROR, "bogus varattno for subquery var: %d", var->varattno);
3801 Assert(netlevelsup == 0);
3802 push_child_plan(dpns, dpns->inner_planstate, &save_dpns);
3805 * Force parentheses because our caller probably assumed a Var is a
3806 * simple expression.
3808 if (!IsA(tle->expr, Var))
3809 appendStringInfoChar(buf, '(');
3810 get_rule_expr((Node *) tle->expr, context, true);
3811 if (!IsA(tle->expr, Var))
3812 appendStringInfoChar(buf, ')');
3814 pop_child_plan(dpns, &save_dpns);
3818 /* Identify names to use */
3819 schemaname = NULL; /* default assumptions */
3820 refname = rte->eref->aliasname;
3822 /* Exceptions occur only if the RTE is alias-less */
3823 if (rte->alias == NULL)
3825 if (rte->rtekind == RTE_RELATION)
3828 * It's possible that use of the bare refname would find another
3829 * more-closely-nested RTE, or be ambiguous, in which case we need
3830 * to specify the schemaname to avoid these errors.
3832 if (find_rte_by_refname(rte->eref->aliasname, context) != rte)
3833 schemaname = get_namespace_name(get_rel_namespace(rte->relid));
3835 else if (rte->rtekind == RTE_JOIN)
3838 * If it's an unnamed join, look at the expansion of the alias
3839 * variable. If it's a simple reference to one of the input vars
3840 * then recursively print the name of that var, instead. (This
3841 * allows correct decompiling of cases where there are identically
3842 * named columns on both sides of the join.) When it's not a
3843 * simple reference, we have to just print the unqualified
3844 * variable name (this can only happen with columns that were
3845 * merged by USING or NATURAL clauses).
3847 * This wouldn't work in decompiling plan trees, because we don't
3848 * store joinaliasvars lists after planning; but a plan tree
3849 * should never contain a join alias variable.
3851 if (rte->joinaliasvars == NIL)
3852 elog(ERROR, "cannot decompile join alias var in plan tree");
3857 aliasvar = (Var *) list_nth(rte->joinaliasvars, attnum - 1);
3858 if (IsA(aliasvar, Var))
3860 return get_variable(aliasvar, var->varlevelsup + levelsup,
3864 /* Unnamed join has neither schemaname nor refname */
3869 if (attnum == InvalidAttrNumber)
3872 attname = get_rte_attribute_name(rte, attnum);
3874 if (refname && (context->varprefix || attname == NULL))
3877 appendStringInfo(buf, "%s.",
3878 quote_identifier(schemaname));
3879 appendStringInfoString(buf, quote_identifier(refname));
3880 if (attname || showstar)
3881 appendStringInfoChar(buf, '.');
3884 appendStringInfoString(buf, quote_identifier(attname));
3886 appendStringInfoChar(buf, '*');
3893 * Get the name of a field of an expression of composite type.
3895 * This is fairly straightforward except for the case of a Var of type RECORD.
3896 * Since no actual table or view column is allowed to have type RECORD, such
3897 * a Var must refer to a JOIN or FUNCTION RTE or to a subquery output. We
3898 * drill down to find the ultimate defining expression and attempt to infer
3899 * the field name from it. We ereport if we can't determine the name.
3901 * levelsup is an extra offset to interpret the Var's varlevelsup correctly.
3904 get_name_for_var_field(Var *var, int fieldno,
3905 int levelsup, deparse_context *context)
3910 deparse_namespace *dpns;
3911 TupleDesc tupleDesc;
3915 * If it's a RowExpr that was expanded from a whole-row Var, use the
3916 * column names attached to it.
3918 if (IsA(var, RowExpr))
3920 RowExpr *r = (RowExpr *) var;
3922 if (fieldno > 0 && fieldno <= list_length(r->colnames))
3923 return strVal(list_nth(r->colnames, fieldno - 1));
3927 * If it's a Var of type RECORD, we have to find what the Var refers to;
3928 * if not, we can use get_expr_result_type. If that fails, we try
3929 * lookup_rowtype_tupdesc, which will probably fail too, but will ereport
3930 * an acceptable message.
3932 if (!IsA(var, Var) ||
3933 var->vartype != RECORDOID)
3935 if (get_expr_result_type((Node *) var, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
3936 tupleDesc = lookup_rowtype_tupdesc_copy(exprType((Node *) var),
3937 exprTypmod((Node *) var));
3939 /* Got the tupdesc, so we can extract the field name */
3940 Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
3941 return NameStr(tupleDesc->attrs[fieldno - 1]->attname);
3944 /* Find appropriate nesting depth */
3945 netlevelsup = var->varlevelsup + levelsup;
3946 if (netlevelsup >= list_length(context->namespaces))
3947 elog(ERROR, "bogus varlevelsup: %d offset %d",
3948 var->varlevelsup, levelsup);
3949 dpns = (deparse_namespace *) list_nth(context->namespaces,
3953 * Try to find the relevant RTE in this rtable. In a plan tree, it's
3954 * likely that varno is OUTER or INNER, in which case we must dig down
3955 * into the subplans.
3957 if (var->varno >= 1 && var->varno <= list_length(dpns->rtable))
3959 rte = rt_fetch(var->varno, dpns->rtable);
3960 attnum = var->varattno;
3962 else if (var->varno == OUTER && dpns->outer_plan)
3965 deparse_namespace save_dpns;
3968 tle = get_tle_by_resno(dpns->outer_plan->targetlist, var->varattno);
3970 elog(ERROR, "bogus varattno for OUTER var: %d", var->varattno);
3972 Assert(netlevelsup == 0);
3973 push_child_plan(dpns, dpns->outer_planstate, &save_dpns);
3975 result = get_name_for_var_field((Var *) tle->expr, fieldno,
3978 pop_child_plan(dpns, &save_dpns);
3981 else if (var->varno == INNER && dpns->inner_plan)
3984 deparse_namespace save_dpns;
3987 tle = get_tle_by_resno(dpns->inner_plan->targetlist, var->varattno);
3989 elog(ERROR, "bogus varattno for INNER var: %d", var->varattno);
3991 Assert(netlevelsup == 0);
3992 push_child_plan(dpns, dpns->inner_planstate, &save_dpns);
3994 result = get_name_for_var_field((Var *) tle->expr, fieldno,
3997 pop_child_plan(dpns, &save_dpns);
4002 elog(ERROR, "bogus varno: %d", var->varno);
4003 return NULL; /* keep compiler quiet */
4006 if (attnum == InvalidAttrNumber)
4008 /* Var is whole-row reference to RTE, so select the right field */
4009 return get_rte_attribute_name(rte, fieldno);
4013 * This part has essentially the same logic as the parser's
4014 * expandRecordVariable() function, but we are dealing with a different
4015 * representation of the input context, and we only need one field name
4016 * not a TupleDesc. Also, we need special cases for finding subquery and
4017 * CTE subplans when deparsing Plan trees.
4019 expr = (Node *) var; /* default if we can't drill down */
4021 switch (rte->rtekind)
4027 * This case should not occur: a column of a table or values list
4028 * shouldn't have type RECORD. Fall through and fail (most
4029 * likely) at the bottom.
4033 /* Subselect-in-FROM: examine sub-select's output expr */
4037 TargetEntry *ste = get_tle_by_resno(rte->subquery->targetList,
4040 if (ste == NULL || ste->resjunk)
4041 elog(ERROR, "subquery %s does not have attribute %d",
4042 rte->eref->aliasname, attnum);
4043 expr = (Node *) ste->expr;
4047 * Recurse into the sub-select to see what its Var
4048 * refers to. We have to build an additional level of
4049 * namespace to keep in step with varlevelsup in the
4052 deparse_namespace mydpns;
4055 memset(&mydpns, 0, sizeof(mydpns));
4056 mydpns.rtable = rte->subquery->rtable;
4057 mydpns.ctes = rte->subquery->cteList;
4059 context->namespaces = lcons(&mydpns,
4060 context->namespaces);
4062 result = get_name_for_var_field((Var *) expr, fieldno,
4065 context->namespaces =
4066 list_delete_first(context->namespaces);
4070 /* else fall through to inspect the expression */
4075 * We're deparsing a Plan tree so we don't have complete
4076 * RTE entries (in particular, rte->subquery is NULL). But
4077 * the only place we'd see a Var directly referencing a
4078 * SUBQUERY RTE is in a SubqueryScan plan node, and we can
4079 * look into the child plan's tlist instead.
4082 deparse_namespace save_dpns;
4085 if (!dpns->inner_plan)
4086 elog(ERROR, "failed to find plan for subquery %s",
4087 rte->eref->aliasname);
4088 tle = get_tle_by_resno(dpns->inner_plan->targetlist,
4091 elog(ERROR, "bogus varattno for subquery var: %d",
4093 Assert(netlevelsup == 0);
4094 push_child_plan(dpns, dpns->inner_planstate, &save_dpns);
4096 result = get_name_for_var_field((Var *) tle->expr, fieldno,
4099 pop_child_plan(dpns, &save_dpns);
4105 /* Join RTE --- recursively inspect the alias variable */
4106 if (rte->joinaliasvars == NIL)
4107 elog(ERROR, "cannot decompile join alias var in plan tree");
4108 Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars));
4109 expr = (Node *) list_nth(rte->joinaliasvars, attnum - 1);
4111 return get_name_for_var_field((Var *) expr, fieldno,
4112 var->varlevelsup + levelsup,
4114 /* else fall through to inspect the expression */
4119 * We couldn't get here unless a function is declared with one of
4120 * its result columns as RECORD, which is not allowed.
4124 /* CTE reference: examine subquery's output expr */
4126 CommonTableExpr *cte = NULL;
4131 * Try to find the referenced CTE using the namespace stack.
4133 ctelevelsup = rte->ctelevelsup + netlevelsup;
4134 if (ctelevelsup >= list_length(context->namespaces))
4138 deparse_namespace *ctedpns;
4140 ctedpns = (deparse_namespace *)
4141 list_nth(context->namespaces, ctelevelsup);
4142 foreach(lc, ctedpns->ctes)
4144 cte = (CommonTableExpr *) lfirst(lc);
4145 if (strcmp(cte->ctename, rte->ctename) == 0)
4151 Query *ctequery = (Query *) cte->ctequery;
4152 TargetEntry *ste = get_tle_by_resno(GetCTETargetList(cte),
4155 if (ste == NULL || ste->resjunk)
4156 elog(ERROR, "subquery %s does not have attribute %d",
4157 rte->eref->aliasname, attnum);
4158 expr = (Node *) ste->expr;
4162 * Recurse into the CTE to see what its Var refers to.
4163 * We have to build an additional level of namespace
4164 * to keep in step with varlevelsup in the CTE.
4165 * Furthermore it could be an outer CTE, so we may
4166 * have to delete some levels of namespace.
4168 List *save_nslist = context->namespaces;
4170 deparse_namespace mydpns;
4173 memset(&mydpns, 0, sizeof(mydpns));
4174 mydpns.rtable = ctequery->rtable;
4175 mydpns.ctes = ctequery->cteList;
4177 new_nslist = list_copy_tail(context->namespaces,
4179 context->namespaces = lcons(&mydpns, new_nslist);
4181 result = get_name_for_var_field((Var *) expr, fieldno,
4184 context->namespaces = save_nslist;
4188 /* else fall through to inspect the expression */
4193 * We're deparsing a Plan tree so we don't have a CTE
4194 * list. But the only place we'd see a Var directly
4195 * referencing a CTE RTE is in a CteScan plan node, and we
4196 * can look into the subplan's tlist instead.
4199 deparse_namespace save_dpns;
4202 if (!dpns->inner_plan)
4203 elog(ERROR, "failed to find plan for CTE %s",
4204 rte->eref->aliasname);
4205 tle = get_tle_by_resno(dpns->inner_plan->targetlist,
4208 elog(ERROR, "bogus varattno for subquery var: %d",
4210 Assert(netlevelsup == 0);
4211 push_child_plan(dpns, dpns->inner_planstate, &save_dpns);
4213 result = get_name_for_var_field((Var *) tle->expr, fieldno,
4216 pop_child_plan(dpns, &save_dpns);
4224 * We now have an expression we can't expand any more, so see if
4225 * get_expr_result_type() can do anything with it. If not, pass to
4226 * lookup_rowtype_tupdesc() which will probably fail, but will give an
4227 * appropriate error message while failing.
4229 if (get_expr_result_type(expr, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
4230 tupleDesc = lookup_rowtype_tupdesc_copy(exprType(expr),
4233 /* Got the tupdesc, so we can extract the field name */
4234 Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
4235 return NameStr(tupleDesc->attrs[fieldno - 1]->attname);
4240 * find_rte_by_refname - look up an RTE by refname in a deparse context
4242 * Returns NULL if there is no matching RTE or the refname is ambiguous.
4244 * NOTE: this code is not really correct since it does not take account of
4245 * the fact that not all the RTEs in a rangetable may be visible from the
4246 * point where a Var reference appears. For the purposes we need, however,
4247 * the only consequence of a false match is that we might stick a schema
4248 * qualifier on a Var that doesn't really need it. So it seems close
4251 static RangeTblEntry *
4252 find_rte_by_refname(const char *refname, deparse_context *context)
4254 RangeTblEntry *result = NULL;
4257 foreach(nslist, context->namespaces)
4259 deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist);
4262 foreach(rtlist, dpns->rtable)
4264 RangeTblEntry *rte = (RangeTblEntry *) lfirst(rtlist);
4266 if (strcmp(rte->eref->aliasname, refname) == 0)
4269 return NULL; /* it's ambiguous */
4280 * Display a Param appropriately.
4283 get_parameter(Param *param, deparse_context *context)
4286 * If it's a PARAM_EXEC parameter, try to locate the expression from which
4287 * the parameter was computed. This will necessarily be in some ancestor
4288 * of the current expression's PlanState. Note that failing to find a
4289 * referent isn't an error, since the Param might well be a subplan output
4290 * rather than an input.
4292 if (param->paramkind == PARAM_EXEC)
4294 deparse_namespace *dpns;
4295 PlanState *child_ps;
4296 bool in_same_plan_level;
4299 dpns = (deparse_namespace *) linitial(context->namespaces);
4300 child_ps = dpns->planstate;
4301 in_same_plan_level = true;
4303 foreach(lc, dpns->ancestors)
4305 PlanState *ps = (PlanState *) lfirst(lc);
4309 * NestLoops transmit params to their inner child only; also, once
4310 * we've crawled up out of a subplan, this couldn't possibly be
4313 if (IsA(ps, NestLoopState) &&
4314 child_ps == innerPlanState(ps) &&
4317 NestLoop *nl = (NestLoop *) ps->plan;
4319 foreach(lc2, nl->nestParams)
4321 NestLoopParam *nlp = (NestLoopParam *) lfirst(lc2);
4323 if (nlp->paramno == param->paramid)
4325 /* Found a match, so print it */
4326 print_parameter_expr((Node *) nlp->paramval, lc,
4334 * Check to see if we're crawling up from a subplan.
4336 foreach(lc2, ps->subPlan)
4338 SubPlanState *sstate = (SubPlanState *) lfirst(lc2);
4339 SubPlan *subplan = (SubPlan *) sstate->xprstate.expr;
4343 if (child_ps != sstate->planstate)
4346 /* Matched subplan, so check its arguments */
4347 forboth(lc3, subplan->parParam, lc4, subplan->args)
4349 int paramid = lfirst_int(lc3);
4350 Node *arg = (Node *) lfirst(lc4);
4352 if (paramid == param->paramid)
4354 /* Found a match, so print it */
4355 print_parameter_expr(arg, lc, dpns, context);
4360 /* Keep looking, but we are emerging from a subplan. */
4361 in_same_plan_level = false;
4366 * Likewise check to see if we're emerging from an initplan.
4367 * Initplans never have any parParams, so no need to search that
4368 * list, but we need to know if we should reset
4369 * in_same_plan_level.
4371 foreach(lc2, ps->initPlan)
4373 SubPlanState *sstate = (SubPlanState *) lfirst(lc2);
4375 if (child_ps != sstate->planstate)
4378 /* No parameters to be had here. */
4379 Assert(((SubPlan *) sstate->xprstate.expr)->parParam == NIL);
4381 /* Keep looking, but we are emerging from an initplan. */
4382 in_same_plan_level = false;
4386 /* No luck, crawl up to next ancestor */
4392 * Not PARAM_EXEC, or couldn't find referent: just print $N.
4394 appendStringInfo(context->buf, "$%d", param->paramid);
4397 /* Print a parameter reference expression found by get_parameter */
4399 print_parameter_expr(Node *expr, ListCell *ancestor_cell,
4400 deparse_namespace *dpns, deparse_context *context)
4402 deparse_namespace save_dpns;
4403 bool save_varprefix;
4406 /* Switch attention to the ancestor plan node */
4407 push_ancestor_plan(dpns, ancestor_cell, &save_dpns);
4410 * Force prefixing of Vars, since they won't belong to the relation being
4411 * scanned in the original plan node.
4413 save_varprefix = context->varprefix;
4414 context->varprefix = true;
4417 * A Param's expansion is typically a Var, Aggref, or upper-level Param,
4418 * which wouldn't need extra parentheses. Otherwise, insert parens to
4419 * ensure the expression looks atomic.
4421 need_paren = !(IsA(expr, Var) ||
4422 IsA(expr, Aggref) ||
4425 appendStringInfoChar(context->buf, '(');
4427 get_rule_expr(expr, context, false);
4430 appendStringInfoChar(context->buf, ')');
4432 context->varprefix = save_varprefix;
4434 pop_ancestor_plan(dpns, &save_dpns);
4438 * get_simple_binary_op_name
4440 * helper function for isSimpleNode
4441 * will return single char binary operator name, or NULL if it's not
4444 get_simple_binary_op_name(OpExpr *expr)
4446 List *args = expr->args;
4448 if (list_length(args) == 2)
4450 /* binary operator */
4451 Node *arg1 = (Node *) linitial(args);
4452 Node *arg2 = (Node *) lsecond(args);
4455 op = generate_operator_name(expr->opno, exprType(arg1), exprType(arg2));
4456 if (strlen(op) == 1)
4464 * isSimpleNode - check if given node is simple (doesn't need parenthesizing)
4466 * true : simple in the context of parent node's type
4467 * false : not simple
4470 isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
4475 switch (nodeTag(node))
4480 case T_CoerceToDomainValue:
4481 case T_SetToDefault:
4482 case T_CurrentOfExpr:
4483 /* single words: always simple */
4489 case T_CoalesceExpr:
4496 /* function-like: name(..) or name[..] */
4499 /* CASE keywords act as parentheses */
4506 * appears simple since . has top precedence, unless parent is
4507 * T_FieldSelect itself!
4509 return (IsA(parentNode, FieldSelect) ? false : true);
4514 * treat like FieldSelect (probably doesn't matter)
4516 return (IsA(parentNode, FieldStore) ? false : true);
4518 case T_CoerceToDomain:
4519 /* maybe simple, check args */
4520 return isSimpleNode((Node *) ((CoerceToDomain *) node)->arg,
4523 return isSimpleNode((Node *) ((RelabelType *) node)->arg,
4526 return isSimpleNode((Node *) ((CoerceViaIO *) node)->arg,
4528 case T_ArrayCoerceExpr:
4529 return isSimpleNode((Node *) ((ArrayCoerceExpr *) node)->arg,
4531 case T_ConvertRowtypeExpr:
4532 return isSimpleNode((Node *) ((ConvertRowtypeExpr *) node)->arg,
4537 /* depends on parent node type; needs further checking */
4538 if (prettyFlags & PRETTYFLAG_PAREN && IsA(parentNode, OpExpr))
4541 const char *parentOp;
4544 bool is_lopriparent;
4545 bool is_hipriparent;
4547 op = get_simple_binary_op_name((OpExpr *) node);
4551 /* We know only the basic operators + - and * / % */
4552 is_lopriop = (strchr("+-", *op) != NULL);
4553 is_hipriop = (strchr("*/%", *op) != NULL);
4554 if (!(is_lopriop || is_hipriop))
4557 parentOp = get_simple_binary_op_name((OpExpr *) parentNode);
4561 is_lopriparent = (strchr("+-", *parentOp) != NULL);
4562 is_hipriparent = (strchr("*/%", *parentOp) != NULL);
4563 if (!(is_lopriparent || is_hipriparent))
4566 if (is_hipriop && is_lopriparent)
4567 return true; /* op binds tighter than parent */
4569 if (is_lopriop && is_hipriparent)
4573 * Operators are same priority --- can skip parens only if
4574 * we have (a - b) - c, not a - (b - c).
4576 if (node == (Node *) linitial(((OpExpr *) parentNode)->args))
4581 /* else do the same stuff as for T_SubLink et al. */
4588 case T_DistinctExpr:
4589 switch (nodeTag(parentNode))
4593 /* special handling for casts */
4594 CoercionForm type = ((FuncExpr *) parentNode)->funcformat;
4596 if (type == COERCE_EXPLICIT_CAST ||
4597 type == COERCE_IMPLICIT_CAST)
4599 return true; /* own parentheses */
4601 case T_BoolExpr: /* lower precedence */
4602 case T_ArrayRef: /* other separators */
4603 case T_ArrayExpr: /* other separators */
4604 case T_RowExpr: /* other separators */
4605 case T_CoalesceExpr: /* own parentheses */
4606 case T_MinMaxExpr: /* own parentheses */
4607 case T_XmlExpr: /* own parentheses */
4608 case T_NullIfExpr: /* other separators */
4609 case T_Aggref: /* own parentheses */
4610 case T_WindowFunc: /* own parentheses */
4611 case T_CaseExpr: /* other separators */
4618 switch (nodeTag(parentNode))
4621 if (prettyFlags & PRETTYFLAG_PAREN)
4624 BoolExprType parentType;
4626 type = ((BoolExpr *) node)->boolop;
4627 parentType = ((BoolExpr *) parentNode)->boolop;
4632 if (parentType == AND_EXPR || parentType == OR_EXPR)
4636 if (parentType == OR_EXPR)
4644 /* special handling for casts */
4645 CoercionForm type = ((FuncExpr *) parentNode)->funcformat;
4647 if (type == COERCE_EXPLICIT_CAST ||
4648 type == COERCE_IMPLICIT_CAST)
4650 return true; /* own parentheses */
4652 case T_ArrayRef: /* other separators */
4653 case T_ArrayExpr: /* other separators */
4654 case T_RowExpr: /* other separators */
4655 case T_CoalesceExpr: /* own parentheses */
4656 case T_MinMaxExpr: /* own parentheses */
4657 case T_XmlExpr: /* own parentheses */
4658 case T_NullIfExpr: /* other separators */
4659 case T_Aggref: /* own parentheses */
4660 case T_WindowFunc: /* own parentheses */
4661 case T_CaseExpr: /* other separators */
4670 /* those we don't know: in dubio complexo */
4676 * appendContextKeyword - append a keyword to buffer
4678 * If prettyPrint is enabled, perform a line break, and adjust indentation.
4679 * Otherwise, just append the keyword.
4682 appendContextKeyword(deparse_context *context, const char *str,
4683 int indentBefore, int indentAfter, int indentPlus)
4685 if (PRETTY_INDENT(context))
4687 context->indentLevel += indentBefore;
4689 appendStringInfoChar(context->buf, '\n');
4690 appendStringInfoSpaces(context->buf,
4691 Max(context->indentLevel, 0) + indentPlus);
4692 appendStringInfoString(context->buf, str);
4694 context->indentLevel += indentAfter;
4695 if (context->indentLevel < 0)
4696 context->indentLevel = 0;
4699 appendStringInfoString(context->buf, str);
4703 * get_rule_expr_paren - deparse expr using get_rule_expr,
4704 * embracing the string with parentheses if necessary for prettyPrint.
4706 * Never embrace if prettyFlags=0, because it's done in the calling node.
4708 * Any node that does *not* embrace its argument node by sql syntax (with
4709 * parentheses, non-operator keywords like CASE/WHEN/ON, or comma etc) should
4710 * use get_rule_expr_paren instead of get_rule_expr so parentheses can be
4714 get_rule_expr_paren(Node *node, deparse_context *context,
4715 bool showimplicit, Node *parentNode)
4719 need_paren = PRETTY_PAREN(context) &&
4720 !isSimpleNode(node, parentNode, context->prettyFlags);
4723 appendStringInfoChar(context->buf, '(');
4725 get_rule_expr(node, context, showimplicit);
4728 appendStringInfoChar(context->buf, ')');
4733 * get_rule_expr - Parse back an expression
4735 * Note: showimplicit determines whether we display any implicit cast that
4736 * is present at the top of the expression tree. It is a passed argument,
4737 * not a field of the context struct, because we change the value as we
4738 * recurse down into the expression. In general we suppress implicit casts
4739 * when the result type is known with certainty (eg, the arguments of an
4740 * OR must be boolean). We display implicit casts for arguments of functions
4741 * and operators, since this is needed to be certain that the same function
4742 * or operator will be chosen when the expression is re-parsed.
4746 get_rule_expr(Node *node, deparse_context *context,
4749 StringInfo buf = context->buf;
4755 * Each level of get_rule_expr must emit an indivisible term
4756 * (parenthesized if necessary) to ensure result is reparsed into the same
4757 * expression tree. The only exception is that when the input is a List,
4758 * we emit the component items comma-separated with no surrounding
4759 * decoration; this is convenient for most callers.
4761 switch (nodeTag(node))
4764 (void) get_variable((Var *) node, 0, true, context);
4768 get_const_expr((Const *) node, context, 0);
4772 get_parameter((Param *) node, context);
4776 get_agg_expr((Aggref *) node, context);
4780 get_windowfunc_expr((WindowFunc *) node, context);
4785 ArrayRef *aref = (ArrayRef *) node;
4789 * If the argument is a CaseTestExpr, we must be inside a
4790 * FieldStore, ie, we are assigning to an element of an array
4791 * within a composite column. Since we already punted on
4792 * displaying the FieldStore's target information, just punt
4793 * here too, and display only the assignment source
4796 if (IsA(aref->refexpr, CaseTestExpr))
4798 Assert(aref->refassgnexpr);
4799 get_rule_expr((Node *) aref->refassgnexpr,
4800 context, showimplicit);
4805 * Parenthesize the argument unless it's a simple Var or a
4806 * FieldSelect. (In particular, if it's another ArrayRef, we
4807 * *must* parenthesize to avoid confusion.)
4809 need_parens = !IsA(aref->refexpr, Var) &&
4810 !IsA(aref->refexpr, FieldSelect);
4812 appendStringInfoChar(buf, '(');
4813 get_rule_expr((Node *) aref->refexpr, context, showimplicit);
4815 appendStringInfoChar(buf, ')');
4818 * If there's a refassgnexpr, we want to print the node in the
4819 * format "array[subscripts] := refassgnexpr". This is not
4820 * legal SQL, so decompilation of INSERT or UPDATE statements
4821 * should always use processIndirection as part of the
4822 * statement-level syntax. We should only see this when
4823 * EXPLAIN tries to print the targetlist of a plan resulting
4824 * from such a statement.
4826 if (aref->refassgnexpr)
4831 * Use processIndirection to print this node's subscripts
4832 * as well as any additional field selections or
4833 * subscripting in immediate descendants. It returns the
4834 * RHS expr that is actually being "assigned".
4836 refassgnexpr = processIndirection(node, context, true);
4837 appendStringInfoString(buf, " := ");
4838 get_rule_expr(refassgnexpr, context, showimplicit);
4842 /* Just an ordinary array fetch, so print subscripts */
4843 printSubscripts(aref, context);
4849 get_func_expr((FuncExpr *) node, context, showimplicit);
4852 case T_NamedArgExpr:
4854 NamedArgExpr *na = (NamedArgExpr *) node;
4856 appendStringInfo(buf, "%s := ", quote_identifier(na->name));
4857 get_rule_expr((Node *) na->arg, context, showimplicit);
4862 get_oper_expr((OpExpr *) node, context);
4865 case T_DistinctExpr:
4867 DistinctExpr *expr = (DistinctExpr *) node;
4868 List *args = expr->args;
4869 Node *arg1 = (Node *) linitial(args);
4870 Node *arg2 = (Node *) lsecond(args);
4872 if (!PRETTY_PAREN(context))
4873 appendStringInfoChar(buf, '(');
4874 get_rule_expr_paren(arg1, context, true, node);
4875 appendStringInfo(buf, " IS DISTINCT FROM ");
4876 get_rule_expr_paren(arg2, context, true, node);
4877 if (!PRETTY_PAREN(context))
4878 appendStringInfoChar(buf, ')');
4884 NullIfExpr *nullifexpr = (NullIfExpr *) node;
4886 appendStringInfo(buf, "NULLIF(");
4887 get_rule_expr((Node *) nullifexpr->args, context, true);
4888 appendStringInfoChar(buf, ')');
4892 case T_ScalarArrayOpExpr:
4894 ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
4895 List *args = expr->args;
4896 Node *arg1 = (Node *) linitial(args);
4897 Node *arg2 = (Node *) lsecond(args);
4899 if (!PRETTY_PAREN(context))
4900 appendStringInfoChar(buf, '(');
4901 get_rule_expr_paren(arg1, context, true, node);
4902 appendStringInfo(buf, " %s %s (",
4903 generate_operator_name(expr->opno,
4905 get_base_element_type(exprType(arg2))),
4906 expr->useOr ? "ANY" : "ALL");
4907 get_rule_expr_paren(arg2, context, true, node);
4908 appendStringInfoChar(buf, ')');
4909 if (!PRETTY_PAREN(context))
4910 appendStringInfoChar(buf, ')');
4916 BoolExpr *expr = (BoolExpr *) node;
4917 Node *first_arg = linitial(expr->args);
4918 ListCell *arg = lnext(list_head(expr->args));
4920 switch (expr->boolop)
4923 if (!PRETTY_PAREN(context))
4924 appendStringInfoChar(buf, '(');
4925 get_rule_expr_paren(first_arg, context,
4929 appendStringInfo(buf, " AND ");
4930 get_rule_expr_paren((Node *) lfirst(arg), context,
4934 if (!PRETTY_PAREN(context))
4935 appendStringInfoChar(buf, ')');
4939 if (!PRETTY_PAREN(context))
4940 appendStringInfoChar(buf, '(');
4941 get_rule_expr_paren(first_arg, context,
4945 appendStringInfo(buf, " OR ");
4946 get_rule_expr_paren((Node *) lfirst(arg), context,
4950 if (!PRETTY_PAREN(context))
4951 appendStringInfoChar(buf, ')');
4955 if (!PRETTY_PAREN(context))
4956 appendStringInfoChar(buf, '(');
4957 appendStringInfo(buf, "NOT ");
4958 get_rule_expr_paren(first_arg, context,
4960 if (!PRETTY_PAREN(context))
4961 appendStringInfoChar(buf, ')');
4965 elog(ERROR, "unrecognized boolop: %d",
4966 (int) expr->boolop);
4972 get_sublink_expr((SubLink *) node, context);
4977 SubPlan *subplan = (SubPlan *) node;
4980 * We cannot see an already-planned subplan in rule deparsing,
4981 * only while EXPLAINing a query plan. We don't try to
4982 * reconstruct the original SQL, just reference the subplan
4983 * that appears elsewhere in EXPLAIN's result.
4985 if (subplan->useHashTable)
4986 appendStringInfo(buf, "(hashed %s)", subplan->plan_name);
4988 appendStringInfo(buf, "(%s)", subplan->plan_name);
4992 case T_AlternativeSubPlan:
4994 AlternativeSubPlan *asplan = (AlternativeSubPlan *) node;
4997 /* As above, this can only happen during EXPLAIN */
4998 appendStringInfo(buf, "(alternatives: ");
4999 foreach(lc, asplan->subplans)
5001 SubPlan *splan = (SubPlan *) lfirst(lc);
5003 Assert(IsA(splan, SubPlan));
5004 if (splan->useHashTable)
5005 appendStringInfo(buf, "hashed %s", splan->plan_name);
5007 appendStringInfo(buf, "%s", splan->plan_name);
5009 appendStringInfo(buf, " or ");
5011 appendStringInfo(buf, ")");
5017 FieldSelect *fselect = (FieldSelect *) node;
5018 Node *arg = (Node *) fselect->arg;
5019 int fno = fselect->fieldnum;
5020 const char *fieldname;
5024 * Parenthesize the argument unless it's an ArrayRef or
5025 * another FieldSelect. Note in particular that it would be
5026 * WRONG to not parenthesize a Var argument; simplicity is not
5027 * the issue here, having the right number of names is.
5029 need_parens = !IsA(arg, ArrayRef) &&!IsA(arg, FieldSelect);
5031 appendStringInfoChar(buf, '(');
5032 get_rule_expr(arg, context, true);
5034 appendStringInfoChar(buf, ')');
5037 * Get and print the field name.
5039 fieldname = get_name_for_var_field((Var *) arg, fno,
5041 appendStringInfo(buf, ".%s", quote_identifier(fieldname));
5047 FieldStore *fstore = (FieldStore *) node;
5051 * There is no good way to represent a FieldStore as real SQL,
5052 * so decompilation of INSERT or UPDATE statements should
5053 * always use processIndirection as part of the
5054 * statement-level syntax. We should only get here when
5055 * EXPLAIN tries to print the targetlist of a plan resulting
5056 * from such a statement. The plan case is even harder than
5057 * ordinary rules would be, because the planner tries to
5058 * collapse multiple assignments to the same field or subfield
5059 * into one FieldStore; so we can see a list of target fields
5060 * not just one, and the arguments could be FieldStores
5061 * themselves. We don't bother to try to print the target
5062 * field names; we just print the source arguments, with a
5063 * ROW() around them if there's more than one. This isn't
5064 * terribly complete, but it's probably good enough for
5065 * EXPLAIN's purposes; especially since anything more would be
5066 * either hopelessly confusing or an even poorer
5067 * representation of what the plan is actually doing.
5069 need_parens = (list_length(fstore->newvals) != 1);
5071 appendStringInfoString(buf, "ROW(");
5072 get_rule_expr((Node *) fstore->newvals, context, showimplicit);
5074 appendStringInfoChar(buf, ')');
5080 RelabelType *relabel = (RelabelType *) node;
5081 Node *arg = (Node *) relabel->arg;
5083 if (relabel->relabelformat == COERCE_IMPLICIT_CAST &&
5086 /* don't show the implicit cast */
5087 get_rule_expr_paren(arg, context, false, node);
5091 get_coercion_expr(arg, context,
5092 relabel->resulttype,
5093 relabel->resulttypmod,
5101 CoerceViaIO *iocoerce = (CoerceViaIO *) node;
5102 Node *arg = (Node *) iocoerce->arg;
5104 if (iocoerce->coerceformat == COERCE_IMPLICIT_CAST &&
5107 /* don't show the implicit cast */
5108 get_rule_expr_paren(arg, context, false, node);
5112 get_coercion_expr(arg, context,
5113 iocoerce->resulttype,
5120 case T_ArrayCoerceExpr:
5122 ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;
5123 Node *arg = (Node *) acoerce->arg;
5125 if (acoerce->coerceformat == COERCE_IMPLICIT_CAST &&
5128 /* don't show the implicit cast */
5129 get_rule_expr_paren(arg, context, false, node);
5133 get_coercion_expr(arg, context,
5134 acoerce->resulttype,
5135 acoerce->resulttypmod,
5141 case T_ConvertRowtypeExpr:
5143 ConvertRowtypeExpr *convert = (ConvertRowtypeExpr *) node;
5144 Node *arg = (Node *) convert->arg;
5146 if (convert->convertformat == COERCE_IMPLICIT_CAST &&
5149 /* don't show the implicit cast */
5150 get_rule_expr_paren(arg, context, false, node);
5154 get_coercion_expr(arg, context,
5155 convert->resulttype, -1,
5163 CollateExpr *collate = (CollateExpr *) node;
5164 Node *arg = (Node *) collate->arg;
5166 if (!PRETTY_PAREN(context))
5167 appendStringInfoChar(buf, '(');
5168 get_rule_expr_paren(arg, context, showimplicit, node);
5169 appendStringInfo(buf, " COLLATE %s",
5170 generate_collation_name(collate->collOid));
5171 if (!PRETTY_PAREN(context))
5172 appendStringInfoChar(buf, ')');
5178 CaseExpr *caseexpr = (CaseExpr *) node;
5181 appendContextKeyword(context, "CASE",
5182 0, PRETTYINDENT_VAR, 0);
5185 appendStringInfoChar(buf, ' ');
5186 get_rule_expr((Node *) caseexpr->arg, context, true);
5188 foreach(temp, caseexpr->args)
5190 CaseWhen *when = (CaseWhen *) lfirst(temp);
5191 Node *w = (Node *) when->expr;
5196 * The parser should have produced WHEN clauses of
5197 * the form "CaseTestExpr = RHS", possibly with an
5198 * implicit coercion inserted above the CaseTestExpr.
5199 * For accurate decompilation of rules it's essential
5200 * that we show just the RHS. However in an
5201 * expression that's been through the optimizer, the
5202 * WHEN clause could be almost anything (since the
5203 * equality operator could have been expanded into an
5204 * inline function). If we don't recognize the form
5205 * of the WHEN clause, just punt and display it as-is.
5209 List *args = ((OpExpr *) w)->args;
5211 if (list_length(args) == 2 &&
5212 IsA(strip_implicit_coercions(linitial(args)),
5214 w = (Node *) lsecond(args);
5218 if (!PRETTY_INDENT(context))
5219 appendStringInfoChar(buf, ' ');
5220 appendContextKeyword(context, "WHEN ",
5222 get_rule_expr(w, context, false);
5223 appendStringInfo(buf, " THEN ");
5224 get_rule_expr((Node *) when->result, context, true);
5226 if (!PRETTY_INDENT(context))
5227 appendStringInfoChar(buf, ' ');
5228 appendContextKeyword(context, "ELSE ",
5230 get_rule_expr((Node *) caseexpr->defresult, context, true);
5231 if (!PRETTY_INDENT(context))
5232 appendStringInfoChar(buf, ' ');
5233 appendContextKeyword(context, "END",
5234 -PRETTYINDENT_VAR, 0, 0);
5238 case T_CaseTestExpr:
5241 * Normally we should never get here, since for expressions
5242 * that can contain this node type we attempt to avoid
5243 * recursing to it. But in an optimized expression we might
5244 * be unable to avoid that (see comments for CaseExpr). If we
5245 * do see one, print it as CASE_TEST_EXPR.
5247 appendStringInfo(buf, "CASE_TEST_EXPR");
5253 ArrayExpr *arrayexpr = (ArrayExpr *) node;
5255 appendStringInfo(buf, "ARRAY[");
5256 get_rule_expr((Node *) arrayexpr->elements, context, true);
5257 appendStringInfoChar(buf, ']');
5260 * If the array isn't empty, we assume its elements are
5261 * coerced to the desired type. If it's empty, though, we
5262 * need an explicit coercion to the array type.
5264 if (arrayexpr->elements == NIL)
5265 appendStringInfo(buf, "::%s",
5266 format_type_with_typemod(arrayexpr->array_typeid, -1));
5272 RowExpr *rowexpr = (RowExpr *) node;
5273 TupleDesc tupdesc = NULL;
5279 * If it's a named type and not RECORD, we may have to skip
5280 * dropped columns and/or claim there are NULLs for added
5283 if (rowexpr->row_typeid != RECORDOID)
5285 tupdesc = lookup_rowtype_tupdesc(rowexpr->row_typeid, -1);
5286 Assert(list_length(rowexpr->args) <= tupdesc->natts);
5290 * SQL99 allows "ROW" to be omitted when there is more than
5291 * one column, but for simplicity we always print it.
5293 appendStringInfo(buf, "ROW(");
5296 foreach(arg, rowexpr->args)
5298 Node *e = (Node *) lfirst(arg);
5300 if (tupdesc == NULL ||
5301 !tupdesc->attrs[i]->attisdropped)
5303 appendStringInfoString(buf, sep);
5304 get_rule_expr(e, context, true);
5309 if (tupdesc != NULL)
5311 while (i < tupdesc->natts)
5313 if (!tupdesc->attrs[i]->attisdropped)
5315 appendStringInfoString(buf, sep);
5316 appendStringInfo(buf, "NULL");
5322 ReleaseTupleDesc(tupdesc);
5324 appendStringInfo(buf, ")");
5325 if (rowexpr->row_format == COERCE_EXPLICIT_CAST)
5326 appendStringInfo(buf, "::%s",
5327 format_type_with_typemod(rowexpr->row_typeid, -1));
5331 case T_RowCompareExpr:
5333 RowCompareExpr *rcexpr = (RowCompareExpr *) node;
5338 * SQL99 allows "ROW" to be omitted when there is more than
5339 * one column, but for simplicity we always print it.
5341 appendStringInfo(buf, "(ROW(");
5343 foreach(arg, rcexpr->largs)
5345 Node *e = (Node *) lfirst(arg);
5347 appendStringInfoString(buf, sep);
5348 get_rule_expr(e, context, true);
5353 * We assume that the name of the first-column operator will
5354 * do for all the rest too. This is definitely open to
5355 * failure, eg if some but not all operators were renamed
5356 * since the construct was parsed, but there seems no way to
5359 appendStringInfo(buf, ") %s ROW(",
5360 generate_operator_name(linitial_oid(rcexpr->opnos),
5361 exprType(linitial(rcexpr->largs)),
5362 exprType(linitial(rcexpr->rargs))));
5364 foreach(arg, rcexpr->rargs)
5366 Node *e = (Node *) lfirst(arg);
5368 appendStringInfoString(buf, sep);
5369 get_rule_expr(e, context, true);
5372 appendStringInfo(buf, "))");
5376 case T_CoalesceExpr:
5378 CoalesceExpr *coalesceexpr = (CoalesceExpr *) node;
5380 appendStringInfo(buf, "COALESCE(");
5381 get_rule_expr((Node *) coalesceexpr->args, context, true);
5382 appendStringInfoChar(buf, ')');
5388 MinMaxExpr *minmaxexpr = (MinMaxExpr *) node;
5390 switch (minmaxexpr->op)
5393 appendStringInfo(buf, "GREATEST(");
5396 appendStringInfo(buf, "LEAST(");
5399 get_rule_expr((Node *) minmaxexpr->args, context, true);
5400 appendStringInfoChar(buf, ')');
5406 XmlExpr *xexpr = (XmlExpr *) node;
5407 bool needcomma = false;
5415 appendStringInfoString(buf, "XMLCONCAT(");
5418 appendStringInfoString(buf, "XMLELEMENT(");
5421 appendStringInfoString(buf, "XMLFOREST(");
5424 appendStringInfoString(buf, "XMLPARSE(");
5427 appendStringInfoString(buf, "XMLPI(");
5430 appendStringInfoString(buf, "XMLROOT(");
5432 case IS_XMLSERIALIZE:
5433 appendStringInfoString(buf, "XMLSERIALIZE(");
5438 if (xexpr->op == IS_XMLPARSE || xexpr->op == IS_XMLSERIALIZE)
5440 if (xexpr->xmloption == XMLOPTION_DOCUMENT)
5441 appendStringInfoString(buf, "DOCUMENT ");
5443 appendStringInfoString(buf, "CONTENT ");
5447 appendStringInfo(buf, "NAME %s",
5448 quote_identifier(map_xml_name_to_sql_identifier(xexpr->name)));
5451 if (xexpr->named_args)
5453 if (xexpr->op != IS_XMLFOREST)
5456 appendStringInfoString(buf, ", ");
5457 appendStringInfoString(buf, "XMLATTRIBUTES(");
5460 forboth(arg, xexpr->named_args, narg, xexpr->arg_names)
5462 Node *e = (Node *) lfirst(arg);
5463 char *argname = strVal(lfirst(narg));
5466 appendStringInfoString(buf, ", ");
5467 get_rule_expr((Node *) e, context, true);
5468 appendStringInfo(buf, " AS %s",
5469 quote_identifier(map_xml_name_to_sql_identifier(argname)));
5472 if (xexpr->op != IS_XMLFOREST)
5473 appendStringInfoChar(buf, ')');
5478 appendStringInfoString(buf, ", ");
5485 case IS_XMLSERIALIZE:
5486 /* no extra decoration needed */
5487 get_rule_expr((Node *) xexpr->args, context, true);
5490 Assert(list_length(xexpr->args) == 2);
5492 get_rule_expr((Node *) linitial(xexpr->args),
5495 con = (Const *) lsecond(xexpr->args);
5496 Assert(IsA(con, Const));
5497 Assert(!con->constisnull);
5498 if (DatumGetBool(con->constvalue))
5499 appendStringInfoString(buf,
5500 " PRESERVE WHITESPACE");
5502 appendStringInfoString(buf,
5503 " STRIP WHITESPACE");
5506 Assert(list_length(xexpr->args) == 3);
5508 get_rule_expr((Node *) linitial(xexpr->args),
5511 appendStringInfoString(buf, ", VERSION ");
5512 con = (Const *) lsecond(xexpr->args);
5513 if (IsA(con, Const) &&
5515 appendStringInfoString(buf, "NO VALUE");
5517 get_rule_expr((Node *) con, context, false);
5519 con = (Const *) lthird(xexpr->args);
5520 Assert(IsA(con, Const));
5521 if (con->constisnull)
5522 /* suppress STANDALONE NO VALUE */ ;
5525 switch (DatumGetInt32(con->constvalue))
5527 case XML_STANDALONE_YES:
5528 appendStringInfoString(buf,
5529 ", STANDALONE YES");
5531 case XML_STANDALONE_NO:
5532 appendStringInfoString(buf,
5535 case XML_STANDALONE_NO_VALUE:
5536 appendStringInfoString(buf,
5537 ", STANDALONE NO VALUE");
5545 get_rule_expr_paren((Node *) xexpr->args, context, false, node);
5550 if (xexpr->op == IS_XMLSERIALIZE)
5551 appendStringInfo(buf, " AS %s",
5552 format_type_with_typemod(xexpr->type,
5554 if (xexpr->op == IS_DOCUMENT)
5555 appendStringInfoString(buf, " IS DOCUMENT");
5557 appendStringInfoChar(buf, ')');
5563 NullTest *ntest = (NullTest *) node;
5565 if (!PRETTY_PAREN(context))
5566 appendStringInfoChar(buf, '(');
5567 get_rule_expr_paren((Node *) ntest->arg, context, true, node);
5568 switch (ntest->nulltesttype)
5571 appendStringInfo(buf, " IS NULL");
5574 appendStringInfo(buf, " IS NOT NULL");
5577 elog(ERROR, "unrecognized nulltesttype: %d",
5578 (int) ntest->nulltesttype);
5580 if (!PRETTY_PAREN(context))
5581 appendStringInfoChar(buf, ')');
5587 BooleanTest *btest = (BooleanTest *) node;
5589 if (!PRETTY_PAREN(context))
5590 appendStringInfoChar(buf, '(');
5591 get_rule_expr_paren((Node *) btest->arg, context, false, node);
5592 switch (btest->booltesttype)
5595 appendStringInfo(buf, " IS TRUE");
5598 appendStringInfo(buf, " IS NOT TRUE");
5601 appendStringInfo(buf, " IS FALSE");
5604 appendStringInfo(buf, " IS NOT FALSE");
5607 appendStringInfo(buf, " IS UNKNOWN");
5609 case IS_NOT_UNKNOWN:
5610 appendStringInfo(buf, " IS NOT UNKNOWN");
5613 elog(ERROR, "unrecognized booltesttype: %d",
5614 (int) btest->booltesttype);
5616 if (!PRETTY_PAREN(context))
5617 appendStringInfoChar(buf, ')');
5621 case T_CoerceToDomain:
5623 CoerceToDomain *ctest = (CoerceToDomain *) node;
5624 Node *arg = (Node *) ctest->arg;
5626 if (ctest->coercionformat == COERCE_IMPLICIT_CAST &&
5629 /* don't show the implicit cast */
5630 get_rule_expr(arg, context, false);
5634 get_coercion_expr(arg, context,
5636 ctest->resulttypmod,
5642 case T_CoerceToDomainValue:
5643 appendStringInfo(buf, "VALUE");
5646 case T_SetToDefault:
5647 appendStringInfo(buf, "DEFAULT");
5650 case T_CurrentOfExpr:
5652 CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
5654 if (cexpr->cursor_name)
5655 appendStringInfo(buf, "CURRENT OF %s",
5656 quote_identifier(cexpr->cursor_name));
5658 appendStringInfo(buf, "CURRENT OF $%d",
5659 cexpr->cursor_param);
5669 foreach(l, (List *) node)
5671 appendStringInfoString(buf, sep);
5672 get_rule_expr((Node *) lfirst(l), context, showimplicit);
5679 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
5686 * get_oper_expr - Parse back an OpExpr node
5689 get_oper_expr(OpExpr *expr, deparse_context *context)
5691 StringInfo buf = context->buf;
5692 Oid opno = expr->opno;
5693 List *args = expr->args;
5695 if (!PRETTY_PAREN(context))
5696 appendStringInfoChar(buf, '(');
5697 if (list_length(args) == 2)
5699 /* binary operator */
5700 Node *arg1 = (Node *) linitial(args);
5701 Node *arg2 = (Node *) lsecond(args);
5703 get_rule_expr_paren(arg1, context, true, (Node *) expr);
5704 appendStringInfo(buf, " %s ",
5705 generate_operator_name(opno,
5708 get_rule_expr_paren(arg2, context, true, (Node *) expr);
5712 /* unary operator --- but which side? */
5713 Node *arg = (Node *) linitial(args);
5715 Form_pg_operator optup;
5717 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
5718 if (!HeapTupleIsValid(tp))
5719 elog(ERROR, "cache lookup failed for operator %u", opno);
5720 optup = (Form_pg_operator) GETSTRUCT(tp);
5721 switch (optup->oprkind)
5724 appendStringInfo(buf, "%s ",
5725 generate_operator_name(opno,
5728 get_rule_expr_paren(arg, context, true, (Node *) expr);
5731 get_rule_expr_paren(arg, context, true, (Node *) expr);
5732 appendStringInfo(buf, " %s",
5733 generate_operator_name(opno,
5738 elog(ERROR, "bogus oprkind: %d", optup->oprkind);
5740 ReleaseSysCache(tp);
5742 if (!PRETTY_PAREN(context))
5743 appendStringInfoChar(buf, ')');
5747 * get_func_expr - Parse back a FuncExpr node
5750 get_func_expr(FuncExpr *expr, deparse_context *context,
5753 StringInfo buf = context->buf;
5754 Oid funcoid = expr->funcid;
5755 Oid argtypes[FUNC_MAX_ARGS];
5762 * If the function call came from an implicit coercion, then just show the
5763 * first argument --- unless caller wants to see implicit coercions.
5765 if (expr->funcformat == COERCE_IMPLICIT_CAST && !showimplicit)
5767 get_rule_expr_paren((Node *) linitial(expr->args), context,
5768 false, (Node *) expr);
5773 * If the function call came from a cast, then show the first argument
5774 * plus an explicit cast operation.
5776 if (expr->funcformat == COERCE_EXPLICIT_CAST ||
5777 expr->funcformat == COERCE_IMPLICIT_CAST)
5779 Node *arg = linitial(expr->args);
5780 Oid rettype = expr->funcresulttype;
5781 int32 coercedTypmod;
5783 /* Get the typmod if this is a length-coercion function */
5784 (void) exprIsLengthCoercion((Node *) expr, &coercedTypmod);
5786 get_coercion_expr(arg, context,
5787 rettype, coercedTypmod,
5794 * Normal function: display as proname(args). First we need to extract
5795 * the argument datatypes.
5797 if (list_length(expr->args) > FUNC_MAX_ARGS)
5799 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
5800 errmsg("too many arguments")));
5803 foreach(l, expr->args)
5805 Node *arg = (Node *) lfirst(l);
5807 if (IsA(arg, NamedArgExpr))
5808 argnames = lappend(argnames, ((NamedArgExpr *) arg)->name);
5809 argtypes[nargs] = exprType(arg);
5813 appendStringInfo(buf, "%s(",
5814 generate_function_name(funcoid, nargs,
5818 foreach(l, expr->args)
5821 appendStringInfoString(buf, ", ");
5822 if (is_variadic && lnext(l) == NULL)
5823 appendStringInfoString(buf, "VARIADIC ");
5824 get_rule_expr((Node *) lfirst(l), context, true);
5826 appendStringInfoChar(buf, ')');
5830 * get_agg_expr - Parse back an Aggref node
5833 get_agg_expr(Aggref *aggref, deparse_context *context)
5835 StringInfo buf = context->buf;
5836 Oid argtypes[FUNC_MAX_ARGS];
5841 /* Extract the regular arguments, ignoring resjunk stuff for the moment */
5844 foreach(l, aggref->args)
5846 TargetEntry *tle = (TargetEntry *) lfirst(l);
5847 Node *arg = (Node *) tle->expr;
5849 Assert(!IsA(arg, NamedArgExpr));
5852 if (nargs >= FUNC_MAX_ARGS) /* paranoia */
5854 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
5855 errmsg("too many arguments")));
5856 argtypes[nargs] = exprType(arg);
5857 arglist = lappend(arglist, arg);
5861 appendStringInfo(buf, "%s(%s",
5862 generate_function_name(aggref->aggfnoid, nargs,
5863 NIL, argtypes, NULL),
5864 (aggref->aggdistinct != NIL) ? "DISTINCT " : "");
5865 /* aggstar can be set only in zero-argument aggregates */
5866 if (aggref->aggstar)
5867 appendStringInfoChar(buf, '*');
5869 get_rule_expr((Node *) arglist, context, true);
5870 if (aggref->aggorder != NIL)
5872 appendStringInfoString(buf, " ORDER BY ");
5873 get_rule_orderby(aggref->aggorder, aggref->args, false, context);
5875 appendStringInfoChar(buf, ')');
5879 * get_windowfunc_expr - Parse back a WindowFunc node
5882 get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context)
5884 StringInfo buf = context->buf;
5885 Oid argtypes[FUNC_MAX_ARGS];
5889 if (list_length(wfunc->args) > FUNC_MAX_ARGS)
5891 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
5892 errmsg("too many arguments")));
5894 foreach(l, wfunc->args)
5896 Node *arg = (Node *) lfirst(l);
5898 Assert(!IsA(arg, NamedArgExpr));
5899 argtypes[nargs] = exprType(arg);
5903 appendStringInfo(buf, "%s(",
5904 generate_function_name(wfunc->winfnoid, nargs,
5905 NIL, argtypes, NULL));
5906 /* winstar can be set only in zero-argument aggregates */
5908 appendStringInfoChar(buf, '*');
5910 get_rule_expr((Node *) wfunc->args, context, true);
5911 appendStringInfoString(buf, ") OVER ");
5913 foreach(l, context->windowClause)
5915 WindowClause *wc = (WindowClause *) lfirst(l);
5917 if (wc->winref == wfunc->winref)
5920 appendStringInfoString(buf, quote_identifier(wc->name));
5922 get_rule_windowspec(wc, context->windowTList, context);
5928 if (context->windowClause)
5929 elog(ERROR, "could not find window clause for winref %u",
5933 * In EXPLAIN, we don't have window context information available, so
5934 * we have to settle for this:
5936 appendStringInfoString(buf, "(?)");
5943 * Make a string representation of a value coerced to a specific type
5947 get_coercion_expr(Node *arg, deparse_context *context,
5948 Oid resulttype, int32 resulttypmod,
5951 StringInfo buf = context->buf;
5954 * Since parse_coerce.c doesn't immediately collapse application of
5955 * length-coercion functions to constants, what we'll typically see in
5956 * such cases is a Const with typmod -1 and a length-coercion function
5957 * right above it. Avoid generating redundant output. However, beware of
5958 * suppressing casts when the user actually wrote something like
5959 * 'foo'::text::char(3).
5961 if (arg && IsA(arg, Const) &&
5962 ((Const *) arg)->consttype == resulttype &&
5963 ((Const *) arg)->consttypmod == -1)
5965 /* Show the constant without normal ::typename decoration */
5966 get_const_expr((Const *) arg, context, -1);
5970 if (!PRETTY_PAREN(context))
5971 appendStringInfoChar(buf, '(');
5972 get_rule_expr_paren(arg, context, false, parentNode);
5973 if (!PRETTY_PAREN(context))
5974 appendStringInfoChar(buf, ')');
5976 appendStringInfo(buf, "::%s",
5977 format_type_with_typemod(resulttype, resulttypmod));
5983 * Make a string representation of a Const
5985 * showtype can be -1 to never show "::typename" decoration, or +1 to always
5986 * show it, or 0 to show it only if the constant wouldn't be assumed to be
5987 * the right type by default.
5989 * If the Const's collation isn't default for its type, show that too.
5990 * This can only happen in trees that have been through constant-folding.
5991 * We assume we don't need to do this when showtype is -1.
5995 get_const_expr(Const *constval, deparse_context *context, int showtype)
5997 StringInfo buf = context->buf;
6001 bool isfloat = false;
6004 if (constval->constisnull)
6007 * Always label the type of a NULL constant to prevent misdecisions
6008 * about type when reparsing.
6010 appendStringInfo(buf, "NULL");
6013 appendStringInfo(buf, "::%s",
6014 format_type_with_typemod(constval->consttype,
6015 constval->consttypmod));
6016 get_const_collation(constval, context);
6021 getTypeOutputInfo(constval->consttype,
6022 &typoutput, &typIsVarlena);
6024 extval = OidOutputFunctionCall(typoutput, constval->constvalue);
6026 switch (constval->consttype)
6037 * These types are printed without quotes unless they contain
6038 * values that aren't accepted by the scanner unquoted (e.g.,
6039 * 'NaN'). Note that strtod() and friends might accept NaN,
6040 * so we can't use that to test.
6042 * In reality we only need to defend against infinity and NaN,
6043 * so we need not get too crazy about pattern matching here.
6045 * There is a special-case gotcha: if the constant is signed,
6046 * we need to parenthesize it, else the parser might see a
6047 * leading plus/minus as binding less tightly than adjacent
6048 * operators --- particularly, the cast that we might attach
6051 if (strspn(extval, "0123456789+-eE.") == strlen(extval))
6053 if (extval[0] == '+' || extval[0] == '-')
6054 appendStringInfo(buf, "(%s)", extval);
6056 appendStringInfoString(buf, extval);
6057 if (strcspn(extval, "eE.") != strlen(extval))
6058 isfloat = true; /* it looks like a float */
6061 appendStringInfo(buf, "'%s'", extval);
6067 appendStringInfo(buf, "B'%s'", extval);
6071 if (strcmp(extval, "t") == 0)
6072 appendStringInfo(buf, "true");
6074 appendStringInfo(buf, "false");
6078 simple_quote_literal(buf, extval);
6088 * For showtype == 0, append ::typename unless the constant will be
6089 * implicitly typed as the right type when it is read in.
6091 * XXX this code has to be kept in sync with the behavior of the parser,
6092 * especially make_const.
6094 switch (constval->consttype)
6099 /* These types can be left unlabeled */
6105 * Float-looking constants will be typed as numeric, but if
6106 * there's a specific typmod we need to show it.
6108 needlabel = !isfloat || (constval->consttypmod >= 0);
6114 if (needlabel || showtype > 0)
6115 appendStringInfo(buf, "::%s",
6116 format_type_with_typemod(constval->consttype,
6117 constval->consttypmod));
6119 get_const_collation(constval, context);
6123 * helper for get_const_expr: append COLLATE if needed
6126 get_const_collation(Const *constval, deparse_context *context)
6128 StringInfo buf = context->buf;
6130 if (OidIsValid(constval->constcollid))
6132 Oid typcollation = get_typcollation(constval->consttype);
6134 if (constval->constcollid != typcollation)
6136 appendStringInfo(buf, " COLLATE %s",
6137 generate_collation_name(constval->constcollid));
6143 * simple_quote_literal - Format a string as a SQL literal, append to buf
6146 simple_quote_literal(StringInfo buf, const char *val)
6151 * We form the string literal according to the prevailing setting of
6152 * standard_conforming_strings; we never use E''. User is responsible for
6153 * making sure result is used correctly.
6155 appendStringInfoChar(buf, '\'');
6156 for (valptr = val; *valptr; valptr++)
6160 if (SQL_STR_DOUBLE(ch, !standard_conforming_strings))
6161 appendStringInfoChar(buf, ch);
6162 appendStringInfoChar(buf, ch);
6164 appendStringInfoChar(buf, '\'');
6169 * get_sublink_expr - Parse back a sublink
6173 get_sublink_expr(SubLink *sublink, deparse_context *context)
6175 StringInfo buf = context->buf;
6176 Query *query = (Query *) (sublink->subselect);
6177 char *opname = NULL;
6180 if (sublink->subLinkType == ARRAY_SUBLINK)
6181 appendStringInfo(buf, "ARRAY(");
6183 appendStringInfoChar(buf, '(');
6186 * Note that we print the name of only the first operator, when there are
6187 * multiple combining operators. This is an approximation that could go
6188 * wrong in various scenarios (operators in different schemas, renamed
6189 * operators, etc) but there is not a whole lot we can do about it, since
6190 * the syntax allows only one operator to be shown.
6192 if (sublink->testexpr)
6194 if (IsA(sublink->testexpr, OpExpr))
6196 /* single combining operator */
6197 OpExpr *opexpr = (OpExpr *) sublink->testexpr;
6199 get_rule_expr(linitial(opexpr->args), context, true);
6200 opname = generate_operator_name(opexpr->opno,
6201 exprType(linitial(opexpr->args)),
6202 exprType(lsecond(opexpr->args)));
6204 else if (IsA(sublink->testexpr, BoolExpr))
6206 /* multiple combining operators, = or <> cases */
6210 appendStringInfoChar(buf, '(');
6212 foreach(l, ((BoolExpr *) sublink->testexpr)->args)
6214 OpExpr *opexpr = (OpExpr *) lfirst(l);
6216 Assert(IsA(opexpr, OpExpr));
6217 appendStringInfoString(buf, sep);
6218 get_rule_expr(linitial(opexpr->args), context, true);
6220 opname = generate_operator_name(opexpr->opno,
6221 exprType(linitial(opexpr->args)),
6222 exprType(lsecond(opexpr->args)));
6225 appendStringInfoChar(buf, ')');
6227 else if (IsA(sublink->testexpr, RowCompareExpr))
6229 /* multiple combining operators, < <= > >= cases */
6230 RowCompareExpr *rcexpr = (RowCompareExpr *) sublink->testexpr;
6232 appendStringInfoChar(buf, '(');
6233 get_rule_expr((Node *) rcexpr->largs, context, true);
6234 opname = generate_operator_name(linitial_oid(rcexpr->opnos),
6235 exprType(linitial(rcexpr->largs)),
6236 exprType(linitial(rcexpr->rargs)));
6237 appendStringInfoChar(buf, ')');
6240 elog(ERROR, "unrecognized testexpr type: %d",
6241 (int) nodeTag(sublink->testexpr));
6246 switch (sublink->subLinkType)
6248 case EXISTS_SUBLINK:
6249 appendStringInfo(buf, "EXISTS ");
6253 if (strcmp(opname, "=") == 0) /* Represent = ANY as IN */
6254 appendStringInfo(buf, " IN ");
6256 appendStringInfo(buf, " %s ANY ", opname);
6260 appendStringInfo(buf, " %s ALL ", opname);
6263 case ROWCOMPARE_SUBLINK:
6264 appendStringInfo(buf, " %s ", opname);
6272 case CTE_SUBLINK: /* shouldn't occur in a SubLink */
6274 elog(ERROR, "unrecognized sublink type: %d",
6275 (int) sublink->subLinkType);
6280 appendStringInfoChar(buf, '(');
6282 get_query_def(query, buf, context->namespaces, NULL,
6283 context->prettyFlags, context->indentLevel);
6286 appendStringInfo(buf, "))");
6288 appendStringInfoChar(buf, ')');
6293 * get_from_clause - Parse back a FROM clause
6295 * "prefix" is the keyword that denotes the start of the list of FROM
6296 * elements. It is FROM when used to parse back SELECT and UPDATE, but
6297 * is USING when parsing back DELETE.
6301 get_from_clause(Query *query, const char *prefix, deparse_context *context)
6303 StringInfo buf = context->buf;
6308 * We use the query's jointree as a guide to what to print. However, we
6309 * must ignore auto-added RTEs that are marked not inFromCl. (These can
6310 * only appear at the top level of the jointree, so it's sufficient to
6311 * check here.) This check also ensures we ignore the rule pseudo-RTEs
6314 foreach(l, query->jointree->fromlist)
6316 Node *jtnode = (Node *) lfirst(l);
6318 if (IsA(jtnode, RangeTblRef))
6320 int varno = ((RangeTblRef *) jtnode)->rtindex;
6321 RangeTblEntry *rte = rt_fetch(varno, query->rtable);
6329 appendContextKeyword(context, prefix,
6330 -PRETTYINDENT_STD, PRETTYINDENT_STD, 2);
6334 appendStringInfoString(buf, ", ");
6336 get_from_clause_item(jtnode, query, context);
6341 get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
6343 StringInfo buf = context->buf;
6345 if (IsA(jtnode, RangeTblRef))
6347 int varno = ((RangeTblRef *) jtnode)->rtindex;
6348 RangeTblEntry *rte = rt_fetch(varno, query->rtable);
6349 bool gavealias = false;
6351 switch (rte->rtekind)
6354 /* Normal relation RTE */
6355 appendStringInfo(buf, "%s%s",
6357 generate_relation_name(rte->relid,
6358 context->namespaces));
6362 appendStringInfoChar(buf, '(');
6363 get_query_def(rte->subquery, buf, context->namespaces, NULL,
6364 context->prettyFlags, context->indentLevel);
6365 appendStringInfoChar(buf, ')');
6369 get_rule_expr(rte->funcexpr, context, true);
6372 /* Values list RTE */
6373 get_values_def(rte->values_lists, context);
6376 appendStringInfoString(buf, quote_identifier(rte->ctename));
6379 elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
6383 if (rte->alias != NULL)
6385 appendStringInfo(buf, " %s",
6386 quote_identifier(rte->alias->aliasname));
6389 else if (rte->rtekind == RTE_RELATION &&
6390 strcmp(rte->eref->aliasname, get_relation_name(rte->relid)) != 0)
6393 * Apparently the rel has been renamed since the rule was made.
6394 * Emit a fake alias clause so that variable references will still
6395 * work. This is not a 100% solution but should work in most
6396 * reasonable situations.
6398 appendStringInfo(buf, " %s",
6399 quote_identifier(rte->eref->aliasname));
6402 else if (rte->rtekind == RTE_FUNCTION)
6405 * For a function RTE, always give an alias. This covers possible
6406 * renaming of the function and/or instability of the
6407 * FigureColname rules for things that aren't simple functions.
6409 appendStringInfo(buf, " %s",
6410 quote_identifier(rte->eref->aliasname));
6414 if (rte->rtekind == RTE_FUNCTION)
6416 if (rte->funccoltypes != NIL)
6418 /* Function returning RECORD, reconstruct the columndefs */
6420 appendStringInfo(buf, " AS ");
6421 get_from_clause_coldeflist(rte->eref->colnames,
6423 rte->funccoltypmods,
6424 rte->funccolcollations,
6430 * For a function RTE, always emit a complete column alias
6431 * list; this is to protect against possible instability of
6432 * the default column names (eg, from altering parameter
6435 get_from_clause_alias(rte->eref, rte, context);
6441 * For non-function RTEs, just report whatever the user originally
6442 * gave as column aliases.
6444 get_from_clause_alias(rte->alias, rte, context);
6447 else if (IsA(jtnode, JoinExpr))
6449 JoinExpr *j = (JoinExpr *) jtnode;
6450 bool need_paren_on_right;
6452 need_paren_on_right = PRETTY_PAREN(context) &&
6453 !IsA(j->rarg, RangeTblRef) &&
6454 !(IsA(j->rarg, JoinExpr) &&((JoinExpr *) j->rarg)->alias != NULL);
6456 if (!PRETTY_PAREN(context) || j->alias != NULL)
6457 appendStringInfoChar(buf, '(');
6459 get_from_clause_item(j->larg, query, context);
6463 if (!PRETTY_INDENT(context))
6464 appendStringInfoChar(buf, ' ');
6465 switch (j->jointype)
6468 appendContextKeyword(context, "NATURAL JOIN ",
6470 PRETTYINDENT_JOIN, 0);
6473 appendContextKeyword(context, "NATURAL LEFT JOIN ",
6475 PRETTYINDENT_JOIN, 0);
6478 appendContextKeyword(context, "NATURAL FULL JOIN ",
6480 PRETTYINDENT_JOIN, 0);
6483 appendContextKeyword(context, "NATURAL RIGHT JOIN ",
6485 PRETTYINDENT_JOIN, 0);
6488 elog(ERROR, "unrecognized join type: %d",
6494 switch (j->jointype)
6498 appendContextKeyword(context, " JOIN ",
6500 PRETTYINDENT_JOIN, 2);
6502 appendContextKeyword(context, " CROSS JOIN ",
6504 PRETTYINDENT_JOIN, 1);
6507 appendContextKeyword(context, " LEFT JOIN ",
6509 PRETTYINDENT_JOIN, 2);
6512 appendContextKeyword(context, " FULL JOIN ",
6514 PRETTYINDENT_JOIN, 2);
6517 appendContextKeyword(context, " RIGHT JOIN ",
6519 PRETTYINDENT_JOIN, 2);
6522 elog(ERROR, "unrecognized join type: %d",
6527 if (need_paren_on_right)
6528 appendStringInfoChar(buf, '(');
6529 get_from_clause_item(j->rarg, query, context);
6530 if (need_paren_on_right)
6531 appendStringInfoChar(buf, ')');
6533 context->indentLevel -= PRETTYINDENT_JOIN_ON;
6541 appendStringInfo(buf, " USING (");
6542 foreach(col, j->usingClause)
6544 if (col != list_head(j->usingClause))
6545 appendStringInfo(buf, ", ");
6546 appendStringInfoString(buf,
6547 quote_identifier(strVal(lfirst(col))));
6549 appendStringInfoChar(buf, ')');
6553 appendStringInfo(buf, " ON ");
6554 if (!PRETTY_PAREN(context))
6555 appendStringInfoChar(buf, '(');
6556 get_rule_expr(j->quals, context, false);
6557 if (!PRETTY_PAREN(context))
6558 appendStringInfoChar(buf, ')');
6561 if (!PRETTY_PAREN(context) || j->alias != NULL)
6562 appendStringInfoChar(buf, ')');
6564 /* Yes, it's correct to put alias after the right paren ... */
6565 if (j->alias != NULL)
6567 appendStringInfo(buf, " %s",
6568 quote_identifier(j->alias->aliasname));
6569 get_from_clause_alias(j->alias,
6570 rt_fetch(j->rtindex, query->rtable),
6575 elog(ERROR, "unrecognized node type: %d",
6576 (int) nodeTag(jtnode));
6580 * get_from_clause_alias - reproduce column alias list
6582 * This is tricky because we must ignore dropped columns.
6585 get_from_clause_alias(Alias *alias, RangeTblEntry *rte,
6586 deparse_context *context)
6588 StringInfo buf = context->buf;
6593 if (alias == NULL || alias->colnames == NIL)
6594 return; /* definitely nothing to do */
6597 foreach(col, alias->colnames)
6600 if (get_rte_attribute_is_dropped(rte, attnum))
6604 appendStringInfoChar(buf, '(');
6608 appendStringInfo(buf, ", ");
6609 appendStringInfoString(buf,
6610 quote_identifier(strVal(lfirst(col))));
6613 appendStringInfoChar(buf, ')');
6617 * get_from_clause_coldeflist - reproduce FROM clause coldeflist
6619 * The coldeflist is appended immediately (no space) to buf. Caller is
6620 * responsible for ensuring that an alias or AS is present before it.
6623 get_from_clause_coldeflist(List *names,
6624 List *types, List *typmods, List *collations,
6625 deparse_context *context)
6627 StringInfo buf = context->buf;
6634 appendStringInfoChar(buf, '(');
6636 l2 = list_head(types);
6637 l3 = list_head(typmods);
6638 l4 = list_head(collations);
6641 char *attname = strVal(lfirst(l1));
6646 atttypid = lfirst_oid(l2);
6648 atttypmod = lfirst_int(l3);
6650 attcollation = lfirst_oid(l4);
6654 appendStringInfo(buf, ", ");
6655 appendStringInfo(buf, "%s %s",
6656 quote_identifier(attname),
6657 format_type_with_typemod(atttypid, atttypmod));
6658 if (OidIsValid(attcollation) &&
6659 attcollation != get_typcollation(atttypid))
6660 appendStringInfo(buf, " COLLATE %s",
6661 generate_collation_name(attcollation));
6665 appendStringInfoChar(buf, ')');
6669 * get_opclass_name - fetch name of an index operator class
6671 * The opclass name is appended (after a space) to buf.
6673 * Output is suppressed if the opclass is the default for the given
6674 * actual_datatype. (If you don't want this behavior, just pass
6675 * InvalidOid for actual_datatype.)
6678 get_opclass_name(Oid opclass, Oid actual_datatype,
6682 Form_pg_opclass opcrec;
6686 ht_opc = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
6687 if (!HeapTupleIsValid(ht_opc))
6688 elog(ERROR, "cache lookup failed for opclass %u", opclass);
6689 opcrec = (Form_pg_opclass) GETSTRUCT(ht_opc);
6691 if (!OidIsValid(actual_datatype) ||
6692 GetDefaultOpClass(actual_datatype, opcrec->opcmethod) != opclass)
6694 /* Okay, we need the opclass name. Do we need to qualify it? */
6695 opcname = NameStr(opcrec->opcname);
6696 if (OpclassIsVisible(opclass))
6697 appendStringInfo(buf, " %s", quote_identifier(opcname));
6700 nspname = get_namespace_name(opcrec->opcnamespace);
6701 appendStringInfo(buf, " %s.%s",
6702 quote_identifier(nspname),
6703 quote_identifier(opcname));
6706 ReleaseSysCache(ht_opc);
6710 * processIndirection - take care of array and subfield assignment
6712 * We strip any top-level FieldStore or assignment ArrayRef nodes that
6713 * appear in the input, and return the subexpression that's to be assigned.
6714 * If printit is true, we also print out the appropriate decoration for the
6715 * base column name (that the caller just printed).
6718 processIndirection(Node *node, deparse_context *context, bool printit)
6720 StringInfo buf = context->buf;
6726 if (IsA(node, FieldStore))
6728 FieldStore *fstore = (FieldStore *) node;
6732 /* lookup tuple type */
6733 typrelid = get_typ_typrelid(fstore->resulttype);
6734 if (!OidIsValid(typrelid))
6735 elog(ERROR, "argument type %s of FieldStore is not a tuple type",
6736 format_type_be(fstore->resulttype));
6739 * Print the field name. There should only be one target field in
6740 * stored rules. There could be more than that in executable
6741 * target lists, but this function cannot be used for that case.
6743 Assert(list_length(fstore->fieldnums) == 1);
6744 fieldname = get_relid_attribute_name(typrelid,
6745 linitial_int(fstore->fieldnums));
6747 appendStringInfo(buf, ".%s", quote_identifier(fieldname));
6750 * We ignore arg since it should be an uninteresting reference to
6751 * the target column or subcolumn.
6753 node = (Node *) linitial(fstore->newvals);
6755 else if (IsA(node, ArrayRef))
6757 ArrayRef *aref = (ArrayRef *) node;
6759 if (aref->refassgnexpr == NULL)
6762 printSubscripts(aref, context);
6765 * We ignore refexpr since it should be an uninteresting reference
6766 * to the target column or subcolumn.
6768 node = (Node *) aref->refassgnexpr;
6778 printSubscripts(ArrayRef *aref, deparse_context *context)
6780 StringInfo buf = context->buf;
6781 ListCell *lowlist_item;
6782 ListCell *uplist_item;
6784 lowlist_item = list_head(aref->reflowerindexpr); /* could be NULL */
6785 foreach(uplist_item, aref->refupperindexpr)
6787 appendStringInfoChar(buf, '[');
6790 get_rule_expr((Node *) lfirst(lowlist_item), context, false);
6791 appendStringInfoChar(buf, ':');
6792 lowlist_item = lnext(lowlist_item);
6794 get_rule_expr((Node *) lfirst(uplist_item), context, false);
6795 appendStringInfoChar(buf, ']');
6800 * quote_identifier - Quote an identifier only if needed
6802 * When quotes are needed, we palloc the required space; slightly
6803 * space-wasteful but well worth it for notational simplicity.
6806 quote_identifier(const char *ident)
6809 * Can avoid quoting if ident starts with a lowercase letter or underscore
6810 * and contains only lowercase letters, digits, and underscores, *and* is
6811 * not any SQL keyword. Otherwise, supply quotes.
6820 * would like to use <ctype.h> macros here, but they might yield unwanted
6821 * locale-specific results...
6823 safe = ((ident[0] >= 'a' && ident[0] <= 'z') || ident[0] == '_');
6825 for (ptr = ident; *ptr; ptr++)
6829 if ((ch >= 'a' && ch <= 'z') ||
6830 (ch >= '0' && ch <= '9') ||
6843 if (quote_all_identifiers)
6849 * Check for keyword. We quote keywords except for unreserved ones.
6850 * (In some cases we could avoid quoting a col_name or type_func_name
6851 * keyword, but it seems much harder than it's worth to tell that.)
6853 * Note: ScanKeywordLookup() does case-insensitive comparison, but
6854 * that's fine, since we already know we have all-lower-case.
6856 const ScanKeyword *keyword = ScanKeywordLookup(ident,
6860 if (keyword != NULL && keyword->category != UNRESERVED_KEYWORD)
6865 return ident; /* no change needed */
6867 result = (char *) palloc(strlen(ident) + nquotes + 2 + 1);
6871 for (ptr = ident; *ptr; ptr++)
6886 * quote_qualified_identifier - Quote a possibly-qualified identifier
6888 * Return a name of the form qualifier.ident, or just ident if qualifier
6889 * is NULL, quoting each component if necessary. The result is palloc'd.
6892 quote_qualified_identifier(const char *qualifier,
6897 initStringInfo(&buf);
6899 appendStringInfo(&buf, "%s.", quote_identifier(qualifier));
6900 appendStringInfoString(&buf, quote_identifier(ident));
6906 * Get the unqualified name of a relation specified by OID
6908 * This differs from the underlying get_rel_name() function in that it will
6909 * throw error instead of silently returning NULL if the OID is bad.
6912 get_relation_name(Oid relid)
6914 char *relname = get_rel_name(relid);
6917 elog(ERROR, "cache lookup failed for relation %u", relid);
6922 * generate_relation_name
6923 * Compute the name to display for a relation specified by OID
6925 * The result includes all necessary quoting and schema-prefixing.
6927 * If namespaces isn't NIL, it must be a list of deparse_namespace nodes.
6928 * We will forcibly qualify the relation name if it equals any CTE name
6929 * visible in the namespace list.
6932 generate_relation_name(Oid relid, List *namespaces)
6935 Form_pg_class reltup;
6942 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
6943 if (!HeapTupleIsValid(tp))
6944 elog(ERROR, "cache lookup failed for relation %u", relid);
6945 reltup = (Form_pg_class) GETSTRUCT(tp);
6946 relname = NameStr(reltup->relname);
6948 /* Check for conflicting CTE name */
6950 foreach(nslist, namespaces)
6952 deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist);
6955 foreach(ctlist, dpns->ctes)
6957 CommonTableExpr *cte = (CommonTableExpr *) lfirst(ctlist);
6959 if (strcmp(cte->ctename, relname) == 0)
6969 /* Otherwise, qualify the name if not visible in search path */
6971 need_qual = !RelationIsVisible(relid);
6974 nspname = get_namespace_name(reltup->relnamespace);
6978 result = quote_qualified_identifier(nspname, relname);
6980 ReleaseSysCache(tp);
6986 * generate_function_name
6987 * Compute the name to display for a function specified by OID,
6988 * given that it is being called with the specified actual arg names and
6989 * types. (Those matter because of ambiguous-function resolution rules.)
6991 * The result includes all necessary quoting and schema-prefixing. We can
6992 * also pass back an indication of whether the function is variadic.
6995 generate_function_name(Oid funcid, int nargs, List *argnames,
6996 Oid *argtypes, bool *is_variadic)
6999 Form_pg_proc procform;
7003 FuncDetailCode p_result;
7008 Oid *p_true_typeids;
7010 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
7011 if (!HeapTupleIsValid(proctup))
7012 elog(ERROR, "cache lookup failed for function %u", funcid);
7013 procform = (Form_pg_proc) GETSTRUCT(proctup);
7014 proname = NameStr(procform->proname);
7017 * The idea here is to schema-qualify only if the parser would fail to
7018 * resolve the correct function given the unqualified func name with the
7019 * specified argtypes. If the function is variadic, we should presume
7020 * that VARIADIC will be included in the call.
7022 p_result = func_get_detail(list_make1(makeString(proname)),
7023 NIL, argnames, nargs, argtypes,
7024 !OidIsValid(procform->provariadic), true,
7025 &p_funcid, &p_rettype,
7026 &p_retset, &p_nvargs, &p_true_typeids, NULL);
7027 if ((p_result == FUNCDETAIL_NORMAL ||
7028 p_result == FUNCDETAIL_AGGREGATE ||
7029 p_result == FUNCDETAIL_WINDOWFUNC) &&
7033 nspname = get_namespace_name(procform->pronamespace);
7035 result = quote_qualified_identifier(nspname, proname);
7037 /* Check variadic-ness if caller cares */
7040 /* "any" variadics are not treated as variadics for listing */
7041 if (OidIsValid(procform->provariadic) &&
7042 procform->provariadic != ANYOID)
7043 *is_variadic = true;
7045 *is_variadic = false;
7048 ReleaseSysCache(proctup);
7054 * generate_operator_name
7055 * Compute the name to display for an operator specified by OID,
7056 * given that it is being called with the specified actual arg types.
7057 * (Arg types matter because of ambiguous-operator resolution rules.
7058 * Pass InvalidOid for unused arg of a unary operator.)
7060 * The result includes all necessary quoting and schema-prefixing,
7061 * plus the OPERATOR() decoration needed to use a qualified operator name
7065 generate_operator_name(Oid operid, Oid arg1, Oid arg2)
7069 Form_pg_operator operform;
7074 initStringInfo(&buf);
7076 opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operid));
7077 if (!HeapTupleIsValid(opertup))
7078 elog(ERROR, "cache lookup failed for operator %u", operid);
7079 operform = (Form_pg_operator) GETSTRUCT(opertup);
7080 oprname = NameStr(operform->oprname);
7083 * The idea here is to schema-qualify only if the parser would fail to
7084 * resolve the correct operator given the unqualified op name with the
7085 * specified argtypes.
7087 switch (operform->oprkind)
7090 p_result = oper(NULL, list_make1(makeString(oprname)), arg1, arg2,
7094 p_result = left_oper(NULL, list_make1(makeString(oprname)), arg2,
7098 p_result = right_oper(NULL, list_make1(makeString(oprname)), arg1,
7102 elog(ERROR, "unrecognized oprkind: %d", operform->oprkind);
7103 p_result = NULL; /* keep compiler quiet */
7107 if (p_result != NULL && oprid(p_result) == operid)
7111 nspname = get_namespace_name(operform->oprnamespace);
7112 appendStringInfo(&buf, "OPERATOR(%s.", quote_identifier(nspname));
7115 appendStringInfoString(&buf, oprname);
7118 appendStringInfoChar(&buf, ')');
7120 if (p_result != NULL)
7121 ReleaseSysCache(p_result);
7123 ReleaseSysCache(opertup);
7129 * generate_collation_name
7130 * Compute the name to display for a collation specified by OID
7132 * The result includes all necessary quoting and schema-prefixing.
7135 generate_collation_name(Oid collid)
7138 Form_pg_collation colltup;
7143 tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
7144 if (!HeapTupleIsValid(tp))
7145 elog(ERROR, "cache lookup failed for collation %u", collid);
7146 colltup = (Form_pg_collation) GETSTRUCT(tp);
7147 collname = NameStr(colltup->collname);
7149 if (!CollationIsVisible(collid))
7150 nspname = get_namespace_name(colltup->collnamespace);
7154 result = quote_qualified_identifier(nspname, collname);
7156 ReleaseSysCache(tp);
7162 * Given a C string, produce a TEXT datum.
7164 * We assume that the input was palloc'd and may be freed.
7167 string_to_text(char *str)
7171 result = cstring_to_text(str);
7177 * Generate a C string representing a relation's reloptions, or NULL if none.
7180 flatten_reloptions(Oid relid)
7182 char *result = NULL;
7187 tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
7188 if (!HeapTupleIsValid(tuple))
7189 elog(ERROR, "cache lookup failed for relation %u", relid);
7191 reloptions = SysCacheGetAttr(RELOID, tuple,
7192 Anum_pg_class_reloptions, &isnull);
7199 * We want to use array_to_text(reloptions, ', ') --- but
7200 * DirectFunctionCall2(array_to_text) does not work, because
7201 * array_to_text() relies on flinfo to be valid. So use
7204 sep = CStringGetTextDatum(", ");
7205 txt = OidFunctionCall2(F_ARRAY_TO_TEXT, reloptions, sep);
7206 result = TextDatumGetCString(txt);
7209 ReleaseSysCache(tuple);