1 /*-------------------------------------------------------------------------
4 * Functions to convert stored expressions/querytrees back to
7 * Portions Copyright (c) 1996-2008, 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.292 2008/12/31 00:08:37 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_opclass.h"
29 #include "catalog/pg_operator.h"
30 #include "catalog/pg_trigger.h"
31 #include "commands/defrem.h"
32 #include "commands/tablespace.h"
33 #include "executor/spi.h"
35 #include "nodes/makefuncs.h"
36 #include "nodes/nodeFuncs.h"
37 #include "optimizer/clauses.h"
38 #include "optimizer/tlist.h"
39 #include "parser/gramparse.h"
40 #include "parser/keywords.h"
41 #include "parser/parse_func.h"
42 #include "parser/parse_oper.h"
43 #include "parser/parsetree.h"
44 #include "rewrite/rewriteHandler.h"
45 #include "rewrite/rewriteManip.h"
46 #include "rewrite/rewriteSupport.h"
47 #include "utils/fmgroids.h"
48 #include "utils/lsyscache.h"
49 #include "utils/tqual.h"
50 #include "utils/typcache.h"
51 #include "utils/xml.h"
55 * Pretty formatting constants
60 #define PRETTYINDENT_STD 8
61 #define PRETTYINDENT_JOIN 13
62 #define PRETTYINDENT_JOIN_ON (PRETTYINDENT_JOIN-PRETTYINDENT_STD)
63 #define PRETTYINDENT_VAR 4
66 #define PRETTYFLAG_PAREN 1
67 #define PRETTYFLAG_INDENT 2
69 /* macro to test if pretty action needed */
70 #define PRETTY_PAREN(context) ((context)->prettyFlags & PRETTYFLAG_PAREN)
71 #define PRETTY_INDENT(context) ((context)->prettyFlags & PRETTYFLAG_INDENT)
79 /* Context info needed for invoking a recursive querytree display routine */
82 StringInfo buf; /* output buffer to append to */
83 List *namespaces; /* List of deparse_namespace nodes */
84 List *windowClause; /* Current query level's WINDOW clause */
85 List *windowTList; /* targetlist for resolving WINDOW clause */
86 int prettyFlags; /* enabling of pretty-print functions */
87 int indentLevel; /* current indent level for prettyprint */
88 bool varprefix; /* TRUE to print prefixes on Vars */
92 * Each level of query context around a subtree needs a level of Var namespace.
93 * A Var having varlevelsup=N refers to the N'th item (counting from 0) in
94 * the current context's namespaces list.
96 * The rangetable is the list of actual RTEs from the query tree, and the
97 * cte list is the list of actual CTEs.
99 * For deparsing plan trees, we provide for outer and inner subplan nodes.
100 * The tlists of these nodes are used to resolve OUTER and INNER varnos.
101 * Also, in the plan-tree case we don't have access to the parse-time CTE
102 * list, so we need a list of subplans instead.
106 List *rtable; /* List of RangeTblEntry nodes */
107 List *ctes; /* List of CommonTableExpr nodes */
108 List *subplans; /* List of subplans, in plan-tree case */
109 Plan *outer_plan; /* OUTER subplan, or NULL if none */
110 Plan *inner_plan; /* INNER subplan, or NULL if none */
118 static SPIPlanPtr plan_getrulebyoid = NULL;
119 static const char *query_getrulebyoid = "SELECT * FROM pg_catalog.pg_rewrite WHERE oid = $1";
120 static SPIPlanPtr plan_getviewrule = NULL;
121 static const char *query_getviewrule = "SELECT * FROM pg_catalog.pg_rewrite WHERE ev_class = $1 AND rulename = $2";
127 * Most of these functions used to use fixed-size buffers to build their
128 * results. Now, they take an (already initialized) StringInfo object
129 * as a parameter, and append their text output to its contents.
132 static char *deparse_expression_pretty(Node *expr, List *dpcontext,
133 bool forceprefix, bool showimplicit,
134 int prettyFlags, int startIndent);
135 static char *pg_get_viewdef_worker(Oid viewoid, int prettyFlags);
136 static void decompile_column_index_array(Datum column_index_array, Oid relId,
138 static char *pg_get_ruledef_worker(Oid ruleoid, int prettyFlags);
139 static char *pg_get_indexdef_worker(Oid indexrelid, int colno, bool showTblSpc,
141 static char *pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
143 static char *pg_get_expr_worker(text *expr, Oid relid, char *relname,
145 static int print_function_arguments(StringInfo buf, HeapTuple proctup,
146 bool print_table_args, bool print_defaults);
147 static void print_function_rettype(StringInfo buf, HeapTuple proctup);
148 static void make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
150 static void make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
152 static void get_query_def(Query *query, StringInfo buf, List *parentnamespace,
153 TupleDesc resultDesc, int prettyFlags, int startIndent);
154 static void get_values_def(List *values_lists, deparse_context *context);
155 static void get_with_clause(Query *query, deparse_context *context);
156 static void get_select_query_def(Query *query, deparse_context *context,
157 TupleDesc resultDesc);
158 static void get_insert_query_def(Query *query, deparse_context *context);
159 static void get_update_query_def(Query *query, deparse_context *context);
160 static void get_delete_query_def(Query *query, deparse_context *context);
161 static void get_utility_query_def(Query *query, deparse_context *context);
162 static void get_basic_select_query(Query *query, deparse_context *context,
163 TupleDesc resultDesc);
164 static void get_target_list(List *targetList, deparse_context *context,
165 TupleDesc resultDesc);
166 static void get_setop_query(Node *setOp, Query *query,
167 deparse_context *context,
168 TupleDesc resultDesc);
169 static Node *get_rule_sortgroupclause(SortGroupClause *srt, List *tlist,
171 deparse_context *context);
172 static void get_rule_orderby(List *orderList, List *targetList,
173 bool force_colno, deparse_context *context);
174 static void get_rule_windowclause(Query *query, deparse_context *context);
175 static void get_rule_windowspec(WindowClause *wc, List *targetList,
176 deparse_context *context);
177 static void push_plan(deparse_namespace *dpns, Plan *subplan);
178 static char *get_variable(Var *var, int levelsup, bool showstar,
179 deparse_context *context);
180 static RangeTblEntry *find_rte_by_refname(const char *refname,
181 deparse_context *context);
182 static const char *get_simple_binary_op_name(OpExpr *expr);
183 static bool isSimpleNode(Node *node, Node *parentNode, int prettyFlags);
184 static void appendStringInfoSpaces(StringInfo buf, int count);
185 static void appendContextKeyword(deparse_context *context, const char *str,
186 int indentBefore, int indentAfter, int indentPlus);
187 static void get_rule_expr(Node *node, deparse_context *context,
189 static void get_oper_expr(OpExpr *expr, deparse_context *context);
190 static void get_func_expr(FuncExpr *expr, deparse_context *context,
192 static void get_agg_expr(Aggref *aggref, deparse_context *context);
193 static void get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context);
194 static void get_coercion_expr(Node *arg, deparse_context *context,
195 Oid resulttype, int32 resulttypmod,
197 static void get_const_expr(Const *constval, deparse_context *context,
199 static void simple_quote_literal(StringInfo buf, const char *val);
200 static void get_sublink_expr(SubLink *sublink, deparse_context *context);
201 static void get_from_clause(Query *query, const char *prefix,
202 deparse_context *context);
203 static void get_from_clause_item(Node *jtnode, Query *query,
204 deparse_context *context);
205 static void get_from_clause_alias(Alias *alias, RangeTblEntry *rte,
206 deparse_context *context);
207 static void get_from_clause_coldeflist(List *names, List *types, List *typmods,
208 deparse_context *context);
209 static void get_opclass_name(Oid opclass, Oid actual_datatype,
211 static Node *processIndirection(Node *node, deparse_context *context,
213 static void printSubscripts(ArrayRef *aref, deparse_context *context);
214 static char *generate_relation_name(Oid relid, List *namespaces);
215 static char *generate_function_name(Oid funcid, int nargs, Oid *argtypes,
217 static char *generate_operator_name(Oid operid, Oid arg1, Oid arg2);
218 static text *string_to_text(char *str);
219 static char *flatten_reloptions(Oid relid);
221 #define only_marker(rte) ((rte)->inh ? "" : "ONLY ")
225 * get_ruledef - Do it all and return a text
226 * that could be used as a statement
227 * to recreate the rule
231 pg_get_ruledef(PG_FUNCTION_ARGS)
233 Oid ruleoid = PG_GETARG_OID(0);
235 PG_RETURN_TEXT_P(string_to_text(pg_get_ruledef_worker(ruleoid, 0)));
240 pg_get_ruledef_ext(PG_FUNCTION_ARGS)
242 Oid ruleoid = PG_GETARG_OID(0);
243 bool pretty = PG_GETARG_BOOL(1);
246 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
247 PG_RETURN_TEXT_P(string_to_text(pg_get_ruledef_worker(ruleoid, prettyFlags)));
252 pg_get_ruledef_worker(Oid ruleoid, int prettyFlags)
262 * Do this first so that string is alloc'd in outer context not SPI's.
264 initStringInfo(&buf);
267 * Connect to SPI manager
269 if (SPI_connect() != SPI_OK_CONNECT)
270 elog(ERROR, "SPI_connect failed");
273 * On the first call prepare the plan to lookup pg_rewrite. We read
274 * pg_rewrite over the SPI manager instead of using the syscache to be
275 * checked for read access on pg_rewrite.
277 if (plan_getrulebyoid == NULL)
282 argtypes[0] = OIDOID;
283 plan = SPI_prepare(query_getrulebyoid, 1, argtypes);
285 elog(ERROR, "SPI_prepare failed for \"%s\"", query_getrulebyoid);
286 plan_getrulebyoid = SPI_saveplan(plan);
290 * Get the pg_rewrite tuple for this rule
292 args[0] = ObjectIdGetDatum(ruleoid);
294 spirc = SPI_execute_plan(plan_getrulebyoid, args, nulls, true, 1);
295 if (spirc != SPI_OK_SELECT)
296 elog(ERROR, "failed to get pg_rewrite tuple for rule %u", ruleoid);
297 if (SPI_processed != 1)
298 appendStringInfo(&buf, "-");
302 * Get the rule's definition and put it into executor's memory
304 ruletup = SPI_tuptable->vals[0];
305 rulettc = SPI_tuptable->tupdesc;
306 make_ruledef(&buf, ruletup, rulettc, prettyFlags);
310 * Disconnect from SPI manager
312 if (SPI_finish() != SPI_OK_FINISH)
313 elog(ERROR, "SPI_finish failed");
320 * get_viewdef - Mainly the same thing, but we
321 * only return the SELECT part of a view
325 pg_get_viewdef(PG_FUNCTION_ARGS)
328 Oid viewoid = PG_GETARG_OID(0);
330 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, 0)));
335 pg_get_viewdef_ext(PG_FUNCTION_ARGS)
338 Oid viewoid = PG_GETARG_OID(0);
339 bool pretty = PG_GETARG_BOOL(1);
342 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
343 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, prettyFlags)));
347 pg_get_viewdef_name(PG_FUNCTION_ARGS)
349 /* By qualified name */
350 text *viewname = PG_GETARG_TEXT_P(0);
354 viewrel = makeRangeVarFromNameList(textToQualifiedNameList(viewname));
355 viewoid = RangeVarGetRelid(viewrel, false);
357 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, 0)));
362 pg_get_viewdef_name_ext(PG_FUNCTION_ARGS)
364 /* By qualified name */
365 text *viewname = PG_GETARG_TEXT_P(0);
366 bool pretty = PG_GETARG_BOOL(1);
371 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
372 viewrel = makeRangeVarFromNameList(textToQualifiedNameList(viewname));
373 viewoid = RangeVarGetRelid(viewrel, false);
375 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, prettyFlags)));
379 * Common code for by-OID and by-name variants of pg_get_viewdef
382 pg_get_viewdef_worker(Oid viewoid, int prettyFlags)
392 * Do this first so that string is alloc'd in outer context not SPI's.
394 initStringInfo(&buf);
397 * Connect to SPI manager
399 if (SPI_connect() != SPI_OK_CONNECT)
400 elog(ERROR, "SPI_connect failed");
403 * On the first call prepare the plan to lookup pg_rewrite. We read
404 * pg_rewrite over the SPI manager instead of using the syscache to be
405 * checked for read access on pg_rewrite.
407 if (plan_getviewrule == NULL)
412 argtypes[0] = OIDOID;
413 argtypes[1] = NAMEOID;
414 plan = SPI_prepare(query_getviewrule, 2, argtypes);
416 elog(ERROR, "SPI_prepare failed for \"%s\"", query_getviewrule);
417 plan_getviewrule = SPI_saveplan(plan);
421 * Get the pg_rewrite tuple for the view's SELECT rule
423 args[0] = ObjectIdGetDatum(viewoid);
424 args[1] = PointerGetDatum(ViewSelectRuleName);
427 spirc = SPI_execute_plan(plan_getviewrule, args, nulls, true, 2);
428 if (spirc != SPI_OK_SELECT)
429 elog(ERROR, "failed to get pg_rewrite tuple for view %u", viewoid);
430 if (SPI_processed != 1)
431 appendStringInfo(&buf, "Not a view");
435 * Get the rule's definition and put it into executor's memory
437 ruletup = SPI_tuptable->vals[0];
438 rulettc = SPI_tuptable->tupdesc;
439 make_viewdef(&buf, ruletup, rulettc, prettyFlags);
443 * Disconnect from SPI manager
445 if (SPI_finish() != SPI_OK_FINISH)
446 elog(ERROR, "SPI_finish failed");
452 * get_triggerdef - Get the definition of a trigger
456 pg_get_triggerdef(PG_FUNCTION_ARGS)
458 Oid trigid = PG_GETARG_OID(0);
460 Form_pg_trigger trigrec;
469 * Fetch the pg_trigger tuple by the Oid of the trigger
471 tgrel = heap_open(TriggerRelationId, AccessShareLock);
473 ScanKeyInit(&skey[0],
474 ObjectIdAttributeNumber,
475 BTEqualStrategyNumber, F_OIDEQ,
476 ObjectIdGetDatum(trigid));
478 tgscan = systable_beginscan(tgrel, TriggerOidIndexId, true,
479 SnapshotNow, 1, skey);
481 ht_trig = systable_getnext(tgscan);
483 if (!HeapTupleIsValid(ht_trig))
484 elog(ERROR, "could not find tuple for trigger %u", trigid);
486 trigrec = (Form_pg_trigger) GETSTRUCT(ht_trig);
489 * Start the trigger definition. Note that the trigger's name should never
490 * be schema-qualified, but the trigger rel's name may be.
492 initStringInfo(&buf);
494 tgname = NameStr(trigrec->tgname);
495 appendStringInfo(&buf, "CREATE %sTRIGGER %s ",
496 trigrec->tgisconstraint ? "CONSTRAINT " : "",
497 quote_identifier(tgname));
499 if (TRIGGER_FOR_BEFORE(trigrec->tgtype))
500 appendStringInfo(&buf, "BEFORE");
502 appendStringInfo(&buf, "AFTER");
503 if (TRIGGER_FOR_INSERT(trigrec->tgtype))
505 appendStringInfo(&buf, " INSERT");
508 if (TRIGGER_FOR_DELETE(trigrec->tgtype))
511 appendStringInfo(&buf, " OR DELETE");
513 appendStringInfo(&buf, " DELETE");
516 if (TRIGGER_FOR_UPDATE(trigrec->tgtype))
519 appendStringInfo(&buf, " OR UPDATE");
521 appendStringInfo(&buf, " UPDATE");
523 if (TRIGGER_FOR_TRUNCATE(trigrec->tgtype))
526 appendStringInfo(&buf, " OR TRUNCATE");
528 appendStringInfo(&buf, " TRUNCATE");
530 appendStringInfo(&buf, " ON %s ",
531 generate_relation_name(trigrec->tgrelid, NIL));
533 if (trigrec->tgisconstraint)
535 if (trigrec->tgconstrrelid != InvalidOid)
536 appendStringInfo(&buf, "FROM %s ",
537 generate_relation_name(trigrec->tgconstrrelid,
539 if (!trigrec->tgdeferrable)
540 appendStringInfo(&buf, "NOT ");
541 appendStringInfo(&buf, "DEFERRABLE INITIALLY ");
542 if (trigrec->tginitdeferred)
543 appendStringInfo(&buf, "DEFERRED ");
545 appendStringInfo(&buf, "IMMEDIATE ");
549 if (TRIGGER_FOR_ROW(trigrec->tgtype))
550 appendStringInfo(&buf, "FOR EACH ROW ");
552 appendStringInfo(&buf, "FOR EACH STATEMENT ");
554 appendStringInfo(&buf, "EXECUTE PROCEDURE %s(",
555 generate_function_name(trigrec->tgfoid, 0, NULL, NULL));
557 if (trigrec->tgnargs > 0)
564 val = DatumGetByteaP(fastgetattr(ht_trig,
565 Anum_pg_trigger_tgargs,
566 tgrel->rd_att, &isnull));
568 elog(ERROR, "tgargs is null for trigger %u", trigid);
569 p = (char *) VARDATA(val);
570 for (i = 0; i < trigrec->tgnargs; i++)
573 appendStringInfo(&buf, ", ");
574 simple_quote_literal(&buf, p);
575 /* advance p to next string embedded in tgargs */
582 /* We deliberately do not put semi-colon at end */
583 appendStringInfo(&buf, ")");
586 systable_endscan(tgscan);
588 heap_close(tgrel, AccessShareLock);
590 PG_RETURN_TEXT_P(string_to_text(buf.data));
594 * get_indexdef - Get the definition of an index
596 * In the extended version, there is a colno argument as well as pretty bool.
597 * if colno == 0, we want a complete index definition.
598 * if colno > 0, we only want the Nth index key's variable or expression.
600 * Note that the SQL-function versions of this omit any info about the
601 * index tablespace; this is intentional because pg_dump wants it that way.
602 * However pg_get_indexdef_string() includes index tablespace if not default.
606 pg_get_indexdef(PG_FUNCTION_ARGS)
608 Oid indexrelid = PG_GETARG_OID(0);
610 PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, 0,
615 pg_get_indexdef_ext(PG_FUNCTION_ARGS)
617 Oid indexrelid = PG_GETARG_OID(0);
618 int32 colno = PG_GETARG_INT32(1);
619 bool pretty = PG_GETARG_BOOL(2);
622 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
623 PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, colno,
624 false, prettyFlags)));
627 /* Internal version that returns a palloc'd C string */
629 pg_get_indexdef_string(Oid indexrelid)
631 return pg_get_indexdef_worker(indexrelid, 0, true, 0);
635 pg_get_indexdef_worker(Oid indexrelid, int colno, bool showTblSpc,
641 Form_pg_index idxrec;
642 Form_pg_class idxrelrec;
645 ListCell *indexpr_item;
651 Datum indoptionDatum;
654 int2vector *indoption;
660 * Fetch the pg_index tuple by the Oid of the index
662 ht_idx = SearchSysCache(INDEXRELID,
663 ObjectIdGetDatum(indexrelid),
665 if (!HeapTupleIsValid(ht_idx))
666 elog(ERROR, "cache lookup failed for index %u", indexrelid);
667 idxrec = (Form_pg_index) GETSTRUCT(ht_idx);
669 indrelid = idxrec->indrelid;
670 Assert(indexrelid == idxrec->indexrelid);
672 /* Must get indclass and indoption the hard way */
673 indclassDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
674 Anum_pg_index_indclass, &isnull);
676 indclass = (oidvector *) DatumGetPointer(indclassDatum);
677 indoptionDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
678 Anum_pg_index_indoption, &isnull);
680 indoption = (int2vector *) DatumGetPointer(indoptionDatum);
683 * Fetch the pg_class tuple of the index relation
685 ht_idxrel = SearchSysCache(RELOID,
686 ObjectIdGetDatum(indexrelid),
688 if (!HeapTupleIsValid(ht_idxrel))
689 elog(ERROR, "cache lookup failed for relation %u", indexrelid);
690 idxrelrec = (Form_pg_class) GETSTRUCT(ht_idxrel);
693 * Fetch the pg_am tuple of the index' access method
695 ht_am = SearchSysCache(AMOID,
696 ObjectIdGetDatum(idxrelrec->relam),
698 if (!HeapTupleIsValid(ht_am))
699 elog(ERROR, "cache lookup failed for access method %u",
701 amrec = (Form_pg_am) GETSTRUCT(ht_am);
704 * Get the index expressions, if any. (NOTE: we do not use the relcache
705 * versions of the expressions and predicate, because we want to display
706 * non-const-folded expressions.)
708 if (!heap_attisnull(ht_idx, Anum_pg_index_indexprs))
714 exprsDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
715 Anum_pg_index_indexprs, &isnull);
717 exprsString = TextDatumGetCString(exprsDatum);
718 indexprs = (List *) stringToNode(exprsString);
724 indexpr_item = list_head(indexprs);
726 context = deparse_context_for(get_rel_name(indrelid), indrelid);
729 * Start the index definition. Note that the index's name should never be
730 * schema-qualified, but the indexed rel's name may be.
732 initStringInfo(&buf);
735 appendStringInfo(&buf, "CREATE %sINDEX %s ON %s USING %s (",
736 idxrec->indisunique ? "UNIQUE " : "",
737 quote_identifier(NameStr(idxrelrec->relname)),
738 generate_relation_name(indrelid, NIL),
739 quote_identifier(NameStr(amrec->amname)));
742 * Report the indexed attributes
745 for (keyno = 0; keyno < idxrec->indnatts; keyno++)
747 AttrNumber attnum = idxrec->indkey.values[keyno];
748 int16 opt = indoption->values[keyno];
751 appendStringInfoString(&buf, sep);
756 /* Simple index column */
759 attname = get_relid_attribute_name(indrelid, attnum);
760 if (!colno || colno == keyno + 1)
761 appendStringInfoString(&buf, quote_identifier(attname));
762 keycoltype = get_atttype(indrelid, attnum);
766 /* expressional index */
769 if (indexpr_item == NULL)
770 elog(ERROR, "too few entries in indexprs list");
771 indexkey = (Node *) lfirst(indexpr_item);
772 indexpr_item = lnext(indexpr_item);
774 str = deparse_expression_pretty(indexkey, context, false, false,
776 if (!colno || colno == keyno + 1)
778 /* Need parens if it's not a bare function call */
779 if (indexkey && IsA(indexkey, FuncExpr) &&
780 ((FuncExpr *) indexkey)->funcformat == COERCE_EXPLICIT_CALL)
781 appendStringInfoString(&buf, str);
783 appendStringInfo(&buf, "(%s)", str);
785 keycoltype = exprType(indexkey);
788 /* Provide decoration only in the colno=0 case */
791 /* Add the operator class name, if not default */
792 get_opclass_name(indclass->values[keyno], keycoltype, &buf);
794 /* Add options if relevant */
795 if (amrec->amcanorder)
797 /* if it supports sort ordering, report DESC and NULLS opts */
798 if (opt & INDOPTION_DESC)
800 appendStringInfo(&buf, " DESC");
801 /* NULLS FIRST is the default in this case */
802 if (!(opt & INDOPTION_NULLS_FIRST))
803 appendStringInfo(&buf, " NULLS LAST");
807 if (opt & INDOPTION_NULLS_FIRST)
808 appendStringInfo(&buf, " NULLS FIRST");
816 appendStringInfoChar(&buf, ')');
819 * If it has options, append "WITH (options)"
821 str = flatten_reloptions(indexrelid);
824 appendStringInfo(&buf, " WITH (%s)", str);
829 * If it's in a nondefault tablespace, say so, but only if requested
835 tblspc = get_rel_tablespace(indexrelid);
836 if (OidIsValid(tblspc))
837 appendStringInfo(&buf, " TABLESPACE %s",
838 quote_identifier(get_tablespace_name(tblspc)));
842 * If it's a partial index, decompile and append the predicate
844 if (!heap_attisnull(ht_idx, Anum_pg_index_indpred))
851 /* Convert text string to node tree */
852 predDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
853 Anum_pg_index_indpred, &isnull);
855 predString = TextDatumGetCString(predDatum);
856 node = (Node *) stringToNode(predString);
860 str = deparse_expression_pretty(node, context, false, false,
862 appendStringInfo(&buf, " WHERE %s", str);
867 ReleaseSysCache(ht_idx);
868 ReleaseSysCache(ht_idxrel);
869 ReleaseSysCache(ht_am);
876 * pg_get_constraintdef
878 * Returns the definition for the constraint, ie, everything that needs to
879 * appear after "ALTER TABLE ... ADD CONSTRAINT <constraintname>".
882 pg_get_constraintdef(PG_FUNCTION_ARGS)
884 Oid constraintId = PG_GETARG_OID(0);
886 PG_RETURN_TEXT_P(string_to_text(pg_get_constraintdef_worker(constraintId,
891 pg_get_constraintdef_ext(PG_FUNCTION_ARGS)
893 Oid constraintId = PG_GETARG_OID(0);
894 bool pretty = PG_GETARG_BOOL(1);
897 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
898 PG_RETURN_TEXT_P(string_to_text(pg_get_constraintdef_worker(constraintId,
899 false, prettyFlags)));
902 /* Internal version that returns a palloc'd C string */
904 pg_get_constraintdef_string(Oid constraintId)
906 return pg_get_constraintdef_worker(constraintId, true, 0);
910 pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
914 Form_pg_constraint conForm;
917 tup = SearchSysCache(CONSTROID,
918 ObjectIdGetDatum(constraintId),
920 if (!HeapTupleIsValid(tup)) /* should not happen */
921 elog(ERROR, "cache lookup failed for constraint %u", constraintId);
922 conForm = (Form_pg_constraint) GETSTRUCT(tup);
924 initStringInfo(&buf);
926 if (fullCommand && OidIsValid(conForm->conrelid))
928 appendStringInfo(&buf, "ALTER TABLE ONLY %s ADD CONSTRAINT %s ",
929 generate_relation_name(conForm->conrelid, NIL),
930 quote_identifier(NameStr(conForm->conname)));
933 switch (conForm->contype)
935 case CONSTRAINT_FOREIGN:
941 /* Start off the constraint definition */
942 appendStringInfo(&buf, "FOREIGN KEY (");
944 /* Fetch and build referencing-column list */
945 val = SysCacheGetAttr(CONSTROID, tup,
946 Anum_pg_constraint_conkey, &isnull);
948 elog(ERROR, "null conkey for constraint %u",
951 decompile_column_index_array(val, conForm->conrelid, &buf);
953 /* add foreign relation name */
954 appendStringInfo(&buf, ") REFERENCES %s(",
955 generate_relation_name(conForm->confrelid,
958 /* Fetch and build referenced-column list */
959 val = SysCacheGetAttr(CONSTROID, tup,
960 Anum_pg_constraint_confkey, &isnull);
962 elog(ERROR, "null confkey for constraint %u",
965 decompile_column_index_array(val, conForm->confrelid, &buf);
967 appendStringInfo(&buf, ")");
970 switch (conForm->confmatchtype)
972 case FKCONSTR_MATCH_FULL:
973 string = " MATCH FULL";
975 case FKCONSTR_MATCH_PARTIAL:
976 string = " MATCH PARTIAL";
978 case FKCONSTR_MATCH_UNSPECIFIED:
982 elog(ERROR, "unrecognized confmatchtype: %d",
983 conForm->confmatchtype);
984 string = ""; /* keep compiler quiet */
987 appendStringInfoString(&buf, string);
989 /* Add ON UPDATE and ON DELETE clauses, if needed */
990 switch (conForm->confupdtype)
992 case FKCONSTR_ACTION_NOACTION:
993 string = NULL; /* suppress default */
995 case FKCONSTR_ACTION_RESTRICT:
998 case FKCONSTR_ACTION_CASCADE:
1001 case FKCONSTR_ACTION_SETNULL:
1002 string = "SET NULL";
1004 case FKCONSTR_ACTION_SETDEFAULT:
1005 string = "SET DEFAULT";
1008 elog(ERROR, "unrecognized confupdtype: %d",
1009 conForm->confupdtype);
1010 string = NULL; /* keep compiler quiet */
1014 appendStringInfo(&buf, " ON UPDATE %s", string);
1016 switch (conForm->confdeltype)
1018 case FKCONSTR_ACTION_NOACTION:
1019 string = NULL; /* suppress default */
1021 case FKCONSTR_ACTION_RESTRICT:
1022 string = "RESTRICT";
1024 case FKCONSTR_ACTION_CASCADE:
1027 case FKCONSTR_ACTION_SETNULL:
1028 string = "SET NULL";
1030 case FKCONSTR_ACTION_SETDEFAULT:
1031 string = "SET DEFAULT";
1034 elog(ERROR, "unrecognized confdeltype: %d",
1035 conForm->confdeltype);
1036 string = NULL; /* keep compiler quiet */
1040 appendStringInfo(&buf, " ON DELETE %s", string);
1042 if (conForm->condeferrable)
1043 appendStringInfo(&buf, " DEFERRABLE");
1044 if (conForm->condeferred)
1045 appendStringInfo(&buf, " INITIALLY DEFERRED");
1049 case CONSTRAINT_PRIMARY:
1050 case CONSTRAINT_UNIQUE:
1056 /* Start off the constraint definition */
1057 if (conForm->contype == CONSTRAINT_PRIMARY)
1058 appendStringInfo(&buf, "PRIMARY KEY (");
1060 appendStringInfo(&buf, "UNIQUE (");
1062 /* Fetch and build target column list */
1063 val = SysCacheGetAttr(CONSTROID, tup,
1064 Anum_pg_constraint_conkey, &isnull);
1066 elog(ERROR, "null conkey for constraint %u",
1069 decompile_column_index_array(val, conForm->conrelid, &buf);
1071 appendStringInfo(&buf, ")");
1073 indexId = get_constraint_index(constraintId);
1075 /* XXX why do we only print these bits if fullCommand? */
1076 if (fullCommand && OidIsValid(indexId))
1078 char *options = flatten_reloptions(indexId);
1083 appendStringInfo(&buf, " WITH (%s)", options);
1087 tblspc = get_rel_tablespace(indexId);
1088 if (OidIsValid(tblspc))
1089 appendStringInfo(&buf, " USING INDEX TABLESPACE %s",
1090 quote_identifier(get_tablespace_name(tblspc)));
1095 case CONSTRAINT_CHECK:
1104 /* Fetch constraint expression in parsetree form */
1105 val = SysCacheGetAttr(CONSTROID, tup,
1106 Anum_pg_constraint_conbin, &isnull);
1108 elog(ERROR, "null conbin for constraint %u",
1111 conbin = TextDatumGetCString(val);
1112 expr = stringToNode(conbin);
1114 /* Set up deparsing context for Var nodes in constraint */
1115 if (conForm->conrelid != InvalidOid)
1117 /* relation constraint */
1118 context = deparse_context_for(get_rel_name(conForm->conrelid),
1123 /* domain constraint --- can't have Vars */
1127 consrc = deparse_expression_pretty(expr, context, false, false,
1131 * Now emit the constraint definition. There are cases where
1132 * the constraint expression will be fully parenthesized and
1133 * we don't need the outer parens ... but there are other
1134 * cases where we do need 'em. Be conservative for now.
1136 * Note that simply checking for leading '(' and trailing ')'
1137 * would NOT be good enough, consider "(x > 0) AND (y > 0)".
1139 appendStringInfo(&buf, "CHECK (%s)", consrc);
1144 elog(ERROR, "invalid constraint type \"%c\"", conForm->contype);
1149 ReleaseSysCache(tup);
1156 * Convert an int16[] Datum into a comma-separated list of column names
1157 * for the indicated relation; append the list to buf.
1160 decompile_column_index_array(Datum column_index_array, Oid relId,
1167 /* Extract data from array of int16 */
1168 deconstruct_array(DatumGetArrayTypeP(column_index_array),
1169 INT2OID, 2, true, 's',
1170 &keys, NULL, &nKeys);
1172 for (j = 0; j < nKeys; j++)
1176 colName = get_relid_attribute_name(relId, DatumGetInt16(keys[j]));
1179 appendStringInfoString(buf, quote_identifier(colName));
1181 appendStringInfo(buf, ", %s", quote_identifier(colName));
1187 * get_expr - Decompile an expression tree
1189 * Input: an expression tree in nodeToString form, and a relation OID
1191 * Output: reverse-listed expression
1193 * Currently, the expression can only refer to a single relation, namely
1194 * the one specified by the second parameter. This is sufficient for
1195 * partial indexes, column default expressions, etc.
1199 pg_get_expr(PG_FUNCTION_ARGS)
1201 text *expr = PG_GETARG_TEXT_P(0);
1202 Oid relid = PG_GETARG_OID(1);
1205 /* Get the name for the relation */
1206 relname = get_rel_name(relid);
1207 if (relname == NULL)
1208 PG_RETURN_NULL(); /* should we raise an error? */
1210 PG_RETURN_TEXT_P(string_to_text(pg_get_expr_worker(expr, relid, relname, 0)));
1214 pg_get_expr_ext(PG_FUNCTION_ARGS)
1216 text *expr = PG_GETARG_TEXT_P(0);
1217 Oid relid = PG_GETARG_OID(1);
1218 bool pretty = PG_GETARG_BOOL(2);
1222 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
1224 /* Get the name for the relation */
1225 relname = get_rel_name(relid);
1226 if (relname == NULL)
1227 PG_RETURN_NULL(); /* should we raise an error? */
1229 PG_RETURN_TEXT_P(string_to_text(pg_get_expr_worker(expr, relid, relname, prettyFlags)));
1233 pg_get_expr_worker(text *expr, Oid relid, char *relname, int prettyFlags)
1240 /* Convert input TEXT object to C string */
1241 exprstr = text_to_cstring(expr);
1243 /* Convert expression to node tree */
1244 node = (Node *) stringToNode(exprstr);
1247 context = deparse_context_for(relname, relid);
1248 str = deparse_expression_pretty(node, context, false, false,
1258 * get_userbyid - Get a user name by roleid and
1259 * fallback to 'unknown (OID=n)'
1263 pg_get_userbyid(PG_FUNCTION_ARGS)
1265 Oid roleid = PG_GETARG_OID(0);
1268 Form_pg_authid role_rec;
1271 * Allocate space for the result
1273 result = (Name) palloc(NAMEDATALEN);
1274 memset(NameStr(*result), 0, NAMEDATALEN);
1277 * Get the pg_authid entry and print the result
1279 roletup = SearchSysCache(AUTHOID,
1280 ObjectIdGetDatum(roleid),
1282 if (HeapTupleIsValid(roletup))
1284 role_rec = (Form_pg_authid) GETSTRUCT(roletup);
1285 StrNCpy(NameStr(*result), NameStr(role_rec->rolname), NAMEDATALEN);
1286 ReleaseSysCache(roletup);
1289 sprintf(NameStr(*result), "unknown (OID=%u)", roleid);
1291 PG_RETURN_NAME(result);
1296 * pg_get_serial_sequence
1297 * Get the name of the sequence used by a serial column,
1298 * formatted suitably for passing to setval, nextval or currval.
1299 * First parameter is not treated as double-quoted, second parameter
1300 * is --- see documentation for reason.
1303 pg_get_serial_sequence(PG_FUNCTION_ARGS)
1305 text *tablename = PG_GETARG_TEXT_P(0);
1306 text *columnname = PG_GETARG_TEXT_PP(1);
1311 Oid sequenceId = InvalidOid;
1317 /* Get the OID of the table */
1318 tablerv = makeRangeVarFromNameList(textToQualifiedNameList(tablename));
1319 tableOid = RangeVarGetRelid(tablerv, false);
1321 /* Get the number of the column */
1322 column = text_to_cstring(columnname);
1324 attnum = get_attnum(tableOid, column);
1325 if (attnum == InvalidAttrNumber)
1327 (errcode(ERRCODE_UNDEFINED_COLUMN),
1328 errmsg("column \"%s\" of relation \"%s\" does not exist",
1329 column, tablerv->relname)));
1331 /* Search the dependency table for the dependent sequence */
1332 depRel = heap_open(DependRelationId, AccessShareLock);
1334 ScanKeyInit(&key[0],
1335 Anum_pg_depend_refclassid,
1336 BTEqualStrategyNumber, F_OIDEQ,
1337 ObjectIdGetDatum(RelationRelationId));
1338 ScanKeyInit(&key[1],
1339 Anum_pg_depend_refobjid,
1340 BTEqualStrategyNumber, F_OIDEQ,
1341 ObjectIdGetDatum(tableOid));
1342 ScanKeyInit(&key[2],
1343 Anum_pg_depend_refobjsubid,
1344 BTEqualStrategyNumber, F_INT4EQ,
1345 Int32GetDatum(attnum));
1347 scan = systable_beginscan(depRel, DependReferenceIndexId, true,
1348 SnapshotNow, 3, key);
1350 while (HeapTupleIsValid(tup = systable_getnext(scan)))
1352 Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
1355 * We assume any auto dependency of a sequence on a column must be
1356 * what we are looking for. (We need the relkind test because indexes
1357 * can also have auto dependencies on columns.)
1359 if (deprec->classid == RelationRelationId &&
1360 deprec->objsubid == 0 &&
1361 deprec->deptype == DEPENDENCY_AUTO &&
1362 get_rel_relkind(deprec->objid) == RELKIND_SEQUENCE)
1364 sequenceId = deprec->objid;
1369 systable_endscan(scan);
1370 heap_close(depRel, AccessShareLock);
1372 if (OidIsValid(sequenceId))
1375 Form_pg_class classtuple;
1379 /* Get the sequence's pg_class entry */
1380 classtup = SearchSysCache(RELOID,
1381 ObjectIdGetDatum(sequenceId),
1383 if (!HeapTupleIsValid(classtup))
1384 elog(ERROR, "cache lookup failed for relation %u", sequenceId);
1385 classtuple = (Form_pg_class) GETSTRUCT(classtup);
1387 /* Get the namespace */
1388 nspname = get_namespace_name(classtuple->relnamespace);
1390 elog(ERROR, "cache lookup failed for namespace %u",
1391 classtuple->relnamespace);
1393 /* And construct the result string */
1394 result = quote_qualified_identifier(nspname,
1395 NameStr(classtuple->relname));
1397 ReleaseSysCache(classtup);
1399 PG_RETURN_TEXT_P(string_to_text(result));
1407 * pg_get_functiondef
1408 * Returns the complete "CREATE OR REPLACE FUNCTION ..." statement for
1409 * the specified function.
1412 pg_get_functiondef(PG_FUNCTION_ARGS)
1414 Oid funcid = PG_GETARG_OID(0);
1420 Form_pg_language lang;
1429 initStringInfo(&buf);
1431 /* Look up the function */
1432 proctup = SearchSysCache(PROCOID,
1433 ObjectIdGetDatum(funcid),
1435 if (!HeapTupleIsValid(proctup))
1436 elog(ERROR, "cache lookup failed for function %u", funcid);
1437 proc = (Form_pg_proc) GETSTRUCT(proctup);
1438 name = NameStr(proc->proname);
1442 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1443 errmsg("\"%s\" is an aggregate function", name)));
1445 /* Need its pg_language tuple for the language name */
1446 langtup = SearchSysCache(LANGOID,
1447 ObjectIdGetDatum(proc->prolang),
1449 if (!HeapTupleIsValid(langtup))
1450 elog(ERROR, "cache lookup failed for language %u", proc->prolang);
1451 lang = (Form_pg_language) GETSTRUCT(langtup);
1454 * We always qualify the function name, to ensure the right function
1457 nsp = get_namespace_name(proc->pronamespace);
1458 appendStringInfo(&buf, "CREATE OR REPLACE FUNCTION %s(",
1459 quote_qualified_identifier(nsp, name));
1460 (void) print_function_arguments(&buf, proctup, false, true);
1461 appendStringInfoString(&buf, ")\n RETURNS ");
1462 print_function_rettype(&buf, proctup);
1463 appendStringInfo(&buf, "\n LANGUAGE %s\n",
1464 quote_identifier(NameStr(lang->lanname)));
1466 /* Emit some miscellaneous options on one line */
1469 switch (proc->provolatile)
1471 case PROVOLATILE_IMMUTABLE:
1472 appendStringInfoString(&buf, " IMMUTABLE");
1474 case PROVOLATILE_STABLE:
1475 appendStringInfoString(&buf, " STABLE");
1477 case PROVOLATILE_VOLATILE:
1480 if (proc->proisstrict)
1481 appendStringInfoString(&buf, " STRICT");
1482 if (proc->prosecdef)
1483 appendStringInfoString(&buf, " SECURITY DEFINER");
1485 /* This code for the default cost and rows should match functioncmds.c */
1486 if (proc->prolang == INTERNALlanguageId ||
1487 proc->prolang == ClanguageId)
1491 if (proc->procost != procost)
1492 appendStringInfo(&buf, " COST %g", proc->procost);
1494 if (proc->prorows > 0 && proc->prorows != 1000)
1495 appendStringInfo(&buf, " ROWS %g", proc->prorows);
1497 if (oldlen != buf.len)
1498 appendStringInfoChar(&buf, '\n');
1500 /* Emit any proconfig options, one per line */
1501 tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_proconfig, &isnull);
1504 ArrayType *a = DatumGetArrayTypeP(tmp);
1507 Assert(ARR_ELEMTYPE(a) == TEXTOID);
1508 Assert(ARR_NDIM(a) == 1);
1509 Assert(ARR_LBOUND(a)[0] == 1);
1511 for (i = 1; i <= ARR_DIMS(a)[0]; i++)
1515 d = array_ref(a, 1, &i,
1516 -1 /* varlenarray */ ,
1517 -1 /* TEXT's typlen */ ,
1518 false /* TEXT's typbyval */ ,
1519 'i' /* TEXT's typalign */ ,
1523 char *configitem = TextDatumGetCString(d);
1526 pos = strchr(configitem, '=');
1531 appendStringInfo(&buf, " SET %s TO ",
1532 quote_identifier(configitem));
1535 * Some GUC variable names are 'LIST' type and hence must not
1538 if (pg_strcasecmp(configitem, "DateStyle") == 0
1539 || pg_strcasecmp(configitem, "search_path") == 0)
1540 appendStringInfoString(&buf, pos);
1542 simple_quote_literal(&buf, pos);
1543 appendStringInfoChar(&buf, '\n');
1548 /* And finally the function definition ... */
1549 appendStringInfoString(&buf, "AS ");
1551 tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_probin, &isnull);
1554 simple_quote_literal(&buf, TextDatumGetCString(tmp));
1555 appendStringInfoString(&buf, ", "); /* assume prosrc isn't null */
1558 tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_prosrc, &isnull);
1560 elog(ERROR, "null prosrc");
1561 prosrc = TextDatumGetCString(tmp);
1564 * We always use dollar quoting. Figure out a suitable delimiter.
1566 * Since the user is likely to be editing the function body string,
1567 * we shouldn't use a short delimiter that he might easily create a
1568 * conflict with. Hence prefer "$function$", but extend if needed.
1570 initStringInfo(&dq);
1571 appendStringInfoString(&dq, "$function");
1572 while (strstr(prosrc, dq.data) != NULL)
1573 appendStringInfoChar(&dq, 'x');
1574 appendStringInfoChar(&dq, '$');
1576 appendStringInfoString(&buf, dq.data);
1577 appendStringInfoString(&buf, prosrc);
1578 appendStringInfoString(&buf, dq.data);
1580 appendStringInfoString(&buf, "\n");
1582 ReleaseSysCache(langtup);
1583 ReleaseSysCache(proctup);
1585 PG_RETURN_TEXT_P(string_to_text(buf.data));
1589 * pg_get_function_arguments
1590 * Get a nicely-formatted list of arguments for a function.
1591 * This is everything that would go between the parentheses in
1595 pg_get_function_arguments(PG_FUNCTION_ARGS)
1597 Oid funcid = PG_GETARG_OID(0);
1601 initStringInfo(&buf);
1603 proctup = SearchSysCache(PROCOID,
1604 ObjectIdGetDatum(funcid),
1606 if (!HeapTupleIsValid(proctup))
1607 elog(ERROR, "cache lookup failed for function %u", funcid);
1609 (void) print_function_arguments(&buf, proctup, false, true);
1611 ReleaseSysCache(proctup);
1613 PG_RETURN_TEXT_P(string_to_text(buf.data));
1617 * pg_get_function_identity_arguments
1618 * Get a formatted list of arguments for a function.
1619 * This is everything that would go between the parentheses in
1620 * ALTER FUNCTION, etc. In particular, don't print defaults.
1623 pg_get_function_identity_arguments(PG_FUNCTION_ARGS)
1625 Oid funcid = PG_GETARG_OID(0);
1629 initStringInfo(&buf);
1631 proctup = SearchSysCache(PROCOID,
1632 ObjectIdGetDatum(funcid),
1634 if (!HeapTupleIsValid(proctup))
1635 elog(ERROR, "cache lookup failed for function %u", funcid);
1637 (void) print_function_arguments(&buf, proctup, false, false);
1639 ReleaseSysCache(proctup);
1641 PG_RETURN_TEXT_P(string_to_text(buf.data));
1645 * pg_get_function_result
1646 * Get a nicely-formatted version of the result type of a function.
1647 * This is what would appear after RETURNS in CREATE FUNCTION.
1650 pg_get_function_result(PG_FUNCTION_ARGS)
1652 Oid funcid = PG_GETARG_OID(0);
1656 initStringInfo(&buf);
1658 proctup = SearchSysCache(PROCOID,
1659 ObjectIdGetDatum(funcid),
1661 if (!HeapTupleIsValid(proctup))
1662 elog(ERROR, "cache lookup failed for function %u", funcid);
1664 print_function_rettype(&buf, proctup);
1666 ReleaseSysCache(proctup);
1668 PG_RETURN_TEXT_P(string_to_text(buf.data));
1672 * Guts of pg_get_function_result: append the function's return type
1673 * to the specified buffer.
1676 print_function_rettype(StringInfo buf, HeapTuple proctup)
1678 Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(proctup);
1680 StringInfoData rbuf;
1682 initStringInfo(&rbuf);
1684 if (proc->proretset)
1686 /* It might be a table function; try to print the arguments */
1687 appendStringInfoString(&rbuf, "TABLE(");
1688 ntabargs = print_function_arguments(&rbuf, proctup, true, false);
1690 appendStringInfoString(&rbuf, ")");
1692 resetStringInfo(&rbuf);
1697 /* Not a table function, so do the normal thing */
1698 if (proc->proretset)
1699 appendStringInfoString(&rbuf, "SETOF ");
1700 appendStringInfoString(&rbuf, format_type_be(proc->prorettype));
1703 appendStringInfoString(buf, rbuf.data);
1707 * Common code for pg_get_function_arguments and pg_get_function_result:
1708 * append the desired subset of arguments to buf. We print only TABLE
1709 * arguments when print_table_args is true, and all the others when it's false.
1710 * We print argument defaults only if print_defaults is true.
1711 * Function return value is the number of arguments printed.
1714 print_function_arguments(StringInfo buf, HeapTuple proctup,
1715 bool print_table_args, bool print_defaults)
1717 Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(proctup);
1725 ListCell *nextargdefault = NULL;
1728 numargs = get_func_arg_info(proctup,
1729 &argtypes, &argnames, &argmodes);
1731 nlackdefaults = numargs;
1732 if (print_defaults && proc->pronargdefaults > 0)
1734 Datum proargdefaults;
1737 proargdefaults = SysCacheGetAttr(PROCOID, proctup,
1738 Anum_pg_proc_proargdefaults,
1745 str = TextDatumGetCString(proargdefaults);
1746 argdefaults = (List *) stringToNode(str);
1747 Assert(IsA(argdefaults, List));
1749 nextargdefault = list_head(argdefaults);
1750 /* nlackdefaults counts only *input* arguments lacking defaults */
1751 nlackdefaults = proc->pronargs - list_length(argdefaults);
1757 for (i = 0; i < numargs; i++)
1759 Oid argtype = argtypes[i];
1760 char *argname = argnames ? argnames[i] : NULL;
1761 char argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
1762 const char *modename;
1771 case PROARGMODE_INOUT:
1772 modename = "INOUT ";
1775 case PROARGMODE_OUT:
1779 case PROARGMODE_VARIADIC:
1780 modename = "VARIADIC ";
1783 case PROARGMODE_TABLE:
1788 elog(ERROR, "invalid parameter mode '%c'", argmode);
1789 modename = NULL; /* keep compiler quiet */
1794 inputargno++; /* this is a 1-based counter */
1796 if (print_table_args != (argmode == PROARGMODE_TABLE))
1800 appendStringInfoString(buf, ", ");
1801 appendStringInfoString(buf, modename);
1802 if (argname && argname[0])
1803 appendStringInfo(buf, "%s ", argname);
1804 appendStringInfoString(buf, format_type_be(argtype));
1805 if (print_defaults && isinput && inputargno > nlackdefaults)
1809 Assert(nextargdefault != NULL);
1810 expr = (Node *) lfirst(nextargdefault);
1811 nextargdefault = lnext(nextargdefault);
1813 appendStringInfo(buf, " DEFAULT %s",
1814 deparse_expression(expr, NIL, false, false));
1824 * deparse_expression - General utility for deparsing expressions
1826 * calls deparse_expression_pretty with all prettyPrinting disabled
1829 deparse_expression(Node *expr, List *dpcontext,
1830 bool forceprefix, bool showimplicit)
1832 return deparse_expression_pretty(expr, dpcontext, forceprefix,
1833 showimplicit, 0, 0);
1837 * deparse_expression_pretty - General utility for deparsing expressions
1839 * expr is the node tree to be deparsed. It must be a transformed expression
1840 * tree (ie, not the raw output of gram.y).
1842 * dpcontext is a list of deparse_namespace nodes representing the context
1843 * for interpreting Vars in the node tree.
1845 * forceprefix is TRUE to force all Vars to be prefixed with their table names.
1847 * showimplicit is TRUE to force all implicit casts to be shown explicitly.
1849 * tries to pretty up the output according to prettyFlags and startIndent.
1851 * The result is a palloc'd string.
1855 deparse_expression_pretty(Node *expr, List *dpcontext,
1856 bool forceprefix, bool showimplicit,
1857 int prettyFlags, int startIndent)
1860 deparse_context context;
1862 initStringInfo(&buf);
1864 context.namespaces = dpcontext;
1865 context.windowClause = NIL;
1866 context.windowTList = NIL;
1867 context.varprefix = forceprefix;
1868 context.prettyFlags = prettyFlags;
1869 context.indentLevel = startIndent;
1871 get_rule_expr(expr, &context, showimplicit);
1877 * deparse_context_for - Build deparse context for a single relation
1879 * Given the reference name (alias) and OID of a relation, build deparsing
1880 * context for an expression referencing only that relation (as varno 1,
1881 * varlevelsup 0). This is sufficient for many uses of deparse_expression.
1885 deparse_context_for(const char *aliasname, Oid relid)
1887 deparse_namespace *dpns;
1890 dpns = (deparse_namespace *) palloc(sizeof(deparse_namespace));
1892 /* Build a minimal RTE for the rel */
1893 rte = makeNode(RangeTblEntry);
1894 rte->rtekind = RTE_RELATION;
1896 rte->eref = makeAlias(aliasname, NIL);
1898 rte->inFromCl = true;
1900 /* Build one-element rtable */
1901 dpns->rtable = list_make1(rte);
1903 dpns->subplans = NIL;
1904 dpns->outer_plan = dpns->inner_plan = NULL;
1906 /* Return a one-deep namespace stack */
1907 return list_make1(dpns);
1911 * deparse_context_for_plan - Build deparse context for a plan node
1913 * When deparsing an expression in a Plan tree, we might have to resolve
1914 * OUTER or INNER references. To do this, the caller must provide the
1915 * parent Plan node. In the normal case of a join plan node, OUTER and
1916 * INNER references can be resolved by drilling down into the left and
1917 * right child plans. A special case is that a nestloop inner indexscan
1918 * might have OUTER Vars, but the outer side of the join is not a child
1919 * plan node. To handle such cases the outer plan node must be passed
1920 * separately. (Pass NULL for outer_plan otherwise.)
1922 * Note: plan and outer_plan really ought to be declared as "Plan *", but
1923 * we use "Node *" to avoid having to include plannodes.h in builtins.h.
1925 * The plan's rangetable list must also be passed. We actually prefer to use
1926 * the rangetable to resolve simple Vars, but the plan inputs are necessary
1927 * for Vars that reference expressions computed in subplan target lists.
1929 * We also need the list of subplans associated with the Plan tree; this
1930 * is for resolving references to CTE subplans.
1933 deparse_context_for_plan(Node *plan, Node *outer_plan,
1934 List *rtable, List *subplans)
1936 deparse_namespace *dpns;
1938 dpns = (deparse_namespace *) palloc(sizeof(deparse_namespace));
1940 dpns->rtable = rtable;
1942 dpns->subplans = subplans;
1945 * Set up outer_plan and inner_plan from the Plan node (this includes
1946 * various special cases for particular Plan types).
1948 push_plan(dpns, (Plan *) plan);
1951 * If outer_plan is given, that overrides whatever we got from the plan.
1954 dpns->outer_plan = (Plan *) outer_plan;
1956 /* Return a one-deep namespace stack */
1957 return list_make1(dpns);
1961 * make_ruledef - reconstruct the CREATE RULE command
1962 * for a given pg_rewrite tuple
1966 make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
1976 List *actions = NIL;
1982 * Get the attribute values from the rules tuple
1984 fno = SPI_fnumber(rulettc, "rulename");
1985 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
1987 rulename = NameStr(*(DatumGetName(dat)));
1989 fno = SPI_fnumber(rulettc, "ev_type");
1990 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
1992 ev_type = DatumGetChar(dat);
1994 fno = SPI_fnumber(rulettc, "ev_class");
1995 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
1997 ev_class = DatumGetObjectId(dat);
1999 fno = SPI_fnumber(rulettc, "ev_attr");
2000 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
2002 ev_attr = DatumGetInt16(dat);
2004 fno = SPI_fnumber(rulettc, "is_instead");
2005 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
2007 is_instead = DatumGetBool(dat);
2009 /* these could be nulls */
2010 fno = SPI_fnumber(rulettc, "ev_qual");
2011 ev_qual = SPI_getvalue(ruletup, rulettc, fno);
2013 fno = SPI_fnumber(rulettc, "ev_action");
2014 ev_action = SPI_getvalue(ruletup, rulettc, fno);
2015 if (ev_action != NULL)
2016 actions = (List *) stringToNode(ev_action);
2019 * Build the rules definition text
2021 appendStringInfo(buf, "CREATE RULE %s AS",
2022 quote_identifier(rulename));
2024 if (prettyFlags & PRETTYFLAG_INDENT)
2025 appendStringInfoString(buf, "\n ON ");
2027 appendStringInfoString(buf, " ON ");
2029 /* The event the rule is fired for */
2033 appendStringInfo(buf, "SELECT");
2037 appendStringInfo(buf, "UPDATE");
2041 appendStringInfo(buf, "INSERT");
2045 appendStringInfo(buf, "DELETE");
2050 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2051 errmsg("rule \"%s\" has unsupported event type %d",
2052 rulename, ev_type)));
2056 /* The relation the rule is fired on */
2057 appendStringInfo(buf, " TO %s", generate_relation_name(ev_class, NIL));
2059 appendStringInfo(buf, ".%s",
2060 quote_identifier(get_relid_attribute_name(ev_class,
2063 /* If the rule has an event qualification, add it */
2064 if (ev_qual == NULL)
2066 if (strlen(ev_qual) > 0 && strcmp(ev_qual, "<>") != 0)
2070 deparse_context context;
2071 deparse_namespace dpns;
2073 if (prettyFlags & PRETTYFLAG_INDENT)
2074 appendStringInfoString(buf, "\n ");
2075 appendStringInfo(buf, " WHERE ");
2077 qual = stringToNode(ev_qual);
2080 * We need to make a context for recognizing any Vars in the qual
2081 * (which can only be references to OLD and NEW). Use the rtable of
2082 * the first query in the action list for this purpose.
2084 query = (Query *) linitial(actions);
2087 * If the action is INSERT...SELECT, OLD/NEW have been pushed down
2088 * into the SELECT, and that's what we need to look at. (Ugly kluge
2089 * ... try to fix this when we redesign querytrees.)
2091 query = getInsertSelectQuery(query, NULL);
2093 /* Must acquire locks right away; see notes in get_query_def() */
2094 AcquireRewriteLocks(query);
2097 context.namespaces = list_make1(&dpns);
2098 context.windowClause = NIL;
2099 context.windowTList = NIL;
2100 context.varprefix = (list_length(query->rtable) != 1);
2101 context.prettyFlags = prettyFlags;
2102 context.indentLevel = PRETTYINDENT_STD;
2103 dpns.rtable = query->rtable;
2104 dpns.ctes = query->cteList;
2105 dpns.subplans = NIL;
2106 dpns.outer_plan = dpns.inner_plan = NULL;
2108 get_rule_expr(qual, &context, false);
2111 appendStringInfo(buf, " DO ");
2113 /* The INSTEAD keyword (if so) */
2115 appendStringInfo(buf, "INSTEAD ");
2117 /* Finally the rules actions */
2118 if (list_length(actions) > 1)
2123 appendStringInfo(buf, "(");
2124 foreach(action, actions)
2126 query = (Query *) lfirst(action);
2127 get_query_def(query, buf, NIL, NULL, prettyFlags, 0);
2129 appendStringInfo(buf, ";\n");
2131 appendStringInfo(buf, "; ");
2133 appendStringInfo(buf, ");");
2135 else if (list_length(actions) == 0)
2137 appendStringInfo(buf, "NOTHING;");
2143 query = (Query *) linitial(actions);
2144 get_query_def(query, buf, NIL, NULL, prettyFlags, 0);
2145 appendStringInfo(buf, ";");
2151 * make_viewdef - reconstruct the SELECT part of a
2156 make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
2166 List *actions = NIL;
2167 Relation ev_relation;
2172 * Get the attribute values from the rules tuple
2174 fno = SPI_fnumber(rulettc, "ev_type");
2175 ev_type = (char) SPI_getbinval(ruletup, rulettc, fno, &isnull);
2177 fno = SPI_fnumber(rulettc, "ev_class");
2178 ev_class = (Oid) SPI_getbinval(ruletup, rulettc, fno, &isnull);
2180 fno = SPI_fnumber(rulettc, "ev_attr");
2181 ev_attr = (int2) SPI_getbinval(ruletup, rulettc, fno, &isnull);
2183 fno = SPI_fnumber(rulettc, "is_instead");
2184 is_instead = (bool) SPI_getbinval(ruletup, rulettc, fno, &isnull);
2186 fno = SPI_fnumber(rulettc, "ev_qual");
2187 ev_qual = SPI_getvalue(ruletup, rulettc, fno);
2189 fno = SPI_fnumber(rulettc, "ev_action");
2190 ev_action = SPI_getvalue(ruletup, rulettc, fno);
2191 if (ev_action != NULL)
2192 actions = (List *) stringToNode(ev_action);
2194 if (list_length(actions) != 1)
2196 appendStringInfo(buf, "Not a view");
2200 query = (Query *) linitial(actions);
2202 if (ev_type != '1' || ev_attr >= 0 || !is_instead ||
2203 strcmp(ev_qual, "<>") != 0 || query->commandType != CMD_SELECT)
2205 appendStringInfo(buf, "Not a view");
2209 ev_relation = heap_open(ev_class, AccessShareLock);
2211 get_query_def(query, buf, NIL, RelationGetDescr(ev_relation),
2213 appendStringInfo(buf, ";");
2215 heap_close(ev_relation, AccessShareLock);
2220 * get_query_def - Parse back one query parsetree
2222 * If resultDesc is not NULL, then it is the output tuple descriptor for
2223 * the view represented by a SELECT query.
2227 get_query_def(Query *query, StringInfo buf, List *parentnamespace,
2228 TupleDesc resultDesc, int prettyFlags, int startIndent)
2230 deparse_context context;
2231 deparse_namespace dpns;
2234 * Before we begin to examine the query, acquire locks on referenced
2235 * relations, and fix up deleted columns in JOIN RTEs. This ensures
2236 * consistent results. Note we assume it's OK to scribble on the passed
2239 AcquireRewriteLocks(query);
2242 context.namespaces = lcons(&dpns, list_copy(parentnamespace));
2243 context.windowClause = NIL;
2244 context.windowTList = NIL;
2245 context.varprefix = (parentnamespace != NIL ||
2246 list_length(query->rtable) != 1);
2247 context.prettyFlags = prettyFlags;
2248 context.indentLevel = startIndent;
2250 dpns.rtable = query->rtable;
2251 dpns.ctes = query->cteList;
2252 dpns.subplans = NIL;
2253 dpns.outer_plan = dpns.inner_plan = NULL;
2255 switch (query->commandType)
2258 get_select_query_def(query, &context, resultDesc);
2262 get_update_query_def(query, &context);
2266 get_insert_query_def(query, &context);
2270 get_delete_query_def(query, &context);
2274 appendStringInfo(buf, "NOTHING");
2278 get_utility_query_def(query, &context);
2282 elog(ERROR, "unrecognized query command type: %d",
2283 query->commandType);
2289 * get_values_def - Parse back a VALUES list
2293 get_values_def(List *values_lists, deparse_context *context)
2295 StringInfo buf = context->buf;
2296 bool first_list = true;
2299 appendStringInfoString(buf, "VALUES ");
2301 foreach(vtl, values_lists)
2303 List *sublist = (List *) lfirst(vtl);
2304 bool first_col = true;
2310 appendStringInfoString(buf, ", ");
2312 appendStringInfoChar(buf, '(');
2313 foreach(lc, sublist)
2315 Node *col = (Node *) lfirst(lc);
2320 appendStringInfoChar(buf, ',');
2323 * Strip any top-level nodes representing indirection assignments,
2324 * then print the result.
2326 get_rule_expr(processIndirection(col, context, false),
2329 appendStringInfoChar(buf, ')');
2334 * get_with_clause - Parse back a WITH clause
2338 get_with_clause(Query *query, deparse_context *context)
2340 StringInfo buf = context->buf;
2344 if (query->cteList == NIL)
2347 if (PRETTY_INDENT(context))
2349 context->indentLevel += PRETTYINDENT_STD;
2350 appendStringInfoChar(buf, ' ');
2353 if (query->hasRecursive)
2354 sep = "WITH RECURSIVE ";
2357 foreach(l, query->cteList)
2359 CommonTableExpr *cte = (CommonTableExpr *) lfirst(l);
2361 appendStringInfoString(buf, sep);
2362 appendStringInfoString(buf, quote_identifier(cte->ctename));
2363 if (cte->aliascolnames)
2368 appendStringInfoChar(buf, '(');
2369 foreach(col, cte->aliascolnames)
2374 appendStringInfoString(buf, ", ");
2375 appendStringInfoString(buf,
2376 quote_identifier(strVal(lfirst(col))));
2378 appendStringInfoChar(buf, ')');
2380 appendStringInfoString(buf, " AS (");
2381 if (PRETTY_INDENT(context))
2382 appendContextKeyword(context, "", 0, 0, 0);
2383 get_query_def((Query *) cte->ctequery, buf, context->namespaces, NULL,
2384 context->prettyFlags, context->indentLevel);
2385 if (PRETTY_INDENT(context))
2386 appendContextKeyword(context, "", 0, 0, 0);
2387 appendStringInfoChar(buf, ')');
2391 if (PRETTY_INDENT(context))
2393 context->indentLevel -= PRETTYINDENT_STD;
2394 appendContextKeyword(context, "", 0, 0, 0);
2397 appendStringInfoChar(buf, ' ');
2401 * get_select_query_def - Parse back a SELECT parsetree
2405 get_select_query_def(Query *query, deparse_context *context,
2406 TupleDesc resultDesc)
2408 StringInfo buf = context->buf;
2409 List *save_windowclause;
2410 List *save_windowtlist;
2414 /* Insert the WITH clause if given */
2415 get_with_clause(query, context);
2417 /* Set up context for possible window functions */
2418 save_windowclause = context->windowClause;
2419 context->windowClause = query->windowClause;
2420 save_windowtlist = context->windowTList;
2421 context->windowTList = query->targetList;
2424 * If the Query node has a setOperations tree, then it's the top level of
2425 * a UNION/INTERSECT/EXCEPT query; only the WITH, ORDER BY and LIMIT
2426 * fields are interesting in the top query itself.
2428 if (query->setOperations)
2430 get_setop_query(query->setOperations, query, context, resultDesc);
2431 /* ORDER BY clauses must be simple in this case */
2436 get_basic_select_query(query, context, resultDesc);
2437 force_colno = false;
2440 /* Add the ORDER BY clause if given */
2441 if (query->sortClause != NIL)
2443 appendContextKeyword(context, " ORDER BY ",
2444 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2445 get_rule_orderby(query->sortClause, query->targetList,
2446 force_colno, context);
2449 /* Add the LIMIT clause if given */
2450 if (query->limitOffset != NULL)
2452 appendContextKeyword(context, " OFFSET ",
2453 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2454 get_rule_expr(query->limitOffset, context, false);
2456 if (query->limitCount != NULL)
2458 appendContextKeyword(context, " LIMIT ",
2459 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2460 if (IsA(query->limitCount, Const) &&
2461 ((Const *) query->limitCount)->constisnull)
2462 appendStringInfo(buf, "ALL");
2464 get_rule_expr(query->limitCount, context, false);
2467 /* Add FOR UPDATE/SHARE clauses if present */
2468 foreach(l, query->rowMarks)
2470 RowMarkClause *rc = (RowMarkClause *) lfirst(l);
2471 RangeTblEntry *rte = rt_fetch(rc->rti, query->rtable);
2474 appendContextKeyword(context, " FOR UPDATE",
2475 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2477 appendContextKeyword(context, " FOR SHARE",
2478 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2479 appendStringInfo(buf, " OF %s",
2480 quote_identifier(rte->eref->aliasname));
2482 appendStringInfo(buf, " NOWAIT");
2485 context->windowClause = save_windowclause;
2486 context->windowTList = save_windowtlist;
2490 get_basic_select_query(Query *query, deparse_context *context,
2491 TupleDesc resultDesc)
2493 StringInfo buf = context->buf;
2497 if (PRETTY_INDENT(context))
2499 context->indentLevel += PRETTYINDENT_STD;
2500 appendStringInfoChar(buf, ' ');
2504 * If the query looks like SELECT * FROM (VALUES ...), then print just the
2505 * VALUES part. This reverses what transformValuesClause() did at parse
2506 * time. If the jointree contains just a single VALUES RTE, we assume
2507 * this case applies (without looking at the targetlist...)
2509 if (list_length(query->jointree->fromlist) == 1)
2511 RangeTblRef *rtr = (RangeTblRef *) linitial(query->jointree->fromlist);
2513 if (IsA(rtr, RangeTblRef))
2515 RangeTblEntry *rte = rt_fetch(rtr->rtindex, query->rtable);
2517 if (rte->rtekind == RTE_VALUES)
2519 get_values_def(rte->values_lists, context);
2526 * Build up the query string - first we say SELECT
2528 appendStringInfo(buf, "SELECT");
2530 /* Add the DISTINCT clause if given */
2531 if (query->distinctClause != NIL)
2533 if (query->hasDistinctOn)
2535 appendStringInfo(buf, " DISTINCT ON (");
2537 foreach(l, query->distinctClause)
2539 SortGroupClause *srt = (SortGroupClause *) lfirst(l);
2541 appendStringInfoString(buf, sep);
2542 get_rule_sortgroupclause(srt, query->targetList,
2546 appendStringInfo(buf, ")");
2549 appendStringInfo(buf, " DISTINCT");
2552 /* Then we tell what to select (the targetlist) */
2553 get_target_list(query->targetList, context, resultDesc);
2555 /* Add the FROM clause if needed */
2556 get_from_clause(query, " FROM ", context);
2558 /* Add the WHERE clause if given */
2559 if (query->jointree->quals != NULL)
2561 appendContextKeyword(context, " WHERE ",
2562 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2563 get_rule_expr(query->jointree->quals, context, false);
2566 /* Add the GROUP BY clause if given */
2567 if (query->groupClause != NULL)
2569 appendContextKeyword(context, " GROUP BY ",
2570 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2572 foreach(l, query->groupClause)
2574 SortGroupClause *grp = (SortGroupClause *) lfirst(l);
2576 appendStringInfoString(buf, sep);
2577 get_rule_sortgroupclause(grp, query->targetList,
2583 /* Add the HAVING clause if given */
2584 if (query->havingQual != NULL)
2586 appendContextKeyword(context, " HAVING ",
2587 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2588 get_rule_expr(query->havingQual, context, false);
2591 /* Add the WINDOW clause if needed */
2592 if (query->windowClause != NIL)
2593 get_rule_windowclause(query, context);
2597 * get_target_list - Parse back a SELECT target list
2599 * This is also used for RETURNING lists in INSERT/UPDATE/DELETE.
2603 get_target_list(List *targetList, deparse_context *context,
2604 TupleDesc resultDesc)
2606 StringInfo buf = context->buf;
2613 foreach(l, targetList)
2615 TargetEntry *tle = (TargetEntry *) lfirst(l);
2620 continue; /* ignore junk entries */
2622 appendStringInfoString(buf, sep);
2627 * We special-case Var nodes rather than using get_rule_expr. This is
2628 * needed because get_rule_expr will display a whole-row Var as
2629 * "foo.*", which is the preferred notation in most contexts, but at
2630 * the top level of a SELECT list it's not right (the parser will
2631 * expand that notation into multiple columns, yielding behavior
2632 * different from a whole-row Var). We want just "foo", instead.
2634 if (tle->expr && IsA(tle->expr, Var))
2636 attname = get_variable((Var *) tle->expr, 0, false, context);
2640 get_rule_expr((Node *) tle->expr, context, true);
2641 /* We'll show the AS name unless it's this: */
2642 attname = "?column?";
2646 * Figure out what the result column should be called. In the context
2647 * of a view, use the view's tuple descriptor (so as to pick up the
2648 * effects of any column RENAME that's been done on the view).
2649 * Otherwise, just use what we can find in the TLE.
2651 if (resultDesc && colno <= resultDesc->natts)
2652 colname = NameStr(resultDesc->attrs[colno - 1]->attname);
2654 colname = tle->resname;
2656 /* Show AS unless the column's name is correct as-is */
2657 if (colname) /* resname could be NULL */
2659 if (attname == NULL || strcmp(attname, colname) != 0)
2660 appendStringInfo(buf, " AS %s", quote_identifier(colname));
2666 get_setop_query(Node *setOp, Query *query, deparse_context *context,
2667 TupleDesc resultDesc)
2669 StringInfo buf = context->buf;
2672 if (IsA(setOp, RangeTblRef))
2674 RangeTblRef *rtr = (RangeTblRef *) setOp;
2675 RangeTblEntry *rte = rt_fetch(rtr->rtindex, query->rtable);
2676 Query *subquery = rte->subquery;
2678 Assert(subquery != NULL);
2679 Assert(subquery->setOperations == NULL);
2680 /* Need parens if WITH, ORDER BY, FOR UPDATE, or LIMIT; see gram.y */
2681 need_paren = (subquery->cteList ||
2682 subquery->sortClause ||
2683 subquery->rowMarks ||
2684 subquery->limitOffset ||
2685 subquery->limitCount);
2687 appendStringInfoChar(buf, '(');
2688 get_query_def(subquery, buf, context->namespaces, resultDesc,
2689 context->prettyFlags, context->indentLevel);
2691 appendStringInfoChar(buf, ')');
2693 else if (IsA(setOp, SetOperationStmt))
2695 SetOperationStmt *op = (SetOperationStmt *) setOp;
2697 if (PRETTY_INDENT(context))
2699 context->indentLevel += PRETTYINDENT_STD;
2700 appendStringInfoSpaces(buf, PRETTYINDENT_STD);
2704 * We force parens whenever nesting two SetOperationStmts. There are
2705 * some cases in which parens are needed around a leaf query too, but
2706 * those are more easily handled at the next level down (see code
2709 need_paren = !IsA(op->larg, RangeTblRef);
2712 appendStringInfoChar(buf, '(');
2713 get_setop_query(op->larg, query, context, resultDesc);
2715 appendStringInfoChar(buf, ')');
2717 if (!PRETTY_INDENT(context))
2718 appendStringInfoChar(buf, ' ');
2722 appendContextKeyword(context, "UNION ",
2723 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2725 case SETOP_INTERSECT:
2726 appendContextKeyword(context, "INTERSECT ",
2727 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2730 appendContextKeyword(context, "EXCEPT ",
2731 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2734 elog(ERROR, "unrecognized set op: %d",
2738 appendStringInfo(buf, "ALL ");
2740 if (PRETTY_INDENT(context))
2741 appendContextKeyword(context, "", 0, 0, 0);
2743 need_paren = !IsA(op->rarg, RangeTblRef);
2746 appendStringInfoChar(buf, '(');
2747 get_setop_query(op->rarg, query, context, resultDesc);
2749 appendStringInfoChar(buf, ')');
2751 if (PRETTY_INDENT(context))
2752 context->indentLevel -= PRETTYINDENT_STD;
2756 elog(ERROR, "unrecognized node type: %d",
2757 (int) nodeTag(setOp));
2762 * Display a sort/group clause.
2764 * Also returns the expression tree, so caller need not find it again.
2767 get_rule_sortgroupclause(SortGroupClause *srt, List *tlist, bool force_colno,
2768 deparse_context *context)
2770 StringInfo buf = context->buf;
2774 tle = get_sortgroupclause_tle(srt, tlist);
2775 expr = (Node *) tle->expr;
2778 * Use column-number form if requested by caller. Otherwise, if
2779 * expression is a constant, force it to be dumped with an explicit
2780 * cast as decoration --- this is because a simple integer constant
2781 * is ambiguous (and will be misinterpreted by findTargetlistEntry())
2782 * if we dump it without any decoration. Otherwise, just dump the
2783 * expression normally.
2787 Assert(!tle->resjunk);
2788 appendStringInfo(buf, "%d", tle->resno);
2790 else if (expr && IsA(expr, Const))
2791 get_const_expr((Const *) expr, context, 1);
2793 get_rule_expr(expr, context, true);
2799 * Display an ORDER BY list.
2802 get_rule_orderby(List *orderList, List *targetList,
2803 bool force_colno, deparse_context *context)
2805 StringInfo buf = context->buf;
2810 foreach(l, orderList)
2812 SortGroupClause *srt = (SortGroupClause *) lfirst(l);
2815 TypeCacheEntry *typentry;
2817 appendStringInfoString(buf, sep);
2818 sortexpr = get_rule_sortgroupclause(srt, targetList,
2819 force_colno, context);
2820 sortcoltype = exprType(sortexpr);
2821 /* See whether operator is default < or > for datatype */
2822 typentry = lookup_type_cache(sortcoltype,
2823 TYPECACHE_LT_OPR | TYPECACHE_GT_OPR);
2824 if (srt->sortop == typentry->lt_opr)
2826 /* ASC is default, so emit nothing for it */
2827 if (srt->nulls_first)
2828 appendStringInfo(buf, " NULLS FIRST");
2830 else if (srt->sortop == typentry->gt_opr)
2832 appendStringInfo(buf, " DESC");
2833 /* DESC defaults to NULLS FIRST */
2834 if (!srt->nulls_first)
2835 appendStringInfo(buf, " NULLS LAST");
2839 appendStringInfo(buf, " USING %s",
2840 generate_operator_name(srt->sortop,
2843 /* be specific to eliminate ambiguity */
2844 if (srt->nulls_first)
2845 appendStringInfo(buf, " NULLS FIRST");
2847 appendStringInfo(buf, " NULLS LAST");
2854 * Display a WINDOW clause.
2856 * Note that the windowClause list might contain only anonymous window
2857 * specifications, in which case we should print nothing here.
2860 get_rule_windowclause(Query *query, deparse_context *context)
2862 StringInfo buf = context->buf;
2867 foreach(l, query->windowClause)
2869 WindowClause *wc = (WindowClause *) lfirst(l);
2871 if (wc->name == NULL)
2872 continue; /* ignore anonymous windows */
2875 appendContextKeyword(context, " WINDOW ",
2876 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2878 appendStringInfoString(buf, sep);
2880 appendStringInfo(buf, "%s AS ", quote_identifier(wc->name));
2882 get_rule_windowspec(wc, query->targetList, context);
2889 * Display a window definition
2892 get_rule_windowspec(WindowClause *wc, List *targetList,
2893 deparse_context *context)
2895 StringInfo buf = context->buf;
2896 bool needspace = false;
2900 appendStringInfoChar(buf, '(');
2903 appendStringInfoString(buf, quote_identifier(wc->refname));
2906 /* partition clauses are always inherited, so only print if no refname */
2907 if (wc->partitionClause && !wc->refname)
2910 appendStringInfoChar(buf, ' ');
2911 appendStringInfoString(buf, "PARTITION BY ");
2913 foreach(l, wc->partitionClause)
2915 SortGroupClause *grp = (SortGroupClause *) lfirst(l);
2917 appendStringInfoString(buf, sep);
2918 get_rule_sortgroupclause(grp, targetList,
2924 /* print ordering clause only if not inherited */
2925 if (wc->orderClause && !wc->copiedOrder)
2928 appendStringInfoChar(buf, ' ');
2929 appendStringInfoString(buf, "ORDER BY ");
2930 get_rule_orderby(wc->orderClause, targetList, false, context);
2933 /* framing clause is never inherited, so print unless it's default */
2934 if (wc->frameOptions & FRAMEOPTION_NONDEFAULT)
2937 appendStringInfoChar(buf, ' ');
2938 if (wc->frameOptions & FRAMEOPTION_RANGE)
2939 appendStringInfoString(buf, "RANGE ");
2940 else if (wc->frameOptions & FRAMEOPTION_ROWS)
2941 appendStringInfoString(buf, "ROWS ");
2944 if (wc->frameOptions & FRAMEOPTION_BETWEEN)
2945 appendStringInfoString(buf, "BETWEEN ");
2946 if (wc->frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING)
2947 appendStringInfoString(buf, "UNBOUNDED PRECEDING ");
2948 else if (wc->frameOptions & FRAMEOPTION_START_CURRENT_ROW)
2949 appendStringInfoString(buf, "CURRENT ROW ");
2952 if (wc->frameOptions & FRAMEOPTION_BETWEEN)
2954 appendStringInfoString(buf, "AND ");
2955 if (wc->frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING)
2956 appendStringInfoString(buf, "UNBOUNDED FOLLOWING ");
2957 else if (wc->frameOptions & FRAMEOPTION_END_CURRENT_ROW)
2958 appendStringInfoString(buf, "CURRENT ROW ");
2962 /* we will now have a trailing space; remove it */
2965 appendStringInfoChar(buf, ')');
2969 * get_insert_query_def - Parse back an INSERT parsetree
2973 get_insert_query_def(Query *query, deparse_context *context)
2975 StringInfo buf = context->buf;
2976 RangeTblEntry *select_rte = NULL;
2977 RangeTblEntry *values_rte = NULL;
2980 ListCell *values_cell;
2982 List *strippedexprs;
2985 * If it's an INSERT ... SELECT or VALUES (...), (...), ... there will be
2986 * a single RTE for the SELECT or VALUES.
2988 foreach(l, query->rtable)
2990 rte = (RangeTblEntry *) lfirst(l);
2992 if (rte->rtekind == RTE_SUBQUERY)
2995 elog(ERROR, "too many subquery RTEs in INSERT");
2999 if (rte->rtekind == RTE_VALUES)
3002 elog(ERROR, "too many values RTEs in INSERT");
3006 if (select_rte && values_rte)
3007 elog(ERROR, "both subquery and values RTEs in INSERT");
3010 * Start the query with INSERT INTO relname
3012 rte = rt_fetch(query->resultRelation, query->rtable);
3013 Assert(rte->rtekind == RTE_RELATION);
3015 if (PRETTY_INDENT(context))
3017 context->indentLevel += PRETTYINDENT_STD;
3018 appendStringInfoChar(buf, ' ');
3020 appendStringInfo(buf, "INSERT INTO %s (",
3021 generate_relation_name(rte->relid, NIL));
3024 * Add the insert-column-names list. To handle indirection properly, we
3025 * need to look for indirection nodes in the top targetlist (if it's
3026 * INSERT ... SELECT or INSERT ... single VALUES), or in the first
3027 * expression list of the VALUES RTE (if it's INSERT ... multi VALUES). We
3028 * assume that all the expression lists will have similar indirection in
3032 values_cell = list_head((List *) linitial(values_rte->values_lists));
3035 strippedexprs = NIL;
3037 foreach(l, query->targetList)
3039 TargetEntry *tle = (TargetEntry *) lfirst(l);
3042 continue; /* ignore junk entries */
3044 appendStringInfoString(buf, sep);
3048 * Put out name of target column; look in the catalogs, not at
3049 * tle->resname, since resname will fail to track RENAME.
3051 appendStringInfoString(buf,
3052 quote_identifier(get_relid_attribute_name(rte->relid,
3056 * Print any indirection needed (subfields or subscripts), and strip
3057 * off the top-level nodes representing the indirection assignments.
3061 /* we discard the stripped expression in this case */
3062 processIndirection((Node *) lfirst(values_cell), context, true);
3063 values_cell = lnext(values_cell);
3067 /* we keep a list of the stripped expressions in this case */
3068 strippedexprs = lappend(strippedexprs,
3069 processIndirection((Node *) tle->expr,
3073 appendStringInfo(buf, ") ");
3077 /* Add the SELECT */
3078 get_query_def(select_rte->subquery, buf, NIL, NULL,
3079 context->prettyFlags, context->indentLevel);
3081 else if (values_rte)
3083 /* A WITH clause is possible here */
3084 get_with_clause(query, context);
3085 /* Add the multi-VALUES expression lists */
3086 get_values_def(values_rte->values_lists, context);
3090 /* A WITH clause is possible here */
3091 get_with_clause(query, context);
3092 /* Add the single-VALUES expression list */
3093 appendContextKeyword(context, "VALUES (",
3094 -PRETTYINDENT_STD, PRETTYINDENT_STD, 2);
3095 get_rule_expr((Node *) strippedexprs, context, false);
3096 appendStringInfoChar(buf, ')');
3099 /* Add RETURNING if present */
3100 if (query->returningList)
3102 appendContextKeyword(context, " RETURNING",
3103 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
3104 get_target_list(query->returningList, context, NULL);
3110 * get_update_query_def - Parse back an UPDATE parsetree
3114 get_update_query_def(Query *query, deparse_context *context)
3116 StringInfo buf = context->buf;
3122 * Start the query with UPDATE relname SET
3124 rte = rt_fetch(query->resultRelation, query->rtable);
3125 Assert(rte->rtekind == RTE_RELATION);
3126 if (PRETTY_INDENT(context))
3128 appendStringInfoChar(buf, ' ');
3129 context->indentLevel += PRETTYINDENT_STD;
3131 appendStringInfo(buf, "UPDATE %s%s",
3133 generate_relation_name(rte->relid, NIL));
3134 if (rte->alias != NULL)
3135 appendStringInfo(buf, " %s",
3136 quote_identifier(rte->alias->aliasname));
3137 appendStringInfoString(buf, " SET ");
3139 /* Add the comma separated list of 'attname = value' */
3141 foreach(l, query->targetList)
3143 TargetEntry *tle = (TargetEntry *) lfirst(l);
3147 continue; /* ignore junk entries */
3149 appendStringInfoString(buf, sep);
3153 * Put out name of target column; look in the catalogs, not at
3154 * tle->resname, since resname will fail to track RENAME.
3156 appendStringInfoString(buf,
3157 quote_identifier(get_relid_attribute_name(rte->relid,
3161 * Print any indirection needed (subfields or subscripts), and strip
3162 * off the top-level nodes representing the indirection assignments.
3164 expr = processIndirection((Node *) tle->expr, context, true);
3166 appendStringInfo(buf, " = ");
3168 get_rule_expr(expr, context, false);
3171 /* Add the FROM clause if needed */
3172 get_from_clause(query, " FROM ", context);
3174 /* Add a WHERE clause if given */
3175 if (query->jointree->quals != NULL)
3177 appendContextKeyword(context, " WHERE ",
3178 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
3179 get_rule_expr(query->jointree->quals, context, false);
3182 /* Add RETURNING if present */
3183 if (query->returningList)
3185 appendContextKeyword(context, " RETURNING",
3186 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
3187 get_target_list(query->returningList, context, NULL);
3193 * get_delete_query_def - Parse back a DELETE parsetree
3197 get_delete_query_def(Query *query, deparse_context *context)
3199 StringInfo buf = context->buf;
3203 * Start the query with DELETE FROM relname
3205 rte = rt_fetch(query->resultRelation, query->rtable);
3206 Assert(rte->rtekind == RTE_RELATION);
3207 if (PRETTY_INDENT(context))
3209 appendStringInfoChar(buf, ' ');
3210 context->indentLevel += PRETTYINDENT_STD;
3212 appendStringInfo(buf, "DELETE FROM %s%s",
3214 generate_relation_name(rte->relid, NIL));
3215 if (rte->alias != NULL)
3216 appendStringInfo(buf, " %s",
3217 quote_identifier(rte->alias->aliasname));
3219 /* Add the USING clause if given */
3220 get_from_clause(query, " USING ", context);
3222 /* Add a WHERE clause if given */
3223 if (query->jointree->quals != NULL)
3225 appendContextKeyword(context, " WHERE ",
3226 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
3227 get_rule_expr(query->jointree->quals, context, false);
3230 /* Add RETURNING if present */
3231 if (query->returningList)
3233 appendContextKeyword(context, " RETURNING",
3234 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
3235 get_target_list(query->returningList, context, NULL);
3241 * get_utility_query_def - Parse back a UTILITY parsetree
3245 get_utility_query_def(Query *query, deparse_context *context)
3247 StringInfo buf = context->buf;
3249 if (query->utilityStmt && IsA(query->utilityStmt, NotifyStmt))
3251 NotifyStmt *stmt = (NotifyStmt *) query->utilityStmt;
3253 appendContextKeyword(context, "",
3254 0, PRETTYINDENT_STD, 1);
3255 appendStringInfo(buf, "NOTIFY %s",
3256 quote_identifier(stmt->conditionname));
3260 /* Currently only NOTIFY utility commands can appear in rules */
3261 elog(ERROR, "unexpected utility statement type");
3267 * push_plan: set up deparse_namespace to recurse into the tlist of a subplan
3269 * When expanding an OUTER or INNER reference, we must push new outer/inner
3270 * subplans in case the referenced expression itself uses OUTER/INNER. We
3271 * modify the top stack entry in-place to avoid affecting levelsup issues
3272 * (although in a Plan tree there really shouldn't be any).
3274 * Caller must save and restore outer_plan and inner_plan around this.
3276 * We also use this to initialize the fields during deparse_context_for_plan.
3279 push_plan(deparse_namespace *dpns, Plan *subplan)
3282 * We special-case Append to pretend that the first child plan is the
3283 * OUTER referent; otherwise normal.
3285 if (IsA(subplan, Append))
3286 dpns->outer_plan = (Plan *) linitial(((Append *) subplan)->appendplans);
3288 dpns->outer_plan = outerPlan(subplan);
3291 * For a SubqueryScan, pretend the subplan is INNER referent. (We don't
3292 * use OUTER because that could someday conflict with the normal meaning.)
3293 * Likewise, for a CteScan, pretend the subquery's plan is INNER referent.
3295 if (IsA(subplan, SubqueryScan))
3296 dpns->inner_plan = ((SubqueryScan *) subplan)->subplan;
3297 else if (IsA(subplan, CteScan))
3299 int ctePlanId = ((CteScan *) subplan)->ctePlanId;
3301 if (ctePlanId > 0 && ctePlanId <= list_length(dpns->subplans))
3302 dpns->inner_plan = list_nth(dpns->subplans, ctePlanId - 1);
3304 dpns->inner_plan = NULL;
3307 dpns->inner_plan = innerPlan(subplan);
3312 * Display a Var appropriately.
3314 * In some cases (currently only when recursing into an unnamed join)
3315 * the Var's varlevelsup has to be interpreted with respect to a context
3316 * above the current one; levelsup indicates the offset.
3318 * If showstar is TRUE, whole-row Vars are displayed as "foo.*";
3319 * if FALSE, merely as "foo".
3321 * Returns the attname of the Var, or NULL if not determinable.
3324 get_variable(Var *var, int levelsup, bool showstar, deparse_context *context)
3326 StringInfo buf = context->buf;
3330 deparse_namespace *dpns;
3335 /* Find appropriate nesting depth */
3336 netlevelsup = var->varlevelsup + levelsup;
3337 if (netlevelsup >= list_length(context->namespaces))
3338 elog(ERROR, "bogus varlevelsup: %d offset %d",
3339 var->varlevelsup, levelsup);
3340 dpns = (deparse_namespace *) list_nth(context->namespaces,
3344 * Try to find the relevant RTE in this rtable. In a plan tree, it's
3345 * likely that varno is OUTER or INNER, in which case we must dig down
3346 * into the subplans.
3348 if (var->varno >= 1 && var->varno <= list_length(dpns->rtable))
3350 rte = rt_fetch(var->varno, dpns->rtable);
3351 attnum = var->varattno;
3353 else if (var->varno == OUTER && dpns->outer_plan)
3359 tle = get_tle_by_resno(dpns->outer_plan->targetlist, var->varattno);
3361 elog(ERROR, "bogus varattno for OUTER var: %d", var->varattno);
3363 Assert(netlevelsup == 0);
3364 save_outer = dpns->outer_plan;
3365 save_inner = dpns->inner_plan;
3366 push_plan(dpns, dpns->outer_plan);
3369 * Force parentheses because our caller probably assumed a Var is a
3370 * simple expression.
3372 if (!IsA(tle->expr, Var))
3373 appendStringInfoChar(buf, '(');
3374 get_rule_expr((Node *) tle->expr, context, true);
3375 if (!IsA(tle->expr, Var))
3376 appendStringInfoChar(buf, ')');
3378 dpns->outer_plan = save_outer;
3379 dpns->inner_plan = save_inner;
3382 else if (var->varno == INNER && dpns->inner_plan)
3388 tle = get_tle_by_resno(dpns->inner_plan->targetlist, var->varattno);
3390 elog(ERROR, "bogus varattno for INNER var: %d", var->varattno);
3392 Assert(netlevelsup == 0);
3393 save_outer = dpns->outer_plan;
3394 save_inner = dpns->inner_plan;
3395 push_plan(dpns, dpns->inner_plan);
3398 * Force parentheses because our caller probably assumed a Var is a
3399 * simple expression.
3401 if (!IsA(tle->expr, Var))
3402 appendStringInfoChar(buf, '(');
3403 get_rule_expr((Node *) tle->expr, context, true);
3404 if (!IsA(tle->expr, Var))
3405 appendStringInfoChar(buf, ')');
3407 dpns->outer_plan = save_outer;
3408 dpns->inner_plan = save_inner;
3413 elog(ERROR, "bogus varno: %d", var->varno);
3414 return NULL; /* keep compiler quiet */
3417 /* Identify names to use */
3418 schemaname = NULL; /* default assumptions */
3419 refname = rte->eref->aliasname;
3421 /* Exceptions occur only if the RTE is alias-less */
3422 if (rte->alias == NULL)
3424 if (rte->rtekind == RTE_RELATION)
3427 * It's possible that use of the bare refname would find another
3428 * more-closely-nested RTE, or be ambiguous, in which case we need
3429 * to specify the schemaname to avoid these errors.
3431 if (find_rte_by_refname(rte->eref->aliasname, context) != rte)
3432 schemaname = get_namespace_name(get_rel_namespace(rte->relid));
3434 else if (rte->rtekind == RTE_JOIN)
3437 * If it's an unnamed join, look at the expansion of the alias
3438 * variable. If it's a simple reference to one of the input vars
3439 * then recursively print the name of that var, instead. (This
3440 * allows correct decompiling of cases where there are identically
3441 * named columns on both sides of the join.) When it's not a
3442 * simple reference, we have to just print the unqualified
3443 * variable name (this can only happen with columns that were
3444 * merged by USING or NATURAL clauses).
3446 * This wouldn't work in decompiling plan trees, because we don't
3447 * store joinaliasvars lists after planning; but a plan tree
3448 * should never contain a join alias variable.
3450 if (rte->joinaliasvars == NIL)
3451 elog(ERROR, "cannot decompile join alias var in plan tree");
3456 aliasvar = (Var *) list_nth(rte->joinaliasvars, attnum - 1);
3457 if (IsA(aliasvar, Var))
3459 return get_variable(aliasvar, var->varlevelsup + levelsup,
3463 /* Unnamed join has neither schemaname nor refname */
3468 if (attnum == InvalidAttrNumber)
3471 attname = get_rte_attribute_name(rte, attnum);
3473 if (refname && (context->varprefix || attname == NULL))
3476 appendStringInfo(buf, "%s.",
3477 quote_identifier(schemaname));
3479 if (strcmp(refname, "*NEW*") == 0)
3480 appendStringInfoString(buf, "new");
3481 else if (strcmp(refname, "*OLD*") == 0)
3482 appendStringInfoString(buf, "old");
3484 appendStringInfoString(buf, quote_identifier(refname));
3486 if (attname || showstar)
3487 appendStringInfoChar(buf, '.');
3490 appendStringInfoString(buf, quote_identifier(attname));
3492 appendStringInfoChar(buf, '*');
3499 * Get the name of a field of an expression of composite type.
3501 * This is fairly straightforward except for the case of a Var of type RECORD.
3502 * Since no actual table or view column is allowed to have type RECORD, such
3503 * a Var must refer to a JOIN or FUNCTION RTE or to a subquery output. We
3504 * drill down to find the ultimate defining expression and attempt to infer
3505 * the field name from it. We ereport if we can't determine the name.
3507 * levelsup is an extra offset to interpret the Var's varlevelsup correctly.
3510 get_name_for_var_field(Var *var, int fieldno,
3511 int levelsup, deparse_context *context)
3516 deparse_namespace *dpns;
3517 TupleDesc tupleDesc;
3521 * If it's a RowExpr that was expanded from a whole-row Var, use the
3522 * column names attached to it.
3524 if (IsA(var, RowExpr))
3526 RowExpr *r = (RowExpr *) var;
3528 if (fieldno > 0 && fieldno <= list_length(r->colnames))
3529 return strVal(list_nth(r->colnames, fieldno - 1));
3533 * If it's a Var of type RECORD, we have to find what the Var refers to;
3534 * if not, we can use get_expr_result_type. If that fails, we try
3535 * lookup_rowtype_tupdesc, which will probably fail too, but will ereport
3536 * an acceptable message.
3538 if (!IsA(var, Var) ||
3539 var->vartype != RECORDOID)
3541 if (get_expr_result_type((Node *) var, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
3542 tupleDesc = lookup_rowtype_tupdesc_copy(exprType((Node *) var),
3543 exprTypmod((Node *) var));
3545 /* Got the tupdesc, so we can extract the field name */
3546 Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
3547 return NameStr(tupleDesc->attrs[fieldno - 1]->attname);
3550 /* Find appropriate nesting depth */
3551 netlevelsup = var->varlevelsup + levelsup;
3552 if (netlevelsup >= list_length(context->namespaces))
3553 elog(ERROR, "bogus varlevelsup: %d offset %d",
3554 var->varlevelsup, levelsup);
3555 dpns = (deparse_namespace *) list_nth(context->namespaces,
3559 * Try to find the relevant RTE in this rtable. In a plan tree, it's
3560 * likely that varno is OUTER or INNER, in which case we must dig down
3561 * into the subplans.
3563 if (var->varno >= 1 && var->varno <= list_length(dpns->rtable))
3565 rte = rt_fetch(var->varno, dpns->rtable);
3566 attnum = var->varattno;
3568 else if (var->varno == OUTER && dpns->outer_plan)
3575 tle = get_tle_by_resno(dpns->outer_plan->targetlist, var->varattno);
3577 elog(ERROR, "bogus varattno for OUTER var: %d", var->varattno);
3579 Assert(netlevelsup == 0);
3580 save_outer = dpns->outer_plan;
3581 save_inner = dpns->inner_plan;
3582 push_plan(dpns, dpns->outer_plan);
3584 result = get_name_for_var_field((Var *) tle->expr, fieldno,
3587 dpns->outer_plan = save_outer;
3588 dpns->inner_plan = save_inner;
3591 else if (var->varno == INNER && dpns->inner_plan)
3598 tle = get_tle_by_resno(dpns->inner_plan->targetlist, var->varattno);
3600 elog(ERROR, "bogus varattno for INNER var: %d", var->varattno);
3602 Assert(netlevelsup == 0);
3603 save_outer = dpns->outer_plan;
3604 save_inner = dpns->inner_plan;
3605 push_plan(dpns, dpns->inner_plan);
3607 result = get_name_for_var_field((Var *) tle->expr, fieldno,
3610 dpns->outer_plan = save_outer;
3611 dpns->inner_plan = save_inner;
3616 elog(ERROR, "bogus varno: %d", var->varno);
3617 return NULL; /* keep compiler quiet */
3620 if (attnum == InvalidAttrNumber)
3622 /* Var is whole-row reference to RTE, so select the right field */
3623 return get_rte_attribute_name(rte, fieldno);
3627 * This part has essentially the same logic as the parser's
3628 * expandRecordVariable() function, but we are dealing with a different
3629 * representation of the input context, and we only need one field name
3630 * not a TupleDesc. Also, we need special cases for finding subquery
3631 * and CTE subplans when deparsing Plan trees.
3633 expr = (Node *) var; /* default if we can't drill down */
3635 switch (rte->rtekind)
3642 * This case should not occur: a column of a table or values list
3643 * shouldn't have type RECORD. Fall through and fail (most
3644 * likely) at the bottom.
3648 /* Subselect-in-FROM: examine sub-select's output expr */
3652 TargetEntry *ste = get_tle_by_resno(rte->subquery->targetList,
3655 if (ste == NULL || ste->resjunk)
3656 elog(ERROR, "subquery %s does not have attribute %d",
3657 rte->eref->aliasname, attnum);
3658 expr = (Node *) ste->expr;
3662 * Recurse into the sub-select to see what its Var
3663 * refers to. We have to build an additional level of
3664 * namespace to keep in step with varlevelsup in the
3667 deparse_namespace mydpns;
3670 mydpns.rtable = rte->subquery->rtable;
3671 mydpns.ctes = rte->subquery->cteList;
3672 mydpns.subplans = NIL;
3673 mydpns.outer_plan = mydpns.inner_plan = NULL;
3675 context->namespaces = lcons(&mydpns,
3676 context->namespaces);
3678 result = get_name_for_var_field((Var *) expr, fieldno,
3681 context->namespaces =
3682 list_delete_first(context->namespaces);
3686 /* else fall through to inspect the expression */
3691 * We're deparsing a Plan tree so we don't have complete
3692 * RTE entries (in particular, rte->subquery is NULL).
3693 * But the only place we'd see a Var directly referencing
3694 * a SUBQUERY RTE is in a SubqueryScan plan node, and we
3695 * can look into the child plan's tlist instead.
3702 if (!dpns->inner_plan)
3703 elog(ERROR, "failed to find plan for subquery %s",
3704 rte->eref->aliasname);
3705 tle = get_tle_by_resno(dpns->inner_plan->targetlist,
3708 elog(ERROR, "bogus varattno for subquery var: %d",
3710 Assert(netlevelsup == 0);
3711 save_outer = dpns->outer_plan;
3712 save_inner = dpns->inner_plan;
3713 push_plan(dpns, dpns->inner_plan);
3715 result = get_name_for_var_field((Var *) tle->expr, fieldno,
3718 dpns->outer_plan = save_outer;
3719 dpns->inner_plan = save_inner;
3725 /* Join RTE --- recursively inspect the alias variable */
3726 if (rte->joinaliasvars == NIL)
3727 elog(ERROR, "cannot decompile join alias var in plan tree");
3728 Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars));
3729 expr = (Node *) list_nth(rte->joinaliasvars, attnum - 1);
3731 return get_name_for_var_field((Var *) expr, fieldno,
3732 var->varlevelsup + levelsup,
3734 /* else fall through to inspect the expression */
3739 * We couldn't get here unless a function is declared with one of
3740 * its result columns as RECORD, which is not allowed.
3744 /* CTE reference: examine subquery's output expr */
3746 CommonTableExpr *cte = NULL;
3751 * Try to find the referenced CTE using the namespace stack.
3753 ctelevelsup = rte->ctelevelsup + netlevelsup;
3754 if (ctelevelsup >= list_length(context->namespaces))
3758 deparse_namespace *ctedpns;
3760 ctedpns = (deparse_namespace *)
3761 list_nth(context->namespaces, ctelevelsup);
3762 foreach(lc, ctedpns->ctes)
3764 cte = (CommonTableExpr *) lfirst(lc);
3765 if (strcmp(cte->ctename, rte->ctename) == 0)
3771 Query *ctequery = (Query *) cte->ctequery;
3772 TargetEntry *ste = get_tle_by_resno(ctequery->targetList,
3775 if (ste == NULL || ste->resjunk)
3776 elog(ERROR, "subquery %s does not have attribute %d",
3777 rte->eref->aliasname, attnum);
3778 expr = (Node *) ste->expr;
3782 * Recurse into the CTE to see what its Var refers
3783 * to. We have to build an additional level of
3784 * namespace to keep in step with varlevelsup in the
3785 * CTE. Furthermore it could be an outer CTE, so
3786 * we may have to delete some levels of namespace.
3788 List *save_nslist = context->namespaces;
3790 deparse_namespace mydpns;
3793 mydpns.rtable = ctequery->rtable;
3794 mydpns.ctes = ctequery->cteList;
3795 mydpns.subplans = NIL;
3796 mydpns.outer_plan = mydpns.inner_plan = NULL;
3798 new_nslist = list_copy_tail(context->namespaces,
3800 context->namespaces = lcons(&mydpns, new_nslist);
3802 result = get_name_for_var_field((Var *) expr, fieldno,
3805 context->namespaces = save_nslist;
3809 /* else fall through to inspect the expression */
3814 * We're deparsing a Plan tree so we don't have a CTE
3815 * list. But the only place we'd see a Var directly
3816 * referencing a CTE RTE is in a CteScan plan node, and
3817 * we can look into the subplan's tlist instead.
3824 if (!dpns->inner_plan)
3825 elog(ERROR, "failed to find plan for CTE %s",
3826 rte->eref->aliasname);
3827 tle = get_tle_by_resno(dpns->inner_plan->targetlist,
3830 elog(ERROR, "bogus varattno for subquery var: %d",
3832 Assert(netlevelsup == 0);
3833 save_outer = dpns->outer_plan;
3834 save_inner = dpns->inner_plan;
3835 push_plan(dpns, dpns->inner_plan);
3837 result = get_name_for_var_field((Var *) tle->expr, fieldno,
3840 dpns->outer_plan = save_outer;
3841 dpns->inner_plan = save_inner;
3849 * We now have an expression we can't expand any more, so see if
3850 * get_expr_result_type() can do anything with it. If not, pass to
3851 * lookup_rowtype_tupdesc() which will probably fail, but will give an
3852 * appropriate error message while failing.
3854 if (get_expr_result_type(expr, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
3855 tupleDesc = lookup_rowtype_tupdesc_copy(exprType(expr),
3858 /* Got the tupdesc, so we can extract the field name */
3859 Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
3860 return NameStr(tupleDesc->attrs[fieldno - 1]->attname);
3865 * find_rte_by_refname - look up an RTE by refname in a deparse context
3867 * Returns NULL if there is no matching RTE or the refname is ambiguous.
3869 * NOTE: this code is not really correct since it does not take account of
3870 * the fact that not all the RTEs in a rangetable may be visible from the
3871 * point where a Var reference appears. For the purposes we need, however,
3872 * the only consequence of a false match is that we might stick a schema
3873 * qualifier on a Var that doesn't really need it. So it seems close
3876 static RangeTblEntry *
3877 find_rte_by_refname(const char *refname, deparse_context *context)
3879 RangeTblEntry *result = NULL;
3882 foreach(nslist, context->namespaces)
3884 deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist);
3887 foreach(rtlist, dpns->rtable)
3889 RangeTblEntry *rte = (RangeTblEntry *) lfirst(rtlist);
3891 if (strcmp(rte->eref->aliasname, refname) == 0)
3894 return NULL; /* it's ambiguous */
3906 * get_simple_binary_op_name
3908 * helper function for isSimpleNode
3909 * will return single char binary operator name, or NULL if it's not
3912 get_simple_binary_op_name(OpExpr *expr)
3914 List *args = expr->args;
3916 if (list_length(args) == 2)
3918 /* binary operator */
3919 Node *arg1 = (Node *) linitial(args);
3920 Node *arg2 = (Node *) lsecond(args);
3923 op = generate_operator_name(expr->opno, exprType(arg1), exprType(arg2));
3924 if (strlen(op) == 1)
3932 * isSimpleNode - check if given node is simple (doesn't need parenthesizing)
3934 * true : simple in the context of parent node's type
3935 * false : not simple
3938 isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
3943 switch (nodeTag(node))
3948 case T_CoerceToDomainValue:
3949 case T_SetToDefault:
3950 case T_CurrentOfExpr:
3951 /* single words: always simple */
3957 case T_CoalesceExpr:
3964 /* function-like: name(..) or name[..] */
3967 /* CASE keywords act as parentheses */
3974 * appears simple since . has top precedence, unless parent is
3975 * T_FieldSelect itself!
3977 return (IsA(parentNode, FieldSelect) ? false : true);
3982 * treat like FieldSelect (probably doesn't matter)
3984 return (IsA(parentNode, FieldStore) ? false : true);
3986 case T_CoerceToDomain:
3987 /* maybe simple, check args */
3988 return isSimpleNode((Node *) ((CoerceToDomain *) node)->arg,
3991 return isSimpleNode((Node *) ((RelabelType *) node)->arg,
3994 return isSimpleNode((Node *) ((CoerceViaIO *) node)->arg,
3996 case T_ArrayCoerceExpr:
3997 return isSimpleNode((Node *) ((ArrayCoerceExpr *) node)->arg,
3999 case T_ConvertRowtypeExpr:
4000 return isSimpleNode((Node *) ((ConvertRowtypeExpr *) node)->arg,
4005 /* depends on parent node type; needs further checking */
4006 if (prettyFlags & PRETTYFLAG_PAREN && IsA(parentNode, OpExpr))
4009 const char *parentOp;
4012 bool is_lopriparent;
4013 bool is_hipriparent;
4015 op = get_simple_binary_op_name((OpExpr *) node);
4019 /* We know only the basic operators + - and * / % */
4020 is_lopriop = (strchr("+-", *op) != NULL);
4021 is_hipriop = (strchr("*/%", *op) != NULL);
4022 if (!(is_lopriop || is_hipriop))
4025 parentOp = get_simple_binary_op_name((OpExpr *) parentNode);
4029 is_lopriparent = (strchr("+-", *parentOp) != NULL);
4030 is_hipriparent = (strchr("*/%", *parentOp) != NULL);
4031 if (!(is_lopriparent || is_hipriparent))
4034 if (is_hipriop && is_lopriparent)
4035 return true; /* op binds tighter than parent */
4037 if (is_lopriop && is_hipriparent)
4041 * Operators are same priority --- can skip parens only if
4042 * we have (a - b) - c, not a - (b - c).
4044 if (node == (Node *) linitial(((OpExpr *) parentNode)->args))
4049 /* else do the same stuff as for T_SubLink et al. */
4056 case T_DistinctExpr:
4057 switch (nodeTag(parentNode))
4061 /* special handling for casts */
4062 CoercionForm type = ((FuncExpr *) parentNode)->funcformat;
4064 if (type == COERCE_EXPLICIT_CAST ||
4065 type == COERCE_IMPLICIT_CAST)
4067 return true; /* own parentheses */
4069 case T_BoolExpr: /* lower precedence */
4070 case T_ArrayRef: /* other separators */
4071 case T_ArrayExpr: /* other separators */
4072 case T_RowExpr: /* other separators */
4073 case T_CoalesceExpr: /* own parentheses */
4074 case T_MinMaxExpr: /* own parentheses */
4075 case T_XmlExpr: /* own parentheses */
4076 case T_NullIfExpr: /* other separators */
4077 case T_Aggref: /* own parentheses */
4078 case T_WindowFunc: /* own parentheses */
4079 case T_CaseExpr: /* other separators */
4086 switch (nodeTag(parentNode))
4089 if (prettyFlags & PRETTYFLAG_PAREN)
4092 BoolExprType parentType;
4094 type = ((BoolExpr *) node)->boolop;
4095 parentType = ((BoolExpr *) parentNode)->boolop;
4100 if (parentType == AND_EXPR || parentType == OR_EXPR)
4104 if (parentType == OR_EXPR)
4112 /* special handling for casts */
4113 CoercionForm type = ((FuncExpr *) parentNode)->funcformat;
4115 if (type == COERCE_EXPLICIT_CAST ||
4116 type == COERCE_IMPLICIT_CAST)
4118 return true; /* own parentheses */
4120 case T_ArrayRef: /* other separators */
4121 case T_ArrayExpr: /* other separators */
4122 case T_RowExpr: /* other separators */
4123 case T_CoalesceExpr: /* own parentheses */
4124 case T_MinMaxExpr: /* own parentheses */
4125 case T_XmlExpr: /* own parentheses */
4126 case T_NullIfExpr: /* other separators */
4127 case T_Aggref: /* own parentheses */
4128 case T_WindowFunc: /* own parentheses */
4129 case T_CaseExpr: /* other separators */
4138 /* those we don't know: in dubio complexo */
4144 * appendStringInfoSpaces - append spaces to buffer
4147 appendStringInfoSpaces(StringInfo buf, int count)
4150 appendStringInfoChar(buf, ' ');
4154 * appendContextKeyword - append a keyword to buffer
4156 * If prettyPrint is enabled, perform a line break, and adjust indentation.
4157 * Otherwise, just append the keyword.
4160 appendContextKeyword(deparse_context *context, const char *str,
4161 int indentBefore, int indentAfter, int indentPlus)
4163 if (PRETTY_INDENT(context))
4165 context->indentLevel += indentBefore;
4167 appendStringInfoChar(context->buf, '\n');
4168 appendStringInfoSpaces(context->buf,
4169 Max(context->indentLevel, 0) + indentPlus);
4170 appendStringInfoString(context->buf, str);
4172 context->indentLevel += indentAfter;
4173 if (context->indentLevel < 0)
4174 context->indentLevel = 0;
4177 appendStringInfoString(context->buf, str);
4181 * get_rule_expr_paren - deparse expr using get_rule_expr,
4182 * embracing the string with parentheses if necessary for prettyPrint.
4184 * Never embrace if prettyFlags=0, because it's done in the calling node.
4186 * Any node that does *not* embrace its argument node by sql syntax (with
4187 * parentheses, non-operator keywords like CASE/WHEN/ON, or comma etc) should
4188 * use get_rule_expr_paren instead of get_rule_expr so parentheses can be
4192 get_rule_expr_paren(Node *node, deparse_context *context,
4193 bool showimplicit, Node *parentNode)
4197 need_paren = PRETTY_PAREN(context) &&
4198 !isSimpleNode(node, parentNode, context->prettyFlags);
4201 appendStringInfoChar(context->buf, '(');
4203 get_rule_expr(node, context, showimplicit);
4206 appendStringInfoChar(context->buf, ')');
4211 * get_rule_expr - Parse back an expression
4213 * Note: showimplicit determines whether we display any implicit cast that
4214 * is present at the top of the expression tree. It is a passed argument,
4215 * not a field of the context struct, because we change the value as we
4216 * recurse down into the expression. In general we suppress implicit casts
4217 * when the result type is known with certainty (eg, the arguments of an
4218 * OR must be boolean). We display implicit casts for arguments of functions
4219 * and operators, since this is needed to be certain that the same function
4220 * or operator will be chosen when the expression is re-parsed.
4224 get_rule_expr(Node *node, deparse_context *context,
4227 StringInfo buf = context->buf;
4233 * Each level of get_rule_expr must emit an indivisible term
4234 * (parenthesized if necessary) to ensure result is reparsed into the same
4235 * expression tree. The only exception is that when the input is a List,
4236 * we emit the component items comma-separated with no surrounding
4237 * decoration; this is convenient for most callers.
4239 switch (nodeTag(node))
4242 (void) get_variable((Var *) node, 0, true, context);
4246 get_const_expr((Const *) node, context, 0);
4250 appendStringInfo(buf, "$%d", ((Param *) node)->paramid);
4254 get_agg_expr((Aggref *) node, context);
4258 get_windowfunc_expr((WindowFunc *) node, context);
4263 ArrayRef *aref = (ArrayRef *) node;
4267 * Parenthesize the argument unless it's a simple Var or a
4268 * FieldSelect. (In particular, if it's another ArrayRef, we
4269 * *must* parenthesize to avoid confusion.)
4271 need_parens = !IsA(aref->refexpr, Var) &&
4272 !IsA(aref->refexpr, FieldSelect);
4274 appendStringInfoChar(buf, '(');
4275 get_rule_expr((Node *) aref->refexpr, context, showimplicit);
4277 appendStringInfoChar(buf, ')');
4278 printSubscripts(aref, context);
4281 * Array assignment nodes should have been handled in
4282 * processIndirection().
4284 if (aref->refassgnexpr)
4285 elog(ERROR, "unexpected refassgnexpr");
4290 get_func_expr((FuncExpr *) node, context, showimplicit);
4294 get_oper_expr((OpExpr *) node, context);
4297 case T_DistinctExpr:
4299 DistinctExpr *expr = (DistinctExpr *) node;
4300 List *args = expr->args;
4301 Node *arg1 = (Node *) linitial(args);
4302 Node *arg2 = (Node *) lsecond(args);
4304 if (!PRETTY_PAREN(context))
4305 appendStringInfoChar(buf, '(');
4306 get_rule_expr_paren(arg1, context, true, node);
4307 appendStringInfo(buf, " IS DISTINCT FROM ");
4308 get_rule_expr_paren(arg2, context, true, node);
4309 if (!PRETTY_PAREN(context))
4310 appendStringInfoChar(buf, ')');
4314 case T_ScalarArrayOpExpr:
4316 ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
4317 List *args = expr->args;
4318 Node *arg1 = (Node *) linitial(args);
4319 Node *arg2 = (Node *) lsecond(args);
4321 if (!PRETTY_PAREN(context))
4322 appendStringInfoChar(buf, '(');
4323 get_rule_expr_paren(arg1, context, true, node);
4324 appendStringInfo(buf, " %s %s (",
4325 generate_operator_name(expr->opno,
4327 get_element_type(exprType(arg2))),
4328 expr->useOr ? "ANY" : "ALL");
4329 get_rule_expr_paren(arg2, context, true, node);
4330 appendStringInfoChar(buf, ')');
4331 if (!PRETTY_PAREN(context))
4332 appendStringInfoChar(buf, ')');
4338 BoolExpr *expr = (BoolExpr *) node;
4339 Node *first_arg = linitial(expr->args);
4340 ListCell *arg = lnext(list_head(expr->args));
4342 switch (expr->boolop)
4345 if (!PRETTY_PAREN(context))
4346 appendStringInfoChar(buf, '(');
4347 get_rule_expr_paren(first_arg, context,
4351 appendStringInfo(buf, " AND ");
4352 get_rule_expr_paren((Node *) lfirst(arg), context,
4356 if (!PRETTY_PAREN(context))
4357 appendStringInfoChar(buf, ')');
4361 if (!PRETTY_PAREN(context))
4362 appendStringInfoChar(buf, '(');
4363 get_rule_expr_paren(first_arg, context,
4367 appendStringInfo(buf, " OR ");
4368 get_rule_expr_paren((Node *) lfirst(arg), context,
4372 if (!PRETTY_PAREN(context))
4373 appendStringInfoChar(buf, ')');
4377 if (!PRETTY_PAREN(context))
4378 appendStringInfoChar(buf, '(');
4379 appendStringInfo(buf, "NOT ");
4380 get_rule_expr_paren(first_arg, context,
4382 if (!PRETTY_PAREN(context))
4383 appendStringInfoChar(buf, ')');
4387 elog(ERROR, "unrecognized boolop: %d",
4388 (int) expr->boolop);
4394 get_sublink_expr((SubLink *) node, context);
4400 * We cannot see an already-planned subplan in rule deparsing,
4401 * only while EXPLAINing a query plan. For now, just punt.
4403 if (((SubPlan *) node)->useHashTable)
4404 appendStringInfo(buf, "(hashed subplan)");
4406 appendStringInfo(buf, "(subplan)");
4410 case T_AlternativeSubPlan:
4411 /* As above, just punt */
4412 appendStringInfo(buf, "(alternative subplans)");
4417 FieldSelect *fselect = (FieldSelect *) node;
4418 Node *arg = (Node *) fselect->arg;
4419 int fno = fselect->fieldnum;
4420 const char *fieldname;
4424 * Parenthesize the argument unless it's an ArrayRef or
4425 * another FieldSelect. Note in particular that it would be
4426 * WRONG to not parenthesize a Var argument; simplicity is not
4427 * the issue here, having the right number of names is.
4429 need_parens = !IsA(arg, ArrayRef) &&!IsA(arg, FieldSelect);
4431 appendStringInfoChar(buf, '(');
4432 get_rule_expr(arg, context, true);
4434 appendStringInfoChar(buf, ')');
4437 * Get and print the field name.
4439 fieldname = get_name_for_var_field((Var *) arg, fno,
4441 appendStringInfo(buf, ".%s", quote_identifier(fieldname));
4448 * We shouldn't see FieldStore here; it should have been stripped
4449 * off by processIndirection().
4451 elog(ERROR, "unexpected FieldStore");
4456 RelabelType *relabel = (RelabelType *) node;
4457 Node *arg = (Node *) relabel->arg;
4459 if (relabel->relabelformat == COERCE_IMPLICIT_CAST &&
4462 /* don't show the implicit cast */
4463 get_rule_expr_paren(arg, context, false, node);
4467 get_coercion_expr(arg, context,
4468 relabel->resulttype,
4469 relabel->resulttypmod,
4477 CoerceViaIO *iocoerce = (CoerceViaIO *) node;
4478 Node *arg = (Node *) iocoerce->arg;
4480 if (iocoerce->coerceformat == COERCE_IMPLICIT_CAST &&
4483 /* don't show the implicit cast */
4484 get_rule_expr_paren(arg, context, false, node);
4488 get_coercion_expr(arg, context,
4489 iocoerce->resulttype,
4496 case T_ArrayCoerceExpr:
4498 ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;
4499 Node *arg = (Node *) acoerce->arg;
4501 if (acoerce->coerceformat == COERCE_IMPLICIT_CAST &&
4504 /* don't show the implicit cast */
4505 get_rule_expr_paren(arg, context, false, node);
4509 get_coercion_expr(arg, context,
4510 acoerce->resulttype,
4511 acoerce->resulttypmod,
4517 case T_ConvertRowtypeExpr:
4519 ConvertRowtypeExpr *convert = (ConvertRowtypeExpr *) node;
4520 Node *arg = (Node *) convert->arg;
4522 if (convert->convertformat == COERCE_IMPLICIT_CAST &&
4525 /* don't show the implicit cast */
4526 get_rule_expr_paren(arg, context, false, node);
4530 get_coercion_expr(arg, context,
4531 convert->resulttype, -1,
4539 CaseExpr *caseexpr = (CaseExpr *) node;
4542 appendContextKeyword(context, "CASE",
4543 0, PRETTYINDENT_VAR, 0);
4546 appendStringInfoChar(buf, ' ');
4547 get_rule_expr((Node *) caseexpr->arg, context, true);
4549 foreach(temp, caseexpr->args)
4551 CaseWhen *when = (CaseWhen *) lfirst(temp);
4552 Node *w = (Node *) when->expr;
4554 if (!PRETTY_INDENT(context))
4555 appendStringInfoChar(buf, ' ');
4556 appendContextKeyword(context, "WHEN ",
4561 * The parser should have produced WHEN clauses of the
4562 * form "CaseTestExpr = RHS"; we want to show just the
4563 * RHS. If the user wrote something silly like "CASE
4564 * boolexpr WHEN TRUE THEN ...", then the optimizer's
4565 * simplify_boolean_equality() may have reduced this
4566 * to just "CaseTestExpr" or "NOT CaseTestExpr", for
4567 * which we have to show "TRUE" or "FALSE". Also,
4568 * depending on context the original CaseTestExpr
4569 * might have been reduced to a Const (but we won't
4570 * see "WHEN Const").
4576 Assert(IsA(linitial(((OpExpr *) w)->args),
4578 IsA(linitial(((OpExpr *) w)->args),
4580 rhs = (Node *) lsecond(((OpExpr *) w)->args);
4581 get_rule_expr(rhs, context, false);
4583 else if (IsA(w, CaseTestExpr))
4584 appendStringInfo(buf, "TRUE");
4585 else if (not_clause(w))
4587 Assert(IsA(get_notclausearg((Expr *) w),
4589 appendStringInfo(buf, "FALSE");
4592 elog(ERROR, "unexpected CASE WHEN clause: %d",
4596 get_rule_expr(w, context, false);
4597 appendStringInfo(buf, " THEN ");
4598 get_rule_expr((Node *) when->result, context, true);
4600 if (!PRETTY_INDENT(context))
4601 appendStringInfoChar(buf, ' ');
4602 appendContextKeyword(context, "ELSE ",
4604 get_rule_expr((Node *) caseexpr->defresult, context, true);
4605 if (!PRETTY_INDENT(context))
4606 appendStringInfoChar(buf, ' ');
4607 appendContextKeyword(context, "END",
4608 -PRETTYINDENT_VAR, 0, 0);
4614 ArrayExpr *arrayexpr = (ArrayExpr *) node;
4616 appendStringInfo(buf, "ARRAY[");
4617 get_rule_expr((Node *) arrayexpr->elements, context, true);
4618 appendStringInfoChar(buf, ']');
4620 * If the array isn't empty, we assume its elements are
4621 * coerced to the desired type. If it's empty, though, we
4622 * need an explicit coercion to the array type.
4624 if (arrayexpr->elements == NIL)
4625 appendStringInfo(buf, "::%s",
4626 format_type_with_typemod(arrayexpr->array_typeid, -1));
4632 RowExpr *rowexpr = (RowExpr *) node;
4633 TupleDesc tupdesc = NULL;
4639 * If it's a named type and not RECORD, we may have to skip
4640 * dropped columns and/or claim there are NULLs for added
4643 if (rowexpr->row_typeid != RECORDOID)
4645 tupdesc = lookup_rowtype_tupdesc(rowexpr->row_typeid, -1);
4646 Assert(list_length(rowexpr->args) <= tupdesc->natts);
4650 * SQL99 allows "ROW" to be omitted when there is more than
4651 * one column, but for simplicity we always print it.
4653 appendStringInfo(buf, "ROW(");
4656 foreach(arg, rowexpr->args)
4658 Node *e = (Node *) lfirst(arg);
4660 if (tupdesc == NULL ||
4661 !tupdesc->attrs[i]->attisdropped)
4663 appendStringInfoString(buf, sep);
4664 get_rule_expr(e, context, true);
4669 if (tupdesc != NULL)
4671 while (i < tupdesc->natts)
4673 if (!tupdesc->attrs[i]->attisdropped)
4675 appendStringInfoString(buf, sep);
4676 appendStringInfo(buf, "NULL");
4682 ReleaseTupleDesc(tupdesc);
4684 appendStringInfo(buf, ")");
4685 if (rowexpr->row_format == COERCE_EXPLICIT_CAST)
4686 appendStringInfo(buf, "::%s",
4687 format_type_with_typemod(rowexpr->row_typeid, -1));
4691 case T_RowCompareExpr:
4693 RowCompareExpr *rcexpr = (RowCompareExpr *) node;
4698 * SQL99 allows "ROW" to be omitted when there is more than
4699 * one column, but for simplicity we always print it.
4701 appendStringInfo(buf, "(ROW(");
4703 foreach(arg, rcexpr->largs)
4705 Node *e = (Node *) lfirst(arg);
4707 appendStringInfoString(buf, sep);
4708 get_rule_expr(e, context, true);
4713 * We assume that the name of the first-column operator will
4714 * do for all the rest too. This is definitely open to
4715 * failure, eg if some but not all operators were renamed
4716 * since the construct was parsed, but there seems no way to
4719 appendStringInfo(buf, ") %s ROW(",
4720 generate_operator_name(linitial_oid(rcexpr->opnos),
4721 exprType(linitial(rcexpr->largs)),
4722 exprType(linitial(rcexpr->rargs))));
4724 foreach(arg, rcexpr->rargs)
4726 Node *e = (Node *) lfirst(arg);
4728 appendStringInfoString(buf, sep);
4729 get_rule_expr(e, context, true);
4732 appendStringInfo(buf, "))");
4736 case T_CoalesceExpr:
4738 CoalesceExpr *coalesceexpr = (CoalesceExpr *) node;
4740 appendStringInfo(buf, "COALESCE(");
4741 get_rule_expr((Node *) coalesceexpr->args, context, true);
4742 appendStringInfoChar(buf, ')');
4748 MinMaxExpr *minmaxexpr = (MinMaxExpr *) node;
4750 switch (minmaxexpr->op)
4753 appendStringInfo(buf, "GREATEST(");
4756 appendStringInfo(buf, "LEAST(");
4759 get_rule_expr((Node *) minmaxexpr->args, context, true);
4760 appendStringInfoChar(buf, ')');
4766 XmlExpr *xexpr = (XmlExpr *) node;
4767 bool needcomma = false;
4775 appendStringInfoString(buf, "XMLCONCAT(");
4778 appendStringInfoString(buf, "XMLELEMENT(");
4781 appendStringInfoString(buf, "XMLFOREST(");
4784 appendStringInfoString(buf, "XMLPARSE(");
4787 appendStringInfoString(buf, "XMLPI(");
4790 appendStringInfoString(buf, "XMLROOT(");
4792 case IS_XMLSERIALIZE:
4793 appendStringInfoString(buf, "XMLSERIALIZE(");
4798 if (xexpr->op == IS_XMLPARSE || xexpr->op == IS_XMLSERIALIZE)
4800 if (xexpr->xmloption == XMLOPTION_DOCUMENT)
4801 appendStringInfoString(buf, "DOCUMENT ");
4803 appendStringInfoString(buf, "CONTENT ");
4807 appendStringInfo(buf, "NAME %s",
4808 quote_identifier(map_xml_name_to_sql_identifier(xexpr->name)));
4811 if (xexpr->named_args)
4813 if (xexpr->op != IS_XMLFOREST)
4816 appendStringInfoString(buf, ", ");
4817 appendStringInfoString(buf, "XMLATTRIBUTES(");
4820 forboth(arg, xexpr->named_args, narg, xexpr->arg_names)
4822 Node *e = (Node *) lfirst(arg);
4823 char *argname = strVal(lfirst(narg));
4826 appendStringInfoString(buf, ", ");
4827 get_rule_expr((Node *) e, context, true);
4828 appendStringInfo(buf, " AS %s",
4829 quote_identifier(map_xml_name_to_sql_identifier(argname)));
4832 if (xexpr->op != IS_XMLFOREST)
4833 appendStringInfoChar(buf, ')');
4838 appendStringInfoString(buf, ", ");
4845 case IS_XMLSERIALIZE:
4846 /* no extra decoration needed */
4847 get_rule_expr((Node *) xexpr->args, context, true);
4850 Assert(list_length(xexpr->args) == 2);
4852 get_rule_expr((Node *) linitial(xexpr->args),
4855 con = (Const *) lsecond(xexpr->args);
4856 Assert(IsA(con, Const));
4857 Assert(!con->constisnull);
4858 if (DatumGetBool(con->constvalue))
4859 appendStringInfoString(buf,
4860 " PRESERVE WHITESPACE");
4862 appendStringInfoString(buf,
4863 " STRIP WHITESPACE");
4866 Assert(list_length(xexpr->args) == 3);
4868 get_rule_expr((Node *) linitial(xexpr->args),
4871 appendStringInfoString(buf, ", VERSION ");
4872 con = (Const *) lsecond(xexpr->args);
4873 if (IsA(con, Const) &&
4875 appendStringInfoString(buf, "NO VALUE");
4877 get_rule_expr((Node *) con, context, false);
4879 con = (Const *) lthird(xexpr->args);
4880 Assert(IsA(con, Const));
4881 if (con->constisnull)
4882 /* suppress STANDALONE NO VALUE */ ;
4885 switch (DatumGetInt32(con->constvalue))
4887 case XML_STANDALONE_YES:
4888 appendStringInfoString(buf,
4889 ", STANDALONE YES");
4891 case XML_STANDALONE_NO:
4892 appendStringInfoString(buf,
4895 case XML_STANDALONE_NO_VALUE:
4896 appendStringInfoString(buf,
4897 ", STANDALONE NO VALUE");
4905 get_rule_expr_paren((Node *) xexpr->args, context, false, node);
4910 if (xexpr->op == IS_XMLSERIALIZE)
4911 appendStringInfo(buf, " AS %s", format_type_with_typemod(xexpr->type,
4913 if (xexpr->op == IS_DOCUMENT)
4914 appendStringInfoString(buf, " IS DOCUMENT");
4916 appendStringInfoChar(buf, ')');
4922 NullIfExpr *nullifexpr = (NullIfExpr *) node;
4924 appendStringInfo(buf, "NULLIF(");
4925 get_rule_expr((Node *) nullifexpr->args, context, true);
4926 appendStringInfoChar(buf, ')');
4932 NullTest *ntest = (NullTest *) node;
4934 if (!PRETTY_PAREN(context))
4935 appendStringInfoChar(buf, '(');
4936 get_rule_expr_paren((Node *) ntest->arg, context, true, node);
4937 switch (ntest->nulltesttype)
4940 appendStringInfo(buf, " IS NULL");
4943 appendStringInfo(buf, " IS NOT NULL");
4946 elog(ERROR, "unrecognized nulltesttype: %d",
4947 (int) ntest->nulltesttype);
4949 if (!PRETTY_PAREN(context))
4950 appendStringInfoChar(buf, ')');
4956 BooleanTest *btest = (BooleanTest *) node;
4958 if (!PRETTY_PAREN(context))
4959 appendStringInfoChar(buf, '(');
4960 get_rule_expr_paren((Node *) btest->arg, context, false, node);
4961 switch (btest->booltesttype)
4964 appendStringInfo(buf, " IS TRUE");
4967 appendStringInfo(buf, " IS NOT TRUE");
4970 appendStringInfo(buf, " IS FALSE");
4973 appendStringInfo(buf, " IS NOT FALSE");
4976 appendStringInfo(buf, " IS UNKNOWN");
4978 case IS_NOT_UNKNOWN:
4979 appendStringInfo(buf, " IS NOT UNKNOWN");
4982 elog(ERROR, "unrecognized booltesttype: %d",
4983 (int) btest->booltesttype);
4985 if (!PRETTY_PAREN(context))
4986 appendStringInfoChar(buf, ')');
4990 case T_CoerceToDomain:
4992 CoerceToDomain *ctest = (CoerceToDomain *) node;
4993 Node *arg = (Node *) ctest->arg;
4995 if (ctest->coercionformat == COERCE_IMPLICIT_CAST &&
4998 /* don't show the implicit cast */
4999 get_rule_expr(arg, context, false);
5003 get_coercion_expr(arg, context,
5005 ctest->resulttypmod,
5011 case T_CoerceToDomainValue:
5012 appendStringInfo(buf, "VALUE");
5015 case T_SetToDefault:
5016 appendStringInfo(buf, "DEFAULT");
5019 case T_CurrentOfExpr:
5021 CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
5023 if (cexpr->cursor_name)
5024 appendStringInfo(buf, "CURRENT OF %s",
5025 quote_identifier(cexpr->cursor_name));
5027 appendStringInfo(buf, "CURRENT OF $%d",
5028 cexpr->cursor_param);
5038 foreach(l, (List *) node)
5040 appendStringInfoString(buf, sep);
5041 get_rule_expr((Node *) lfirst(l), context, showimplicit);
5048 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
5055 * get_oper_expr - Parse back an OpExpr node
5058 get_oper_expr(OpExpr *expr, deparse_context *context)
5060 StringInfo buf = context->buf;
5061 Oid opno = expr->opno;
5062 List *args = expr->args;
5064 if (!PRETTY_PAREN(context))
5065 appendStringInfoChar(buf, '(');
5066 if (list_length(args) == 2)
5068 /* binary operator */
5069 Node *arg1 = (Node *) linitial(args);
5070 Node *arg2 = (Node *) lsecond(args);
5072 get_rule_expr_paren(arg1, context, true, (Node *) expr);
5073 appendStringInfo(buf, " %s ",
5074 generate_operator_name(opno,
5077 get_rule_expr_paren(arg2, context, true, (Node *) expr);
5081 /* unary operator --- but which side? */
5082 Node *arg = (Node *) linitial(args);
5084 Form_pg_operator optup;
5086 tp = SearchSysCache(OPEROID,
5087 ObjectIdGetDatum(opno),
5089 if (!HeapTupleIsValid(tp))
5090 elog(ERROR, "cache lookup failed for operator %u", opno);
5091 optup = (Form_pg_operator) GETSTRUCT(tp);
5092 switch (optup->oprkind)
5095 appendStringInfo(buf, "%s ",
5096 generate_operator_name(opno,
5099 get_rule_expr_paren(arg, context, true, (Node *) expr);
5102 get_rule_expr_paren(arg, context, true, (Node *) expr);
5103 appendStringInfo(buf, " %s",
5104 generate_operator_name(opno,
5109 elog(ERROR, "bogus oprkind: %d", optup->oprkind);
5111 ReleaseSysCache(tp);
5113 if (!PRETTY_PAREN(context))
5114 appendStringInfoChar(buf, ')');
5118 * get_func_expr - Parse back a FuncExpr node
5121 get_func_expr(FuncExpr *expr, deparse_context *context,
5124 StringInfo buf = context->buf;
5125 Oid funcoid = expr->funcid;
5126 Oid argtypes[FUNC_MAX_ARGS];
5132 * If the function call came from an implicit coercion, then just show the
5133 * first argument --- unless caller wants to see implicit coercions.
5135 if (expr->funcformat == COERCE_IMPLICIT_CAST && !showimplicit)
5137 get_rule_expr_paren((Node *) linitial(expr->args), context,
5138 false, (Node *) expr);
5143 * If the function call came from a cast, then show the first argument
5144 * plus an explicit cast operation.
5146 if (expr->funcformat == COERCE_EXPLICIT_CAST ||
5147 expr->funcformat == COERCE_IMPLICIT_CAST)
5149 Node *arg = linitial(expr->args);
5150 Oid rettype = expr->funcresulttype;
5151 int32 coercedTypmod;
5153 /* Get the typmod if this is a length-coercion function */
5154 (void) exprIsLengthCoercion((Node *) expr, &coercedTypmod);
5156 get_coercion_expr(arg, context,
5157 rettype, coercedTypmod,
5164 * Normal function: display as proname(args). First we need to extract
5165 * the argument datatypes.
5167 if (list_length(expr->args) > FUNC_MAX_ARGS)
5169 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
5170 errmsg("too many arguments")));
5172 foreach(l, expr->args)
5174 argtypes[nargs] = exprType((Node *) lfirst(l));
5178 appendStringInfo(buf, "%s(",
5179 generate_function_name(funcoid, nargs, argtypes,
5182 foreach(l, expr->args)
5185 appendStringInfoString(buf, ", ");
5186 if (is_variadic && lnext(l) == NULL)
5187 appendStringInfoString(buf, "VARIADIC ");
5188 get_rule_expr((Node *) lfirst(l), context, true);
5190 appendStringInfoChar(buf, ')');
5194 * get_agg_expr - Parse back an Aggref node
5197 get_agg_expr(Aggref *aggref, deparse_context *context)
5199 StringInfo buf = context->buf;
5200 Oid argtypes[FUNC_MAX_ARGS];
5204 if (list_length(aggref->args) > FUNC_MAX_ARGS)
5206 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
5207 errmsg("too many arguments")));
5209 foreach(l, aggref->args)
5211 argtypes[nargs] = exprType((Node *) lfirst(l));
5215 appendStringInfo(buf, "%s(%s",
5216 generate_function_name(aggref->aggfnoid,
5217 nargs, argtypes, NULL),
5218 aggref->aggdistinct ? "DISTINCT " : "");
5219 /* aggstar can be set only in zero-argument aggregates */
5220 if (aggref->aggstar)
5221 appendStringInfoChar(buf, '*');
5223 get_rule_expr((Node *) aggref->args, context, true);
5224 appendStringInfoChar(buf, ')');
5228 * get_windowfunc_expr - Parse back a WindowFunc node
5231 get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context)
5233 StringInfo buf = context->buf;
5234 Oid argtypes[FUNC_MAX_ARGS];
5238 if (list_length(wfunc->args) > FUNC_MAX_ARGS)
5240 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
5241 errmsg("too many arguments")));
5243 foreach(l, wfunc->args)
5245 argtypes[nargs] = exprType((Node *) lfirst(l));
5249 appendStringInfo(buf, "%s(%s",
5250 generate_function_name(wfunc->winfnoid,
5251 nargs, argtypes, NULL), "");
5252 /* winstar can be set only in zero-argument aggregates */
5254 appendStringInfoChar(buf, '*');
5256 get_rule_expr((Node *) wfunc->args, context, true);
5257 appendStringInfoString(buf, ") OVER ");
5259 foreach(l, context->windowClause)
5261 WindowClause *wc = (WindowClause *) lfirst(l);
5263 if (wc->winref == wfunc->winref)
5266 appendStringInfoString(buf, quote_identifier(wc->name));
5268 get_rule_windowspec(wc, context->windowTList, context);
5274 if (context->windowClause)
5275 elog(ERROR, "could not find window clause for winref %u",
5278 * In EXPLAIN, we don't have window context information available,
5279 * so we have to settle for this:
5281 appendStringInfoString(buf, "(?)");
5288 * Make a string representation of a value coerced to a specific type
5292 get_coercion_expr(Node *arg, deparse_context *context,
5293 Oid resulttype, int32 resulttypmod,
5296 StringInfo buf = context->buf;
5299 * Since parse_coerce.c doesn't immediately collapse application of
5300 * length-coercion functions to constants, what we'll typically see in
5301 * such cases is a Const with typmod -1 and a length-coercion function
5302 * right above it. Avoid generating redundant output. However, beware of
5303 * suppressing casts when the user actually wrote something like
5304 * 'foo'::text::char(3).
5306 if (arg && IsA(arg, Const) &&
5307 ((Const *) arg)->consttype == resulttype &&
5308 ((Const *) arg)->consttypmod == -1)
5310 /* Show the constant without normal ::typename decoration */
5311 get_const_expr((Const *) arg, context, -1);
5315 if (!PRETTY_PAREN(context))
5316 appendStringInfoChar(buf, '(');
5317 get_rule_expr_paren(arg, context, false, parentNode);
5318 if (!PRETTY_PAREN(context))
5319 appendStringInfoChar(buf, ')');
5321 appendStringInfo(buf, "::%s",
5322 format_type_with_typemod(resulttype, resulttypmod));
5328 * Make a string representation of a Const
5330 * showtype can be -1 to never show "::typename" decoration, or +1 to always
5331 * show it, or 0 to show it only if the constant wouldn't be assumed to be
5332 * the right type by default.
5336 get_const_expr(Const *constval, deparse_context *context, int showtype)
5338 StringInfo buf = context->buf;
5342 bool isfloat = false;
5345 if (constval->constisnull)
5348 * Always label the type of a NULL constant to prevent misdecisions
5349 * about type when reparsing.
5351 appendStringInfo(buf, "NULL");
5353 appendStringInfo(buf, "::%s",
5354 format_type_with_typemod(constval->consttype,
5355 constval->consttypmod));
5359 getTypeOutputInfo(constval->consttype,
5360 &typoutput, &typIsVarlena);
5362 extval = OidOutputFunctionCall(typoutput, constval->constvalue);
5364 switch (constval->consttype)
5375 * These types are printed without quotes unless they contain
5376 * values that aren't accepted by the scanner unquoted (e.g.,
5377 * 'NaN'). Note that strtod() and friends might accept NaN,
5378 * so we can't use that to test.
5380 * In reality we only need to defend against infinity and NaN,
5381 * so we need not get too crazy about pattern matching here.
5383 * There is a special-case gotcha: if the constant is signed,
5384 * we need to parenthesize it, else the parser might see a
5385 * leading plus/minus as binding less tightly than adjacent
5386 * operators --- particularly, the cast that we might attach
5389 if (strspn(extval, "0123456789+-eE.") == strlen(extval))
5391 if (extval[0] == '+' || extval[0] == '-')
5392 appendStringInfo(buf, "(%s)", extval);
5394 appendStringInfoString(buf, extval);
5395 if (strcspn(extval, "eE.") != strlen(extval))
5396 isfloat = true; /* it looks like a float */
5399 appendStringInfo(buf, "'%s'", extval);
5405 appendStringInfo(buf, "B'%s'", extval);
5409 if (strcmp(extval, "t") == 0)
5410 appendStringInfo(buf, "true");
5412 appendStringInfo(buf, "false");
5416 simple_quote_literal(buf, extval);
5426 * For showtype == 0, append ::typename unless the constant will be
5427 * implicitly typed as the right type when it is read in.
5429 * XXX this code has to be kept in sync with the behavior of the parser,
5430 * especially make_const.
5432 switch (constval->consttype)
5437 /* These types can be left unlabeled */
5443 * Float-looking constants will be typed as numeric, but if
5444 * there's a specific typmod we need to show it.
5446 needlabel = !isfloat || (constval->consttypmod >= 0);
5452 if (needlabel || showtype > 0)
5453 appendStringInfo(buf, "::%s",
5454 format_type_with_typemod(constval->consttype,
5455 constval->consttypmod));
5459 * simple_quote_literal - Format a string as a SQL literal, append to buf
5462 simple_quote_literal(StringInfo buf, const char *val)
5467 * We form the string literal according to the prevailing setting
5468 * of standard_conforming_strings; we never use E''. User is
5469 * responsible for making sure result is used correctly.
5471 appendStringInfoChar(buf, '\'');
5472 for (valptr = val; *valptr; valptr++)
5476 if (SQL_STR_DOUBLE(ch, !standard_conforming_strings))
5477 appendStringInfoChar(buf, ch);
5478 appendStringInfoChar(buf, ch);
5480 appendStringInfoChar(buf, '\'');
5485 * get_sublink_expr - Parse back a sublink
5489 get_sublink_expr(SubLink *sublink, deparse_context *context)
5491 StringInfo buf = context->buf;
5492 Query *query = (Query *) (sublink->subselect);
5493 char *opname = NULL;
5496 if (sublink->subLinkType == ARRAY_SUBLINK)
5497 appendStringInfo(buf, "ARRAY(");
5499 appendStringInfoChar(buf, '(');
5502 * Note that we print the name of only the first operator, when there are
5503 * multiple combining operators. This is an approximation that could go
5504 * wrong in various scenarios (operators in different schemas, renamed
5505 * operators, etc) but there is not a whole lot we can do about it, since
5506 * the syntax allows only one operator to be shown.
5508 if (sublink->testexpr)
5510 if (IsA(sublink->testexpr, OpExpr))
5512 /* single combining operator */
5513 OpExpr *opexpr = (OpExpr *) sublink->testexpr;
5515 get_rule_expr(linitial(opexpr->args), context, true);
5516 opname = generate_operator_name(opexpr->opno,
5517 exprType(linitial(opexpr->args)),
5518 exprType(lsecond(opexpr->args)));
5520 else if (IsA(sublink->testexpr, BoolExpr))
5522 /* multiple combining operators, = or <> cases */
5526 appendStringInfoChar(buf, '(');
5528 foreach(l, ((BoolExpr *) sublink->testexpr)->args)
5530 OpExpr *opexpr = (OpExpr *) lfirst(l);
5532 Assert(IsA(opexpr, OpExpr));
5533 appendStringInfoString(buf, sep);
5534 get_rule_expr(linitial(opexpr->args), context, true);
5536 opname = generate_operator_name(opexpr->opno,
5537 exprType(linitial(opexpr->args)),
5538 exprType(lsecond(opexpr->args)));
5541 appendStringInfoChar(buf, ')');
5543 else if (IsA(sublink->testexpr, RowCompareExpr))
5545 /* multiple combining operators, < <= > >= cases */
5546 RowCompareExpr *rcexpr = (RowCompareExpr *) sublink->testexpr;
5548 appendStringInfoChar(buf, '(');
5549 get_rule_expr((Node *) rcexpr->largs, context, true);
5550 opname = generate_operator_name(linitial_oid(rcexpr->opnos),
5551 exprType(linitial(rcexpr->largs)),
5552 exprType(linitial(rcexpr->rargs)));
5553 appendStringInfoChar(buf, ')');
5556 elog(ERROR, "unrecognized testexpr type: %d",
5557 (int) nodeTag(sublink->testexpr));
5562 switch (sublink->subLinkType)
5564 case EXISTS_SUBLINK:
5565 appendStringInfo(buf, "EXISTS ");
5569 if (strcmp(opname, "=") == 0) /* Represent = ANY as IN */
5570 appendStringInfo(buf, " IN ");
5572 appendStringInfo(buf, " %s ANY ", opname);
5576 appendStringInfo(buf, " %s ALL ", opname);
5579 case ROWCOMPARE_SUBLINK:
5580 appendStringInfo(buf, " %s ", opname);
5588 case CTE_SUBLINK: /* shouldn't occur in a SubLink */
5590 elog(ERROR, "unrecognized sublink type: %d",
5591 (int) sublink->subLinkType);
5596 appendStringInfoChar(buf, '(');
5598 get_query_def(query, buf, context->namespaces, NULL,
5599 context->prettyFlags, context->indentLevel);
5602 appendStringInfo(buf, "))");
5604 appendStringInfoChar(buf, ')');
5609 * get_from_clause - Parse back a FROM clause
5611 * "prefix" is the keyword that denotes the start of the list of FROM
5612 * elements. It is FROM when used to parse back SELECT and UPDATE, but
5613 * is USING when parsing back DELETE.
5617 get_from_clause(Query *query, const char *prefix, deparse_context *context)
5619 StringInfo buf = context->buf;
5624 * We use the query's jointree as a guide to what to print. However, we
5625 * must ignore auto-added RTEs that are marked not inFromCl. (These can
5626 * only appear at the top level of the jointree, so it's sufficient to
5627 * check here.) This check also ensures we ignore the rule pseudo-RTEs
5630 foreach(l, query->jointree->fromlist)
5632 Node *jtnode = (Node *) lfirst(l);
5634 if (IsA(jtnode, RangeTblRef))
5636 int varno = ((RangeTblRef *) jtnode)->rtindex;
5637 RangeTblEntry *rte = rt_fetch(varno, query->rtable);
5645 appendContextKeyword(context, prefix,
5646 -PRETTYINDENT_STD, PRETTYINDENT_STD, 2);
5650 appendStringInfoString(buf, ", ");
5652 get_from_clause_item(jtnode, query, context);
5657 get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
5659 StringInfo buf = context->buf;
5661 if (IsA(jtnode, RangeTblRef))
5663 int varno = ((RangeTblRef *) jtnode)->rtindex;
5664 RangeTblEntry *rte = rt_fetch(varno, query->rtable);
5665 bool gavealias = false;
5667 switch (rte->rtekind)
5670 /* Normal relation RTE */
5671 appendStringInfo(buf, "%s%s",
5673 generate_relation_name(rte->relid,
5674 context->namespaces));
5678 appendStringInfoChar(buf, '(');
5679 get_query_def(rte->subquery, buf, context->namespaces, NULL,
5680 context->prettyFlags, context->indentLevel);
5681 appendStringInfoChar(buf, ')');
5685 get_rule_expr(rte->funcexpr, context, true);
5688 /* Values list RTE */
5689 get_values_def(rte->values_lists, context);
5692 appendStringInfoString(buf, quote_identifier(rte->ctename));
5695 elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
5699 if (rte->alias != NULL)
5701 appendStringInfo(buf, " %s",
5702 quote_identifier(rte->alias->aliasname));
5705 else if (rte->rtekind == RTE_RELATION &&
5706 strcmp(rte->eref->aliasname, get_rel_name(rte->relid)) != 0)
5709 * Apparently the rel has been renamed since the rule was made.
5710 * Emit a fake alias clause so that variable references will still
5711 * work. This is not a 100% solution but should work in most
5712 * reasonable situations.
5714 appendStringInfo(buf, " %s",
5715 quote_identifier(rte->eref->aliasname));
5718 else if (rte->rtekind == RTE_FUNCTION)
5721 * For a function RTE, always give an alias. This covers possible
5722 * renaming of the function and/or instability of the
5723 * FigureColname rules for things that aren't simple functions.
5725 appendStringInfo(buf, " %s",
5726 quote_identifier(rte->eref->aliasname));
5730 if (rte->rtekind == RTE_FUNCTION)
5732 if (rte->funccoltypes != NIL)
5734 /* Function returning RECORD, reconstruct the columndefs */
5736 appendStringInfo(buf, " AS ");
5737 get_from_clause_coldeflist(rte->eref->colnames,
5739 rte->funccoltypmods,
5745 * For a function RTE, always emit a complete column alias
5746 * list; this is to protect against possible instability of
5747 * the default column names (eg, from altering parameter
5750 get_from_clause_alias(rte->eref, rte, context);
5756 * For non-function RTEs, just report whatever the user originally
5757 * gave as column aliases.
5759 get_from_clause_alias(rte->alias, rte, context);
5762 else if (IsA(jtnode, JoinExpr))
5764 JoinExpr *j = (JoinExpr *) jtnode;
5765 bool need_paren_on_right;
5767 need_paren_on_right = PRETTY_PAREN(context) &&
5768 !IsA(j->rarg, RangeTblRef) &&
5769 !(IsA(j->rarg, JoinExpr) &&((JoinExpr *) j->rarg)->alias != NULL);
5771 if (!PRETTY_PAREN(context) || j->alias != NULL)
5772 appendStringInfoChar(buf, '(');
5774 get_from_clause_item(j->larg, query, context);
5778 if (!PRETTY_INDENT(context))
5779 appendStringInfoChar(buf, ' ');
5780 switch (j->jointype)
5783 appendContextKeyword(context, "NATURAL JOIN ",
5785 PRETTYINDENT_JOIN, 0);
5788 appendContextKeyword(context, "NATURAL LEFT JOIN ",
5790 PRETTYINDENT_JOIN, 0);
5793 appendContextKeyword(context, "NATURAL FULL JOIN ",
5795 PRETTYINDENT_JOIN, 0);
5798 appendContextKeyword(context, "NATURAL RIGHT JOIN ",
5800 PRETTYINDENT_JOIN, 0);
5803 elog(ERROR, "unrecognized join type: %d",
5809 switch (j->jointype)
5813 appendContextKeyword(context, " JOIN ",
5815 PRETTYINDENT_JOIN, 2);
5817 appendContextKeyword(context, " CROSS JOIN ",
5819 PRETTYINDENT_JOIN, 1);
5822 appendContextKeyword(context, " LEFT JOIN ",
5824 PRETTYINDENT_JOIN, 2);
5827 appendContextKeyword(context, " FULL JOIN ",
5829 PRETTYINDENT_JOIN, 2);
5832 appendContextKeyword(context, " RIGHT JOIN ",
5834 PRETTYINDENT_JOIN, 2);
5837 elog(ERROR, "unrecognized join type: %d",
5842 if (need_paren_on_right)
5843 appendStringInfoChar(buf, '(');
5844 get_from_clause_item(j->rarg, query, context);
5845 if (need_paren_on_right)
5846 appendStringInfoChar(buf, ')');
5848 context->indentLevel -= PRETTYINDENT_JOIN_ON;
5856 appendStringInfo(buf, " USING (");
5857 foreach(col, j->using)
5859 if (col != list_head(j->using))
5860 appendStringInfo(buf, ", ");
5861 appendStringInfoString(buf,
5862 quote_identifier(strVal(lfirst(col))));
5864 appendStringInfoChar(buf, ')');
5868 appendStringInfo(buf, " ON ");
5869 if (!PRETTY_PAREN(context))
5870 appendStringInfoChar(buf, '(');
5871 get_rule_expr(j->quals, context, false);
5872 if (!PRETTY_PAREN(context))
5873 appendStringInfoChar(buf, ')');
5876 if (!PRETTY_PAREN(context) || j->alias != NULL)
5877 appendStringInfoChar(buf, ')');
5879 /* Yes, it's correct to put alias after the right paren ... */
5880 if (j->alias != NULL)
5882 appendStringInfo(buf, " %s",
5883 quote_identifier(j->alias->aliasname));
5884 get_from_clause_alias(j->alias,
5885 rt_fetch(j->rtindex, query->rtable),
5890 elog(ERROR, "unrecognized node type: %d",
5891 (int) nodeTag(jtnode));
5895 * get_from_clause_alias - reproduce column alias list
5897 * This is tricky because we must ignore dropped columns.
5900 get_from_clause_alias(Alias *alias, RangeTblEntry *rte,
5901 deparse_context *context)
5903 StringInfo buf = context->buf;
5908 if (alias == NULL || alias->colnames == NIL)
5909 return; /* definitely nothing to do */
5912 foreach(col, alias->colnames)
5915 if (get_rte_attribute_is_dropped(rte, attnum))
5919 appendStringInfoChar(buf, '(');
5923 appendStringInfo(buf, ", ");
5924 appendStringInfoString(buf,
5925 quote_identifier(strVal(lfirst(col))));
5928 appendStringInfoChar(buf, ')');
5932 * get_from_clause_coldeflist - reproduce FROM clause coldeflist
5934 * The coldeflist is appended immediately (no space) to buf. Caller is
5935 * responsible for ensuring that an alias or AS is present before it.
5938 get_from_clause_coldeflist(List *names, List *types, List *typmods,
5939 deparse_context *context)
5941 StringInfo buf = context->buf;
5947 appendStringInfoChar(buf, '(');
5949 l2 = list_head(types);
5950 l3 = list_head(typmods);
5953 char *attname = strVal(lfirst(l1));
5957 atttypid = lfirst_oid(l2);
5959 atttypmod = lfirst_int(l3);
5963 appendStringInfo(buf, ", ");
5964 appendStringInfo(buf, "%s %s",
5965 quote_identifier(attname),
5966 format_type_with_typemod(atttypid, atttypmod));
5970 appendStringInfoChar(buf, ')');
5974 * get_opclass_name - fetch name of an index operator class
5976 * The opclass name is appended (after a space) to buf.
5978 * Output is suppressed if the opclass is the default for the given
5979 * actual_datatype. (If you don't want this behavior, just pass
5980 * InvalidOid for actual_datatype.)
5983 get_opclass_name(Oid opclass, Oid actual_datatype,
5987 Form_pg_opclass opcrec;
5991 ht_opc = SearchSysCache(CLAOID,
5992 ObjectIdGetDatum(opclass),
5994 if (!HeapTupleIsValid(ht_opc))
5995 elog(ERROR, "cache lookup failed for opclass %u", opclass);
5996 opcrec = (Form_pg_opclass) GETSTRUCT(ht_opc);
5998 if (!OidIsValid(actual_datatype) ||
5999 GetDefaultOpClass(actual_datatype, opcrec->opcmethod) != opclass)
6001 /* Okay, we need the opclass name. Do we need to qualify it? */
6002 opcname = NameStr(opcrec->opcname);
6003 if (OpclassIsVisible(opclass))
6004 appendStringInfo(buf, " %s", quote_identifier(opcname));
6007 nspname = get_namespace_name(opcrec->opcnamespace);
6008 appendStringInfo(buf, " %s.%s",
6009 quote_identifier(nspname),
6010 quote_identifier(opcname));
6013 ReleaseSysCache(ht_opc);
6017 * processIndirection - take care of array and subfield assignment
6019 * We strip any top-level FieldStore or assignment ArrayRef nodes that
6020 * appear in the input, and return the subexpression that's to be assigned.
6021 * If printit is true, we also print out the appropriate decoration for the
6022 * base column name (that the caller just printed).
6025 processIndirection(Node *node, deparse_context *context, bool printit)
6027 StringInfo buf = context->buf;
6033 if (IsA(node, FieldStore))
6035 FieldStore *fstore = (FieldStore *) node;
6039 /* lookup tuple type */
6040 typrelid = get_typ_typrelid(fstore->resulttype);
6041 if (!OidIsValid(typrelid))
6042 elog(ERROR, "argument type %s of FieldStore is not a tuple type",
6043 format_type_be(fstore->resulttype));
6046 * Print the field name. Note we assume here that there's only
6047 * one field being assigned to. This is okay in stored rules but
6048 * could be wrong in executable target lists. Presently no
6049 * problem since explain.c doesn't print plan targetlists, but
6050 * someday may have to think of something ...
6052 fieldname = get_relid_attribute_name(typrelid,
6053 linitial_int(fstore->fieldnums));
6055 appendStringInfo(buf, ".%s", quote_identifier(fieldname));
6058 * We ignore arg since it should be an uninteresting reference to
6059 * the target column or subcolumn.
6061 node = (Node *) linitial(fstore->newvals);
6063 else if (IsA(node, ArrayRef))
6065 ArrayRef *aref = (ArrayRef *) node;
6067 if (aref->refassgnexpr == NULL)
6070 printSubscripts(aref, context);
6073 * We ignore refexpr since it should be an uninteresting reference
6074 * to the target column or subcolumn.
6076 node = (Node *) aref->refassgnexpr;
6086 printSubscripts(ArrayRef *aref, deparse_context *context)
6088 StringInfo buf = context->buf;
6089 ListCell *lowlist_item;
6090 ListCell *uplist_item;
6092 lowlist_item = list_head(aref->reflowerindexpr); /* could be NULL */
6093 foreach(uplist_item, aref->refupperindexpr)
6095 appendStringInfoChar(buf, '[');
6098 get_rule_expr((Node *) lfirst(lowlist_item), context, false);
6099 appendStringInfoChar(buf, ':');
6100 lowlist_item = lnext(lowlist_item);
6102 get_rule_expr((Node *) lfirst(uplist_item), context, false);
6103 appendStringInfoChar(buf, ']');
6108 * quote_identifier - Quote an identifier only if needed
6110 * When quotes are needed, we palloc the required space; slightly
6111 * space-wasteful but well worth it for notational simplicity.
6114 quote_identifier(const char *ident)
6117 * Can avoid quoting if ident starts with a lowercase letter or underscore
6118 * and contains only lowercase letters, digits, and underscores, *and* is
6119 * not any SQL keyword. Otherwise, supply quotes.
6128 * would like to use <ctype.h> macros here, but they might yield unwanted
6129 * locale-specific results...
6131 safe = ((ident[0] >= 'a' && ident[0] <= 'z') || ident[0] == '_');
6133 for (ptr = ident; *ptr; ptr++)
6137 if ((ch >= 'a' && ch <= 'z') ||
6138 (ch >= '0' && ch <= '9') ||
6154 * Check for keyword. We quote keywords except for unreserved ones.
6155 * (In some cases we could avoid quoting a col_name or type_func_name
6156 * keyword, but it seems much harder than it's worth to tell that.)
6158 * Note: ScanKeywordLookup() does case-insensitive comparison, but
6159 * that's fine, since we already know we have all-lower-case.
6161 const ScanKeyword *keyword = ScanKeywordLookup(ident);
6163 if (keyword != NULL && keyword->category != UNRESERVED_KEYWORD)
6168 return ident; /* no change needed */
6170 result = (char *) palloc(strlen(ident) + nquotes + 2 + 1);
6174 for (ptr = ident; *ptr; ptr++)
6189 * quote_qualified_identifier - Quote a possibly-qualified identifier
6191 * Return a name of the form namespace.ident, or just ident if namespace
6192 * is NULL, quoting each component if necessary. The result is palloc'd.
6195 quote_qualified_identifier(const char *namespace,
6200 initStringInfo(&buf);
6202 appendStringInfo(&buf, "%s.", quote_identifier(namespace));
6203 appendStringInfoString(&buf, quote_identifier(ident));
6208 * generate_relation_name
6209 * Compute the name to display for a relation specified by OID
6211 * The result includes all necessary quoting and schema-prefixing.
6213 * If namespaces isn't NIL, it must be a list of deparse_namespace nodes.
6214 * We will forcibly qualify the relation name if it equals any CTE name
6215 * visible in the namespace list.
6218 generate_relation_name(Oid relid, List *namespaces)
6221 Form_pg_class reltup;
6228 tp = SearchSysCache(RELOID,
6229 ObjectIdGetDatum(relid),
6231 if (!HeapTupleIsValid(tp))
6232 elog(ERROR, "cache lookup failed for relation %u", relid);
6233 reltup = (Form_pg_class) GETSTRUCT(tp);
6234 relname = NameStr(reltup->relname);
6236 /* Check for conflicting CTE name */
6238 foreach(nslist, namespaces)
6240 deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist);
6243 foreach(ctlist, dpns->ctes)
6245 CommonTableExpr *cte = (CommonTableExpr *) lfirst(ctlist);
6247 if (strcmp(cte->ctename, relname) == 0)
6257 /* Otherwise, qualify the name if not visible in search path */
6259 need_qual = !RelationIsVisible(relid);
6262 nspname = get_namespace_name(reltup->relnamespace);
6266 result = quote_qualified_identifier(nspname, relname);
6268 ReleaseSysCache(tp);
6274 * generate_function_name
6275 * Compute the name to display for a function specified by OID,
6276 * given that it is being called with the specified actual arg types.
6277 * (Arg types matter because of ambiguous-function resolution rules.)
6279 * The result includes all necessary quoting and schema-prefixing. We can
6280 * also pass back an indication of whether the function is variadic.
6283 generate_function_name(Oid funcid, int nargs, Oid *argtypes,
6287 Form_pg_proc procform;
6291 FuncDetailCode p_result;
6296 Oid *p_true_typeids;
6298 proctup = SearchSysCache(PROCOID,
6299 ObjectIdGetDatum(funcid),
6301 if (!HeapTupleIsValid(proctup))
6302 elog(ERROR, "cache lookup failed for function %u", funcid);
6303 procform = (Form_pg_proc) GETSTRUCT(proctup);
6304 proname = NameStr(procform->proname);
6307 * The idea here is to schema-qualify only if the parser would fail to
6308 * resolve the correct function given the unqualified func name with the
6309 * specified argtypes.
6311 p_result = func_get_detail(list_make1(makeString(proname)),
6312 NIL, nargs, argtypes, false, true,
6313 &p_funcid, &p_rettype,
6314 &p_retset, &p_nvargs, &p_true_typeids, NULL);
6315 if ((p_result == FUNCDETAIL_NORMAL ||
6316 p_result == FUNCDETAIL_AGGREGATE ||
6317 p_result == FUNCDETAIL_WINDOWFUNC) &&
6321 nspname = get_namespace_name(procform->pronamespace);
6323 result = quote_qualified_identifier(nspname, proname);
6325 /* Check variadic-ness if caller cares */
6328 /* "any" variadics are not treated as variadics for listing */
6329 if (OidIsValid(procform->provariadic) &&
6330 procform->provariadic != ANYOID)
6331 *is_variadic = true;
6333 *is_variadic = false;
6336 ReleaseSysCache(proctup);
6342 * generate_operator_name
6343 * Compute the name to display for an operator specified by OID,
6344 * given that it is being called with the specified actual arg types.
6345 * (Arg types matter because of ambiguous-operator resolution rules.
6346 * Pass InvalidOid for unused arg of a unary operator.)
6348 * The result includes all necessary quoting and schema-prefixing,
6349 * plus the OPERATOR() decoration needed to use a qualified operator name
6353 generate_operator_name(Oid operid, Oid arg1, Oid arg2)
6357 Form_pg_operator operform;
6362 initStringInfo(&buf);
6364 opertup = SearchSysCache(OPEROID,
6365 ObjectIdGetDatum(operid),
6367 if (!HeapTupleIsValid(opertup))
6368 elog(ERROR, "cache lookup failed for operator %u", operid);
6369 operform = (Form_pg_operator) GETSTRUCT(opertup);
6370 oprname = NameStr(operform->oprname);
6373 * The idea here is to schema-qualify only if the parser would fail to
6374 * resolve the correct operator given the unqualified op name with the
6375 * specified argtypes.
6377 switch (operform->oprkind)
6380 p_result = oper(NULL, list_make1(makeString(oprname)), arg1, arg2,
6384 p_result = left_oper(NULL, list_make1(makeString(oprname)), arg2,
6388 p_result = right_oper(NULL, list_make1(makeString(oprname)), arg1,
6392 elog(ERROR, "unrecognized oprkind: %d", operform->oprkind);
6393 p_result = NULL; /* keep compiler quiet */
6397 if (p_result != NULL && oprid(p_result) == operid)
6401 nspname = get_namespace_name(operform->oprnamespace);
6402 appendStringInfo(&buf, "OPERATOR(%s.", quote_identifier(nspname));
6405 appendStringInfoString(&buf, oprname);
6408 appendStringInfoChar(&buf, ')');
6410 if (p_result != NULL)
6411 ReleaseSysCache(p_result);
6413 ReleaseSysCache(opertup);
6419 * Given a C string, produce a TEXT datum.
6421 * We assume that the input was palloc'd and may be freed.
6424 string_to_text(char *str)
6428 result = cstring_to_text(str);
6434 * Generate a C string representing a relation's reloptions, or NULL if none.
6437 flatten_reloptions(Oid relid)
6439 char *result = NULL;
6444 tuple = SearchSysCache(RELOID,
6445 ObjectIdGetDatum(relid),
6447 if (!HeapTupleIsValid(tuple))
6448 elog(ERROR, "cache lookup failed for relation %u", relid);
6450 reloptions = SysCacheGetAttr(RELOID, tuple,
6451 Anum_pg_class_reloptions, &isnull);
6458 * We want to use array_to_text(reloptions, ', ') --- but
6459 * DirectFunctionCall2(array_to_text) does not work, because
6460 * array_to_text() relies on flinfo to be valid. So use
6463 sep = CStringGetTextDatum(", ");
6464 txt = OidFunctionCall2(F_ARRAY_TO_TEXT, reloptions, sep);
6465 result = TextDatumGetCString(txt);
6468 ReleaseSysCache(tuple);