1 /*-------------------------------------------------------------------------
4 * Functions to convert stored expressions/querytrees back to
7 * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
12 * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.324 2010/02/18 22:43:31 tgl Exp $
14 *-------------------------------------------------------------------------
21 #include "access/genam.h"
22 #include "access/sysattr.h"
23 #include "catalog/dependency.h"
24 #include "catalog/indexing.h"
25 #include "catalog/pg_authid.h"
26 #include "catalog/pg_constraint.h"
27 #include "catalog/pg_depend.h"
28 #include "catalog/pg_language.h"
29 #include "catalog/pg_opclass.h"
30 #include "catalog/pg_operator.h"
31 #include "catalog/pg_proc.h"
32 #include "catalog/pg_trigger.h"
33 #include "catalog/pg_type.h"
34 #include "commands/defrem.h"
35 #include "commands/tablespace.h"
36 #include "executor/spi.h"
38 #include "nodes/makefuncs.h"
39 #include "nodes/nodeFuncs.h"
40 #include "optimizer/clauses.h"
41 #include "optimizer/tlist.h"
42 #include "parser/keywords.h"
43 #include "parser/parse_func.h"
44 #include "parser/parse_oper.h"
45 #include "parser/parser.h"
46 #include "parser/parsetree.h"
47 #include "rewrite/rewriteHandler.h"
48 #include "rewrite/rewriteManip.h"
49 #include "rewrite/rewriteSupport.h"
50 #include "utils/array.h"
51 #include "utils/builtins.h"
52 #include "utils/fmgroids.h"
53 #include "utils/lsyscache.h"
54 #include "utils/tqual.h"
55 #include "utils/syscache.h"
56 #include "utils/typcache.h"
57 #include "utils/xml.h"
61 * Pretty formatting constants
66 #define PRETTYINDENT_STD 8
67 #define PRETTYINDENT_JOIN 13
68 #define PRETTYINDENT_JOIN_ON (PRETTYINDENT_JOIN-PRETTYINDENT_STD)
69 #define PRETTYINDENT_VAR 4
72 #define PRETTYFLAG_PAREN 1
73 #define PRETTYFLAG_INDENT 2
75 /* macro to test if pretty action needed */
76 #define PRETTY_PAREN(context) ((context)->prettyFlags & PRETTYFLAG_PAREN)
77 #define PRETTY_INDENT(context) ((context)->prettyFlags & PRETTYFLAG_INDENT)
85 /* Context info needed for invoking a recursive querytree display routine */
88 StringInfo buf; /* output buffer to append to */
89 List *namespaces; /* List of deparse_namespace nodes */
90 List *windowClause; /* Current query level's WINDOW clause */
91 List *windowTList; /* targetlist for resolving WINDOW clause */
92 int prettyFlags; /* enabling of pretty-print functions */
93 int indentLevel; /* current indent level for prettyprint */
94 bool varprefix; /* TRUE to print prefixes on Vars */
98 * Each level of query context around a subtree needs a level of Var namespace.
99 * A Var having varlevelsup=N refers to the N'th item (counting from 0) in
100 * the current context's namespaces list.
102 * The rangetable is the list of actual RTEs from the query tree, and the
103 * cte list is the list of actual CTEs.
105 * For deparsing plan trees, we provide for outer and inner subplan nodes.
106 * The tlists of these nodes are used to resolve OUTER and INNER varnos.
107 * Also, in the plan-tree case we don't have access to the parse-time CTE
108 * list, so we need a list of subplans instead.
112 List *rtable; /* List of RangeTblEntry nodes */
113 List *ctes; /* List of CommonTableExpr nodes */
114 List *subplans; /* List of subplans, in plan-tree case */
115 Plan *outer_plan; /* OUTER subplan, or NULL if none */
116 Plan *inner_plan; /* INNER subplan, or NULL if none */
124 static SPIPlanPtr plan_getrulebyoid = NULL;
125 static const char *query_getrulebyoid = "SELECT * FROM pg_catalog.pg_rewrite WHERE oid = $1";
126 static SPIPlanPtr plan_getviewrule = NULL;
127 static const char *query_getviewrule = "SELECT * FROM pg_catalog.pg_rewrite WHERE ev_class = $1 AND rulename = $2";
133 * Most of these functions used to use fixed-size buffers to build their
134 * results. Now, they take an (already initialized) StringInfo object
135 * as a parameter, and append their text output to its contents.
138 static char *deparse_expression_pretty(Node *expr, List *dpcontext,
139 bool forceprefix, bool showimplicit,
140 int prettyFlags, int startIndent);
141 static char *pg_get_viewdef_worker(Oid viewoid, int prettyFlags);
142 static char *pg_get_triggerdef_worker(Oid trigid, bool pretty);
143 static void decompile_column_index_array(Datum column_index_array, Oid relId,
145 static char *pg_get_ruledef_worker(Oid ruleoid, int prettyFlags);
146 static char *pg_get_indexdef_worker(Oid indexrelid, int colno,
147 const Oid *excludeOps,
148 bool attrsOnly, bool showTblSpc,
150 static char *pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
152 static text *pg_get_expr_worker(text *expr, Oid relid, const char *relname,
154 static int print_function_arguments(StringInfo buf, HeapTuple proctup,
155 bool print_table_args, bool print_defaults);
156 static void print_function_rettype(StringInfo buf, HeapTuple proctup);
157 static void make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
159 static void make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
161 static void get_query_def(Query *query, StringInfo buf, List *parentnamespace,
162 TupleDesc resultDesc, int prettyFlags, int startIndent);
163 static void get_values_def(List *values_lists, deparse_context *context);
164 static void get_with_clause(Query *query, deparse_context *context);
165 static void get_select_query_def(Query *query, deparse_context *context,
166 TupleDesc resultDesc);
167 static void get_insert_query_def(Query *query, deparse_context *context);
168 static void get_update_query_def(Query *query, deparse_context *context);
169 static void get_delete_query_def(Query *query, deparse_context *context);
170 static void get_utility_query_def(Query *query, deparse_context *context);
171 static void get_basic_select_query(Query *query, deparse_context *context,
172 TupleDesc resultDesc);
173 static void get_target_list(List *targetList, deparse_context *context,
174 TupleDesc resultDesc);
175 static void get_setop_query(Node *setOp, Query *query,
176 deparse_context *context,
177 TupleDesc resultDesc);
178 static Node *get_rule_sortgroupclause(SortGroupClause *srt, List *tlist,
180 deparse_context *context);
181 static void get_rule_orderby(List *orderList, List *targetList,
182 bool force_colno, deparse_context *context);
183 static void get_rule_windowclause(Query *query, deparse_context *context);
184 static void get_rule_windowspec(WindowClause *wc, List *targetList,
185 deparse_context *context);
186 static void push_plan(deparse_namespace *dpns, Plan *subplan);
187 static char *get_variable(Var *var, int levelsup, bool showstar,
188 deparse_context *context);
189 static RangeTblEntry *find_rte_by_refname(const char *refname,
190 deparse_context *context);
191 static const char *get_simple_binary_op_name(OpExpr *expr);
192 static bool isSimpleNode(Node *node, Node *parentNode, int prettyFlags);
193 static void appendContextKeyword(deparse_context *context, const char *str,
194 int indentBefore, int indentAfter, int indentPlus);
195 static void get_rule_expr(Node *node, deparse_context *context,
197 static void get_oper_expr(OpExpr *expr, deparse_context *context);
198 static void get_func_expr(FuncExpr *expr, deparse_context *context,
200 static void get_agg_expr(Aggref *aggref, deparse_context *context);
201 static void get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context);
202 static void get_coercion_expr(Node *arg, deparse_context *context,
203 Oid resulttype, int32 resulttypmod,
205 static void get_const_expr(Const *constval, deparse_context *context,
207 static void simple_quote_literal(StringInfo buf, const char *val);
208 static void get_sublink_expr(SubLink *sublink, deparse_context *context);
209 static void get_from_clause(Query *query, const char *prefix,
210 deparse_context *context);
211 static void get_from_clause_item(Node *jtnode, Query *query,
212 deparse_context *context);
213 static void get_from_clause_alias(Alias *alias, RangeTblEntry *rte,
214 deparse_context *context);
215 static void get_from_clause_coldeflist(List *names, List *types, List *typmods,
216 deparse_context *context);
217 static void get_opclass_name(Oid opclass, Oid actual_datatype,
219 static Node *processIndirection(Node *node, deparse_context *context,
221 static void printSubscripts(ArrayRef *aref, deparse_context *context);
222 static char *generate_relation_name(Oid relid, List *namespaces);
223 static char *generate_function_name(Oid funcid, int nargs, List *argnames,
224 Oid *argtypes, bool *is_variadic);
225 static char *generate_operator_name(Oid operid, Oid arg1, Oid arg2);
226 static text *string_to_text(char *str);
227 static char *flatten_reloptions(Oid relid);
229 #define only_marker(rte) ((rte)->inh ? "" : "ONLY ")
233 * get_ruledef - Do it all and return a text
234 * that could be used as a statement
235 * to recreate the rule
239 pg_get_ruledef(PG_FUNCTION_ARGS)
241 Oid ruleoid = PG_GETARG_OID(0);
243 PG_RETURN_TEXT_P(string_to_text(pg_get_ruledef_worker(ruleoid, 0)));
248 pg_get_ruledef_ext(PG_FUNCTION_ARGS)
250 Oid ruleoid = PG_GETARG_OID(0);
251 bool pretty = PG_GETARG_BOOL(1);
254 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
255 PG_RETURN_TEXT_P(string_to_text(pg_get_ruledef_worker(ruleoid, prettyFlags)));
260 pg_get_ruledef_worker(Oid ruleoid, int prettyFlags)
270 * Do this first so that string is alloc'd in outer context not SPI's.
272 initStringInfo(&buf);
275 * Connect to SPI manager
277 if (SPI_connect() != SPI_OK_CONNECT)
278 elog(ERROR, "SPI_connect failed");
281 * On the first call prepare the plan to lookup pg_rewrite. We read
282 * pg_rewrite over the SPI manager instead of using the syscache to be
283 * checked for read access on pg_rewrite.
285 if (plan_getrulebyoid == NULL)
290 argtypes[0] = OIDOID;
291 plan = SPI_prepare(query_getrulebyoid, 1, argtypes);
293 elog(ERROR, "SPI_prepare failed for \"%s\"", query_getrulebyoid);
294 plan_getrulebyoid = SPI_saveplan(plan);
298 * Get the pg_rewrite tuple for this rule
300 args[0] = ObjectIdGetDatum(ruleoid);
302 spirc = SPI_execute_plan(plan_getrulebyoid, args, nulls, true, 1);
303 if (spirc != SPI_OK_SELECT)
304 elog(ERROR, "failed to get pg_rewrite tuple for rule %u", ruleoid);
305 if (SPI_processed != 1)
306 appendStringInfo(&buf, "-");
310 * Get the rule's definition and put it into executor's memory
312 ruletup = SPI_tuptable->vals[0];
313 rulettc = SPI_tuptable->tupdesc;
314 make_ruledef(&buf, ruletup, rulettc, prettyFlags);
318 * Disconnect from SPI manager
320 if (SPI_finish() != SPI_OK_FINISH)
321 elog(ERROR, "SPI_finish failed");
328 * get_viewdef - Mainly the same thing, but we
329 * only return the SELECT part of a view
333 pg_get_viewdef(PG_FUNCTION_ARGS)
336 Oid viewoid = PG_GETARG_OID(0);
338 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, 0)));
343 pg_get_viewdef_ext(PG_FUNCTION_ARGS)
346 Oid viewoid = PG_GETARG_OID(0);
347 bool pretty = PG_GETARG_BOOL(1);
350 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
351 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, prettyFlags)));
355 pg_get_viewdef_name(PG_FUNCTION_ARGS)
357 /* By qualified name */
358 text *viewname = PG_GETARG_TEXT_P(0);
362 viewrel = makeRangeVarFromNameList(textToQualifiedNameList(viewname));
363 viewoid = RangeVarGetRelid(viewrel, false);
365 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, 0)));
370 pg_get_viewdef_name_ext(PG_FUNCTION_ARGS)
372 /* By qualified name */
373 text *viewname = PG_GETARG_TEXT_P(0);
374 bool pretty = PG_GETARG_BOOL(1);
379 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
380 viewrel = makeRangeVarFromNameList(textToQualifiedNameList(viewname));
381 viewoid = RangeVarGetRelid(viewrel, false);
383 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, prettyFlags)));
387 * Common code for by-OID and by-name variants of pg_get_viewdef
390 pg_get_viewdef_worker(Oid viewoid, int prettyFlags)
400 * Do this first so that string is alloc'd in outer context not SPI's.
402 initStringInfo(&buf);
405 * Connect to SPI manager
407 if (SPI_connect() != SPI_OK_CONNECT)
408 elog(ERROR, "SPI_connect failed");
411 * On the first call prepare the plan to lookup pg_rewrite. We read
412 * pg_rewrite over the SPI manager instead of using the syscache to be
413 * checked for read access on pg_rewrite.
415 if (plan_getviewrule == NULL)
420 argtypes[0] = OIDOID;
421 argtypes[1] = NAMEOID;
422 plan = SPI_prepare(query_getviewrule, 2, argtypes);
424 elog(ERROR, "SPI_prepare failed for \"%s\"", query_getviewrule);
425 plan_getviewrule = SPI_saveplan(plan);
429 * Get the pg_rewrite tuple for the view's SELECT rule
431 args[0] = ObjectIdGetDatum(viewoid);
432 args[1] = PointerGetDatum(ViewSelectRuleName);
435 spirc = SPI_execute_plan(plan_getviewrule, args, nulls, true, 2);
436 if (spirc != SPI_OK_SELECT)
437 elog(ERROR, "failed to get pg_rewrite tuple for view %u", viewoid);
438 if (SPI_processed != 1)
439 appendStringInfo(&buf, "Not a view");
443 * Get the rule's definition and put it into executor's memory
445 ruletup = SPI_tuptable->vals[0];
446 rulettc = SPI_tuptable->tupdesc;
447 make_viewdef(&buf, ruletup, rulettc, prettyFlags);
451 * Disconnect from SPI manager
453 if (SPI_finish() != SPI_OK_FINISH)
454 elog(ERROR, "SPI_finish failed");
460 * get_triggerdef - Get the definition of a trigger
464 pg_get_triggerdef(PG_FUNCTION_ARGS)
466 Oid trigid = PG_GETARG_OID(0);
468 PG_RETURN_TEXT_P(string_to_text(pg_get_triggerdef_worker(trigid, false)));
472 pg_get_triggerdef_ext(PG_FUNCTION_ARGS)
474 Oid trigid = PG_GETARG_OID(0);
475 bool pretty = PG_GETARG_BOOL(1);
477 PG_RETURN_TEXT_P(string_to_text(pg_get_triggerdef_worker(trigid, pretty)));
481 pg_get_triggerdef_worker(Oid trigid, bool pretty)
484 Form_pg_trigger trigrec;
495 * Fetch the pg_trigger tuple by the Oid of the trigger
497 tgrel = heap_open(TriggerRelationId, AccessShareLock);
499 ScanKeyInit(&skey[0],
500 ObjectIdAttributeNumber,
501 BTEqualStrategyNumber, F_OIDEQ,
502 ObjectIdGetDatum(trigid));
504 tgscan = systable_beginscan(tgrel, TriggerOidIndexId, true,
505 SnapshotNow, 1, skey);
507 ht_trig = systable_getnext(tgscan);
509 if (!HeapTupleIsValid(ht_trig))
510 elog(ERROR, "could not find tuple for trigger %u", trigid);
512 trigrec = (Form_pg_trigger) GETSTRUCT(ht_trig);
515 * Start the trigger definition. Note that the trigger's name should never
516 * be schema-qualified, but the trigger rel's name may be.
518 initStringInfo(&buf);
520 tgname = NameStr(trigrec->tgname);
521 appendStringInfo(&buf, "CREATE %sTRIGGER %s ",
522 OidIsValid(trigrec->tgconstraint) ? "CONSTRAINT " : "",
523 quote_identifier(tgname));
525 if (TRIGGER_FOR_BEFORE(trigrec->tgtype))
526 appendStringInfo(&buf, "BEFORE");
528 appendStringInfo(&buf, "AFTER");
529 if (TRIGGER_FOR_INSERT(trigrec->tgtype))
531 appendStringInfo(&buf, " INSERT");
534 if (TRIGGER_FOR_DELETE(trigrec->tgtype))
537 appendStringInfo(&buf, " OR DELETE");
539 appendStringInfo(&buf, " DELETE");
542 if (TRIGGER_FOR_UPDATE(trigrec->tgtype))
545 appendStringInfo(&buf, " OR UPDATE");
547 appendStringInfo(&buf, " UPDATE");
549 /* tgattr is first var-width field, so OK to access directly */
550 if (trigrec->tgattr.dim1 > 0)
554 appendStringInfoString(&buf, " OF ");
555 for (i = 0; i < trigrec->tgattr.dim1; i++)
560 appendStringInfoString(&buf, ", ");
561 attname = get_relid_attribute_name(trigrec->tgrelid,
562 trigrec->tgattr.values[i]);
563 appendStringInfoString(&buf, quote_identifier(attname));
567 if (TRIGGER_FOR_TRUNCATE(trigrec->tgtype))
570 appendStringInfo(&buf, " OR TRUNCATE");
572 appendStringInfo(&buf, " TRUNCATE");
575 appendStringInfo(&buf, " ON %s ",
576 generate_relation_name(trigrec->tgrelid, NIL));
578 if (OidIsValid(trigrec->tgconstraint))
580 if (OidIsValid(trigrec->tgconstrrelid))
581 appendStringInfo(&buf, "FROM %s ",
582 generate_relation_name(trigrec->tgconstrrelid, NIL));
583 if (!trigrec->tgdeferrable)
584 appendStringInfo(&buf, "NOT ");
585 appendStringInfo(&buf, "DEFERRABLE INITIALLY ");
586 if (trigrec->tginitdeferred)
587 appendStringInfo(&buf, "DEFERRED ");
589 appendStringInfo(&buf, "IMMEDIATE ");
592 if (TRIGGER_FOR_ROW(trigrec->tgtype))
593 appendStringInfo(&buf, "FOR EACH ROW ");
595 appendStringInfo(&buf, "FOR EACH STATEMENT ");
597 /* If the trigger has a WHEN qualification, add that */
598 value = fastgetattr(ht_trig, Anum_pg_trigger_tgqual,
599 tgrel->rd_att, &isnull);
603 deparse_context context;
604 deparse_namespace dpns;
605 RangeTblEntry *oldrte;
606 RangeTblEntry *newrte;
608 appendStringInfoString(&buf, "WHEN (");
610 qual = stringToNode(TextDatumGetCString(value));
612 /* Build minimal OLD and NEW RTEs for the rel */
613 oldrte = makeNode(RangeTblEntry);
614 oldrte->rtekind = RTE_RELATION;
615 oldrte->relid = trigrec->tgrelid;
616 oldrte->eref = makeAlias("old", NIL);
618 oldrte->inFromCl = true;
620 newrte = makeNode(RangeTblEntry);
621 newrte->rtekind = RTE_RELATION;
622 newrte->relid = trigrec->tgrelid;
623 newrte->eref = makeAlias("new", NIL);
625 newrte->inFromCl = true;
627 /* Build two-element rtable */
628 dpns.rtable = list_make2(oldrte, newrte);
631 dpns.outer_plan = dpns.inner_plan = NULL;
633 /* Set up context with one-deep namespace stack */
635 context.namespaces = list_make1(&dpns);
636 context.windowClause = NIL;
637 context.windowTList = NIL;
638 context.varprefix = true;
639 context.prettyFlags = pretty ? PRETTYFLAG_PAREN : 0;
640 context.indentLevel = PRETTYINDENT_STD;
642 get_rule_expr(qual, &context, false);
644 appendStringInfo(&buf, ") ");
647 appendStringInfo(&buf, "EXECUTE PROCEDURE %s(",
648 generate_function_name(trigrec->tgfoid, 0,
651 if (trigrec->tgnargs > 0)
656 value = fastgetattr(ht_trig, Anum_pg_trigger_tgargs,
657 tgrel->rd_att, &isnull);
659 elog(ERROR, "tgargs is null for trigger %u", trigid);
660 p = (char *) VARDATA(DatumGetByteaP(value));
661 for (i = 0; i < trigrec->tgnargs; i++)
664 appendStringInfo(&buf, ", ");
665 simple_quote_literal(&buf, p);
666 /* advance p to next string embedded in tgargs */
673 /* We deliberately do not put semi-colon at end */
674 appendStringInfo(&buf, ")");
677 systable_endscan(tgscan);
679 heap_close(tgrel, AccessShareLock);
685 * get_indexdef - Get the definition of an index
687 * In the extended version, there is a colno argument as well as pretty bool.
688 * if colno == 0, we want a complete index definition.
689 * if colno > 0, we only want the Nth index key's variable or expression.
691 * Note that the SQL-function versions of this omit any info about the
692 * index tablespace; this is intentional because pg_dump wants it that way.
693 * However pg_get_indexdef_string() includes index tablespace if not default.
697 pg_get_indexdef(PG_FUNCTION_ARGS)
699 Oid indexrelid = PG_GETARG_OID(0);
701 PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, 0,
707 pg_get_indexdef_ext(PG_FUNCTION_ARGS)
709 Oid indexrelid = PG_GETARG_OID(0);
710 int32 colno = PG_GETARG_INT32(1);
711 bool pretty = PG_GETARG_BOOL(2);
714 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
715 PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, colno,
722 /* Internal version that returns a palloc'd C string */
724 pg_get_indexdef_string(Oid indexrelid)
726 return pg_get_indexdef_worker(indexrelid, 0, NULL, false, true, 0);
729 /* Internal version that just reports the column definitions */
731 pg_get_indexdef_columns(Oid indexrelid, bool pretty)
735 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
736 return pg_get_indexdef_worker(indexrelid, 0, NULL, true, false, prettyFlags);
740 * Internal workhorse to decompile an index definition.
742 * This is now used for exclusion constraints as well: if excludeOps is not
743 * NULL then it points to an array of exclusion operator OIDs.
746 pg_get_indexdef_worker(Oid indexrelid, int colno,
747 const Oid *excludeOps,
748 bool attrsOnly, bool showTblSpc,
751 /* might want a separate isConstraint parameter later */
752 bool isConstraint = (excludeOps != NULL);
756 Form_pg_index idxrec;
757 Form_pg_class idxrelrec;
760 ListCell *indexpr_item;
766 Datum indoptionDatum;
769 int2vector *indoption;
775 * Fetch the pg_index tuple by the Oid of the index
777 ht_idx = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexrelid));
778 if (!HeapTupleIsValid(ht_idx))
779 elog(ERROR, "cache lookup failed for index %u", indexrelid);
780 idxrec = (Form_pg_index) GETSTRUCT(ht_idx);
782 indrelid = idxrec->indrelid;
783 Assert(indexrelid == idxrec->indexrelid);
785 /* Must get indclass and indoption the hard way */
786 indclassDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
787 Anum_pg_index_indclass, &isnull);
789 indclass = (oidvector *) DatumGetPointer(indclassDatum);
790 indoptionDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
791 Anum_pg_index_indoption, &isnull);
793 indoption = (int2vector *) DatumGetPointer(indoptionDatum);
796 * Fetch the pg_class tuple of the index relation
798 ht_idxrel = SearchSysCache1(RELOID, ObjectIdGetDatum(indexrelid));
799 if (!HeapTupleIsValid(ht_idxrel))
800 elog(ERROR, "cache lookup failed for relation %u", indexrelid);
801 idxrelrec = (Form_pg_class) GETSTRUCT(ht_idxrel);
804 * Fetch the pg_am tuple of the index' access method
806 ht_am = SearchSysCache1(AMOID, ObjectIdGetDatum(idxrelrec->relam));
807 if (!HeapTupleIsValid(ht_am))
808 elog(ERROR, "cache lookup failed for access method %u",
810 amrec = (Form_pg_am) GETSTRUCT(ht_am);
813 * Get the index expressions, if any. (NOTE: we do not use the relcache
814 * versions of the expressions and predicate, because we want to display
815 * non-const-folded expressions.)
817 if (!heap_attisnull(ht_idx, Anum_pg_index_indexprs))
823 exprsDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
824 Anum_pg_index_indexprs, &isnull);
826 exprsString = TextDatumGetCString(exprsDatum);
827 indexprs = (List *) stringToNode(exprsString);
833 indexpr_item = list_head(indexprs);
835 context = deparse_context_for(get_rel_name(indrelid), indrelid);
838 * Start the index definition. Note that the index's name should never be
839 * schema-qualified, but the indexed rel's name may be.
841 initStringInfo(&buf);
846 appendStringInfo(&buf, "CREATE %sINDEX %s ON %s USING %s (",
847 idxrec->indisunique ? "UNIQUE " : "",
848 quote_identifier(NameStr(idxrelrec->relname)),
849 generate_relation_name(indrelid, NIL),
850 quote_identifier(NameStr(amrec->amname)));
851 else /* currently, must be EXCLUDE constraint */
852 appendStringInfo(&buf, "EXCLUDE USING %s (",
853 quote_identifier(NameStr(amrec->amname)));
857 * Report the indexed attributes
860 for (keyno = 0; keyno < idxrec->indnatts; keyno++)
862 AttrNumber attnum = idxrec->indkey.values[keyno];
863 int16 opt = indoption->values[keyno];
866 appendStringInfoString(&buf, sep);
871 /* Simple index column */
874 attname = get_relid_attribute_name(indrelid, attnum);
875 if (!colno || colno == keyno + 1)
876 appendStringInfoString(&buf, quote_identifier(attname));
877 keycoltype = get_atttype(indrelid, attnum);
881 /* expressional index */
884 if (indexpr_item == NULL)
885 elog(ERROR, "too few entries in indexprs list");
886 indexkey = (Node *) lfirst(indexpr_item);
887 indexpr_item = lnext(indexpr_item);
889 str = deparse_expression_pretty(indexkey, context, false, false,
891 if (!colno || colno == keyno + 1)
893 /* Need parens if it's not a bare function call */
894 if (indexkey && IsA(indexkey, FuncExpr) &&
895 ((FuncExpr *) indexkey)->funcformat == COERCE_EXPLICIT_CALL)
896 appendStringInfoString(&buf, str);
898 appendStringInfo(&buf, "(%s)", str);
900 keycoltype = exprType(indexkey);
903 if (!attrsOnly && (!colno || colno == keyno + 1))
905 /* Add the operator class name, if not default */
906 get_opclass_name(indclass->values[keyno], keycoltype, &buf);
908 /* Add options if relevant */
909 if (amrec->amcanorder)
911 /* if it supports sort ordering, report DESC and NULLS opts */
912 if (opt & INDOPTION_DESC)
914 appendStringInfo(&buf, " DESC");
915 /* NULLS FIRST is the default in this case */
916 if (!(opt & INDOPTION_NULLS_FIRST))
917 appendStringInfo(&buf, " NULLS LAST");
921 if (opt & INDOPTION_NULLS_FIRST)
922 appendStringInfo(&buf, " NULLS FIRST");
926 /* Add the exclusion operator if relevant */
927 if (excludeOps != NULL)
928 appendStringInfo(&buf, " WITH %s",
929 generate_operator_name(excludeOps[keyno],
937 appendStringInfoChar(&buf, ')');
940 * If it has options, append "WITH (options)"
942 str = flatten_reloptions(indexrelid);
945 appendStringInfo(&buf, " WITH (%s)", str);
950 * If it's in a nondefault tablespace, say so, but only if requested
956 tblspc = get_rel_tablespace(indexrelid);
957 if (OidIsValid(tblspc))
960 appendStringInfoString(&buf, " USING INDEX");
961 appendStringInfo(&buf, " TABLESPACE %s",
962 quote_identifier(get_tablespace_name(tblspc)));
967 * If it's a partial index, decompile and append the predicate
969 if (!heap_attisnull(ht_idx, Anum_pg_index_indpred))
976 /* Convert text string to node tree */
977 predDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
978 Anum_pg_index_indpred, &isnull);
980 predString = TextDatumGetCString(predDatum);
981 node = (Node *) stringToNode(predString);
985 str = deparse_expression_pretty(node, context, false, false,
988 appendStringInfo(&buf, " WHERE (%s)", str);
990 appendStringInfo(&buf, " WHERE %s", str);
995 ReleaseSysCache(ht_idx);
996 ReleaseSysCache(ht_idxrel);
997 ReleaseSysCache(ht_am);
1004 * pg_get_constraintdef
1006 * Returns the definition for the constraint, ie, everything that needs to
1007 * appear after "ALTER TABLE ... ADD CONSTRAINT <constraintname>".
1010 pg_get_constraintdef(PG_FUNCTION_ARGS)
1012 Oid constraintId = PG_GETARG_OID(0);
1014 PG_RETURN_TEXT_P(string_to_text(pg_get_constraintdef_worker(constraintId,
1019 pg_get_constraintdef_ext(PG_FUNCTION_ARGS)
1021 Oid constraintId = PG_GETARG_OID(0);
1022 bool pretty = PG_GETARG_BOOL(1);
1025 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
1026 PG_RETURN_TEXT_P(string_to_text(pg_get_constraintdef_worker(constraintId,
1027 false, prettyFlags)));
1030 /* Internal version that returns a palloc'd C string */
1032 pg_get_constraintdef_string(Oid constraintId)
1034 return pg_get_constraintdef_worker(constraintId, true, 0);
1038 pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
1042 Form_pg_constraint conForm;
1045 tup = SearchSysCache1(CONSTROID, ObjectIdGetDatum(constraintId));
1046 if (!HeapTupleIsValid(tup)) /* should not happen */
1047 elog(ERROR, "cache lookup failed for constraint %u", constraintId);
1048 conForm = (Form_pg_constraint) GETSTRUCT(tup);
1050 initStringInfo(&buf);
1052 if (fullCommand && OidIsValid(conForm->conrelid))
1054 appendStringInfo(&buf, "ALTER TABLE ONLY %s ADD CONSTRAINT %s ",
1055 generate_relation_name(conForm->conrelid, NIL),
1056 quote_identifier(NameStr(conForm->conname)));
1059 switch (conForm->contype)
1061 case CONSTRAINT_FOREIGN:
1067 /* Start off the constraint definition */
1068 appendStringInfo(&buf, "FOREIGN KEY (");
1070 /* Fetch and build referencing-column list */
1071 val = SysCacheGetAttr(CONSTROID, tup,
1072 Anum_pg_constraint_conkey, &isnull);
1074 elog(ERROR, "null conkey for constraint %u",
1077 decompile_column_index_array(val, conForm->conrelid, &buf);
1079 /* add foreign relation name */
1080 appendStringInfo(&buf, ") REFERENCES %s(",
1081 generate_relation_name(conForm->confrelid,
1084 /* Fetch and build referenced-column list */
1085 val = SysCacheGetAttr(CONSTROID, tup,
1086 Anum_pg_constraint_confkey, &isnull);
1088 elog(ERROR, "null confkey for constraint %u",
1091 decompile_column_index_array(val, conForm->confrelid, &buf);
1093 appendStringInfo(&buf, ")");
1095 /* Add match type */
1096 switch (conForm->confmatchtype)
1098 case FKCONSTR_MATCH_FULL:
1099 string = " MATCH FULL";
1101 case FKCONSTR_MATCH_PARTIAL:
1102 string = " MATCH PARTIAL";
1104 case FKCONSTR_MATCH_UNSPECIFIED:
1108 elog(ERROR, "unrecognized confmatchtype: %d",
1109 conForm->confmatchtype);
1110 string = ""; /* keep compiler quiet */
1113 appendStringInfoString(&buf, string);
1115 /* Add ON UPDATE and ON DELETE clauses, if needed */
1116 switch (conForm->confupdtype)
1118 case FKCONSTR_ACTION_NOACTION:
1119 string = NULL; /* suppress default */
1121 case FKCONSTR_ACTION_RESTRICT:
1122 string = "RESTRICT";
1124 case FKCONSTR_ACTION_CASCADE:
1127 case FKCONSTR_ACTION_SETNULL:
1128 string = "SET NULL";
1130 case FKCONSTR_ACTION_SETDEFAULT:
1131 string = "SET DEFAULT";
1134 elog(ERROR, "unrecognized confupdtype: %d",
1135 conForm->confupdtype);
1136 string = NULL; /* keep compiler quiet */
1140 appendStringInfo(&buf, " ON UPDATE %s", string);
1142 switch (conForm->confdeltype)
1144 case FKCONSTR_ACTION_NOACTION:
1145 string = NULL; /* suppress default */
1147 case FKCONSTR_ACTION_RESTRICT:
1148 string = "RESTRICT";
1150 case FKCONSTR_ACTION_CASCADE:
1153 case FKCONSTR_ACTION_SETNULL:
1154 string = "SET NULL";
1156 case FKCONSTR_ACTION_SETDEFAULT:
1157 string = "SET DEFAULT";
1160 elog(ERROR, "unrecognized confdeltype: %d",
1161 conForm->confdeltype);
1162 string = NULL; /* keep compiler quiet */
1166 appendStringInfo(&buf, " ON DELETE %s", string);
1170 case CONSTRAINT_PRIMARY:
1171 case CONSTRAINT_UNIQUE:
1177 /* Start off the constraint definition */
1178 if (conForm->contype == CONSTRAINT_PRIMARY)
1179 appendStringInfo(&buf, "PRIMARY KEY (");
1181 appendStringInfo(&buf, "UNIQUE (");
1183 /* Fetch and build target column list */
1184 val = SysCacheGetAttr(CONSTROID, tup,
1185 Anum_pg_constraint_conkey, &isnull);
1187 elog(ERROR, "null conkey for constraint %u",
1190 decompile_column_index_array(val, conForm->conrelid, &buf);
1192 appendStringInfo(&buf, ")");
1194 indexId = get_constraint_index(constraintId);
1196 /* XXX why do we only print these bits if fullCommand? */
1197 if (fullCommand && OidIsValid(indexId))
1199 char *options = flatten_reloptions(indexId);
1204 appendStringInfo(&buf, " WITH (%s)", options);
1208 tblspc = get_rel_tablespace(indexId);
1209 if (OidIsValid(tblspc))
1210 appendStringInfo(&buf, " USING INDEX TABLESPACE %s",
1211 quote_identifier(get_tablespace_name(tblspc)));
1216 case CONSTRAINT_CHECK:
1225 /* Fetch constraint expression in parsetree form */
1226 val = SysCacheGetAttr(CONSTROID, tup,
1227 Anum_pg_constraint_conbin, &isnull);
1229 elog(ERROR, "null conbin for constraint %u",
1232 conbin = TextDatumGetCString(val);
1233 expr = stringToNode(conbin);
1235 /* Set up deparsing context for Var nodes in constraint */
1236 if (conForm->conrelid != InvalidOid)
1238 /* relation constraint */
1239 context = deparse_context_for(get_rel_name(conForm->conrelid),
1244 /* domain constraint --- can't have Vars */
1248 consrc = deparse_expression_pretty(expr, context, false, false,
1252 * Now emit the constraint definition. There are cases where
1253 * the constraint expression will be fully parenthesized and
1254 * we don't need the outer parens ... but there are other
1255 * cases where we do need 'em. Be conservative for now.
1257 * Note that simply checking for leading '(' and trailing ')'
1258 * would NOT be good enough, consider "(x > 0) AND (y > 0)".
1260 appendStringInfo(&buf, "CHECK (%s)", consrc);
1264 case CONSTRAINT_TRIGGER:
1266 * There isn't an ALTER TABLE syntax for creating a user-defined
1267 * constraint trigger, but it seems better to print something
1268 * than throw an error; if we throw error then this function
1269 * couldn't safely be applied to all rows of pg_constraint.
1271 appendStringInfo(&buf, "TRIGGER");
1273 case CONSTRAINT_EXCLUSION:
1275 Oid indexOid = conForm->conindid;
1283 /* Extract operator OIDs from the pg_constraint tuple */
1284 val = SysCacheGetAttr(CONSTROID, tup,
1285 Anum_pg_constraint_conexclop,
1288 elog(ERROR, "null conexclop for constraint %u",
1291 deconstruct_array(DatumGetArrayTypeP(val),
1292 OIDOID, sizeof(Oid), true, 'i',
1293 &elems, NULL, &nElems);
1295 operators = (Oid *) palloc(nElems * sizeof(Oid));
1296 for (i = 0; i < nElems; i++)
1297 operators[i] = DatumGetObjectId(elems[i]);
1299 /* pg_get_indexdef_worker does the rest */
1300 /* suppress tablespace because pg_dump wants it that way */
1301 appendStringInfoString(&buf,
1302 pg_get_indexdef_worker(indexOid,
1311 elog(ERROR, "invalid constraint type \"%c\"", conForm->contype);
1315 if (conForm->condeferrable)
1316 appendStringInfo(&buf, " DEFERRABLE");
1317 if (conForm->condeferred)
1318 appendStringInfo(&buf, " INITIALLY DEFERRED");
1321 ReleaseSysCache(tup);
1328 * Convert an int16[] Datum into a comma-separated list of column names
1329 * for the indicated relation; append the list to buf.
1332 decompile_column_index_array(Datum column_index_array, Oid relId,
1339 /* Extract data from array of int16 */
1340 deconstruct_array(DatumGetArrayTypeP(column_index_array),
1341 INT2OID, 2, true, 's',
1342 &keys, NULL, &nKeys);
1344 for (j = 0; j < nKeys; j++)
1348 colName = get_relid_attribute_name(relId, DatumGetInt16(keys[j]));
1351 appendStringInfoString(buf, quote_identifier(colName));
1353 appendStringInfo(buf, ", %s", quote_identifier(colName));
1359 * get_expr - Decompile an expression tree
1361 * Input: an expression tree in nodeToString form, and a relation OID
1363 * Output: reverse-listed expression
1365 * Currently, the expression can only refer to a single relation, namely
1366 * the one specified by the second parameter. This is sufficient for
1367 * partial indexes, column default expressions, etc. We also support
1368 * Var-free expressions, for which the OID can be InvalidOid.
1372 pg_get_expr(PG_FUNCTION_ARGS)
1374 text *expr = PG_GETARG_TEXT_P(0);
1375 Oid relid = PG_GETARG_OID(1);
1378 if (OidIsValid(relid))
1380 /* Get the name for the relation */
1381 relname = get_rel_name(relid);
1384 * If the OID isn't actually valid, don't throw an error, just return
1385 * NULL. This is a bit questionable, but it's what we've done
1386 * historically, and it can help avoid unwanted failures when
1387 * examining catalog entries for just-deleted relations.
1389 if (relname == NULL)
1395 PG_RETURN_TEXT_P(pg_get_expr_worker(expr, relid, relname, 0));
1399 pg_get_expr_ext(PG_FUNCTION_ARGS)
1401 text *expr = PG_GETARG_TEXT_P(0);
1402 Oid relid = PG_GETARG_OID(1);
1403 bool pretty = PG_GETARG_BOOL(2);
1407 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
1409 if (OidIsValid(relid))
1411 /* Get the name for the relation */
1412 relname = get_rel_name(relid);
1413 /* See notes above */
1414 if (relname == NULL)
1420 PG_RETURN_TEXT_P(pg_get_expr_worker(expr, relid, relname, prettyFlags));
1424 pg_get_expr_worker(text *expr, Oid relid, const char *relname, int prettyFlags)
1431 /* Convert input TEXT object to C string */
1432 exprstr = text_to_cstring(expr);
1434 /* Convert expression to node tree */
1435 node = (Node *) stringToNode(exprstr);
1439 /* Prepare deparse context if needed */
1440 if (OidIsValid(relid))
1441 context = deparse_context_for(relname, relid);
1446 str = deparse_expression_pretty(node, context, false, false,
1449 return string_to_text(str);
1454 * get_userbyid - Get a user name by roleid and
1455 * fallback to 'unknown (OID=n)'
1459 pg_get_userbyid(PG_FUNCTION_ARGS)
1461 Oid roleid = PG_GETARG_OID(0);
1464 Form_pg_authid role_rec;
1467 * Allocate space for the result
1469 result = (Name) palloc(NAMEDATALEN);
1470 memset(NameStr(*result), 0, NAMEDATALEN);
1473 * Get the pg_authid entry and print the result
1475 roletup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
1476 if (HeapTupleIsValid(roletup))
1478 role_rec = (Form_pg_authid) GETSTRUCT(roletup);
1479 StrNCpy(NameStr(*result), NameStr(role_rec->rolname), NAMEDATALEN);
1480 ReleaseSysCache(roletup);
1483 sprintf(NameStr(*result), "unknown (OID=%u)", roleid);
1485 PG_RETURN_NAME(result);
1490 * pg_get_serial_sequence
1491 * Get the name of the sequence used by a serial column,
1492 * formatted suitably for passing to setval, nextval or currval.
1493 * First parameter is not treated as double-quoted, second parameter
1494 * is --- see documentation for reason.
1497 pg_get_serial_sequence(PG_FUNCTION_ARGS)
1499 text *tablename = PG_GETARG_TEXT_P(0);
1500 text *columnname = PG_GETARG_TEXT_PP(1);
1505 Oid sequenceId = InvalidOid;
1511 /* Get the OID of the table */
1512 tablerv = makeRangeVarFromNameList(textToQualifiedNameList(tablename));
1513 tableOid = RangeVarGetRelid(tablerv, false);
1515 /* Get the number of the column */
1516 column = text_to_cstring(columnname);
1518 attnum = get_attnum(tableOid, column);
1519 if (attnum == InvalidAttrNumber)
1521 (errcode(ERRCODE_UNDEFINED_COLUMN),
1522 errmsg("column \"%s\" of relation \"%s\" does not exist",
1523 column, tablerv->relname)));
1525 /* Search the dependency table for the dependent sequence */
1526 depRel = heap_open(DependRelationId, AccessShareLock);
1528 ScanKeyInit(&key[0],
1529 Anum_pg_depend_refclassid,
1530 BTEqualStrategyNumber, F_OIDEQ,
1531 ObjectIdGetDatum(RelationRelationId));
1532 ScanKeyInit(&key[1],
1533 Anum_pg_depend_refobjid,
1534 BTEqualStrategyNumber, F_OIDEQ,
1535 ObjectIdGetDatum(tableOid));
1536 ScanKeyInit(&key[2],
1537 Anum_pg_depend_refobjsubid,
1538 BTEqualStrategyNumber, F_INT4EQ,
1539 Int32GetDatum(attnum));
1541 scan = systable_beginscan(depRel, DependReferenceIndexId, true,
1542 SnapshotNow, 3, key);
1544 while (HeapTupleIsValid(tup = systable_getnext(scan)))
1546 Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
1549 * We assume any auto dependency of a sequence on a column must be
1550 * what we are looking for. (We need the relkind test because indexes
1551 * can also have auto dependencies on columns.)
1553 if (deprec->classid == RelationRelationId &&
1554 deprec->objsubid == 0 &&
1555 deprec->deptype == DEPENDENCY_AUTO &&
1556 get_rel_relkind(deprec->objid) == RELKIND_SEQUENCE)
1558 sequenceId = deprec->objid;
1563 systable_endscan(scan);
1564 heap_close(depRel, AccessShareLock);
1566 if (OidIsValid(sequenceId))
1569 Form_pg_class classtuple;
1573 /* Get the sequence's pg_class entry */
1574 classtup = SearchSysCache1(RELOID, ObjectIdGetDatum(sequenceId));
1575 if (!HeapTupleIsValid(classtup))
1576 elog(ERROR, "cache lookup failed for relation %u", sequenceId);
1577 classtuple = (Form_pg_class) GETSTRUCT(classtup);
1579 /* Get the namespace */
1580 nspname = get_namespace_name(classtuple->relnamespace);
1582 elog(ERROR, "cache lookup failed for namespace %u",
1583 classtuple->relnamespace);
1585 /* And construct the result string */
1586 result = quote_qualified_identifier(nspname,
1587 NameStr(classtuple->relname));
1589 ReleaseSysCache(classtup);
1591 PG_RETURN_TEXT_P(string_to_text(result));
1599 * pg_get_functiondef
1600 * Returns the complete "CREATE OR REPLACE FUNCTION ..." statement for
1601 * the specified function.
1604 pg_get_functiondef(PG_FUNCTION_ARGS)
1606 Oid funcid = PG_GETARG_OID(0);
1612 Form_pg_language lang;
1621 initStringInfo(&buf);
1623 /* Look up the function */
1624 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1625 if (!HeapTupleIsValid(proctup))
1626 elog(ERROR, "cache lookup failed for function %u", funcid);
1627 proc = (Form_pg_proc) GETSTRUCT(proctup);
1628 name = NameStr(proc->proname);
1632 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1633 errmsg("\"%s\" is an aggregate function", name)));
1635 /* Need its pg_language tuple for the language name */
1636 langtup = SearchSysCache1(LANGOID, ObjectIdGetDatum(proc->prolang));
1637 if (!HeapTupleIsValid(langtup))
1638 elog(ERROR, "cache lookup failed for language %u", proc->prolang);
1639 lang = (Form_pg_language) GETSTRUCT(langtup);
1642 * We always qualify the function name, to ensure the right function gets
1645 nsp = get_namespace_name(proc->pronamespace);
1646 appendStringInfo(&buf, "CREATE OR REPLACE FUNCTION %s(",
1647 quote_qualified_identifier(nsp, name));
1648 (void) print_function_arguments(&buf, proctup, false, true);
1649 appendStringInfoString(&buf, ")\n RETURNS ");
1650 print_function_rettype(&buf, proctup);
1651 appendStringInfo(&buf, "\n LANGUAGE %s\n",
1652 quote_identifier(NameStr(lang->lanname)));
1654 /* Emit some miscellaneous options on one line */
1657 if (proc->proiswindow)
1658 appendStringInfoString(&buf, " WINDOW");
1659 switch (proc->provolatile)
1661 case PROVOLATILE_IMMUTABLE:
1662 appendStringInfoString(&buf, " IMMUTABLE");
1664 case PROVOLATILE_STABLE:
1665 appendStringInfoString(&buf, " STABLE");
1667 case PROVOLATILE_VOLATILE:
1670 if (proc->proisstrict)
1671 appendStringInfoString(&buf, " STRICT");
1672 if (proc->prosecdef)
1673 appendStringInfoString(&buf, " SECURITY DEFINER");
1675 /* This code for the default cost and rows should match functioncmds.c */
1676 if (proc->prolang == INTERNALlanguageId ||
1677 proc->prolang == ClanguageId)
1681 if (proc->procost != procost)
1682 appendStringInfo(&buf, " COST %g", proc->procost);
1684 if (proc->prorows > 0 && proc->prorows != 1000)
1685 appendStringInfo(&buf, " ROWS %g", proc->prorows);
1687 if (oldlen != buf.len)
1688 appendStringInfoChar(&buf, '\n');
1690 /* Emit any proconfig options, one per line */
1691 tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_proconfig, &isnull);
1694 ArrayType *a = DatumGetArrayTypeP(tmp);
1697 Assert(ARR_ELEMTYPE(a) == TEXTOID);
1698 Assert(ARR_NDIM(a) == 1);
1699 Assert(ARR_LBOUND(a)[0] == 1);
1701 for (i = 1; i <= ARR_DIMS(a)[0]; i++)
1705 d = array_ref(a, 1, &i,
1706 -1 /* varlenarray */ ,
1707 -1 /* TEXT's typlen */ ,
1708 false /* TEXT's typbyval */ ,
1709 'i' /* TEXT's typalign */ ,
1713 char *configitem = TextDatumGetCString(d);
1716 pos = strchr(configitem, '=');
1721 appendStringInfo(&buf, " SET %s TO ",
1722 quote_identifier(configitem));
1725 * Some GUC variable names are 'LIST' type and hence must not
1728 if (pg_strcasecmp(configitem, "DateStyle") == 0
1729 || pg_strcasecmp(configitem, "search_path") == 0)
1730 appendStringInfoString(&buf, pos);
1732 simple_quote_literal(&buf, pos);
1733 appendStringInfoChar(&buf, '\n');
1738 /* And finally the function definition ... */
1739 appendStringInfoString(&buf, "AS ");
1741 tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_probin, &isnull);
1744 simple_quote_literal(&buf, TextDatumGetCString(tmp));
1745 appendStringInfoString(&buf, ", "); /* assume prosrc isn't null */
1748 tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_prosrc, &isnull);
1750 elog(ERROR, "null prosrc");
1751 prosrc = TextDatumGetCString(tmp);
1754 * We always use dollar quoting. Figure out a suitable delimiter.
1756 * Since the user is likely to be editing the function body string, we
1757 * shouldn't use a short delimiter that he might easily create a conflict
1758 * with. Hence prefer "$function$", but extend if needed.
1760 initStringInfo(&dq);
1761 appendStringInfoString(&dq, "$function");
1762 while (strstr(prosrc, dq.data) != NULL)
1763 appendStringInfoChar(&dq, 'x');
1764 appendStringInfoChar(&dq, '$');
1766 appendStringInfoString(&buf, dq.data);
1767 appendStringInfoString(&buf, prosrc);
1768 appendStringInfoString(&buf, dq.data);
1770 appendStringInfoString(&buf, "\n");
1772 ReleaseSysCache(langtup);
1773 ReleaseSysCache(proctup);
1775 PG_RETURN_TEXT_P(string_to_text(buf.data));
1779 * pg_get_function_arguments
1780 * Get a nicely-formatted list of arguments for a function.
1781 * This is everything that would go between the parentheses in
1785 pg_get_function_arguments(PG_FUNCTION_ARGS)
1787 Oid funcid = PG_GETARG_OID(0);
1791 initStringInfo(&buf);
1793 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1794 if (!HeapTupleIsValid(proctup))
1795 elog(ERROR, "cache lookup failed for function %u", funcid);
1797 (void) print_function_arguments(&buf, proctup, false, true);
1799 ReleaseSysCache(proctup);
1801 PG_RETURN_TEXT_P(string_to_text(buf.data));
1805 * pg_get_function_identity_arguments
1806 * Get a formatted list of arguments for a function.
1807 * This is everything that would go between the parentheses in
1808 * ALTER FUNCTION, etc. In particular, don't print defaults.
1811 pg_get_function_identity_arguments(PG_FUNCTION_ARGS)
1813 Oid funcid = PG_GETARG_OID(0);
1817 initStringInfo(&buf);
1819 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1820 if (!HeapTupleIsValid(proctup))
1821 elog(ERROR, "cache lookup failed for function %u", funcid);
1823 (void) print_function_arguments(&buf, proctup, false, false);
1825 ReleaseSysCache(proctup);
1827 PG_RETURN_TEXT_P(string_to_text(buf.data));
1831 * pg_get_function_result
1832 * Get a nicely-formatted version of the result type of a function.
1833 * This is what would appear after RETURNS in CREATE FUNCTION.
1836 pg_get_function_result(PG_FUNCTION_ARGS)
1838 Oid funcid = PG_GETARG_OID(0);
1842 initStringInfo(&buf);
1844 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1845 if (!HeapTupleIsValid(proctup))
1846 elog(ERROR, "cache lookup failed for function %u", funcid);
1848 print_function_rettype(&buf, proctup);
1850 ReleaseSysCache(proctup);
1852 PG_RETURN_TEXT_P(string_to_text(buf.data));
1856 * Guts of pg_get_function_result: append the function's return type
1857 * to the specified buffer.
1860 print_function_rettype(StringInfo buf, HeapTuple proctup)
1862 Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(proctup);
1864 StringInfoData rbuf;
1866 initStringInfo(&rbuf);
1868 if (proc->proretset)
1870 /* It might be a table function; try to print the arguments */
1871 appendStringInfoString(&rbuf, "TABLE(");
1872 ntabargs = print_function_arguments(&rbuf, proctup, true, false);
1874 appendStringInfoString(&rbuf, ")");
1876 resetStringInfo(&rbuf);
1881 /* Not a table function, so do the normal thing */
1882 if (proc->proretset)
1883 appendStringInfoString(&rbuf, "SETOF ");
1884 appendStringInfoString(&rbuf, format_type_be(proc->prorettype));
1887 appendStringInfoString(buf, rbuf.data);
1891 * Common code for pg_get_function_arguments and pg_get_function_result:
1892 * append the desired subset of arguments to buf. We print only TABLE
1893 * arguments when print_table_args is true, and all the others when it's false.
1894 * We print argument defaults only if print_defaults is true.
1895 * Function return value is the number of arguments printed.
1898 print_function_arguments(StringInfo buf, HeapTuple proctup,
1899 bool print_table_args, bool print_defaults)
1901 Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(proctup);
1909 ListCell *nextargdefault = NULL;
1912 numargs = get_func_arg_info(proctup,
1913 &argtypes, &argnames, &argmodes);
1915 nlackdefaults = numargs;
1916 if (print_defaults && proc->pronargdefaults > 0)
1918 Datum proargdefaults;
1921 proargdefaults = SysCacheGetAttr(PROCOID, proctup,
1922 Anum_pg_proc_proargdefaults,
1929 str = TextDatumGetCString(proargdefaults);
1930 argdefaults = (List *) stringToNode(str);
1931 Assert(IsA(argdefaults, List));
1933 nextargdefault = list_head(argdefaults);
1934 /* nlackdefaults counts only *input* arguments lacking defaults */
1935 nlackdefaults = proc->pronargs - list_length(argdefaults);
1941 for (i = 0; i < numargs; i++)
1943 Oid argtype = argtypes[i];
1944 char *argname = argnames ? argnames[i] : NULL;
1945 char argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
1946 const char *modename;
1955 case PROARGMODE_INOUT:
1956 modename = "INOUT ";
1959 case PROARGMODE_OUT:
1963 case PROARGMODE_VARIADIC:
1964 modename = "VARIADIC ";
1967 case PROARGMODE_TABLE:
1972 elog(ERROR, "invalid parameter mode '%c'", argmode);
1973 modename = NULL; /* keep compiler quiet */
1978 inputargno++; /* this is a 1-based counter */
1980 if (print_table_args != (argmode == PROARGMODE_TABLE))
1984 appendStringInfoString(buf, ", ");
1985 appendStringInfoString(buf, modename);
1986 if (argname && argname[0])
1987 appendStringInfo(buf, "%s ", quote_identifier(argname));
1988 appendStringInfoString(buf, format_type_be(argtype));
1989 if (print_defaults && isinput && inputargno > nlackdefaults)
1993 Assert(nextargdefault != NULL);
1994 expr = (Node *) lfirst(nextargdefault);
1995 nextargdefault = lnext(nextargdefault);
1997 appendStringInfo(buf, " DEFAULT %s",
1998 deparse_expression(expr, NIL, false, false));
2008 * deparse_expression - General utility for deparsing expressions
2010 * calls deparse_expression_pretty with all prettyPrinting disabled
2013 deparse_expression(Node *expr, List *dpcontext,
2014 bool forceprefix, bool showimplicit)
2016 return deparse_expression_pretty(expr, dpcontext, forceprefix,
2017 showimplicit, 0, 0);
2021 * deparse_expression_pretty - General utility for deparsing expressions
2023 * expr is the node tree to be deparsed. It must be a transformed expression
2024 * tree (ie, not the raw output of gram.y).
2026 * dpcontext is a list of deparse_namespace nodes representing the context
2027 * for interpreting Vars in the node tree.
2029 * forceprefix is TRUE to force all Vars to be prefixed with their table names.
2031 * showimplicit is TRUE to force all implicit casts to be shown explicitly.
2033 * tries to pretty up the output according to prettyFlags and startIndent.
2035 * The result is a palloc'd string.
2039 deparse_expression_pretty(Node *expr, List *dpcontext,
2040 bool forceprefix, bool showimplicit,
2041 int prettyFlags, int startIndent)
2044 deparse_context context;
2046 initStringInfo(&buf);
2048 context.namespaces = dpcontext;
2049 context.windowClause = NIL;
2050 context.windowTList = NIL;
2051 context.varprefix = forceprefix;
2052 context.prettyFlags = prettyFlags;
2053 context.indentLevel = startIndent;
2055 get_rule_expr(expr, &context, showimplicit);
2061 * deparse_context_for - Build deparse context for a single relation
2063 * Given the reference name (alias) and OID of a relation, build deparsing
2064 * context for an expression referencing only that relation (as varno 1,
2065 * varlevelsup 0). This is sufficient for many uses of deparse_expression.
2069 deparse_context_for(const char *aliasname, Oid relid)
2071 deparse_namespace *dpns;
2074 dpns = (deparse_namespace *) palloc(sizeof(deparse_namespace));
2076 /* Build a minimal RTE for the rel */
2077 rte = makeNode(RangeTblEntry);
2078 rte->rtekind = RTE_RELATION;
2080 rte->eref = makeAlias(aliasname, NIL);
2082 rte->inFromCl = true;
2084 /* Build one-element rtable */
2085 dpns->rtable = list_make1(rte);
2087 dpns->subplans = NIL;
2088 dpns->outer_plan = dpns->inner_plan = NULL;
2090 /* Return a one-deep namespace stack */
2091 return list_make1(dpns);
2095 * deparse_context_for_plan - Build deparse context for a plan node
2097 * When deparsing an expression in a Plan tree, we might have to resolve
2098 * OUTER or INNER references. To do this, the caller must provide the
2099 * parent Plan node. In the normal case of a join plan node, OUTER and
2100 * INNER references can be resolved by drilling down into the left and
2101 * right child plans. A special case is that a nestloop inner indexscan
2102 * might have OUTER Vars, but the outer side of the join is not a child
2103 * plan node. To handle such cases the outer plan node must be passed
2104 * separately. (Pass NULL for outer_plan otherwise.)
2106 * Note: plan and outer_plan really ought to be declared as "Plan *", but
2107 * we use "Node *" to avoid having to include plannodes.h in builtins.h.
2109 * The plan's rangetable list must also be passed. We actually prefer to use
2110 * the rangetable to resolve simple Vars, but the plan inputs are necessary
2111 * for Vars that reference expressions computed in subplan target lists.
2113 * We also need the list of subplans associated with the Plan tree; this
2114 * is for resolving references to CTE subplans.
2117 deparse_context_for_plan(Node *plan, Node *outer_plan,
2118 List *rtable, List *subplans)
2120 deparse_namespace *dpns;
2122 dpns = (deparse_namespace *) palloc(sizeof(deparse_namespace));
2124 dpns->rtable = rtable;
2126 dpns->subplans = subplans;
2129 * Set up outer_plan and inner_plan from the Plan node (this includes
2130 * various special cases for particular Plan types).
2132 push_plan(dpns, (Plan *) plan);
2135 * If outer_plan is given, that overrides whatever we got from the plan.
2138 dpns->outer_plan = (Plan *) outer_plan;
2140 /* Return a one-deep namespace stack */
2141 return list_make1(dpns);
2145 * make_ruledef - reconstruct the CREATE RULE command
2146 * for a given pg_rewrite tuple
2150 make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
2160 List *actions = NIL;
2166 * Get the attribute values from the rules tuple
2168 fno = SPI_fnumber(rulettc, "rulename");
2169 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
2171 rulename = NameStr(*(DatumGetName(dat)));
2173 fno = SPI_fnumber(rulettc, "ev_type");
2174 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
2176 ev_type = DatumGetChar(dat);
2178 fno = SPI_fnumber(rulettc, "ev_class");
2179 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
2181 ev_class = DatumGetObjectId(dat);
2183 fno = SPI_fnumber(rulettc, "ev_attr");
2184 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
2186 ev_attr = DatumGetInt16(dat);
2188 fno = SPI_fnumber(rulettc, "is_instead");
2189 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
2191 is_instead = DatumGetBool(dat);
2193 /* these could be nulls */
2194 fno = SPI_fnumber(rulettc, "ev_qual");
2195 ev_qual = SPI_getvalue(ruletup, rulettc, fno);
2197 fno = SPI_fnumber(rulettc, "ev_action");
2198 ev_action = SPI_getvalue(ruletup, rulettc, fno);
2199 if (ev_action != NULL)
2200 actions = (List *) stringToNode(ev_action);
2203 * Build the rules definition text
2205 appendStringInfo(buf, "CREATE RULE %s AS",
2206 quote_identifier(rulename));
2208 if (prettyFlags & PRETTYFLAG_INDENT)
2209 appendStringInfoString(buf, "\n ON ");
2211 appendStringInfoString(buf, " ON ");
2213 /* The event the rule is fired for */
2217 appendStringInfo(buf, "SELECT");
2221 appendStringInfo(buf, "UPDATE");
2225 appendStringInfo(buf, "INSERT");
2229 appendStringInfo(buf, "DELETE");
2234 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2235 errmsg("rule \"%s\" has unsupported event type %d",
2236 rulename, ev_type)));
2240 /* The relation the rule is fired on */
2241 appendStringInfo(buf, " TO %s", generate_relation_name(ev_class, NIL));
2243 appendStringInfo(buf, ".%s",
2244 quote_identifier(get_relid_attribute_name(ev_class,
2247 /* If the rule has an event qualification, add it */
2248 if (ev_qual == NULL)
2250 if (strlen(ev_qual) > 0 && strcmp(ev_qual, "<>") != 0)
2254 deparse_context context;
2255 deparse_namespace dpns;
2257 if (prettyFlags & PRETTYFLAG_INDENT)
2258 appendStringInfoString(buf, "\n ");
2259 appendStringInfo(buf, " WHERE ");
2261 qual = stringToNode(ev_qual);
2264 * We need to make a context for recognizing any Vars in the qual
2265 * (which can only be references to OLD and NEW). Use the rtable of
2266 * the first query in the action list for this purpose.
2268 query = (Query *) linitial(actions);
2271 * If the action is INSERT...SELECT, OLD/NEW have been pushed down
2272 * into the SELECT, and that's what we need to look at. (Ugly kluge
2273 * ... try to fix this when we redesign querytrees.)
2275 query = getInsertSelectQuery(query, NULL);
2277 /* Must acquire locks right away; see notes in get_query_def() */
2278 AcquireRewriteLocks(query, false);
2281 context.namespaces = list_make1(&dpns);
2282 context.windowClause = NIL;
2283 context.windowTList = NIL;
2284 context.varprefix = (list_length(query->rtable) != 1);
2285 context.prettyFlags = prettyFlags;
2286 context.indentLevel = PRETTYINDENT_STD;
2287 dpns.rtable = query->rtable;
2288 dpns.ctes = query->cteList;
2289 dpns.subplans = NIL;
2290 dpns.outer_plan = dpns.inner_plan = NULL;
2292 get_rule_expr(qual, &context, false);
2295 appendStringInfo(buf, " DO ");
2297 /* The INSTEAD keyword (if so) */
2299 appendStringInfo(buf, "INSTEAD ");
2301 /* Finally the rules actions */
2302 if (list_length(actions) > 1)
2307 appendStringInfo(buf, "(");
2308 foreach(action, actions)
2310 query = (Query *) lfirst(action);
2311 get_query_def(query, buf, NIL, NULL, prettyFlags, 0);
2313 appendStringInfo(buf, ";\n");
2315 appendStringInfo(buf, "; ");
2317 appendStringInfo(buf, ");");
2319 else if (list_length(actions) == 0)
2321 appendStringInfo(buf, "NOTHING;");
2327 query = (Query *) linitial(actions);
2328 get_query_def(query, buf, NIL, NULL, prettyFlags, 0);
2329 appendStringInfo(buf, ";");
2335 * make_viewdef - reconstruct the SELECT part of a
2340 make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
2350 List *actions = NIL;
2351 Relation ev_relation;
2356 * Get the attribute values from the rules tuple
2358 fno = SPI_fnumber(rulettc, "ev_type");
2359 ev_type = (char) SPI_getbinval(ruletup, rulettc, fno, &isnull);
2361 fno = SPI_fnumber(rulettc, "ev_class");
2362 ev_class = (Oid) SPI_getbinval(ruletup, rulettc, fno, &isnull);
2364 fno = SPI_fnumber(rulettc, "ev_attr");
2365 ev_attr = (int2) SPI_getbinval(ruletup, rulettc, fno, &isnull);
2367 fno = SPI_fnumber(rulettc, "is_instead");
2368 is_instead = (bool) SPI_getbinval(ruletup, rulettc, fno, &isnull);
2370 fno = SPI_fnumber(rulettc, "ev_qual");
2371 ev_qual = SPI_getvalue(ruletup, rulettc, fno);
2373 fno = SPI_fnumber(rulettc, "ev_action");
2374 ev_action = SPI_getvalue(ruletup, rulettc, fno);
2375 if (ev_action != NULL)
2376 actions = (List *) stringToNode(ev_action);
2378 if (list_length(actions) != 1)
2380 appendStringInfo(buf, "Not a view");
2384 query = (Query *) linitial(actions);
2386 if (ev_type != '1' || ev_attr >= 0 || !is_instead ||
2387 strcmp(ev_qual, "<>") != 0 || query->commandType != CMD_SELECT)
2389 appendStringInfo(buf, "Not a view");
2393 ev_relation = heap_open(ev_class, AccessShareLock);
2395 get_query_def(query, buf, NIL, RelationGetDescr(ev_relation),
2397 appendStringInfo(buf, ";");
2399 heap_close(ev_relation, AccessShareLock);
2404 * get_query_def - Parse back one query parsetree
2406 * If resultDesc is not NULL, then it is the output tuple descriptor for
2407 * the view represented by a SELECT query.
2411 get_query_def(Query *query, StringInfo buf, List *parentnamespace,
2412 TupleDesc resultDesc, int prettyFlags, int startIndent)
2414 deparse_context context;
2415 deparse_namespace dpns;
2418 * Before we begin to examine the query, acquire locks on referenced
2419 * relations, and fix up deleted columns in JOIN RTEs. This ensures
2420 * consistent results. Note we assume it's OK to scribble on the passed
2423 AcquireRewriteLocks(query, false);
2426 context.namespaces = lcons(&dpns, list_copy(parentnamespace));
2427 context.windowClause = NIL;
2428 context.windowTList = NIL;
2429 context.varprefix = (parentnamespace != NIL ||
2430 list_length(query->rtable) != 1);
2431 context.prettyFlags = prettyFlags;
2432 context.indentLevel = startIndent;
2434 dpns.rtable = query->rtable;
2435 dpns.ctes = query->cteList;
2436 dpns.subplans = NIL;
2437 dpns.outer_plan = dpns.inner_plan = NULL;
2439 switch (query->commandType)
2442 get_select_query_def(query, &context, resultDesc);
2446 get_update_query_def(query, &context);
2450 get_insert_query_def(query, &context);
2454 get_delete_query_def(query, &context);
2458 appendStringInfo(buf, "NOTHING");
2462 get_utility_query_def(query, &context);
2466 elog(ERROR, "unrecognized query command type: %d",
2467 query->commandType);
2473 * get_values_def - Parse back a VALUES list
2477 get_values_def(List *values_lists, deparse_context *context)
2479 StringInfo buf = context->buf;
2480 bool first_list = true;
2483 appendStringInfoString(buf, "VALUES ");
2485 foreach(vtl, values_lists)
2487 List *sublist = (List *) lfirst(vtl);
2488 bool first_col = true;
2494 appendStringInfoString(buf, ", ");
2496 appendStringInfoChar(buf, '(');
2497 foreach(lc, sublist)
2499 Node *col = (Node *) lfirst(lc);
2504 appendStringInfoChar(buf, ',');
2507 * Strip any top-level nodes representing indirection assignments,
2508 * then print the result.
2510 get_rule_expr(processIndirection(col, context, false),
2513 appendStringInfoChar(buf, ')');
2518 * get_with_clause - Parse back a WITH clause
2522 get_with_clause(Query *query, deparse_context *context)
2524 StringInfo buf = context->buf;
2528 if (query->cteList == NIL)
2531 if (PRETTY_INDENT(context))
2533 context->indentLevel += PRETTYINDENT_STD;
2534 appendStringInfoChar(buf, ' ');
2537 if (query->hasRecursive)
2538 sep = "WITH RECURSIVE ";
2541 foreach(l, query->cteList)
2543 CommonTableExpr *cte = (CommonTableExpr *) lfirst(l);
2545 appendStringInfoString(buf, sep);
2546 appendStringInfoString(buf, quote_identifier(cte->ctename));
2547 if (cte->aliascolnames)
2552 appendStringInfoChar(buf, '(');
2553 foreach(col, cte->aliascolnames)
2558 appendStringInfoString(buf, ", ");
2559 appendStringInfoString(buf,
2560 quote_identifier(strVal(lfirst(col))));
2562 appendStringInfoChar(buf, ')');
2564 appendStringInfoString(buf, " AS (");
2565 if (PRETTY_INDENT(context))
2566 appendContextKeyword(context, "", 0, 0, 0);
2567 get_query_def((Query *) cte->ctequery, buf, context->namespaces, NULL,
2568 context->prettyFlags, context->indentLevel);
2569 if (PRETTY_INDENT(context))
2570 appendContextKeyword(context, "", 0, 0, 0);
2571 appendStringInfoChar(buf, ')');
2575 if (PRETTY_INDENT(context))
2577 context->indentLevel -= PRETTYINDENT_STD;
2578 appendContextKeyword(context, "", 0, 0, 0);
2581 appendStringInfoChar(buf, ' ');
2585 * get_select_query_def - Parse back a SELECT parsetree
2589 get_select_query_def(Query *query, deparse_context *context,
2590 TupleDesc resultDesc)
2592 StringInfo buf = context->buf;
2593 List *save_windowclause;
2594 List *save_windowtlist;
2598 /* Insert the WITH clause if given */
2599 get_with_clause(query, context);
2601 /* Set up context for possible window functions */
2602 save_windowclause = context->windowClause;
2603 context->windowClause = query->windowClause;
2604 save_windowtlist = context->windowTList;
2605 context->windowTList = query->targetList;
2608 * If the Query node has a setOperations tree, then it's the top level of
2609 * a UNION/INTERSECT/EXCEPT query; only the WITH, ORDER BY and LIMIT
2610 * fields are interesting in the top query itself.
2612 if (query->setOperations)
2614 get_setop_query(query->setOperations, query, context, resultDesc);
2615 /* ORDER BY clauses must be simple in this case */
2620 get_basic_select_query(query, context, resultDesc);
2621 force_colno = false;
2624 /* Add the ORDER BY clause if given */
2625 if (query->sortClause != NIL)
2627 appendContextKeyword(context, " ORDER BY ",
2628 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2629 get_rule_orderby(query->sortClause, query->targetList,
2630 force_colno, context);
2633 /* Add the LIMIT clause if given */
2634 if (query->limitOffset != NULL)
2636 appendContextKeyword(context, " OFFSET ",
2637 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2638 get_rule_expr(query->limitOffset, context, false);
2640 if (query->limitCount != NULL)
2642 appendContextKeyword(context, " LIMIT ",
2643 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2644 if (IsA(query->limitCount, Const) &&
2645 ((Const *) query->limitCount)->constisnull)
2646 appendStringInfo(buf, "ALL");
2648 get_rule_expr(query->limitCount, context, false);
2651 /* Add FOR UPDATE/SHARE clauses if present */
2652 if (query->hasForUpdate)
2654 foreach(l, query->rowMarks)
2656 RowMarkClause *rc = (RowMarkClause *) lfirst(l);
2657 RangeTblEntry *rte = rt_fetch(rc->rti, query->rtable);
2659 /* don't print implicit clauses */
2664 appendContextKeyword(context, " FOR UPDATE",
2665 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2667 appendContextKeyword(context, " FOR SHARE",
2668 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2669 appendStringInfo(buf, " OF %s",
2670 quote_identifier(rte->eref->aliasname));
2672 appendStringInfo(buf, " NOWAIT");
2676 context->windowClause = save_windowclause;
2677 context->windowTList = save_windowtlist;
2681 get_basic_select_query(Query *query, deparse_context *context,
2682 TupleDesc resultDesc)
2684 StringInfo buf = context->buf;
2688 if (PRETTY_INDENT(context))
2690 context->indentLevel += PRETTYINDENT_STD;
2691 appendStringInfoChar(buf, ' ');
2695 * If the query looks like SELECT * FROM (VALUES ...), then print just the
2696 * VALUES part. This reverses what transformValuesClause() did at parse
2697 * time. If the jointree contains just a single VALUES RTE, we assume
2698 * this case applies (without looking at the targetlist...)
2700 if (list_length(query->jointree->fromlist) == 1)
2702 RangeTblRef *rtr = (RangeTblRef *) linitial(query->jointree->fromlist);
2704 if (IsA(rtr, RangeTblRef))
2706 RangeTblEntry *rte = rt_fetch(rtr->rtindex, query->rtable);
2708 if (rte->rtekind == RTE_VALUES)
2710 get_values_def(rte->values_lists, context);
2717 * Build up the query string - first we say SELECT
2719 appendStringInfo(buf, "SELECT");
2721 /* Add the DISTINCT clause if given */
2722 if (query->distinctClause != NIL)
2724 if (query->hasDistinctOn)
2726 appendStringInfo(buf, " DISTINCT ON (");
2728 foreach(l, query->distinctClause)
2730 SortGroupClause *srt = (SortGroupClause *) lfirst(l);
2732 appendStringInfoString(buf, sep);
2733 get_rule_sortgroupclause(srt, query->targetList,
2737 appendStringInfo(buf, ")");
2740 appendStringInfo(buf, " DISTINCT");
2743 /* Then we tell what to select (the targetlist) */
2744 get_target_list(query->targetList, context, resultDesc);
2746 /* Add the FROM clause if needed */
2747 get_from_clause(query, " FROM ", context);
2749 /* Add the WHERE clause if given */
2750 if (query->jointree->quals != NULL)
2752 appendContextKeyword(context, " WHERE ",
2753 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2754 get_rule_expr(query->jointree->quals, context, false);
2757 /* Add the GROUP BY clause if given */
2758 if (query->groupClause != NULL)
2760 appendContextKeyword(context, " GROUP BY ",
2761 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2763 foreach(l, query->groupClause)
2765 SortGroupClause *grp = (SortGroupClause *) lfirst(l);
2767 appendStringInfoString(buf, sep);
2768 get_rule_sortgroupclause(grp, query->targetList,
2774 /* Add the HAVING clause if given */
2775 if (query->havingQual != NULL)
2777 appendContextKeyword(context, " HAVING ",
2778 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2779 get_rule_expr(query->havingQual, context, false);
2782 /* Add the WINDOW clause if needed */
2783 if (query->windowClause != NIL)
2784 get_rule_windowclause(query, context);
2788 * get_target_list - Parse back a SELECT target list
2790 * This is also used for RETURNING lists in INSERT/UPDATE/DELETE.
2794 get_target_list(List *targetList, deparse_context *context,
2795 TupleDesc resultDesc)
2797 StringInfo buf = context->buf;
2804 foreach(l, targetList)
2806 TargetEntry *tle = (TargetEntry *) lfirst(l);
2811 continue; /* ignore junk entries */
2813 appendStringInfoString(buf, sep);
2818 * We special-case Var nodes rather than using get_rule_expr. This is
2819 * needed because get_rule_expr will display a whole-row Var as
2820 * "foo.*", which is the preferred notation in most contexts, but at
2821 * the top level of a SELECT list it's not right (the parser will
2822 * expand that notation into multiple columns, yielding behavior
2823 * different from a whole-row Var). We want just "foo", instead.
2825 if (tle->expr && IsA(tle->expr, Var))
2827 attname = get_variable((Var *) tle->expr, 0, false, context);
2831 get_rule_expr((Node *) tle->expr, context, true);
2832 /* We'll show the AS name unless it's this: */
2833 attname = "?column?";
2837 * Figure out what the result column should be called. In the context
2838 * of a view, use the view's tuple descriptor (so as to pick up the
2839 * effects of any column RENAME that's been done on the view).
2840 * Otherwise, just use what we can find in the TLE.
2842 if (resultDesc && colno <= resultDesc->natts)
2843 colname = NameStr(resultDesc->attrs[colno - 1]->attname);
2845 colname = tle->resname;
2847 /* Show AS unless the column's name is correct as-is */
2848 if (colname) /* resname could be NULL */
2850 if (attname == NULL || strcmp(attname, colname) != 0)
2851 appendStringInfo(buf, " AS %s", quote_identifier(colname));
2857 get_setop_query(Node *setOp, Query *query, deparse_context *context,
2858 TupleDesc resultDesc)
2860 StringInfo buf = context->buf;
2863 if (IsA(setOp, RangeTblRef))
2865 RangeTblRef *rtr = (RangeTblRef *) setOp;
2866 RangeTblEntry *rte = rt_fetch(rtr->rtindex, query->rtable);
2867 Query *subquery = rte->subquery;
2869 Assert(subquery != NULL);
2870 Assert(subquery->setOperations == NULL);
2871 /* Need parens if WITH, ORDER BY, FOR UPDATE, or LIMIT; see gram.y */
2872 need_paren = (subquery->cteList ||
2873 subquery->sortClause ||
2874 subquery->rowMarks ||
2875 subquery->limitOffset ||
2876 subquery->limitCount);
2878 appendStringInfoChar(buf, '(');
2879 get_query_def(subquery, buf, context->namespaces, resultDesc,
2880 context->prettyFlags, context->indentLevel);
2882 appendStringInfoChar(buf, ')');
2884 else if (IsA(setOp, SetOperationStmt))
2886 SetOperationStmt *op = (SetOperationStmt *) setOp;
2888 if (PRETTY_INDENT(context))
2890 context->indentLevel += PRETTYINDENT_STD;
2891 appendStringInfoSpaces(buf, PRETTYINDENT_STD);
2895 * We force parens whenever nesting two SetOperationStmts. There are
2896 * some cases in which parens are needed around a leaf query too, but
2897 * those are more easily handled at the next level down (see code
2900 need_paren = !IsA(op->larg, RangeTblRef);
2903 appendStringInfoChar(buf, '(');
2904 get_setop_query(op->larg, query, context, resultDesc);
2906 appendStringInfoChar(buf, ')');
2908 if (!PRETTY_INDENT(context))
2909 appendStringInfoChar(buf, ' ');
2913 appendContextKeyword(context, "UNION ",
2914 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2916 case SETOP_INTERSECT:
2917 appendContextKeyword(context, "INTERSECT ",
2918 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2921 appendContextKeyword(context, "EXCEPT ",
2922 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2925 elog(ERROR, "unrecognized set op: %d",
2929 appendStringInfo(buf, "ALL ");
2931 if (PRETTY_INDENT(context))
2932 appendContextKeyword(context, "", 0, 0, 0);
2934 need_paren = !IsA(op->rarg, RangeTblRef);
2937 appendStringInfoChar(buf, '(');
2938 get_setop_query(op->rarg, query, context, resultDesc);
2940 appendStringInfoChar(buf, ')');
2942 if (PRETTY_INDENT(context))
2943 context->indentLevel -= PRETTYINDENT_STD;
2947 elog(ERROR, "unrecognized node type: %d",
2948 (int) nodeTag(setOp));
2953 * Display a sort/group clause.
2955 * Also returns the expression tree, so caller need not find it again.
2958 get_rule_sortgroupclause(SortGroupClause *srt, List *tlist, bool force_colno,
2959 deparse_context *context)
2961 StringInfo buf = context->buf;
2965 tle = get_sortgroupclause_tle(srt, tlist);
2966 expr = (Node *) tle->expr;
2969 * Use column-number form if requested by caller. Otherwise, if
2970 * expression is a constant, force it to be dumped with an explicit cast
2971 * as decoration --- this is because a simple integer constant is
2972 * ambiguous (and will be misinterpreted by findTargetlistEntry()) if we
2973 * dump it without any decoration. Otherwise, just dump the expression
2978 Assert(!tle->resjunk);
2979 appendStringInfo(buf, "%d", tle->resno);
2981 else if (expr && IsA(expr, Const))
2982 get_const_expr((Const *) expr, context, 1);
2984 get_rule_expr(expr, context, true);
2990 * Display an ORDER BY list.
2993 get_rule_orderby(List *orderList, List *targetList,
2994 bool force_colno, deparse_context *context)
2996 StringInfo buf = context->buf;
3001 foreach(l, orderList)
3003 SortGroupClause *srt = (SortGroupClause *) lfirst(l);
3006 TypeCacheEntry *typentry;
3008 appendStringInfoString(buf, sep);
3009 sortexpr = get_rule_sortgroupclause(srt, targetList,
3010 force_colno, context);
3011 sortcoltype = exprType(sortexpr);
3012 /* See whether operator is default < or > for datatype */
3013 typentry = lookup_type_cache(sortcoltype,
3014 TYPECACHE_LT_OPR | TYPECACHE_GT_OPR);
3015 if (srt->sortop == typentry->lt_opr)
3017 /* ASC is default, so emit nothing for it */
3018 if (srt->nulls_first)
3019 appendStringInfo(buf, " NULLS FIRST");
3021 else if (srt->sortop == typentry->gt_opr)
3023 appendStringInfo(buf, " DESC");
3024 /* DESC defaults to NULLS FIRST */
3025 if (!srt->nulls_first)
3026 appendStringInfo(buf, " NULLS LAST");
3030 appendStringInfo(buf, " USING %s",
3031 generate_operator_name(srt->sortop,
3034 /* be specific to eliminate ambiguity */
3035 if (srt->nulls_first)
3036 appendStringInfo(buf, " NULLS FIRST");
3038 appendStringInfo(buf, " NULLS LAST");
3045 * Display a WINDOW clause.
3047 * Note that the windowClause list might contain only anonymous window
3048 * specifications, in which case we should print nothing here.
3051 get_rule_windowclause(Query *query, deparse_context *context)
3053 StringInfo buf = context->buf;
3058 foreach(l, query->windowClause)
3060 WindowClause *wc = (WindowClause *) lfirst(l);
3062 if (wc->name == NULL)
3063 continue; /* ignore anonymous windows */
3066 appendContextKeyword(context, " WINDOW ",
3067 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
3069 appendStringInfoString(buf, sep);
3071 appendStringInfo(buf, "%s AS ", quote_identifier(wc->name));
3073 get_rule_windowspec(wc, query->targetList, context);
3080 * Display a window definition
3083 get_rule_windowspec(WindowClause *wc, List *targetList,
3084 deparse_context *context)
3086 StringInfo buf = context->buf;
3087 bool needspace = false;
3091 appendStringInfoChar(buf, '(');
3094 appendStringInfoString(buf, quote_identifier(wc->refname));
3097 /* partition clauses are always inherited, so only print if no refname */
3098 if (wc->partitionClause && !wc->refname)
3101 appendStringInfoChar(buf, ' ');
3102 appendStringInfoString(buf, "PARTITION BY ");
3104 foreach(l, wc->partitionClause)
3106 SortGroupClause *grp = (SortGroupClause *) lfirst(l);
3108 appendStringInfoString(buf, sep);
3109 get_rule_sortgroupclause(grp, targetList,
3115 /* print ordering clause only if not inherited */
3116 if (wc->orderClause && !wc->copiedOrder)
3119 appendStringInfoChar(buf, ' ');
3120 appendStringInfoString(buf, "ORDER BY ");
3121 get_rule_orderby(wc->orderClause, targetList, false, context);
3124 /* framing clause is never inherited, so print unless it's default */
3125 if (wc->frameOptions & FRAMEOPTION_NONDEFAULT)
3128 appendStringInfoChar(buf, ' ');
3129 if (wc->frameOptions & FRAMEOPTION_RANGE)
3130 appendStringInfoString(buf, "RANGE ");
3131 else if (wc->frameOptions & FRAMEOPTION_ROWS)
3132 appendStringInfoString(buf, "ROWS ");
3135 if (wc->frameOptions & FRAMEOPTION_BETWEEN)
3136 appendStringInfoString(buf, "BETWEEN ");
3137 if (wc->frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING)
3138 appendStringInfoString(buf, "UNBOUNDED PRECEDING ");
3139 else if (wc->frameOptions & FRAMEOPTION_START_CURRENT_ROW)
3140 appendStringInfoString(buf, "CURRENT ROW ");
3141 else if (wc->frameOptions & FRAMEOPTION_START_VALUE)
3143 get_rule_expr(wc->startOffset, context, false);
3144 if (wc->frameOptions & FRAMEOPTION_START_VALUE_PRECEDING)
3145 appendStringInfoString(buf, " PRECEDING ");
3146 else if (wc->frameOptions & FRAMEOPTION_START_VALUE_FOLLOWING)
3147 appendStringInfoString(buf, " FOLLOWING ");
3153 if (wc->frameOptions & FRAMEOPTION_BETWEEN)
3155 appendStringInfoString(buf, "AND ");
3156 if (wc->frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING)
3157 appendStringInfoString(buf, "UNBOUNDED FOLLOWING ");
3158 else if (wc->frameOptions & FRAMEOPTION_END_CURRENT_ROW)
3159 appendStringInfoString(buf, "CURRENT ROW ");
3160 else if (wc->frameOptions & FRAMEOPTION_END_VALUE)
3162 get_rule_expr(wc->endOffset, context, false);
3163 if (wc->frameOptions & FRAMEOPTION_END_VALUE_PRECEDING)
3164 appendStringInfoString(buf, " PRECEDING ");
3165 else if (wc->frameOptions & FRAMEOPTION_END_VALUE_FOLLOWING)
3166 appendStringInfoString(buf, " FOLLOWING ");
3173 /* we will now have a trailing space; remove it */
3176 appendStringInfoChar(buf, ')');
3180 * get_insert_query_def - Parse back an INSERT parsetree
3184 get_insert_query_def(Query *query, deparse_context *context)
3186 StringInfo buf = context->buf;
3187 RangeTblEntry *select_rte = NULL;
3188 RangeTblEntry *values_rte = NULL;
3191 ListCell *values_cell;
3193 List *strippedexprs;
3196 * If it's an INSERT ... SELECT or VALUES (...), (...), ... there will be
3197 * a single RTE for the SELECT or VALUES.
3199 foreach(l, query->rtable)
3201 rte = (RangeTblEntry *) lfirst(l);
3203 if (rte->rtekind == RTE_SUBQUERY)
3206 elog(ERROR, "too many subquery RTEs in INSERT");
3210 if (rte->rtekind == RTE_VALUES)
3213 elog(ERROR, "too many values RTEs in INSERT");
3217 if (select_rte && values_rte)
3218 elog(ERROR, "both subquery and values RTEs in INSERT");
3221 * Start the query with INSERT INTO relname
3223 rte = rt_fetch(query->resultRelation, query->rtable);
3224 Assert(rte->rtekind == RTE_RELATION);
3226 if (PRETTY_INDENT(context))
3228 context->indentLevel += PRETTYINDENT_STD;
3229 appendStringInfoChar(buf, ' ');
3231 appendStringInfo(buf, "INSERT INTO %s (",
3232 generate_relation_name(rte->relid, NIL));
3235 * Add the insert-column-names list. To handle indirection properly, we
3236 * need to look for indirection nodes in the top targetlist (if it's
3237 * INSERT ... SELECT or INSERT ... single VALUES), or in the first
3238 * expression list of the VALUES RTE (if it's INSERT ... multi VALUES). We
3239 * assume that all the expression lists will have similar indirection in
3243 values_cell = list_head((List *) linitial(values_rte->values_lists));
3246 strippedexprs = NIL;
3248 foreach(l, query->targetList)
3250 TargetEntry *tle = (TargetEntry *) lfirst(l);
3253 continue; /* ignore junk entries */
3255 appendStringInfoString(buf, sep);
3259 * Put out name of target column; look in the catalogs, not at
3260 * tle->resname, since resname will fail to track RENAME.
3262 appendStringInfoString(buf,
3263 quote_identifier(get_relid_attribute_name(rte->relid,
3267 * Print any indirection needed (subfields or subscripts), and strip
3268 * off the top-level nodes representing the indirection assignments.
3272 /* we discard the stripped expression in this case */
3273 processIndirection((Node *) lfirst(values_cell), context, true);
3274 values_cell = lnext(values_cell);
3278 /* we keep a list of the stripped expressions in this case */
3279 strippedexprs = lappend(strippedexprs,
3280 processIndirection((Node *) tle->expr,
3284 appendStringInfo(buf, ") ");
3288 /* Add the SELECT */
3289 get_query_def(select_rte->subquery, buf, NIL, NULL,
3290 context->prettyFlags, context->indentLevel);
3292 else if (values_rte)
3294 /* A WITH clause is possible here */
3295 get_with_clause(query, context);
3296 /* Add the multi-VALUES expression lists */
3297 get_values_def(values_rte->values_lists, context);
3301 /* A WITH clause is possible here */
3302 get_with_clause(query, context);
3303 /* Add the single-VALUES expression list */
3304 appendContextKeyword(context, "VALUES (",
3305 -PRETTYINDENT_STD, PRETTYINDENT_STD, 2);
3306 get_rule_expr((Node *) strippedexprs, context, false);
3307 appendStringInfoChar(buf, ')');
3310 /* Add RETURNING if present */
3311 if (query->returningList)
3313 appendContextKeyword(context, " RETURNING",
3314 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
3315 get_target_list(query->returningList, context, NULL);
3321 * get_update_query_def - Parse back an UPDATE parsetree
3325 get_update_query_def(Query *query, deparse_context *context)
3327 StringInfo buf = context->buf;
3333 * Start the query with UPDATE relname SET
3335 rte = rt_fetch(query->resultRelation, query->rtable);
3336 Assert(rte->rtekind == RTE_RELATION);
3337 if (PRETTY_INDENT(context))
3339 appendStringInfoChar(buf, ' ');
3340 context->indentLevel += PRETTYINDENT_STD;
3342 appendStringInfo(buf, "UPDATE %s%s",
3344 generate_relation_name(rte->relid, NIL));
3345 if (rte->alias != NULL)
3346 appendStringInfo(buf, " %s",
3347 quote_identifier(rte->alias->aliasname));
3348 appendStringInfoString(buf, " SET ");
3350 /* Add the comma separated list of 'attname = value' */
3352 foreach(l, query->targetList)
3354 TargetEntry *tle = (TargetEntry *) lfirst(l);
3358 continue; /* ignore junk entries */
3360 appendStringInfoString(buf, sep);
3364 * Put out name of target column; look in the catalogs, not at
3365 * tle->resname, since resname will fail to track RENAME.
3367 appendStringInfoString(buf,
3368 quote_identifier(get_relid_attribute_name(rte->relid,
3372 * Print any indirection needed (subfields or subscripts), and strip
3373 * off the top-level nodes representing the indirection assignments.
3375 expr = processIndirection((Node *) tle->expr, context, true);
3377 appendStringInfo(buf, " = ");
3379 get_rule_expr(expr, context, false);
3382 /* Add the FROM clause if needed */
3383 get_from_clause(query, " FROM ", context);
3385 /* Add a WHERE clause if given */
3386 if (query->jointree->quals != NULL)
3388 appendContextKeyword(context, " WHERE ",
3389 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
3390 get_rule_expr(query->jointree->quals, context, false);
3393 /* Add RETURNING if present */
3394 if (query->returningList)
3396 appendContextKeyword(context, " RETURNING",
3397 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
3398 get_target_list(query->returningList, context, NULL);
3404 * get_delete_query_def - Parse back a DELETE parsetree
3408 get_delete_query_def(Query *query, deparse_context *context)
3410 StringInfo buf = context->buf;
3414 * Start the query with DELETE FROM relname
3416 rte = rt_fetch(query->resultRelation, query->rtable);
3417 Assert(rte->rtekind == RTE_RELATION);
3418 if (PRETTY_INDENT(context))
3420 appendStringInfoChar(buf, ' ');
3421 context->indentLevel += PRETTYINDENT_STD;
3423 appendStringInfo(buf, "DELETE FROM %s%s",
3425 generate_relation_name(rte->relid, NIL));
3426 if (rte->alias != NULL)
3427 appendStringInfo(buf, " %s",
3428 quote_identifier(rte->alias->aliasname));
3430 /* Add the USING clause if given */
3431 get_from_clause(query, " USING ", context);
3433 /* Add a WHERE clause if given */
3434 if (query->jointree->quals != NULL)
3436 appendContextKeyword(context, " WHERE ",
3437 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
3438 get_rule_expr(query->jointree->quals, context, false);
3441 /* Add RETURNING if present */
3442 if (query->returningList)
3444 appendContextKeyword(context, " RETURNING",
3445 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
3446 get_target_list(query->returningList, context, NULL);
3452 * get_utility_query_def - Parse back a UTILITY parsetree
3456 get_utility_query_def(Query *query, deparse_context *context)
3458 StringInfo buf = context->buf;
3460 if (query->utilityStmt && IsA(query->utilityStmt, NotifyStmt))
3462 NotifyStmt *stmt = (NotifyStmt *) query->utilityStmt;
3464 appendContextKeyword(context, "",
3465 0, PRETTYINDENT_STD, 1);
3466 appendStringInfo(buf, "NOTIFY %s",
3467 quote_identifier(stmt->conditionname));
3470 appendStringInfoString(buf, ", ");
3471 simple_quote_literal(buf, stmt->payload);
3476 /* Currently only NOTIFY utility commands can appear in rules */
3477 elog(ERROR, "unexpected utility statement type");
3483 * push_plan: set up deparse_namespace to recurse into the tlist of a subplan
3485 * When expanding an OUTER or INNER reference, we must push new outer/inner
3486 * subplans in case the referenced expression itself uses OUTER/INNER. We
3487 * modify the top stack entry in-place to avoid affecting levelsup issues
3488 * (although in a Plan tree there really shouldn't be any).
3490 * Caller must save and restore outer_plan and inner_plan around this.
3492 * We also use this to initialize the fields during deparse_context_for_plan.
3495 push_plan(deparse_namespace *dpns, Plan *subplan)
3498 * We special-case Append to pretend that the first child plan is the
3499 * OUTER referent; we have to interpret OUTER Vars in the Append's tlist
3500 * according to one of the children, and the first one is the most
3501 * natural choice. Likewise special-case ModifyTable to pretend that the
3502 * first child plan is the OUTER referent; this is to support RETURNING
3503 * lists containing references to non-target relations.
3505 if (IsA(subplan, Append))
3506 dpns->outer_plan = (Plan *) linitial(((Append *) subplan)->appendplans);
3507 else if (IsA(subplan, ModifyTable))
3508 dpns->outer_plan = (Plan *) linitial(((ModifyTable *) subplan)->plans);
3510 dpns->outer_plan = outerPlan(subplan);
3513 * For a SubqueryScan, pretend the subplan is INNER referent. (We don't
3514 * use OUTER because that could someday conflict with the normal meaning.)
3515 * Likewise, for a CteScan, pretend the subquery's plan is INNER referent.
3517 if (IsA(subplan, SubqueryScan))
3518 dpns->inner_plan = ((SubqueryScan *) subplan)->subplan;
3519 else if (IsA(subplan, CteScan))
3521 int ctePlanId = ((CteScan *) subplan)->ctePlanId;
3523 if (ctePlanId > 0 && ctePlanId <= list_length(dpns->subplans))
3524 dpns->inner_plan = list_nth(dpns->subplans, ctePlanId - 1);
3526 dpns->inner_plan = NULL;
3529 dpns->inner_plan = innerPlan(subplan);
3534 * Display a Var appropriately.
3536 * In some cases (currently only when recursing into an unnamed join)
3537 * the Var's varlevelsup has to be interpreted with respect to a context
3538 * above the current one; levelsup indicates the offset.
3540 * If showstar is TRUE, whole-row Vars are displayed as "foo.*";
3541 * if FALSE, merely as "foo".
3543 * Returns the attname of the Var, or NULL if not determinable.
3546 get_variable(Var *var, int levelsup, bool showstar, deparse_context *context)
3548 StringInfo buf = context->buf;
3552 deparse_namespace *dpns;
3557 /* Find appropriate nesting depth */
3558 netlevelsup = var->varlevelsup + levelsup;
3559 if (netlevelsup >= list_length(context->namespaces))
3560 elog(ERROR, "bogus varlevelsup: %d offset %d",
3561 var->varlevelsup, levelsup);
3562 dpns = (deparse_namespace *) list_nth(context->namespaces,
3566 * Try to find the relevant RTE in this rtable. In a plan tree, it's
3567 * likely that varno is OUTER or INNER, in which case we must dig down
3568 * into the subplans.
3570 if (var->varno >= 1 && var->varno <= list_length(dpns->rtable))
3572 rte = rt_fetch(var->varno, dpns->rtable);
3573 attnum = var->varattno;
3575 else if (var->varno == OUTER && dpns->outer_plan)
3581 tle = get_tle_by_resno(dpns->outer_plan->targetlist, var->varattno);
3583 elog(ERROR, "bogus varattno for OUTER var: %d", var->varattno);
3585 Assert(netlevelsup == 0);
3586 save_outer = dpns->outer_plan;
3587 save_inner = dpns->inner_plan;
3588 push_plan(dpns, dpns->outer_plan);
3591 * Force parentheses because our caller probably assumed a Var is a
3592 * simple expression.
3594 if (!IsA(tle->expr, Var))
3595 appendStringInfoChar(buf, '(');
3596 get_rule_expr((Node *) tle->expr, context, true);
3597 if (!IsA(tle->expr, Var))
3598 appendStringInfoChar(buf, ')');
3600 dpns->outer_plan = save_outer;
3601 dpns->inner_plan = save_inner;
3604 else if (var->varno == INNER && dpns->inner_plan)
3610 tle = get_tle_by_resno(dpns->inner_plan->targetlist, var->varattno);
3612 elog(ERROR, "bogus varattno for INNER var: %d", var->varattno);
3614 Assert(netlevelsup == 0);
3615 save_outer = dpns->outer_plan;
3616 save_inner = dpns->inner_plan;
3617 push_plan(dpns, dpns->inner_plan);
3620 * Force parentheses because our caller probably assumed a Var is a
3621 * simple expression.
3623 if (!IsA(tle->expr, Var))
3624 appendStringInfoChar(buf, '(');
3625 get_rule_expr((Node *) tle->expr, context, true);
3626 if (!IsA(tle->expr, Var))
3627 appendStringInfoChar(buf, ')');
3629 dpns->outer_plan = save_outer;
3630 dpns->inner_plan = save_inner;
3635 elog(ERROR, "bogus varno: %d", var->varno);
3636 return NULL; /* keep compiler quiet */
3639 /* Identify names to use */
3640 schemaname = NULL; /* default assumptions */
3641 refname = rte->eref->aliasname;
3643 /* Exceptions occur only if the RTE is alias-less */
3644 if (rte->alias == NULL)
3646 if (rte->rtekind == RTE_RELATION)
3649 * It's possible that use of the bare refname would find another
3650 * more-closely-nested RTE, or be ambiguous, in which case we need
3651 * to specify the schemaname to avoid these errors.
3653 if (find_rte_by_refname(rte->eref->aliasname, context) != rte)
3654 schemaname = get_namespace_name(get_rel_namespace(rte->relid));
3656 else if (rte->rtekind == RTE_JOIN)
3659 * If it's an unnamed join, look at the expansion of the alias
3660 * variable. If it's a simple reference to one of the input vars
3661 * then recursively print the name of that var, instead. (This
3662 * allows correct decompiling of cases where there are identically
3663 * named columns on both sides of the join.) When it's not a
3664 * simple reference, we have to just print the unqualified
3665 * variable name (this can only happen with columns that were
3666 * merged by USING or NATURAL clauses).
3668 * This wouldn't work in decompiling plan trees, because we don't
3669 * store joinaliasvars lists after planning; but a plan tree
3670 * should never contain a join alias variable.
3672 if (rte->joinaliasvars == NIL)
3673 elog(ERROR, "cannot decompile join alias var in plan tree");
3678 aliasvar = (Var *) list_nth(rte->joinaliasvars, attnum - 1);
3679 if (IsA(aliasvar, Var))
3681 return get_variable(aliasvar, var->varlevelsup + levelsup,
3685 /* Unnamed join has neither schemaname nor refname */
3690 if (attnum == InvalidAttrNumber)
3693 attname = get_rte_attribute_name(rte, attnum);
3695 if (refname && (context->varprefix || attname == NULL))
3698 appendStringInfo(buf, "%s.",
3699 quote_identifier(schemaname));
3700 appendStringInfoString(buf, quote_identifier(refname));
3701 if (attname || showstar)
3702 appendStringInfoChar(buf, '.');
3705 appendStringInfoString(buf, quote_identifier(attname));
3707 appendStringInfoChar(buf, '*');
3714 * Get the name of a field of an expression of composite type.
3716 * This is fairly straightforward except for the case of a Var of type RECORD.
3717 * Since no actual table or view column is allowed to have type RECORD, such
3718 * a Var must refer to a JOIN or FUNCTION RTE or to a subquery output. We
3719 * drill down to find the ultimate defining expression and attempt to infer
3720 * the field name from it. We ereport if we can't determine the name.
3722 * levelsup is an extra offset to interpret the Var's varlevelsup correctly.
3725 get_name_for_var_field(Var *var, int fieldno,
3726 int levelsup, deparse_context *context)
3731 deparse_namespace *dpns;
3732 TupleDesc tupleDesc;
3736 * If it's a RowExpr that was expanded from a whole-row Var, use the
3737 * column names attached to it.
3739 if (IsA(var, RowExpr))
3741 RowExpr *r = (RowExpr *) var;
3743 if (fieldno > 0 && fieldno <= list_length(r->colnames))
3744 return strVal(list_nth(r->colnames, fieldno - 1));
3748 * If it's a Var of type RECORD, we have to find what the Var refers to;
3749 * if not, we can use get_expr_result_type. If that fails, we try
3750 * lookup_rowtype_tupdesc, which will probably fail too, but will ereport
3751 * an acceptable message.
3753 if (!IsA(var, Var) ||
3754 var->vartype != RECORDOID)
3756 if (get_expr_result_type((Node *) var, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
3757 tupleDesc = lookup_rowtype_tupdesc_copy(exprType((Node *) var),
3758 exprTypmod((Node *) var));
3760 /* Got the tupdesc, so we can extract the field name */
3761 Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
3762 return NameStr(tupleDesc->attrs[fieldno - 1]->attname);
3765 /* Find appropriate nesting depth */
3766 netlevelsup = var->varlevelsup + levelsup;
3767 if (netlevelsup >= list_length(context->namespaces))
3768 elog(ERROR, "bogus varlevelsup: %d offset %d",
3769 var->varlevelsup, levelsup);
3770 dpns = (deparse_namespace *) list_nth(context->namespaces,
3774 * Try to find the relevant RTE in this rtable. In a plan tree, it's
3775 * likely that varno is OUTER or INNER, in which case we must dig down
3776 * into the subplans.
3778 if (var->varno >= 1 && var->varno <= list_length(dpns->rtable))
3780 rte = rt_fetch(var->varno, dpns->rtable);
3781 attnum = var->varattno;
3783 else if (var->varno == OUTER && dpns->outer_plan)
3790 tle = get_tle_by_resno(dpns->outer_plan->targetlist, var->varattno);
3792 elog(ERROR, "bogus varattno for OUTER var: %d", var->varattno);
3794 Assert(netlevelsup == 0);
3795 save_outer = dpns->outer_plan;
3796 save_inner = dpns->inner_plan;
3797 push_plan(dpns, dpns->outer_plan);
3799 result = get_name_for_var_field((Var *) tle->expr, fieldno,
3802 dpns->outer_plan = save_outer;
3803 dpns->inner_plan = save_inner;
3806 else if (var->varno == INNER && dpns->inner_plan)
3813 tle = get_tle_by_resno(dpns->inner_plan->targetlist, var->varattno);
3815 elog(ERROR, "bogus varattno for INNER var: %d", var->varattno);
3817 Assert(netlevelsup == 0);
3818 save_outer = dpns->outer_plan;
3819 save_inner = dpns->inner_plan;
3820 push_plan(dpns, dpns->inner_plan);
3822 result = get_name_for_var_field((Var *) tle->expr, fieldno,
3825 dpns->outer_plan = save_outer;
3826 dpns->inner_plan = save_inner;
3831 elog(ERROR, "bogus varno: %d", var->varno);
3832 return NULL; /* keep compiler quiet */
3835 if (attnum == InvalidAttrNumber)
3837 /* Var is whole-row reference to RTE, so select the right field */
3838 return get_rte_attribute_name(rte, fieldno);
3842 * This part has essentially the same logic as the parser's
3843 * expandRecordVariable() function, but we are dealing with a different
3844 * representation of the input context, and we only need one field name
3845 * not a TupleDesc. Also, we need special cases for finding subquery and
3846 * CTE subplans when deparsing Plan trees.
3848 expr = (Node *) var; /* default if we can't drill down */
3850 switch (rte->rtekind)
3857 * This case should not occur: a column of a table or values list
3858 * shouldn't have type RECORD. Fall through and fail (most
3859 * likely) at the bottom.
3863 /* Subselect-in-FROM: examine sub-select's output expr */
3867 TargetEntry *ste = get_tle_by_resno(rte->subquery->targetList,
3870 if (ste == NULL || ste->resjunk)
3871 elog(ERROR, "subquery %s does not have attribute %d",
3872 rte->eref->aliasname, attnum);
3873 expr = (Node *) ste->expr;
3877 * Recurse into the sub-select to see what its Var
3878 * refers to. We have to build an additional level of
3879 * namespace to keep in step with varlevelsup in the
3882 deparse_namespace mydpns;
3885 mydpns.rtable = rte->subquery->rtable;
3886 mydpns.ctes = rte->subquery->cteList;
3887 mydpns.subplans = NIL;
3888 mydpns.outer_plan = mydpns.inner_plan = NULL;
3890 context->namespaces = lcons(&mydpns,
3891 context->namespaces);
3893 result = get_name_for_var_field((Var *) expr, fieldno,
3896 context->namespaces =
3897 list_delete_first(context->namespaces);
3901 /* else fall through to inspect the expression */
3906 * We're deparsing a Plan tree so we don't have complete
3907 * RTE entries (in particular, rte->subquery is NULL). But
3908 * the only place we'd see a Var directly referencing a
3909 * SUBQUERY RTE is in a SubqueryScan plan node, and we can
3910 * look into the child plan's tlist instead.
3917 if (!dpns->inner_plan)
3918 elog(ERROR, "failed to find plan for subquery %s",
3919 rte->eref->aliasname);
3920 tle = get_tle_by_resno(dpns->inner_plan->targetlist,
3923 elog(ERROR, "bogus varattno for subquery var: %d",
3925 Assert(netlevelsup == 0);
3926 save_outer = dpns->outer_plan;
3927 save_inner = dpns->inner_plan;
3928 push_plan(dpns, dpns->inner_plan);
3930 result = get_name_for_var_field((Var *) tle->expr, fieldno,
3933 dpns->outer_plan = save_outer;
3934 dpns->inner_plan = save_inner;
3940 /* Join RTE --- recursively inspect the alias variable */
3941 if (rte->joinaliasvars == NIL)
3942 elog(ERROR, "cannot decompile join alias var in plan tree");
3943 Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars));
3944 expr = (Node *) list_nth(rte->joinaliasvars, attnum - 1);
3946 return get_name_for_var_field((Var *) expr, fieldno,
3947 var->varlevelsup + levelsup,
3949 /* else fall through to inspect the expression */
3954 * We couldn't get here unless a function is declared with one of
3955 * its result columns as RECORD, which is not allowed.
3959 /* CTE reference: examine subquery's output expr */
3961 CommonTableExpr *cte = NULL;
3966 * Try to find the referenced CTE using the namespace stack.
3968 ctelevelsup = rte->ctelevelsup + netlevelsup;
3969 if (ctelevelsup >= list_length(context->namespaces))
3973 deparse_namespace *ctedpns;
3975 ctedpns = (deparse_namespace *)
3976 list_nth(context->namespaces, ctelevelsup);
3977 foreach(lc, ctedpns->ctes)
3979 cte = (CommonTableExpr *) lfirst(lc);
3980 if (strcmp(cte->ctename, rte->ctename) == 0)
3986 Query *ctequery = (Query *) cte->ctequery;
3987 TargetEntry *ste = get_tle_by_resno(ctequery->targetList,
3990 if (ste == NULL || ste->resjunk)
3991 elog(ERROR, "subquery %s does not have attribute %d",
3992 rte->eref->aliasname, attnum);
3993 expr = (Node *) ste->expr;
3997 * Recurse into the CTE to see what its Var refers to.
3998 * We have to build an additional level of namespace
3999 * to keep in step with varlevelsup in the CTE.
4000 * Furthermore it could be an outer CTE, so we may
4001 * have to delete some levels of namespace.
4003 List *save_nslist = context->namespaces;
4005 deparse_namespace mydpns;
4008 mydpns.rtable = ctequery->rtable;
4009 mydpns.ctes = ctequery->cteList;
4010 mydpns.subplans = NIL;
4011 mydpns.outer_plan = mydpns.inner_plan = NULL;
4013 new_nslist = list_copy_tail(context->namespaces,
4015 context->namespaces = lcons(&mydpns, new_nslist);
4017 result = get_name_for_var_field((Var *) expr, fieldno,
4020 context->namespaces = save_nslist;
4024 /* else fall through to inspect the expression */
4029 * We're deparsing a Plan tree so we don't have a CTE
4030 * list. But the only place we'd see a Var directly
4031 * referencing a CTE RTE is in a CteScan plan node, and we
4032 * can look into the subplan's tlist instead.
4039 if (!dpns->inner_plan)
4040 elog(ERROR, "failed to find plan for CTE %s",
4041 rte->eref->aliasname);
4042 tle = get_tle_by_resno(dpns->inner_plan->targetlist,
4045 elog(ERROR, "bogus varattno for subquery var: %d",
4047 Assert(netlevelsup == 0);
4048 save_outer = dpns->outer_plan;
4049 save_inner = dpns->inner_plan;
4050 push_plan(dpns, dpns->inner_plan);
4052 result = get_name_for_var_field((Var *) tle->expr, fieldno,
4055 dpns->outer_plan = save_outer;
4056 dpns->inner_plan = save_inner;
4064 * We now have an expression we can't expand any more, so see if
4065 * get_expr_result_type() can do anything with it. If not, pass to
4066 * lookup_rowtype_tupdesc() which will probably fail, but will give an
4067 * appropriate error message while failing.
4069 if (get_expr_result_type(expr, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
4070 tupleDesc = lookup_rowtype_tupdesc_copy(exprType(expr),
4073 /* Got the tupdesc, so we can extract the field name */
4074 Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
4075 return NameStr(tupleDesc->attrs[fieldno - 1]->attname);
4080 * find_rte_by_refname - look up an RTE by refname in a deparse context
4082 * Returns NULL if there is no matching RTE or the refname is ambiguous.
4084 * NOTE: this code is not really correct since it does not take account of
4085 * the fact that not all the RTEs in a rangetable may be visible from the
4086 * point where a Var reference appears. For the purposes we need, however,
4087 * the only consequence of a false match is that we might stick a schema
4088 * qualifier on a Var that doesn't really need it. So it seems close
4091 static RangeTblEntry *
4092 find_rte_by_refname(const char *refname, deparse_context *context)
4094 RangeTblEntry *result = NULL;
4097 foreach(nslist, context->namespaces)
4099 deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist);
4102 foreach(rtlist, dpns->rtable)
4104 RangeTblEntry *rte = (RangeTblEntry *) lfirst(rtlist);
4106 if (strcmp(rte->eref->aliasname, refname) == 0)
4109 return NULL; /* it's ambiguous */
4121 * get_simple_binary_op_name
4123 * helper function for isSimpleNode
4124 * will return single char binary operator name, or NULL if it's not
4127 get_simple_binary_op_name(OpExpr *expr)
4129 List *args = expr->args;
4131 if (list_length(args) == 2)
4133 /* binary operator */
4134 Node *arg1 = (Node *) linitial(args);
4135 Node *arg2 = (Node *) lsecond(args);
4138 op = generate_operator_name(expr->opno, exprType(arg1), exprType(arg2));
4139 if (strlen(op) == 1)
4147 * isSimpleNode - check if given node is simple (doesn't need parenthesizing)
4149 * true : simple in the context of parent node's type
4150 * false : not simple
4153 isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
4158 switch (nodeTag(node))
4163 case T_CoerceToDomainValue:
4164 case T_SetToDefault:
4165 case T_CurrentOfExpr:
4166 /* single words: always simple */
4172 case T_CoalesceExpr:
4179 /* function-like: name(..) or name[..] */
4182 /* CASE keywords act as parentheses */
4189 * appears simple since . has top precedence, unless parent is
4190 * T_FieldSelect itself!
4192 return (IsA(parentNode, FieldSelect) ? false : true);
4197 * treat like FieldSelect (probably doesn't matter)
4199 return (IsA(parentNode, FieldStore) ? false : true);
4201 case T_CoerceToDomain:
4202 /* maybe simple, check args */
4203 return isSimpleNode((Node *) ((CoerceToDomain *) node)->arg,
4206 return isSimpleNode((Node *) ((RelabelType *) node)->arg,
4209 return isSimpleNode((Node *) ((CoerceViaIO *) node)->arg,
4211 case T_ArrayCoerceExpr:
4212 return isSimpleNode((Node *) ((ArrayCoerceExpr *) node)->arg,
4214 case T_ConvertRowtypeExpr:
4215 return isSimpleNode((Node *) ((ConvertRowtypeExpr *) node)->arg,
4220 /* depends on parent node type; needs further checking */
4221 if (prettyFlags & PRETTYFLAG_PAREN && IsA(parentNode, OpExpr))
4224 const char *parentOp;
4227 bool is_lopriparent;
4228 bool is_hipriparent;
4230 op = get_simple_binary_op_name((OpExpr *) node);
4234 /* We know only the basic operators + - and * / % */
4235 is_lopriop = (strchr("+-", *op) != NULL);
4236 is_hipriop = (strchr("*/%", *op) != NULL);
4237 if (!(is_lopriop || is_hipriop))
4240 parentOp = get_simple_binary_op_name((OpExpr *) parentNode);
4244 is_lopriparent = (strchr("+-", *parentOp) != NULL);
4245 is_hipriparent = (strchr("*/%", *parentOp) != NULL);
4246 if (!(is_lopriparent || is_hipriparent))
4249 if (is_hipriop && is_lopriparent)
4250 return true; /* op binds tighter than parent */
4252 if (is_lopriop && is_hipriparent)
4256 * Operators are same priority --- can skip parens only if
4257 * we have (a - b) - c, not a - (b - c).
4259 if (node == (Node *) linitial(((OpExpr *) parentNode)->args))
4264 /* else do the same stuff as for T_SubLink et al. */
4271 case T_DistinctExpr:
4272 switch (nodeTag(parentNode))
4276 /* special handling for casts */
4277 CoercionForm type = ((FuncExpr *) parentNode)->funcformat;
4279 if (type == COERCE_EXPLICIT_CAST ||
4280 type == COERCE_IMPLICIT_CAST)
4282 return true; /* own parentheses */
4284 case T_BoolExpr: /* lower precedence */
4285 case T_ArrayRef: /* other separators */
4286 case T_ArrayExpr: /* other separators */
4287 case T_RowExpr: /* other separators */
4288 case T_CoalesceExpr: /* own parentheses */
4289 case T_MinMaxExpr: /* own parentheses */
4290 case T_XmlExpr: /* own parentheses */
4291 case T_NullIfExpr: /* other separators */
4292 case T_Aggref: /* own parentheses */
4293 case T_WindowFunc: /* own parentheses */
4294 case T_CaseExpr: /* other separators */
4301 switch (nodeTag(parentNode))
4304 if (prettyFlags & PRETTYFLAG_PAREN)
4307 BoolExprType parentType;
4309 type = ((BoolExpr *) node)->boolop;
4310 parentType = ((BoolExpr *) parentNode)->boolop;
4315 if (parentType == AND_EXPR || parentType == OR_EXPR)
4319 if (parentType == OR_EXPR)
4327 /* special handling for casts */
4328 CoercionForm type = ((FuncExpr *) parentNode)->funcformat;
4330 if (type == COERCE_EXPLICIT_CAST ||
4331 type == COERCE_IMPLICIT_CAST)
4333 return true; /* own parentheses */
4335 case T_ArrayRef: /* other separators */
4336 case T_ArrayExpr: /* other separators */
4337 case T_RowExpr: /* other separators */
4338 case T_CoalesceExpr: /* own parentheses */
4339 case T_MinMaxExpr: /* own parentheses */
4340 case T_XmlExpr: /* own parentheses */
4341 case T_NullIfExpr: /* other separators */
4342 case T_Aggref: /* own parentheses */
4343 case T_WindowFunc: /* own parentheses */
4344 case T_CaseExpr: /* other separators */
4353 /* those we don't know: in dubio complexo */
4359 * appendContextKeyword - append a keyword to buffer
4361 * If prettyPrint is enabled, perform a line break, and adjust indentation.
4362 * Otherwise, just append the keyword.
4365 appendContextKeyword(deparse_context *context, const char *str,
4366 int indentBefore, int indentAfter, int indentPlus)
4368 if (PRETTY_INDENT(context))
4370 context->indentLevel += indentBefore;
4372 appendStringInfoChar(context->buf, '\n');
4373 appendStringInfoSpaces(context->buf,
4374 Max(context->indentLevel, 0) + indentPlus);
4375 appendStringInfoString(context->buf, str);
4377 context->indentLevel += indentAfter;
4378 if (context->indentLevel < 0)
4379 context->indentLevel = 0;
4382 appendStringInfoString(context->buf, str);
4386 * get_rule_expr_paren - deparse expr using get_rule_expr,
4387 * embracing the string with parentheses if necessary for prettyPrint.
4389 * Never embrace if prettyFlags=0, because it's done in the calling node.
4391 * Any node that does *not* embrace its argument node by sql syntax (with
4392 * parentheses, non-operator keywords like CASE/WHEN/ON, or comma etc) should
4393 * use get_rule_expr_paren instead of get_rule_expr so parentheses can be
4397 get_rule_expr_paren(Node *node, deparse_context *context,
4398 bool showimplicit, Node *parentNode)
4402 need_paren = PRETTY_PAREN(context) &&
4403 !isSimpleNode(node, parentNode, context->prettyFlags);
4406 appendStringInfoChar(context->buf, '(');
4408 get_rule_expr(node, context, showimplicit);
4411 appendStringInfoChar(context->buf, ')');
4416 * get_rule_expr - Parse back an expression
4418 * Note: showimplicit determines whether we display any implicit cast that
4419 * is present at the top of the expression tree. It is a passed argument,
4420 * not a field of the context struct, because we change the value as we
4421 * recurse down into the expression. In general we suppress implicit casts
4422 * when the result type is known with certainty (eg, the arguments of an
4423 * OR must be boolean). We display implicit casts for arguments of functions
4424 * and operators, since this is needed to be certain that the same function
4425 * or operator will be chosen when the expression is re-parsed.
4429 get_rule_expr(Node *node, deparse_context *context,
4432 StringInfo buf = context->buf;
4438 * Each level of get_rule_expr must emit an indivisible term
4439 * (parenthesized if necessary) to ensure result is reparsed into the same
4440 * expression tree. The only exception is that when the input is a List,
4441 * we emit the component items comma-separated with no surrounding
4442 * decoration; this is convenient for most callers.
4444 switch (nodeTag(node))
4447 (void) get_variable((Var *) node, 0, true, context);
4451 get_const_expr((Const *) node, context, 0);
4455 appendStringInfo(buf, "$%d", ((Param *) node)->paramid);
4459 get_agg_expr((Aggref *) node, context);
4463 get_windowfunc_expr((WindowFunc *) node, context);
4468 ArrayRef *aref = (ArrayRef *) node;
4472 * If the argument is a CaseTestExpr, we must be inside a
4473 * FieldStore, ie, we are assigning to an element of an
4474 * array within a composite column. Since we already punted
4475 * on displaying the FieldStore's target information, just
4476 * punt here too, and display only the assignment source
4479 if (IsA(aref->refexpr, CaseTestExpr))
4481 Assert(aref->refassgnexpr);
4482 get_rule_expr((Node *) aref->refassgnexpr,
4483 context, showimplicit);
4488 * Parenthesize the argument unless it's a simple Var or a
4489 * FieldSelect. (In particular, if it's another ArrayRef, we
4490 * *must* parenthesize to avoid confusion.)
4492 need_parens = !IsA(aref->refexpr, Var) &&
4493 !IsA(aref->refexpr, FieldSelect);
4495 appendStringInfoChar(buf, '(');
4496 get_rule_expr((Node *) aref->refexpr, context, showimplicit);
4498 appendStringInfoChar(buf, ')');
4501 * If there's a refassgnexpr, we want to print the node in
4502 * the format "array[subscripts] := refassgnexpr". This is
4503 * not legal SQL, so decompilation of INSERT or UPDATE
4504 * statements should always use processIndirection as part
4505 * of the statement-level syntax. We should only see this
4506 * when EXPLAIN tries to print the targetlist of a plan
4507 * resulting from such a statement.
4509 if (aref->refassgnexpr)
4514 * Use processIndirection to print this node's
4515 * subscripts as well as any additional field selections
4516 * or subscripting in immediate descendants. It returns
4517 * the RHS expr that is actually being "assigned".
4519 refassgnexpr = processIndirection(node, context, true);
4520 appendStringInfoString(buf, " := ");
4521 get_rule_expr(refassgnexpr, context, showimplicit);
4525 /* Just an ordinary array fetch, so print subscripts */
4526 printSubscripts(aref, context);
4532 get_func_expr((FuncExpr *) node, context, showimplicit);
4535 case T_NamedArgExpr:
4537 NamedArgExpr *na = (NamedArgExpr *) node;
4539 get_rule_expr((Node *) na->arg, context, showimplicit);
4540 appendStringInfo(buf, " AS %s", quote_identifier(na->name));
4545 get_oper_expr((OpExpr *) node, context);
4548 case T_DistinctExpr:
4550 DistinctExpr *expr = (DistinctExpr *) node;
4551 List *args = expr->args;
4552 Node *arg1 = (Node *) linitial(args);
4553 Node *arg2 = (Node *) lsecond(args);
4555 if (!PRETTY_PAREN(context))
4556 appendStringInfoChar(buf, '(');
4557 get_rule_expr_paren(arg1, context, true, node);
4558 appendStringInfo(buf, " IS DISTINCT FROM ");
4559 get_rule_expr_paren(arg2, context, true, node);
4560 if (!PRETTY_PAREN(context))
4561 appendStringInfoChar(buf, ')');
4565 case T_ScalarArrayOpExpr:
4567 ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
4568 List *args = expr->args;
4569 Node *arg1 = (Node *) linitial(args);
4570 Node *arg2 = (Node *) lsecond(args);
4572 if (!PRETTY_PAREN(context))
4573 appendStringInfoChar(buf, '(');
4574 get_rule_expr_paren(arg1, context, true, node);
4575 appendStringInfo(buf, " %s %s (",
4576 generate_operator_name(expr->opno,
4578 get_element_type(exprType(arg2))),
4579 expr->useOr ? "ANY" : "ALL");
4580 get_rule_expr_paren(arg2, context, true, node);
4581 appendStringInfoChar(buf, ')');
4582 if (!PRETTY_PAREN(context))
4583 appendStringInfoChar(buf, ')');
4589 BoolExpr *expr = (BoolExpr *) node;
4590 Node *first_arg = linitial(expr->args);
4591 ListCell *arg = lnext(list_head(expr->args));
4593 switch (expr->boolop)
4596 if (!PRETTY_PAREN(context))
4597 appendStringInfoChar(buf, '(');
4598 get_rule_expr_paren(first_arg, context,
4602 appendStringInfo(buf, " AND ");
4603 get_rule_expr_paren((Node *) lfirst(arg), context,
4607 if (!PRETTY_PAREN(context))
4608 appendStringInfoChar(buf, ')');
4612 if (!PRETTY_PAREN(context))
4613 appendStringInfoChar(buf, '(');
4614 get_rule_expr_paren(first_arg, context,
4618 appendStringInfo(buf, " OR ");
4619 get_rule_expr_paren((Node *) lfirst(arg), context,
4623 if (!PRETTY_PAREN(context))
4624 appendStringInfoChar(buf, ')');
4628 if (!PRETTY_PAREN(context))
4629 appendStringInfoChar(buf, '(');
4630 appendStringInfo(buf, "NOT ");
4631 get_rule_expr_paren(first_arg, context,
4633 if (!PRETTY_PAREN(context))
4634 appendStringInfoChar(buf, ')');
4638 elog(ERROR, "unrecognized boolop: %d",
4639 (int) expr->boolop);
4645 get_sublink_expr((SubLink *) node, context);
4650 SubPlan *subplan = (SubPlan *) node;
4653 * We cannot see an already-planned subplan in rule deparsing,
4654 * only while EXPLAINing a query plan. We don't try to
4655 * reconstruct the original SQL, just reference the subplan
4656 * that appears elsewhere in EXPLAIN's result.
4658 if (subplan->useHashTable)
4659 appendStringInfo(buf, "(hashed %s)", subplan->plan_name);
4661 appendStringInfo(buf, "(%s)", subplan->plan_name);
4665 case T_AlternativeSubPlan:
4667 AlternativeSubPlan *asplan = (AlternativeSubPlan *) node;
4670 /* As above, this can only happen during EXPLAIN */
4671 appendStringInfo(buf, "(alternatives: ");
4672 foreach(lc, asplan->subplans)
4674 SubPlan *splan = (SubPlan *) lfirst(lc);
4676 Assert(IsA(splan, SubPlan));
4677 if (splan->useHashTable)
4678 appendStringInfo(buf, "hashed %s", splan->plan_name);
4680 appendStringInfo(buf, "%s", splan->plan_name);
4682 appendStringInfo(buf, " or ");
4684 appendStringInfo(buf, ")");
4690 FieldSelect *fselect = (FieldSelect *) node;
4691 Node *arg = (Node *) fselect->arg;
4692 int fno = fselect->fieldnum;
4693 const char *fieldname;
4697 * Parenthesize the argument unless it's an ArrayRef or
4698 * another FieldSelect. Note in particular that it would be
4699 * WRONG to not parenthesize a Var argument; simplicity is not
4700 * the issue here, having the right number of names is.
4702 need_parens = !IsA(arg, ArrayRef) &&!IsA(arg, FieldSelect);
4704 appendStringInfoChar(buf, '(');
4705 get_rule_expr(arg, context, true);
4707 appendStringInfoChar(buf, ')');
4710 * Get and print the field name.
4712 fieldname = get_name_for_var_field((Var *) arg, fno,
4714 appendStringInfo(buf, ".%s", quote_identifier(fieldname));
4720 FieldStore *fstore = (FieldStore *) node;
4724 * There is no good way to represent a FieldStore as real SQL,
4725 * so decompilation of INSERT or UPDATE statements should
4726 * always use processIndirection as part of the
4727 * statement-level syntax. We should only get here when
4728 * EXPLAIN tries to print the targetlist of a plan resulting
4729 * from such a statement. The plan case is even harder than
4730 * ordinary rules would be, because the planner tries to
4731 * collapse multiple assignments to the same field or subfield
4732 * into one FieldStore; so we can see a list of target fields
4733 * not just one, and the arguments could be FieldStores
4734 * themselves. We don't bother to try to print the target
4735 * field names; we just print the source arguments, with a
4736 * ROW() around them if there's more than one. This isn't
4737 * terribly complete, but it's probably good enough for
4738 * EXPLAIN's purposes; especially since anything more would be
4739 * either hopelessly confusing or an even poorer
4740 * representation of what the plan is actually doing.
4742 need_parens = (list_length(fstore->newvals) != 1);
4744 appendStringInfoString(buf, "ROW(");
4745 get_rule_expr((Node *) fstore->newvals, context, showimplicit);
4747 appendStringInfoChar(buf, ')');
4753 RelabelType *relabel = (RelabelType *) node;
4754 Node *arg = (Node *) relabel->arg;
4756 if (relabel->relabelformat == COERCE_IMPLICIT_CAST &&
4759 /* don't show the implicit cast */
4760 get_rule_expr_paren(arg, context, false, node);
4764 get_coercion_expr(arg, context,
4765 relabel->resulttype,
4766 relabel->resulttypmod,
4774 CoerceViaIO *iocoerce = (CoerceViaIO *) node;
4775 Node *arg = (Node *) iocoerce->arg;
4777 if (iocoerce->coerceformat == COERCE_IMPLICIT_CAST &&
4780 /* don't show the implicit cast */
4781 get_rule_expr_paren(arg, context, false, node);
4785 get_coercion_expr(arg, context,
4786 iocoerce->resulttype,
4793 case T_ArrayCoerceExpr:
4795 ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;
4796 Node *arg = (Node *) acoerce->arg;
4798 if (acoerce->coerceformat == COERCE_IMPLICIT_CAST &&
4801 /* don't show the implicit cast */
4802 get_rule_expr_paren(arg, context, false, node);
4806 get_coercion_expr(arg, context,
4807 acoerce->resulttype,
4808 acoerce->resulttypmod,
4814 case T_ConvertRowtypeExpr:
4816 ConvertRowtypeExpr *convert = (ConvertRowtypeExpr *) node;
4817 Node *arg = (Node *) convert->arg;
4819 if (convert->convertformat == COERCE_IMPLICIT_CAST &&
4822 /* don't show the implicit cast */
4823 get_rule_expr_paren(arg, context, false, node);
4827 get_coercion_expr(arg, context,
4828 convert->resulttype, -1,
4836 CaseExpr *caseexpr = (CaseExpr *) node;
4839 appendContextKeyword(context, "CASE",
4840 0, PRETTYINDENT_VAR, 0);
4843 appendStringInfoChar(buf, ' ');
4844 get_rule_expr((Node *) caseexpr->arg, context, true);
4846 foreach(temp, caseexpr->args)
4848 CaseWhen *when = (CaseWhen *) lfirst(temp);
4849 Node *w = (Node *) when->expr;
4851 if (!PRETTY_INDENT(context))
4852 appendStringInfoChar(buf, ' ');
4853 appendContextKeyword(context, "WHEN ",
4858 * The parser should have produced WHEN clauses of the
4859 * form "CaseTestExpr = RHS"; we want to show just the
4860 * RHS. If the user wrote something silly like "CASE
4861 * boolexpr WHEN TRUE THEN ...", then the optimizer's
4862 * simplify_boolean_equality() may have reduced this
4863 * to just "CaseTestExpr" or "NOT CaseTestExpr", for
4864 * which we have to show "TRUE" or "FALSE". Also,
4865 * depending on context the original CaseTestExpr
4866 * might have been reduced to a Const (but we won't
4867 * see "WHEN Const"). We have also to consider the
4868 * possibility that an implicit coercion was inserted
4869 * between the CaseTestExpr and the operator.
4873 List *args = ((OpExpr *) w)->args;
4877 Assert(list_length(args) == 2);
4878 lhs = strip_implicit_coercions(linitial(args));
4879 Assert(IsA(lhs, CaseTestExpr) ||
4881 rhs = (Node *) lsecond(args);
4882 get_rule_expr(rhs, context, false);
4884 else if (IsA(strip_implicit_coercions(w),
4886 appendStringInfo(buf, "TRUE");
4887 else if (not_clause(w))
4889 Assert(IsA(strip_implicit_coercions((Node *) get_notclausearg((Expr *) w)),
4891 appendStringInfo(buf, "FALSE");
4894 elog(ERROR, "unexpected CASE WHEN clause: %d",
4898 get_rule_expr(w, context, false);
4899 appendStringInfo(buf, " THEN ");
4900 get_rule_expr((Node *) when->result, context, true);
4902 if (!PRETTY_INDENT(context))
4903 appendStringInfoChar(buf, ' ');
4904 appendContextKeyword(context, "ELSE ",
4906 get_rule_expr((Node *) caseexpr->defresult, context, true);
4907 if (!PRETTY_INDENT(context))
4908 appendStringInfoChar(buf, ' ');
4909 appendContextKeyword(context, "END",
4910 -PRETTYINDENT_VAR, 0, 0);
4916 ArrayExpr *arrayexpr = (ArrayExpr *) node;
4918 appendStringInfo(buf, "ARRAY[");
4919 get_rule_expr((Node *) arrayexpr->elements, context, true);
4920 appendStringInfoChar(buf, ']');
4923 * If the array isn't empty, we assume its elements are
4924 * coerced to the desired type. If it's empty, though, we
4925 * need an explicit coercion to the array type.
4927 if (arrayexpr->elements == NIL)
4928 appendStringInfo(buf, "::%s",
4929 format_type_with_typemod(arrayexpr->array_typeid, -1));
4935 RowExpr *rowexpr = (RowExpr *) node;
4936 TupleDesc tupdesc = NULL;
4942 * If it's a named type and not RECORD, we may have to skip
4943 * dropped columns and/or claim there are NULLs for added
4946 if (rowexpr->row_typeid != RECORDOID)
4948 tupdesc = lookup_rowtype_tupdesc(rowexpr->row_typeid, -1);
4949 Assert(list_length(rowexpr->args) <= tupdesc->natts);
4953 * SQL99 allows "ROW" to be omitted when there is more than
4954 * one column, but for simplicity we always print it.
4956 appendStringInfo(buf, "ROW(");
4959 foreach(arg, rowexpr->args)
4961 Node *e = (Node *) lfirst(arg);
4963 if (tupdesc == NULL ||
4964 !tupdesc->attrs[i]->attisdropped)
4966 appendStringInfoString(buf, sep);
4967 get_rule_expr(e, context, true);
4972 if (tupdesc != NULL)
4974 while (i < tupdesc->natts)
4976 if (!tupdesc->attrs[i]->attisdropped)
4978 appendStringInfoString(buf, sep);
4979 appendStringInfo(buf, "NULL");
4985 ReleaseTupleDesc(tupdesc);
4987 appendStringInfo(buf, ")");
4988 if (rowexpr->row_format == COERCE_EXPLICIT_CAST)
4989 appendStringInfo(buf, "::%s",
4990 format_type_with_typemod(rowexpr->row_typeid, -1));
4994 case T_RowCompareExpr:
4996 RowCompareExpr *rcexpr = (RowCompareExpr *) node;
5001 * SQL99 allows "ROW" to be omitted when there is more than
5002 * one column, but for simplicity we always print it.
5004 appendStringInfo(buf, "(ROW(");
5006 foreach(arg, rcexpr->largs)
5008 Node *e = (Node *) lfirst(arg);
5010 appendStringInfoString(buf, sep);
5011 get_rule_expr(e, context, true);
5016 * We assume that the name of the first-column operator will
5017 * do for all the rest too. This is definitely open to
5018 * failure, eg if some but not all operators were renamed
5019 * since the construct was parsed, but there seems no way to
5022 appendStringInfo(buf, ") %s ROW(",
5023 generate_operator_name(linitial_oid(rcexpr->opnos),
5024 exprType(linitial(rcexpr->largs)),
5025 exprType(linitial(rcexpr->rargs))));
5027 foreach(arg, rcexpr->rargs)
5029 Node *e = (Node *) lfirst(arg);
5031 appendStringInfoString(buf, sep);
5032 get_rule_expr(e, context, true);
5035 appendStringInfo(buf, "))");
5039 case T_CoalesceExpr:
5041 CoalesceExpr *coalesceexpr = (CoalesceExpr *) node;
5043 appendStringInfo(buf, "COALESCE(");
5044 get_rule_expr((Node *) coalesceexpr->args, context, true);
5045 appendStringInfoChar(buf, ')');
5051 MinMaxExpr *minmaxexpr = (MinMaxExpr *) node;
5053 switch (minmaxexpr->op)
5056 appendStringInfo(buf, "GREATEST(");
5059 appendStringInfo(buf, "LEAST(");
5062 get_rule_expr((Node *) minmaxexpr->args, context, true);
5063 appendStringInfoChar(buf, ')');
5069 XmlExpr *xexpr = (XmlExpr *) node;
5070 bool needcomma = false;
5078 appendStringInfoString(buf, "XMLCONCAT(");
5081 appendStringInfoString(buf, "XMLELEMENT(");
5084 appendStringInfoString(buf, "XMLFOREST(");
5087 appendStringInfoString(buf, "XMLPARSE(");
5090 appendStringInfoString(buf, "XMLPI(");
5093 appendStringInfoString(buf, "XMLROOT(");
5095 case IS_XMLSERIALIZE:
5096 appendStringInfoString(buf, "XMLSERIALIZE(");
5101 if (xexpr->op == IS_XMLPARSE || xexpr->op == IS_XMLSERIALIZE)
5103 if (xexpr->xmloption == XMLOPTION_DOCUMENT)
5104 appendStringInfoString(buf, "DOCUMENT ");
5106 appendStringInfoString(buf, "CONTENT ");
5110 appendStringInfo(buf, "NAME %s",
5111 quote_identifier(map_xml_name_to_sql_identifier(xexpr->name)));
5114 if (xexpr->named_args)
5116 if (xexpr->op != IS_XMLFOREST)
5119 appendStringInfoString(buf, ", ");
5120 appendStringInfoString(buf, "XMLATTRIBUTES(");
5123 forboth(arg, xexpr->named_args, narg, xexpr->arg_names)
5125 Node *e = (Node *) lfirst(arg);
5126 char *argname = strVal(lfirst(narg));
5129 appendStringInfoString(buf, ", ");
5130 get_rule_expr((Node *) e, context, true);
5131 appendStringInfo(buf, " AS %s",
5132 quote_identifier(map_xml_name_to_sql_identifier(argname)));
5135 if (xexpr->op != IS_XMLFOREST)
5136 appendStringInfoChar(buf, ')');
5141 appendStringInfoString(buf, ", ");
5148 case IS_XMLSERIALIZE:
5149 /* no extra decoration needed */
5150 get_rule_expr((Node *) xexpr->args, context, true);
5153 Assert(list_length(xexpr->args) == 2);
5155 get_rule_expr((Node *) linitial(xexpr->args),
5158 con = (Const *) lsecond(xexpr->args);
5159 Assert(IsA(con, Const));
5160 Assert(!con->constisnull);
5161 if (DatumGetBool(con->constvalue))
5162 appendStringInfoString(buf,
5163 " PRESERVE WHITESPACE");
5165 appendStringInfoString(buf,
5166 " STRIP WHITESPACE");
5169 Assert(list_length(xexpr->args) == 3);
5171 get_rule_expr((Node *) linitial(xexpr->args),
5174 appendStringInfoString(buf, ", VERSION ");
5175 con = (Const *) lsecond(xexpr->args);
5176 if (IsA(con, Const) &&
5178 appendStringInfoString(buf, "NO VALUE");
5180 get_rule_expr((Node *) con, context, false);
5182 con = (Const *) lthird(xexpr->args);
5183 Assert(IsA(con, Const));
5184 if (con->constisnull)
5185 /* suppress STANDALONE NO VALUE */ ;
5188 switch (DatumGetInt32(con->constvalue))
5190 case XML_STANDALONE_YES:
5191 appendStringInfoString(buf,
5192 ", STANDALONE YES");
5194 case XML_STANDALONE_NO:
5195 appendStringInfoString(buf,
5198 case XML_STANDALONE_NO_VALUE:
5199 appendStringInfoString(buf,
5200 ", STANDALONE NO VALUE");
5208 get_rule_expr_paren((Node *) xexpr->args, context, false, node);
5213 if (xexpr->op == IS_XMLSERIALIZE)
5214 appendStringInfo(buf, " AS %s", format_type_with_typemod(xexpr->type,
5216 if (xexpr->op == IS_DOCUMENT)
5217 appendStringInfoString(buf, " IS DOCUMENT");
5219 appendStringInfoChar(buf, ')');
5225 NullIfExpr *nullifexpr = (NullIfExpr *) node;
5227 appendStringInfo(buf, "NULLIF(");
5228 get_rule_expr((Node *) nullifexpr->args, context, true);
5229 appendStringInfoChar(buf, ')');
5235 NullTest *ntest = (NullTest *) node;
5237 if (!PRETTY_PAREN(context))
5238 appendStringInfoChar(buf, '(');
5239 get_rule_expr_paren((Node *) ntest->arg, context, true, node);
5240 switch (ntest->nulltesttype)
5243 appendStringInfo(buf, " IS NULL");
5246 appendStringInfo(buf, " IS NOT NULL");
5249 elog(ERROR, "unrecognized nulltesttype: %d",
5250 (int) ntest->nulltesttype);
5252 if (!PRETTY_PAREN(context))
5253 appendStringInfoChar(buf, ')');
5259 BooleanTest *btest = (BooleanTest *) node;
5261 if (!PRETTY_PAREN(context))
5262 appendStringInfoChar(buf, '(');
5263 get_rule_expr_paren((Node *) btest->arg, context, false, node);
5264 switch (btest->booltesttype)
5267 appendStringInfo(buf, " IS TRUE");
5270 appendStringInfo(buf, " IS NOT TRUE");
5273 appendStringInfo(buf, " IS FALSE");
5276 appendStringInfo(buf, " IS NOT FALSE");
5279 appendStringInfo(buf, " IS UNKNOWN");
5281 case IS_NOT_UNKNOWN:
5282 appendStringInfo(buf, " IS NOT UNKNOWN");
5285 elog(ERROR, "unrecognized booltesttype: %d",
5286 (int) btest->booltesttype);
5288 if (!PRETTY_PAREN(context))
5289 appendStringInfoChar(buf, ')');
5293 case T_CoerceToDomain:
5295 CoerceToDomain *ctest = (CoerceToDomain *) node;
5296 Node *arg = (Node *) ctest->arg;
5298 if (ctest->coercionformat == COERCE_IMPLICIT_CAST &&
5301 /* don't show the implicit cast */
5302 get_rule_expr(arg, context, false);
5306 get_coercion_expr(arg, context,
5308 ctest->resulttypmod,
5314 case T_CoerceToDomainValue:
5315 appendStringInfo(buf, "VALUE");
5318 case T_SetToDefault:
5319 appendStringInfo(buf, "DEFAULT");
5322 case T_CurrentOfExpr:
5324 CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
5326 if (cexpr->cursor_name)
5327 appendStringInfo(buf, "CURRENT OF %s",
5328 quote_identifier(cexpr->cursor_name));
5330 appendStringInfo(buf, "CURRENT OF $%d",
5331 cexpr->cursor_param);
5341 foreach(l, (List *) node)
5343 appendStringInfoString(buf, sep);
5344 get_rule_expr((Node *) lfirst(l), context, showimplicit);
5351 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
5358 * get_oper_expr - Parse back an OpExpr node
5361 get_oper_expr(OpExpr *expr, deparse_context *context)
5363 StringInfo buf = context->buf;
5364 Oid opno = expr->opno;
5365 List *args = expr->args;
5367 if (!PRETTY_PAREN(context))
5368 appendStringInfoChar(buf, '(');
5369 if (list_length(args) == 2)
5371 /* binary operator */
5372 Node *arg1 = (Node *) linitial(args);
5373 Node *arg2 = (Node *) lsecond(args);
5375 get_rule_expr_paren(arg1, context, true, (Node *) expr);
5376 appendStringInfo(buf, " %s ",
5377 generate_operator_name(opno,
5380 get_rule_expr_paren(arg2, context, true, (Node *) expr);
5384 /* unary operator --- but which side? */
5385 Node *arg = (Node *) linitial(args);
5387 Form_pg_operator optup;
5389 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
5390 if (!HeapTupleIsValid(tp))
5391 elog(ERROR, "cache lookup failed for operator %u", opno);
5392 optup = (Form_pg_operator) GETSTRUCT(tp);
5393 switch (optup->oprkind)
5396 appendStringInfo(buf, "%s ",
5397 generate_operator_name(opno,
5400 get_rule_expr_paren(arg, context, true, (Node *) expr);
5403 get_rule_expr_paren(arg, context, true, (Node *) expr);
5404 appendStringInfo(buf, " %s",
5405 generate_operator_name(opno,
5410 elog(ERROR, "bogus oprkind: %d", optup->oprkind);
5412 ReleaseSysCache(tp);
5414 if (!PRETTY_PAREN(context))
5415 appendStringInfoChar(buf, ')');
5419 * get_func_expr - Parse back a FuncExpr node
5422 get_func_expr(FuncExpr *expr, deparse_context *context,
5425 StringInfo buf = context->buf;
5426 Oid funcoid = expr->funcid;
5427 Oid argtypes[FUNC_MAX_ARGS];
5434 * If the function call came from an implicit coercion, then just show the
5435 * first argument --- unless caller wants to see implicit coercions.
5437 if (expr->funcformat == COERCE_IMPLICIT_CAST && !showimplicit)
5439 get_rule_expr_paren((Node *) linitial(expr->args), context,
5440 false, (Node *) expr);
5445 * If the function call came from a cast, then show the first argument
5446 * plus an explicit cast operation.
5448 if (expr->funcformat == COERCE_EXPLICIT_CAST ||
5449 expr->funcformat == COERCE_IMPLICIT_CAST)
5451 Node *arg = linitial(expr->args);
5452 Oid rettype = expr->funcresulttype;
5453 int32 coercedTypmod;
5455 /* Get the typmod if this is a length-coercion function */
5456 (void) exprIsLengthCoercion((Node *) expr, &coercedTypmod);
5458 get_coercion_expr(arg, context,
5459 rettype, coercedTypmod,
5466 * Normal function: display as proname(args). First we need to extract
5467 * the argument datatypes.
5469 if (list_length(expr->args) > FUNC_MAX_ARGS)
5471 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
5472 errmsg("too many arguments")));
5475 foreach(l, expr->args)
5477 Node *arg = (Node *) lfirst(l);
5479 if (IsA(arg, NamedArgExpr))
5480 argnames = lappend(argnames, ((NamedArgExpr *) arg)->name);
5481 argtypes[nargs] = exprType(arg);
5485 appendStringInfo(buf, "%s(",
5486 generate_function_name(funcoid, nargs,
5490 foreach(l, expr->args)
5493 appendStringInfoString(buf, ", ");
5494 if (is_variadic && lnext(l) == NULL)
5495 appendStringInfoString(buf, "VARIADIC ");
5496 get_rule_expr((Node *) lfirst(l), context, true);
5498 appendStringInfoChar(buf, ')');
5502 * get_agg_expr - Parse back an Aggref node
5505 get_agg_expr(Aggref *aggref, deparse_context *context)
5507 StringInfo buf = context->buf;
5508 Oid argtypes[FUNC_MAX_ARGS];
5513 /* Extract the regular arguments, ignoring resjunk stuff for the moment */
5516 foreach(l, aggref->args)
5518 TargetEntry *tle = (TargetEntry *) lfirst(l);
5519 Node *arg = (Node *) tle->expr;
5521 Assert(!IsA(arg, NamedArgExpr));
5524 if (nargs >= FUNC_MAX_ARGS) /* paranoia */
5526 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
5527 errmsg("too many arguments")));
5528 argtypes[nargs] = exprType(arg);
5529 arglist = lappend(arglist, arg);
5533 appendStringInfo(buf, "%s(%s",
5534 generate_function_name(aggref->aggfnoid, nargs,
5535 NIL, argtypes, NULL),
5536 (aggref->aggdistinct != NIL) ? "DISTINCT " : "");
5537 /* aggstar can be set only in zero-argument aggregates */
5538 if (aggref->aggstar)
5539 appendStringInfoChar(buf, '*');
5541 get_rule_expr((Node *) arglist, context, true);
5542 if (aggref->aggorder != NIL)
5544 appendStringInfoString(buf, " ORDER BY ");
5545 get_rule_orderby(aggref->aggorder, aggref->args, false, context);
5547 appendStringInfoChar(buf, ')');
5551 * get_windowfunc_expr - Parse back a WindowFunc node
5554 get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context)
5556 StringInfo buf = context->buf;
5557 Oid argtypes[FUNC_MAX_ARGS];
5561 if (list_length(wfunc->args) > FUNC_MAX_ARGS)
5563 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
5564 errmsg("too many arguments")));
5566 foreach(l, wfunc->args)
5568 Node *arg = (Node *) lfirst(l);
5570 Assert(!IsA(arg, NamedArgExpr));
5571 argtypes[nargs] = exprType(arg);
5575 appendStringInfo(buf, "%s(",
5576 generate_function_name(wfunc->winfnoid, nargs,
5577 NIL, argtypes, NULL));
5578 /* winstar can be set only in zero-argument aggregates */
5580 appendStringInfoChar(buf, '*');
5582 get_rule_expr((Node *) wfunc->args, context, true);
5583 appendStringInfoString(buf, ") OVER ");
5585 foreach(l, context->windowClause)
5587 WindowClause *wc = (WindowClause *) lfirst(l);
5589 if (wc->winref == wfunc->winref)
5592 appendStringInfoString(buf, quote_identifier(wc->name));
5594 get_rule_windowspec(wc, context->windowTList, context);
5600 if (context->windowClause)
5601 elog(ERROR, "could not find window clause for winref %u",
5605 * In EXPLAIN, we don't have window context information available, so
5606 * we have to settle for this:
5608 appendStringInfoString(buf, "(?)");
5615 * Make a string representation of a value coerced to a specific type
5619 get_coercion_expr(Node *arg, deparse_context *context,
5620 Oid resulttype, int32 resulttypmod,
5623 StringInfo buf = context->buf;
5626 * Since parse_coerce.c doesn't immediately collapse application of
5627 * length-coercion functions to constants, what we'll typically see in
5628 * such cases is a Const with typmod -1 and a length-coercion function
5629 * right above it. Avoid generating redundant output. However, beware of
5630 * suppressing casts when the user actually wrote something like
5631 * 'foo'::text::char(3).
5633 if (arg && IsA(arg, Const) &&
5634 ((Const *) arg)->consttype == resulttype &&
5635 ((Const *) arg)->consttypmod == -1)
5637 /* Show the constant without normal ::typename decoration */
5638 get_const_expr((Const *) arg, context, -1);
5642 if (!PRETTY_PAREN(context))
5643 appendStringInfoChar(buf, '(');
5644 get_rule_expr_paren(arg, context, false, parentNode);
5645 if (!PRETTY_PAREN(context))
5646 appendStringInfoChar(buf, ')');
5648 appendStringInfo(buf, "::%s",
5649 format_type_with_typemod(resulttype, resulttypmod));
5655 * Make a string representation of a Const
5657 * showtype can be -1 to never show "::typename" decoration, or +1 to always
5658 * show it, or 0 to show it only if the constant wouldn't be assumed to be
5659 * the right type by default.
5663 get_const_expr(Const *constval, deparse_context *context, int showtype)
5665 StringInfo buf = context->buf;
5669 bool isfloat = false;
5672 if (constval->constisnull)
5675 * Always label the type of a NULL constant to prevent misdecisions
5676 * about type when reparsing.
5678 appendStringInfo(buf, "NULL");
5680 appendStringInfo(buf, "::%s",
5681 format_type_with_typemod(constval->consttype,
5682 constval->consttypmod));
5686 getTypeOutputInfo(constval->consttype,
5687 &typoutput, &typIsVarlena);
5689 extval = OidOutputFunctionCall(typoutput, constval->constvalue);
5691 switch (constval->consttype)
5702 * These types are printed without quotes unless they contain
5703 * values that aren't accepted by the scanner unquoted (e.g.,
5704 * 'NaN'). Note that strtod() and friends might accept NaN,
5705 * so we can't use that to test.
5707 * In reality we only need to defend against infinity and NaN,
5708 * so we need not get too crazy about pattern matching here.
5710 * There is a special-case gotcha: if the constant is signed,
5711 * we need to parenthesize it, else the parser might see a
5712 * leading plus/minus as binding less tightly than adjacent
5713 * operators --- particularly, the cast that we might attach
5716 if (strspn(extval, "0123456789+-eE.") == strlen(extval))
5718 if (extval[0] == '+' || extval[0] == '-')
5719 appendStringInfo(buf, "(%s)", extval);
5721 appendStringInfoString(buf, extval);
5722 if (strcspn(extval, "eE.") != strlen(extval))
5723 isfloat = true; /* it looks like a float */
5726 appendStringInfo(buf, "'%s'", extval);
5732 appendStringInfo(buf, "B'%s'", extval);
5736 if (strcmp(extval, "t") == 0)
5737 appendStringInfo(buf, "true");
5739 appendStringInfo(buf, "false");
5743 simple_quote_literal(buf, extval);
5753 * For showtype == 0, append ::typename unless the constant will be
5754 * implicitly typed as the right type when it is read in.
5756 * XXX this code has to be kept in sync with the behavior of the parser,
5757 * especially make_const.
5759 switch (constval->consttype)
5764 /* These types can be left unlabeled */
5770 * Float-looking constants will be typed as numeric, but if
5771 * there's a specific typmod we need to show it.
5773 needlabel = !isfloat || (constval->consttypmod >= 0);
5779 if (needlabel || showtype > 0)
5780 appendStringInfo(buf, "::%s",
5781 format_type_with_typemod(constval->consttype,
5782 constval->consttypmod));
5786 * simple_quote_literal - Format a string as a SQL literal, append to buf
5789 simple_quote_literal(StringInfo buf, const char *val)
5794 * We form the string literal according to the prevailing setting of
5795 * standard_conforming_strings; we never use E''. User is responsible for
5796 * making sure result is used correctly.
5798 appendStringInfoChar(buf, '\'');
5799 for (valptr = val; *valptr; valptr++)
5803 if (SQL_STR_DOUBLE(ch, !standard_conforming_strings))
5804 appendStringInfoChar(buf, ch);
5805 appendStringInfoChar(buf, ch);
5807 appendStringInfoChar(buf, '\'');
5812 * get_sublink_expr - Parse back a sublink
5816 get_sublink_expr(SubLink *sublink, deparse_context *context)
5818 StringInfo buf = context->buf;
5819 Query *query = (Query *) (sublink->subselect);
5820 char *opname = NULL;
5823 if (sublink->subLinkType == ARRAY_SUBLINK)
5824 appendStringInfo(buf, "ARRAY(");
5826 appendStringInfoChar(buf, '(');
5829 * Note that we print the name of only the first operator, when there are
5830 * multiple combining operators. This is an approximation that could go
5831 * wrong in various scenarios (operators in different schemas, renamed
5832 * operators, etc) but there is not a whole lot we can do about it, since
5833 * the syntax allows only one operator to be shown.
5835 if (sublink->testexpr)
5837 if (IsA(sublink->testexpr, OpExpr))
5839 /* single combining operator */
5840 OpExpr *opexpr = (OpExpr *) sublink->testexpr;
5842 get_rule_expr(linitial(opexpr->args), context, true);
5843 opname = generate_operator_name(opexpr->opno,
5844 exprType(linitial(opexpr->args)),
5845 exprType(lsecond(opexpr->args)));
5847 else if (IsA(sublink->testexpr, BoolExpr))
5849 /* multiple combining operators, = or <> cases */
5853 appendStringInfoChar(buf, '(');
5855 foreach(l, ((BoolExpr *) sublink->testexpr)->args)
5857 OpExpr *opexpr = (OpExpr *) lfirst(l);
5859 Assert(IsA(opexpr, OpExpr));
5860 appendStringInfoString(buf, sep);
5861 get_rule_expr(linitial(opexpr->args), context, true);
5863 opname = generate_operator_name(opexpr->opno,
5864 exprType(linitial(opexpr->args)),
5865 exprType(lsecond(opexpr->args)));
5868 appendStringInfoChar(buf, ')');
5870 else if (IsA(sublink->testexpr, RowCompareExpr))
5872 /* multiple combining operators, < <= > >= cases */
5873 RowCompareExpr *rcexpr = (RowCompareExpr *) sublink->testexpr;
5875 appendStringInfoChar(buf, '(');
5876 get_rule_expr((Node *) rcexpr->largs, context, true);
5877 opname = generate_operator_name(linitial_oid(rcexpr->opnos),
5878 exprType(linitial(rcexpr->largs)),
5879 exprType(linitial(rcexpr->rargs)));
5880 appendStringInfoChar(buf, ')');
5883 elog(ERROR, "unrecognized testexpr type: %d",
5884 (int) nodeTag(sublink->testexpr));
5889 switch (sublink->subLinkType)
5891 case EXISTS_SUBLINK:
5892 appendStringInfo(buf, "EXISTS ");
5896 if (strcmp(opname, "=") == 0) /* Represent = ANY as IN */
5897 appendStringInfo(buf, " IN ");
5899 appendStringInfo(buf, " %s ANY ", opname);
5903 appendStringInfo(buf, " %s ALL ", opname);
5906 case ROWCOMPARE_SUBLINK:
5907 appendStringInfo(buf, " %s ", opname);
5915 case CTE_SUBLINK: /* shouldn't occur in a SubLink */
5917 elog(ERROR, "unrecognized sublink type: %d",
5918 (int) sublink->subLinkType);
5923 appendStringInfoChar(buf, '(');
5925 get_query_def(query, buf, context->namespaces, NULL,
5926 context->prettyFlags, context->indentLevel);
5929 appendStringInfo(buf, "))");
5931 appendStringInfoChar(buf, ')');
5936 * get_from_clause - Parse back a FROM clause
5938 * "prefix" is the keyword that denotes the start of the list of FROM
5939 * elements. It is FROM when used to parse back SELECT and UPDATE, but
5940 * is USING when parsing back DELETE.
5944 get_from_clause(Query *query, const char *prefix, deparse_context *context)
5946 StringInfo buf = context->buf;
5951 * We use the query's jointree as a guide to what to print. However, we
5952 * must ignore auto-added RTEs that are marked not inFromCl. (These can
5953 * only appear at the top level of the jointree, so it's sufficient to
5954 * check here.) This check also ensures we ignore the rule pseudo-RTEs
5957 foreach(l, query->jointree->fromlist)
5959 Node *jtnode = (Node *) lfirst(l);
5961 if (IsA(jtnode, RangeTblRef))
5963 int varno = ((RangeTblRef *) jtnode)->rtindex;
5964 RangeTblEntry *rte = rt_fetch(varno, query->rtable);
5972 appendContextKeyword(context, prefix,
5973 -PRETTYINDENT_STD, PRETTYINDENT_STD, 2);
5977 appendStringInfoString(buf, ", ");
5979 get_from_clause_item(jtnode, query, context);
5984 get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
5986 StringInfo buf = context->buf;
5988 if (IsA(jtnode, RangeTblRef))
5990 int varno = ((RangeTblRef *) jtnode)->rtindex;
5991 RangeTblEntry *rte = rt_fetch(varno, query->rtable);
5992 bool gavealias = false;
5994 switch (rte->rtekind)
5997 /* Normal relation RTE */
5998 appendStringInfo(buf, "%s%s",
6000 generate_relation_name(rte->relid,
6001 context->namespaces));
6005 appendStringInfoChar(buf, '(');
6006 get_query_def(rte->subquery, buf, context->namespaces, NULL,
6007 context->prettyFlags, context->indentLevel);
6008 appendStringInfoChar(buf, ')');
6012 get_rule_expr(rte->funcexpr, context, true);
6015 /* Values list RTE */
6016 get_values_def(rte->values_lists, context);
6019 appendStringInfoString(buf, quote_identifier(rte->ctename));
6022 elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
6026 if (rte->alias != NULL)
6028 appendStringInfo(buf, " %s",
6029 quote_identifier(rte->alias->aliasname));
6032 else if (rte->rtekind == RTE_RELATION &&
6033 strcmp(rte->eref->aliasname, get_rel_name(rte->relid)) != 0)
6036 * Apparently the rel has been renamed since the rule was made.
6037 * Emit a fake alias clause so that variable references will still
6038 * work. This is not a 100% solution but should work in most
6039 * reasonable situations.
6041 appendStringInfo(buf, " %s",
6042 quote_identifier(rte->eref->aliasname));
6045 else if (rte->rtekind == RTE_FUNCTION)
6048 * For a function RTE, always give an alias. This covers possible
6049 * renaming of the function and/or instability of the
6050 * FigureColname rules for things that aren't simple functions.
6052 appendStringInfo(buf, " %s",
6053 quote_identifier(rte->eref->aliasname));
6057 if (rte->rtekind == RTE_FUNCTION)
6059 if (rte->funccoltypes != NIL)
6061 /* Function returning RECORD, reconstruct the columndefs */
6063 appendStringInfo(buf, " AS ");
6064 get_from_clause_coldeflist(rte->eref->colnames,
6066 rte->funccoltypmods,
6072 * For a function RTE, always emit a complete column alias
6073 * list; this is to protect against possible instability of
6074 * the default column names (eg, from altering parameter
6077 get_from_clause_alias(rte->eref, rte, context);
6083 * For non-function RTEs, just report whatever the user originally
6084 * gave as column aliases.
6086 get_from_clause_alias(rte->alias, rte, context);
6089 else if (IsA(jtnode, JoinExpr))
6091 JoinExpr *j = (JoinExpr *) jtnode;
6092 bool need_paren_on_right;
6094 need_paren_on_right = PRETTY_PAREN(context) &&
6095 !IsA(j->rarg, RangeTblRef) &&
6096 !(IsA(j->rarg, JoinExpr) &&((JoinExpr *) j->rarg)->alias != NULL);
6098 if (!PRETTY_PAREN(context) || j->alias != NULL)
6099 appendStringInfoChar(buf, '(');
6101 get_from_clause_item(j->larg, query, context);
6105 if (!PRETTY_INDENT(context))
6106 appendStringInfoChar(buf, ' ');
6107 switch (j->jointype)
6110 appendContextKeyword(context, "NATURAL JOIN ",
6112 PRETTYINDENT_JOIN, 0);
6115 appendContextKeyword(context, "NATURAL LEFT JOIN ",
6117 PRETTYINDENT_JOIN, 0);
6120 appendContextKeyword(context, "NATURAL FULL JOIN ",
6122 PRETTYINDENT_JOIN, 0);
6125 appendContextKeyword(context, "NATURAL RIGHT JOIN ",
6127 PRETTYINDENT_JOIN, 0);
6130 elog(ERROR, "unrecognized join type: %d",
6136 switch (j->jointype)
6140 appendContextKeyword(context, " JOIN ",
6142 PRETTYINDENT_JOIN, 2);
6144 appendContextKeyword(context, " CROSS JOIN ",
6146 PRETTYINDENT_JOIN, 1);
6149 appendContextKeyword(context, " LEFT JOIN ",
6151 PRETTYINDENT_JOIN, 2);
6154 appendContextKeyword(context, " FULL JOIN ",
6156 PRETTYINDENT_JOIN, 2);
6159 appendContextKeyword(context, " RIGHT JOIN ",
6161 PRETTYINDENT_JOIN, 2);
6164 elog(ERROR, "unrecognized join type: %d",
6169 if (need_paren_on_right)
6170 appendStringInfoChar(buf, '(');
6171 get_from_clause_item(j->rarg, query, context);
6172 if (need_paren_on_right)
6173 appendStringInfoChar(buf, ')');
6175 context->indentLevel -= PRETTYINDENT_JOIN_ON;
6183 appendStringInfo(buf, " USING (");
6184 foreach(col, j->usingClause)
6186 if (col != list_head(j->usingClause))
6187 appendStringInfo(buf, ", ");
6188 appendStringInfoString(buf,
6189 quote_identifier(strVal(lfirst(col))));
6191 appendStringInfoChar(buf, ')');
6195 appendStringInfo(buf, " ON ");
6196 if (!PRETTY_PAREN(context))
6197 appendStringInfoChar(buf, '(');
6198 get_rule_expr(j->quals, context, false);
6199 if (!PRETTY_PAREN(context))
6200 appendStringInfoChar(buf, ')');
6203 if (!PRETTY_PAREN(context) || j->alias != NULL)
6204 appendStringInfoChar(buf, ')');
6206 /* Yes, it's correct to put alias after the right paren ... */
6207 if (j->alias != NULL)
6209 appendStringInfo(buf, " %s",
6210 quote_identifier(j->alias->aliasname));
6211 get_from_clause_alias(j->alias,
6212 rt_fetch(j->rtindex, query->rtable),
6217 elog(ERROR, "unrecognized node type: %d",
6218 (int) nodeTag(jtnode));
6222 * get_from_clause_alias - reproduce column alias list
6224 * This is tricky because we must ignore dropped columns.
6227 get_from_clause_alias(Alias *alias, RangeTblEntry *rte,
6228 deparse_context *context)
6230 StringInfo buf = context->buf;
6235 if (alias == NULL || alias->colnames == NIL)
6236 return; /* definitely nothing to do */
6239 foreach(col, alias->colnames)
6242 if (get_rte_attribute_is_dropped(rte, attnum))
6246 appendStringInfoChar(buf, '(');
6250 appendStringInfo(buf, ", ");
6251 appendStringInfoString(buf,
6252 quote_identifier(strVal(lfirst(col))));
6255 appendStringInfoChar(buf, ')');
6259 * get_from_clause_coldeflist - reproduce FROM clause coldeflist
6261 * The coldeflist is appended immediately (no space) to buf. Caller is
6262 * responsible for ensuring that an alias or AS is present before it.
6265 get_from_clause_coldeflist(List *names, List *types, List *typmods,
6266 deparse_context *context)
6268 StringInfo buf = context->buf;
6274 appendStringInfoChar(buf, '(');
6276 l2 = list_head(types);
6277 l3 = list_head(typmods);
6280 char *attname = strVal(lfirst(l1));
6284 atttypid = lfirst_oid(l2);
6286 atttypmod = lfirst_int(l3);
6290 appendStringInfo(buf, ", ");
6291 appendStringInfo(buf, "%s %s",
6292 quote_identifier(attname),
6293 format_type_with_typemod(atttypid, atttypmod));
6297 appendStringInfoChar(buf, ')');
6301 * get_opclass_name - fetch name of an index operator class
6303 * The opclass name is appended (after a space) to buf.
6305 * Output is suppressed if the opclass is the default for the given
6306 * actual_datatype. (If you don't want this behavior, just pass
6307 * InvalidOid for actual_datatype.)
6310 get_opclass_name(Oid opclass, Oid actual_datatype,
6314 Form_pg_opclass opcrec;
6318 ht_opc = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
6319 if (!HeapTupleIsValid(ht_opc))
6320 elog(ERROR, "cache lookup failed for opclass %u", opclass);
6321 opcrec = (Form_pg_opclass) GETSTRUCT(ht_opc);
6323 if (!OidIsValid(actual_datatype) ||
6324 GetDefaultOpClass(actual_datatype, opcrec->opcmethod) != opclass)
6326 /* Okay, we need the opclass name. Do we need to qualify it? */
6327 opcname = NameStr(opcrec->opcname);
6328 if (OpclassIsVisible(opclass))
6329 appendStringInfo(buf, " %s", quote_identifier(opcname));
6332 nspname = get_namespace_name(opcrec->opcnamespace);
6333 appendStringInfo(buf, " %s.%s",
6334 quote_identifier(nspname),
6335 quote_identifier(opcname));
6338 ReleaseSysCache(ht_opc);
6342 * processIndirection - take care of array and subfield assignment
6344 * We strip any top-level FieldStore or assignment ArrayRef nodes that
6345 * appear in the input, and return the subexpression that's to be assigned.
6346 * If printit is true, we also print out the appropriate decoration for the
6347 * base column name (that the caller just printed).
6350 processIndirection(Node *node, deparse_context *context, bool printit)
6352 StringInfo buf = context->buf;
6358 if (IsA(node, FieldStore))
6360 FieldStore *fstore = (FieldStore *) node;
6364 /* lookup tuple type */
6365 typrelid = get_typ_typrelid(fstore->resulttype);
6366 if (!OidIsValid(typrelid))
6367 elog(ERROR, "argument type %s of FieldStore is not a tuple type",
6368 format_type_be(fstore->resulttype));
6371 * Print the field name. There should only be one target field
6372 * in stored rules. There could be more than that in executable
6373 * target lists, but this function cannot be used for that case.
6375 Assert(list_length(fstore->fieldnums) == 1);
6376 fieldname = get_relid_attribute_name(typrelid,
6377 linitial_int(fstore->fieldnums));
6379 appendStringInfo(buf, ".%s", quote_identifier(fieldname));
6382 * We ignore arg since it should be an uninteresting reference to
6383 * the target column or subcolumn.
6385 node = (Node *) linitial(fstore->newvals);
6387 else if (IsA(node, ArrayRef))
6389 ArrayRef *aref = (ArrayRef *) node;
6391 if (aref->refassgnexpr == NULL)
6394 printSubscripts(aref, context);
6397 * We ignore refexpr since it should be an uninteresting reference
6398 * to the target column or subcolumn.
6400 node = (Node *) aref->refassgnexpr;
6410 printSubscripts(ArrayRef *aref, deparse_context *context)
6412 StringInfo buf = context->buf;
6413 ListCell *lowlist_item;
6414 ListCell *uplist_item;
6416 lowlist_item = list_head(aref->reflowerindexpr); /* could be NULL */
6417 foreach(uplist_item, aref->refupperindexpr)
6419 appendStringInfoChar(buf, '[');
6422 get_rule_expr((Node *) lfirst(lowlist_item), context, false);
6423 appendStringInfoChar(buf, ':');
6424 lowlist_item = lnext(lowlist_item);
6426 get_rule_expr((Node *) lfirst(uplist_item), context, false);
6427 appendStringInfoChar(buf, ']');
6432 * quote_identifier - Quote an identifier only if needed
6434 * When quotes are needed, we palloc the required space; slightly
6435 * space-wasteful but well worth it for notational simplicity.
6438 quote_identifier(const char *ident)
6441 * Can avoid quoting if ident starts with a lowercase letter or underscore
6442 * and contains only lowercase letters, digits, and underscores, *and* is
6443 * not any SQL keyword. Otherwise, supply quotes.
6452 * would like to use <ctype.h> macros here, but they might yield unwanted
6453 * locale-specific results...
6455 safe = ((ident[0] >= 'a' && ident[0] <= 'z') || ident[0] == '_');
6457 for (ptr = ident; *ptr; ptr++)
6461 if ((ch >= 'a' && ch <= 'z') ||
6462 (ch >= '0' && ch <= '9') ||
6478 * Check for keyword. We quote keywords except for unreserved ones.
6479 * (In some cases we could avoid quoting a col_name or type_func_name
6480 * keyword, but it seems much harder than it's worth to tell that.)
6482 * Note: ScanKeywordLookup() does case-insensitive comparison, but
6483 * that's fine, since we already know we have all-lower-case.
6485 const ScanKeyword *keyword = ScanKeywordLookup(ident,
6489 if (keyword != NULL && keyword->category != UNRESERVED_KEYWORD)
6494 return ident; /* no change needed */
6496 result = (char *) palloc(strlen(ident) + nquotes + 2 + 1);
6500 for (ptr = ident; *ptr; ptr++)
6515 * quote_qualified_identifier - Quote a possibly-qualified identifier
6517 * Return a name of the form qualifier.ident, or just ident if qualifier
6518 * is NULL, quoting each component if necessary. The result is palloc'd.
6521 quote_qualified_identifier(const char *qualifier,
6526 initStringInfo(&buf);
6528 appendStringInfo(&buf, "%s.", quote_identifier(qualifier));
6529 appendStringInfoString(&buf, quote_identifier(ident));
6534 * generate_relation_name
6535 * Compute the name to display for a relation specified by OID
6537 * The result includes all necessary quoting and schema-prefixing.
6539 * If namespaces isn't NIL, it must be a list of deparse_namespace nodes.
6540 * We will forcibly qualify the relation name if it equals any CTE name
6541 * visible in the namespace list.
6544 generate_relation_name(Oid relid, List *namespaces)
6547 Form_pg_class reltup;
6554 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
6555 if (!HeapTupleIsValid(tp))
6556 elog(ERROR, "cache lookup failed for relation %u", relid);
6557 reltup = (Form_pg_class) GETSTRUCT(tp);
6558 relname = NameStr(reltup->relname);
6560 /* Check for conflicting CTE name */
6562 foreach(nslist, namespaces)
6564 deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist);
6567 foreach(ctlist, dpns->ctes)
6569 CommonTableExpr *cte = (CommonTableExpr *) lfirst(ctlist);
6571 if (strcmp(cte->ctename, relname) == 0)
6581 /* Otherwise, qualify the name if not visible in search path */
6583 need_qual = !RelationIsVisible(relid);
6586 nspname = get_namespace_name(reltup->relnamespace);
6590 result = quote_qualified_identifier(nspname, relname);
6592 ReleaseSysCache(tp);
6598 * generate_function_name
6599 * Compute the name to display for a function specified by OID,
6600 * given that it is being called with the specified actual arg names and
6601 * types. (Those matter because of ambiguous-function resolution rules.)
6603 * The result includes all necessary quoting and schema-prefixing. We can
6604 * also pass back an indication of whether the function is variadic.
6607 generate_function_name(Oid funcid, int nargs, List *argnames,
6608 Oid *argtypes, bool *is_variadic)
6611 Form_pg_proc procform;
6615 FuncDetailCode p_result;
6620 Oid *p_true_typeids;
6622 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
6623 if (!HeapTupleIsValid(proctup))
6624 elog(ERROR, "cache lookup failed for function %u", funcid);
6625 procform = (Form_pg_proc) GETSTRUCT(proctup);
6626 proname = NameStr(procform->proname);
6629 * The idea here is to schema-qualify only if the parser would fail to
6630 * resolve the correct function given the unqualified func name with the
6631 * specified argtypes. If the function is variadic, we should presume
6632 * that VARIADIC will be included in the call.
6634 p_result = func_get_detail(list_make1(makeString(proname)),
6635 NIL, argnames, nargs, argtypes,
6636 !OidIsValid(procform->provariadic), true,
6637 &p_funcid, &p_rettype,
6638 &p_retset, &p_nvargs, &p_true_typeids, NULL);
6639 if ((p_result == FUNCDETAIL_NORMAL ||
6640 p_result == FUNCDETAIL_AGGREGATE ||
6641 p_result == FUNCDETAIL_WINDOWFUNC) &&
6645 nspname = get_namespace_name(procform->pronamespace);
6647 result = quote_qualified_identifier(nspname, proname);
6649 /* Check variadic-ness if caller cares */
6652 /* "any" variadics are not treated as variadics for listing */
6653 if (OidIsValid(procform->provariadic) &&
6654 procform->provariadic != ANYOID)
6655 *is_variadic = true;
6657 *is_variadic = false;
6660 ReleaseSysCache(proctup);
6666 * generate_operator_name
6667 * Compute the name to display for an operator specified by OID,
6668 * given that it is being called with the specified actual arg types.
6669 * (Arg types matter because of ambiguous-operator resolution rules.
6670 * Pass InvalidOid for unused arg of a unary operator.)
6672 * The result includes all necessary quoting and schema-prefixing,
6673 * plus the OPERATOR() decoration needed to use a qualified operator name
6677 generate_operator_name(Oid operid, Oid arg1, Oid arg2)
6681 Form_pg_operator operform;
6686 initStringInfo(&buf);
6688 opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operid));
6689 if (!HeapTupleIsValid(opertup))
6690 elog(ERROR, "cache lookup failed for operator %u", operid);
6691 operform = (Form_pg_operator) GETSTRUCT(opertup);
6692 oprname = NameStr(operform->oprname);
6695 * The idea here is to schema-qualify only if the parser would fail to
6696 * resolve the correct operator given the unqualified op name with the
6697 * specified argtypes.
6699 switch (operform->oprkind)
6702 p_result = oper(NULL, list_make1(makeString(oprname)), arg1, arg2,
6706 p_result = left_oper(NULL, list_make1(makeString(oprname)), arg2,
6710 p_result = right_oper(NULL, list_make1(makeString(oprname)), arg1,
6714 elog(ERROR, "unrecognized oprkind: %d", operform->oprkind);
6715 p_result = NULL; /* keep compiler quiet */
6719 if (p_result != NULL && oprid(p_result) == operid)
6723 nspname = get_namespace_name(operform->oprnamespace);
6724 appendStringInfo(&buf, "OPERATOR(%s.", quote_identifier(nspname));
6727 appendStringInfoString(&buf, oprname);
6730 appendStringInfoChar(&buf, ')');
6732 if (p_result != NULL)
6733 ReleaseSysCache(p_result);
6735 ReleaseSysCache(opertup);
6741 * Given a C string, produce a TEXT datum.
6743 * We assume that the input was palloc'd and may be freed.
6746 string_to_text(char *str)
6750 result = cstring_to_text(str);
6756 * Generate a C string representing a relation's reloptions, or NULL if none.
6759 flatten_reloptions(Oid relid)
6761 char *result = NULL;
6766 tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
6767 if (!HeapTupleIsValid(tuple))
6768 elog(ERROR, "cache lookup failed for relation %u", relid);
6770 reloptions = SysCacheGetAttr(RELOID, tuple,
6771 Anum_pg_class_reloptions, &isnull);
6778 * We want to use array_to_text(reloptions, ', ') --- but
6779 * DirectFunctionCall2(array_to_text) does not work, because
6780 * array_to_text() relies on flinfo to be valid. So use
6783 sep = CStringGetTextDatum(", ");
6784 txt = OidFunctionCall2(F_ARRAY_TO_TEXT, reloptions, sep);
6785 result = TextDatumGetCString(txt);
6788 ReleaseSysCache(tuple);