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.290 2008/12/19 05:04:35 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 int prettyFlags; /* enabling of pretty-print functions */
85 int indentLevel; /* current indent level for prettyprint */
86 bool varprefix; /* TRUE to print prefixes on Vars */
90 * Each level of query context around a subtree needs a level of Var namespace.
91 * A Var having varlevelsup=N refers to the N'th item (counting from 0) in
92 * the current context's namespaces list.
94 * The rangetable is the list of actual RTEs from the query tree, and the
95 * cte list is the list of actual CTEs.
97 * For deparsing plan trees, we provide for outer and inner subplan nodes.
98 * The tlists of these nodes are used to resolve OUTER and INNER varnos.
99 * Also, in the plan-tree case we don't have access to the parse-time CTE
100 * list, so we need a list of subplans instead.
104 List *rtable; /* List of RangeTblEntry nodes */
105 List *ctes; /* List of CommonTableExpr nodes */
106 List *subplans; /* List of subplans, in plan-tree case */
107 Plan *outer_plan; /* OUTER subplan, or NULL if none */
108 Plan *inner_plan; /* INNER subplan, or NULL if none */
116 static SPIPlanPtr plan_getrulebyoid = NULL;
117 static const char *query_getrulebyoid = "SELECT * FROM pg_catalog.pg_rewrite WHERE oid = $1";
118 static SPIPlanPtr plan_getviewrule = NULL;
119 static const char *query_getviewrule = "SELECT * FROM pg_catalog.pg_rewrite WHERE ev_class = $1 AND rulename = $2";
125 * Most of these functions used to use fixed-size buffers to build their
126 * results. Now, they take an (already initialized) StringInfo object
127 * as a parameter, and append their text output to its contents.
130 static char *deparse_expression_pretty(Node *expr, List *dpcontext,
131 bool forceprefix, bool showimplicit,
132 int prettyFlags, int startIndent);
133 static char *pg_get_viewdef_worker(Oid viewoid, int prettyFlags);
134 static void decompile_column_index_array(Datum column_index_array, Oid relId,
136 static char *pg_get_ruledef_worker(Oid ruleoid, int prettyFlags);
137 static char *pg_get_indexdef_worker(Oid indexrelid, int colno, bool showTblSpc,
139 static char *pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
141 static char *pg_get_expr_worker(text *expr, Oid relid, char *relname,
143 static int print_function_arguments(StringInfo buf, HeapTuple proctup,
144 bool print_table_args, bool print_defaults);
145 static void print_function_rettype(StringInfo buf, HeapTuple proctup);
146 static void make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
148 static void make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
150 static void get_query_def(Query *query, StringInfo buf, List *parentnamespace,
151 TupleDesc resultDesc, int prettyFlags, int startIndent);
152 static void get_values_def(List *values_lists, deparse_context *context);
153 static void get_with_clause(Query *query, deparse_context *context);
154 static void get_select_query_def(Query *query, deparse_context *context,
155 TupleDesc resultDesc);
156 static void get_insert_query_def(Query *query, deparse_context *context);
157 static void get_update_query_def(Query *query, deparse_context *context);
158 static void get_delete_query_def(Query *query, deparse_context *context);
159 static void get_utility_query_def(Query *query, deparse_context *context);
160 static void get_basic_select_query(Query *query, deparse_context *context,
161 TupleDesc resultDesc);
162 static void get_target_list(List *targetList, deparse_context *context,
163 TupleDesc resultDesc);
164 static void get_setop_query(Node *setOp, Query *query,
165 deparse_context *context,
166 TupleDesc resultDesc);
167 static Node *get_rule_sortgroupclause(SortGroupClause *srt, List *tlist,
169 deparse_context *context);
170 static void push_plan(deparse_namespace *dpns, Plan *subplan);
171 static char *get_variable(Var *var, int levelsup, bool showstar,
172 deparse_context *context);
173 static RangeTblEntry *find_rte_by_refname(const char *refname,
174 deparse_context *context);
175 static const char *get_simple_binary_op_name(OpExpr *expr);
176 static bool isSimpleNode(Node *node, Node *parentNode, int prettyFlags);
177 static void appendStringInfoSpaces(StringInfo buf, int count);
178 static void appendContextKeyword(deparse_context *context, const char *str,
179 int indentBefore, int indentAfter, int indentPlus);
180 static void get_rule_expr(Node *node, deparse_context *context,
182 static void get_oper_expr(OpExpr *expr, deparse_context *context);
183 static void get_func_expr(FuncExpr *expr, deparse_context *context,
185 static void get_agg_expr(Aggref *aggref, deparse_context *context);
186 static void get_coercion_expr(Node *arg, deparse_context *context,
187 Oid resulttype, int32 resulttypmod,
189 static void get_const_expr(Const *constval, deparse_context *context,
191 static void simple_quote_literal(StringInfo buf, const char *val);
192 static void get_sublink_expr(SubLink *sublink, deparse_context *context);
193 static void get_from_clause(Query *query, const char *prefix,
194 deparse_context *context);
195 static void get_from_clause_item(Node *jtnode, Query *query,
196 deparse_context *context);
197 static void get_from_clause_alias(Alias *alias, RangeTblEntry *rte,
198 deparse_context *context);
199 static void get_from_clause_coldeflist(List *names, List *types, List *typmods,
200 deparse_context *context);
201 static void get_opclass_name(Oid opclass, Oid actual_datatype,
203 static Node *processIndirection(Node *node, deparse_context *context,
205 static void printSubscripts(ArrayRef *aref, deparse_context *context);
206 static char *generate_relation_name(Oid relid, List *namespaces);
207 static char *generate_function_name(Oid funcid, int nargs, Oid *argtypes,
209 static char *generate_operator_name(Oid operid, Oid arg1, Oid arg2);
210 static text *string_to_text(char *str);
211 static char *flatten_reloptions(Oid relid);
213 #define only_marker(rte) ((rte)->inh ? "" : "ONLY ")
217 * get_ruledef - Do it all and return a text
218 * that could be used as a statement
219 * to recreate the rule
223 pg_get_ruledef(PG_FUNCTION_ARGS)
225 Oid ruleoid = PG_GETARG_OID(0);
227 PG_RETURN_TEXT_P(string_to_text(pg_get_ruledef_worker(ruleoid, 0)));
232 pg_get_ruledef_ext(PG_FUNCTION_ARGS)
234 Oid ruleoid = PG_GETARG_OID(0);
235 bool pretty = PG_GETARG_BOOL(1);
238 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
239 PG_RETURN_TEXT_P(string_to_text(pg_get_ruledef_worker(ruleoid, prettyFlags)));
244 pg_get_ruledef_worker(Oid ruleoid, int prettyFlags)
254 * Do this first so that string is alloc'd in outer context not SPI's.
256 initStringInfo(&buf);
259 * Connect to SPI manager
261 if (SPI_connect() != SPI_OK_CONNECT)
262 elog(ERROR, "SPI_connect failed");
265 * On the first call prepare the plan to lookup pg_rewrite. We read
266 * pg_rewrite over the SPI manager instead of using the syscache to be
267 * checked for read access on pg_rewrite.
269 if (plan_getrulebyoid == NULL)
274 argtypes[0] = OIDOID;
275 plan = SPI_prepare(query_getrulebyoid, 1, argtypes);
277 elog(ERROR, "SPI_prepare failed for \"%s\"", query_getrulebyoid);
278 plan_getrulebyoid = SPI_saveplan(plan);
282 * Get the pg_rewrite tuple for this rule
284 args[0] = ObjectIdGetDatum(ruleoid);
286 spirc = SPI_execute_plan(plan_getrulebyoid, args, nulls, true, 1);
287 if (spirc != SPI_OK_SELECT)
288 elog(ERROR, "failed to get pg_rewrite tuple for rule %u", ruleoid);
289 if (SPI_processed != 1)
290 appendStringInfo(&buf, "-");
294 * Get the rule's definition and put it into executor's memory
296 ruletup = SPI_tuptable->vals[0];
297 rulettc = SPI_tuptable->tupdesc;
298 make_ruledef(&buf, ruletup, rulettc, prettyFlags);
302 * Disconnect from SPI manager
304 if (SPI_finish() != SPI_OK_FINISH)
305 elog(ERROR, "SPI_finish failed");
312 * get_viewdef - Mainly the same thing, but we
313 * only return the SELECT part of a view
317 pg_get_viewdef(PG_FUNCTION_ARGS)
320 Oid viewoid = PG_GETARG_OID(0);
322 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, 0)));
327 pg_get_viewdef_ext(PG_FUNCTION_ARGS)
330 Oid viewoid = PG_GETARG_OID(0);
331 bool pretty = PG_GETARG_BOOL(1);
334 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
335 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, prettyFlags)));
339 pg_get_viewdef_name(PG_FUNCTION_ARGS)
341 /* By qualified name */
342 text *viewname = PG_GETARG_TEXT_P(0);
346 viewrel = makeRangeVarFromNameList(textToQualifiedNameList(viewname));
347 viewoid = RangeVarGetRelid(viewrel, false);
349 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, 0)));
354 pg_get_viewdef_name_ext(PG_FUNCTION_ARGS)
356 /* By qualified name */
357 text *viewname = PG_GETARG_TEXT_P(0);
358 bool pretty = PG_GETARG_BOOL(1);
363 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
364 viewrel = makeRangeVarFromNameList(textToQualifiedNameList(viewname));
365 viewoid = RangeVarGetRelid(viewrel, false);
367 PG_RETURN_TEXT_P(string_to_text(pg_get_viewdef_worker(viewoid, prettyFlags)));
371 * Common code for by-OID and by-name variants of pg_get_viewdef
374 pg_get_viewdef_worker(Oid viewoid, int prettyFlags)
384 * Do this first so that string is alloc'd in outer context not SPI's.
386 initStringInfo(&buf);
389 * Connect to SPI manager
391 if (SPI_connect() != SPI_OK_CONNECT)
392 elog(ERROR, "SPI_connect failed");
395 * On the first call prepare the plan to lookup pg_rewrite. We read
396 * pg_rewrite over the SPI manager instead of using the syscache to be
397 * checked for read access on pg_rewrite.
399 if (plan_getviewrule == NULL)
404 argtypes[0] = OIDOID;
405 argtypes[1] = NAMEOID;
406 plan = SPI_prepare(query_getviewrule, 2, argtypes);
408 elog(ERROR, "SPI_prepare failed for \"%s\"", query_getviewrule);
409 plan_getviewrule = SPI_saveplan(plan);
413 * Get the pg_rewrite tuple for the view's SELECT rule
415 args[0] = ObjectIdGetDatum(viewoid);
416 args[1] = PointerGetDatum(ViewSelectRuleName);
419 spirc = SPI_execute_plan(plan_getviewrule, args, nulls, true, 2);
420 if (spirc != SPI_OK_SELECT)
421 elog(ERROR, "failed to get pg_rewrite tuple for view %u", viewoid);
422 if (SPI_processed != 1)
423 appendStringInfo(&buf, "Not a view");
427 * Get the rule's definition and put it into executor's memory
429 ruletup = SPI_tuptable->vals[0];
430 rulettc = SPI_tuptable->tupdesc;
431 make_viewdef(&buf, ruletup, rulettc, prettyFlags);
435 * Disconnect from SPI manager
437 if (SPI_finish() != SPI_OK_FINISH)
438 elog(ERROR, "SPI_finish failed");
444 * get_triggerdef - Get the definition of a trigger
448 pg_get_triggerdef(PG_FUNCTION_ARGS)
450 Oid trigid = PG_GETARG_OID(0);
452 Form_pg_trigger trigrec;
461 * Fetch the pg_trigger tuple by the Oid of the trigger
463 tgrel = heap_open(TriggerRelationId, AccessShareLock);
465 ScanKeyInit(&skey[0],
466 ObjectIdAttributeNumber,
467 BTEqualStrategyNumber, F_OIDEQ,
468 ObjectIdGetDatum(trigid));
470 tgscan = systable_beginscan(tgrel, TriggerOidIndexId, true,
471 SnapshotNow, 1, skey);
473 ht_trig = systable_getnext(tgscan);
475 if (!HeapTupleIsValid(ht_trig))
476 elog(ERROR, "could not find tuple for trigger %u", trigid);
478 trigrec = (Form_pg_trigger) GETSTRUCT(ht_trig);
481 * Start the trigger definition. Note that the trigger's name should never
482 * be schema-qualified, but the trigger rel's name may be.
484 initStringInfo(&buf);
486 tgname = NameStr(trigrec->tgname);
487 appendStringInfo(&buf, "CREATE %sTRIGGER %s ",
488 trigrec->tgisconstraint ? "CONSTRAINT " : "",
489 quote_identifier(tgname));
491 if (TRIGGER_FOR_BEFORE(trigrec->tgtype))
492 appendStringInfo(&buf, "BEFORE");
494 appendStringInfo(&buf, "AFTER");
495 if (TRIGGER_FOR_INSERT(trigrec->tgtype))
497 appendStringInfo(&buf, " INSERT");
500 if (TRIGGER_FOR_DELETE(trigrec->tgtype))
503 appendStringInfo(&buf, " OR DELETE");
505 appendStringInfo(&buf, " DELETE");
508 if (TRIGGER_FOR_UPDATE(trigrec->tgtype))
511 appendStringInfo(&buf, " OR UPDATE");
513 appendStringInfo(&buf, " UPDATE");
515 if (TRIGGER_FOR_TRUNCATE(trigrec->tgtype))
518 appendStringInfo(&buf, " OR TRUNCATE");
520 appendStringInfo(&buf, " TRUNCATE");
522 appendStringInfo(&buf, " ON %s ",
523 generate_relation_name(trigrec->tgrelid, NIL));
525 if (trigrec->tgisconstraint)
527 if (trigrec->tgconstrrelid != InvalidOid)
528 appendStringInfo(&buf, "FROM %s ",
529 generate_relation_name(trigrec->tgconstrrelid,
531 if (!trigrec->tgdeferrable)
532 appendStringInfo(&buf, "NOT ");
533 appendStringInfo(&buf, "DEFERRABLE INITIALLY ");
534 if (trigrec->tginitdeferred)
535 appendStringInfo(&buf, "DEFERRED ");
537 appendStringInfo(&buf, "IMMEDIATE ");
541 if (TRIGGER_FOR_ROW(trigrec->tgtype))
542 appendStringInfo(&buf, "FOR EACH ROW ");
544 appendStringInfo(&buf, "FOR EACH STATEMENT ");
546 appendStringInfo(&buf, "EXECUTE PROCEDURE %s(",
547 generate_function_name(trigrec->tgfoid, 0, NULL, NULL));
549 if (trigrec->tgnargs > 0)
556 val = DatumGetByteaP(fastgetattr(ht_trig,
557 Anum_pg_trigger_tgargs,
558 tgrel->rd_att, &isnull));
560 elog(ERROR, "tgargs is null for trigger %u", trigid);
561 p = (char *) VARDATA(val);
562 for (i = 0; i < trigrec->tgnargs; i++)
565 appendStringInfo(&buf, ", ");
566 simple_quote_literal(&buf, p);
567 /* advance p to next string embedded in tgargs */
574 /* We deliberately do not put semi-colon at end */
575 appendStringInfo(&buf, ")");
578 systable_endscan(tgscan);
580 heap_close(tgrel, AccessShareLock);
582 PG_RETURN_TEXT_P(string_to_text(buf.data));
586 * get_indexdef - Get the definition of an index
588 * In the extended version, there is a colno argument as well as pretty bool.
589 * if colno == 0, we want a complete index definition.
590 * if colno > 0, we only want the Nth index key's variable or expression.
592 * Note that the SQL-function versions of this omit any info about the
593 * index tablespace; this is intentional because pg_dump wants it that way.
594 * However pg_get_indexdef_string() includes index tablespace if not default.
598 pg_get_indexdef(PG_FUNCTION_ARGS)
600 Oid indexrelid = PG_GETARG_OID(0);
602 PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, 0,
607 pg_get_indexdef_ext(PG_FUNCTION_ARGS)
609 Oid indexrelid = PG_GETARG_OID(0);
610 int32 colno = PG_GETARG_INT32(1);
611 bool pretty = PG_GETARG_BOOL(2);
614 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
615 PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, colno,
616 false, prettyFlags)));
619 /* Internal version that returns a palloc'd C string */
621 pg_get_indexdef_string(Oid indexrelid)
623 return pg_get_indexdef_worker(indexrelid, 0, true, 0);
627 pg_get_indexdef_worker(Oid indexrelid, int colno, bool showTblSpc,
633 Form_pg_index idxrec;
634 Form_pg_class idxrelrec;
637 ListCell *indexpr_item;
643 Datum indoptionDatum;
646 int2vector *indoption;
652 * Fetch the pg_index tuple by the Oid of the index
654 ht_idx = SearchSysCache(INDEXRELID,
655 ObjectIdGetDatum(indexrelid),
657 if (!HeapTupleIsValid(ht_idx))
658 elog(ERROR, "cache lookup failed for index %u", indexrelid);
659 idxrec = (Form_pg_index) GETSTRUCT(ht_idx);
661 indrelid = idxrec->indrelid;
662 Assert(indexrelid == idxrec->indexrelid);
664 /* Must get indclass and indoption the hard way */
665 indclassDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
666 Anum_pg_index_indclass, &isnull);
668 indclass = (oidvector *) DatumGetPointer(indclassDatum);
669 indoptionDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
670 Anum_pg_index_indoption, &isnull);
672 indoption = (int2vector *) DatumGetPointer(indoptionDatum);
675 * Fetch the pg_class tuple of the index relation
677 ht_idxrel = SearchSysCache(RELOID,
678 ObjectIdGetDatum(indexrelid),
680 if (!HeapTupleIsValid(ht_idxrel))
681 elog(ERROR, "cache lookup failed for relation %u", indexrelid);
682 idxrelrec = (Form_pg_class) GETSTRUCT(ht_idxrel);
685 * Fetch the pg_am tuple of the index' access method
687 ht_am = SearchSysCache(AMOID,
688 ObjectIdGetDatum(idxrelrec->relam),
690 if (!HeapTupleIsValid(ht_am))
691 elog(ERROR, "cache lookup failed for access method %u",
693 amrec = (Form_pg_am) GETSTRUCT(ht_am);
696 * Get the index expressions, if any. (NOTE: we do not use the relcache
697 * versions of the expressions and predicate, because we want to display
698 * non-const-folded expressions.)
700 if (!heap_attisnull(ht_idx, Anum_pg_index_indexprs))
706 exprsDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
707 Anum_pg_index_indexprs, &isnull);
709 exprsString = TextDatumGetCString(exprsDatum);
710 indexprs = (List *) stringToNode(exprsString);
716 indexpr_item = list_head(indexprs);
718 context = deparse_context_for(get_rel_name(indrelid), indrelid);
721 * Start the index definition. Note that the index's name should never be
722 * schema-qualified, but the indexed rel's name may be.
724 initStringInfo(&buf);
727 appendStringInfo(&buf, "CREATE %sINDEX %s ON %s USING %s (",
728 idxrec->indisunique ? "UNIQUE " : "",
729 quote_identifier(NameStr(idxrelrec->relname)),
730 generate_relation_name(indrelid, NIL),
731 quote_identifier(NameStr(amrec->amname)));
734 * Report the indexed attributes
737 for (keyno = 0; keyno < idxrec->indnatts; keyno++)
739 AttrNumber attnum = idxrec->indkey.values[keyno];
740 int16 opt = indoption->values[keyno];
743 appendStringInfoString(&buf, sep);
748 /* Simple index column */
751 attname = get_relid_attribute_name(indrelid, attnum);
752 if (!colno || colno == keyno + 1)
753 appendStringInfoString(&buf, quote_identifier(attname));
754 keycoltype = get_atttype(indrelid, attnum);
758 /* expressional index */
761 if (indexpr_item == NULL)
762 elog(ERROR, "too few entries in indexprs list");
763 indexkey = (Node *) lfirst(indexpr_item);
764 indexpr_item = lnext(indexpr_item);
766 str = deparse_expression_pretty(indexkey, context, false, false,
768 if (!colno || colno == keyno + 1)
770 /* Need parens if it's not a bare function call */
771 if (indexkey && IsA(indexkey, FuncExpr) &&
772 ((FuncExpr *) indexkey)->funcformat == COERCE_EXPLICIT_CALL)
773 appendStringInfoString(&buf, str);
775 appendStringInfo(&buf, "(%s)", str);
777 keycoltype = exprType(indexkey);
780 /* Provide decoration only in the colno=0 case */
783 /* Add the operator class name, if not default */
784 get_opclass_name(indclass->values[keyno], keycoltype, &buf);
786 /* Add options if relevant */
787 if (amrec->amcanorder)
789 /* if it supports sort ordering, report DESC and NULLS opts */
790 if (opt & INDOPTION_DESC)
792 appendStringInfo(&buf, " DESC");
793 /* NULLS FIRST is the default in this case */
794 if (!(opt & INDOPTION_NULLS_FIRST))
795 appendStringInfo(&buf, " NULLS LAST");
799 if (opt & INDOPTION_NULLS_FIRST)
800 appendStringInfo(&buf, " NULLS FIRST");
808 appendStringInfoChar(&buf, ')');
811 * If it has options, append "WITH (options)"
813 str = flatten_reloptions(indexrelid);
816 appendStringInfo(&buf, " WITH (%s)", str);
821 * If it's in a nondefault tablespace, say so, but only if requested
827 tblspc = get_rel_tablespace(indexrelid);
828 if (OidIsValid(tblspc))
829 appendStringInfo(&buf, " TABLESPACE %s",
830 quote_identifier(get_tablespace_name(tblspc)));
834 * If it's a partial index, decompile and append the predicate
836 if (!heap_attisnull(ht_idx, Anum_pg_index_indpred))
843 /* Convert text string to node tree */
844 predDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
845 Anum_pg_index_indpred, &isnull);
847 predString = TextDatumGetCString(predDatum);
848 node = (Node *) stringToNode(predString);
852 str = deparse_expression_pretty(node, context, false, false,
854 appendStringInfo(&buf, " WHERE %s", str);
859 ReleaseSysCache(ht_idx);
860 ReleaseSysCache(ht_idxrel);
861 ReleaseSysCache(ht_am);
868 * pg_get_constraintdef
870 * Returns the definition for the constraint, ie, everything that needs to
871 * appear after "ALTER TABLE ... ADD CONSTRAINT <constraintname>".
874 pg_get_constraintdef(PG_FUNCTION_ARGS)
876 Oid constraintId = PG_GETARG_OID(0);
878 PG_RETURN_TEXT_P(string_to_text(pg_get_constraintdef_worker(constraintId,
883 pg_get_constraintdef_ext(PG_FUNCTION_ARGS)
885 Oid constraintId = PG_GETARG_OID(0);
886 bool pretty = PG_GETARG_BOOL(1);
889 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
890 PG_RETURN_TEXT_P(string_to_text(pg_get_constraintdef_worker(constraintId,
891 false, prettyFlags)));
894 /* Internal version that returns a palloc'd C string */
896 pg_get_constraintdef_string(Oid constraintId)
898 return pg_get_constraintdef_worker(constraintId, true, 0);
902 pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
906 Form_pg_constraint conForm;
909 tup = SearchSysCache(CONSTROID,
910 ObjectIdGetDatum(constraintId),
912 if (!HeapTupleIsValid(tup)) /* should not happen */
913 elog(ERROR, "cache lookup failed for constraint %u", constraintId);
914 conForm = (Form_pg_constraint) GETSTRUCT(tup);
916 initStringInfo(&buf);
918 if (fullCommand && OidIsValid(conForm->conrelid))
920 appendStringInfo(&buf, "ALTER TABLE ONLY %s ADD CONSTRAINT %s ",
921 generate_relation_name(conForm->conrelid, NIL),
922 quote_identifier(NameStr(conForm->conname)));
925 switch (conForm->contype)
927 case CONSTRAINT_FOREIGN:
933 /* Start off the constraint definition */
934 appendStringInfo(&buf, "FOREIGN KEY (");
936 /* Fetch and build referencing-column list */
937 val = SysCacheGetAttr(CONSTROID, tup,
938 Anum_pg_constraint_conkey, &isnull);
940 elog(ERROR, "null conkey for constraint %u",
943 decompile_column_index_array(val, conForm->conrelid, &buf);
945 /* add foreign relation name */
946 appendStringInfo(&buf, ") REFERENCES %s(",
947 generate_relation_name(conForm->confrelid,
950 /* Fetch and build referenced-column list */
951 val = SysCacheGetAttr(CONSTROID, tup,
952 Anum_pg_constraint_confkey, &isnull);
954 elog(ERROR, "null confkey for constraint %u",
957 decompile_column_index_array(val, conForm->confrelid, &buf);
959 appendStringInfo(&buf, ")");
962 switch (conForm->confmatchtype)
964 case FKCONSTR_MATCH_FULL:
965 string = " MATCH FULL";
967 case FKCONSTR_MATCH_PARTIAL:
968 string = " MATCH PARTIAL";
970 case FKCONSTR_MATCH_UNSPECIFIED:
974 elog(ERROR, "unrecognized confmatchtype: %d",
975 conForm->confmatchtype);
976 string = ""; /* keep compiler quiet */
979 appendStringInfoString(&buf, string);
981 /* Add ON UPDATE and ON DELETE clauses, if needed */
982 switch (conForm->confupdtype)
984 case FKCONSTR_ACTION_NOACTION:
985 string = NULL; /* suppress default */
987 case FKCONSTR_ACTION_RESTRICT:
990 case FKCONSTR_ACTION_CASCADE:
993 case FKCONSTR_ACTION_SETNULL:
996 case FKCONSTR_ACTION_SETDEFAULT:
997 string = "SET DEFAULT";
1000 elog(ERROR, "unrecognized confupdtype: %d",
1001 conForm->confupdtype);
1002 string = NULL; /* keep compiler quiet */
1006 appendStringInfo(&buf, " ON UPDATE %s", string);
1008 switch (conForm->confdeltype)
1010 case FKCONSTR_ACTION_NOACTION:
1011 string = NULL; /* suppress default */
1013 case FKCONSTR_ACTION_RESTRICT:
1014 string = "RESTRICT";
1016 case FKCONSTR_ACTION_CASCADE:
1019 case FKCONSTR_ACTION_SETNULL:
1020 string = "SET NULL";
1022 case FKCONSTR_ACTION_SETDEFAULT:
1023 string = "SET DEFAULT";
1026 elog(ERROR, "unrecognized confdeltype: %d",
1027 conForm->confdeltype);
1028 string = NULL; /* keep compiler quiet */
1032 appendStringInfo(&buf, " ON DELETE %s", string);
1034 if (conForm->condeferrable)
1035 appendStringInfo(&buf, " DEFERRABLE");
1036 if (conForm->condeferred)
1037 appendStringInfo(&buf, " INITIALLY DEFERRED");
1041 case CONSTRAINT_PRIMARY:
1042 case CONSTRAINT_UNIQUE:
1048 /* Start off the constraint definition */
1049 if (conForm->contype == CONSTRAINT_PRIMARY)
1050 appendStringInfo(&buf, "PRIMARY KEY (");
1052 appendStringInfo(&buf, "UNIQUE (");
1054 /* Fetch and build target column list */
1055 val = SysCacheGetAttr(CONSTROID, tup,
1056 Anum_pg_constraint_conkey, &isnull);
1058 elog(ERROR, "null conkey for constraint %u",
1061 decompile_column_index_array(val, conForm->conrelid, &buf);
1063 appendStringInfo(&buf, ")");
1065 indexId = get_constraint_index(constraintId);
1067 /* XXX why do we only print these bits if fullCommand? */
1068 if (fullCommand && OidIsValid(indexId))
1070 char *options = flatten_reloptions(indexId);
1075 appendStringInfo(&buf, " WITH (%s)", options);
1079 tblspc = get_rel_tablespace(indexId);
1080 if (OidIsValid(tblspc))
1081 appendStringInfo(&buf, " USING INDEX TABLESPACE %s",
1082 quote_identifier(get_tablespace_name(tblspc)));
1087 case CONSTRAINT_CHECK:
1096 /* Fetch constraint expression in parsetree form */
1097 val = SysCacheGetAttr(CONSTROID, tup,
1098 Anum_pg_constraint_conbin, &isnull);
1100 elog(ERROR, "null conbin for constraint %u",
1103 conbin = TextDatumGetCString(val);
1104 expr = stringToNode(conbin);
1106 /* Set up deparsing context for Var nodes in constraint */
1107 if (conForm->conrelid != InvalidOid)
1109 /* relation constraint */
1110 context = deparse_context_for(get_rel_name(conForm->conrelid),
1115 /* domain constraint --- can't have Vars */
1119 consrc = deparse_expression_pretty(expr, context, false, false,
1123 * Now emit the constraint definition. There are cases where
1124 * the constraint expression will be fully parenthesized and
1125 * we don't need the outer parens ... but there are other
1126 * cases where we do need 'em. Be conservative for now.
1128 * Note that simply checking for leading '(' and trailing ')'
1129 * would NOT be good enough, consider "(x > 0) AND (y > 0)".
1131 appendStringInfo(&buf, "CHECK (%s)", consrc);
1136 elog(ERROR, "invalid constraint type \"%c\"", conForm->contype);
1141 ReleaseSysCache(tup);
1148 * Convert an int16[] Datum into a comma-separated list of column names
1149 * for the indicated relation; append the list to buf.
1152 decompile_column_index_array(Datum column_index_array, Oid relId,
1159 /* Extract data from array of int16 */
1160 deconstruct_array(DatumGetArrayTypeP(column_index_array),
1161 INT2OID, 2, true, 's',
1162 &keys, NULL, &nKeys);
1164 for (j = 0; j < nKeys; j++)
1168 colName = get_relid_attribute_name(relId, DatumGetInt16(keys[j]));
1171 appendStringInfoString(buf, quote_identifier(colName));
1173 appendStringInfo(buf, ", %s", quote_identifier(colName));
1179 * get_expr - Decompile an expression tree
1181 * Input: an expression tree in nodeToString form, and a relation OID
1183 * Output: reverse-listed expression
1185 * Currently, the expression can only refer to a single relation, namely
1186 * the one specified by the second parameter. This is sufficient for
1187 * partial indexes, column default expressions, etc.
1191 pg_get_expr(PG_FUNCTION_ARGS)
1193 text *expr = PG_GETARG_TEXT_P(0);
1194 Oid relid = PG_GETARG_OID(1);
1197 /* Get the name for the relation */
1198 relname = get_rel_name(relid);
1199 if (relname == NULL)
1200 PG_RETURN_NULL(); /* should we raise an error? */
1202 PG_RETURN_TEXT_P(string_to_text(pg_get_expr_worker(expr, relid, relname, 0)));
1206 pg_get_expr_ext(PG_FUNCTION_ARGS)
1208 text *expr = PG_GETARG_TEXT_P(0);
1209 Oid relid = PG_GETARG_OID(1);
1210 bool pretty = PG_GETARG_BOOL(2);
1214 prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
1216 /* Get the name for the relation */
1217 relname = get_rel_name(relid);
1218 if (relname == NULL)
1219 PG_RETURN_NULL(); /* should we raise an error? */
1221 PG_RETURN_TEXT_P(string_to_text(pg_get_expr_worker(expr, relid, relname, prettyFlags)));
1225 pg_get_expr_worker(text *expr, Oid relid, char *relname, int prettyFlags)
1232 /* Convert input TEXT object to C string */
1233 exprstr = text_to_cstring(expr);
1235 /* Convert expression to node tree */
1236 node = (Node *) stringToNode(exprstr);
1239 context = deparse_context_for(relname, relid);
1240 str = deparse_expression_pretty(node, context, false, false,
1250 * get_userbyid - Get a user name by roleid and
1251 * fallback to 'unknown (OID=n)'
1255 pg_get_userbyid(PG_FUNCTION_ARGS)
1257 Oid roleid = PG_GETARG_OID(0);
1260 Form_pg_authid role_rec;
1263 * Allocate space for the result
1265 result = (Name) palloc(NAMEDATALEN);
1266 memset(NameStr(*result), 0, NAMEDATALEN);
1269 * Get the pg_authid entry and print the result
1271 roletup = SearchSysCache(AUTHOID,
1272 ObjectIdGetDatum(roleid),
1274 if (HeapTupleIsValid(roletup))
1276 role_rec = (Form_pg_authid) GETSTRUCT(roletup);
1277 StrNCpy(NameStr(*result), NameStr(role_rec->rolname), NAMEDATALEN);
1278 ReleaseSysCache(roletup);
1281 sprintf(NameStr(*result), "unknown (OID=%u)", roleid);
1283 PG_RETURN_NAME(result);
1288 * pg_get_serial_sequence
1289 * Get the name of the sequence used by a serial column,
1290 * formatted suitably for passing to setval, nextval or currval.
1291 * First parameter is not treated as double-quoted, second parameter
1292 * is --- see documentation for reason.
1295 pg_get_serial_sequence(PG_FUNCTION_ARGS)
1297 text *tablename = PG_GETARG_TEXT_P(0);
1298 text *columnname = PG_GETARG_TEXT_PP(1);
1303 Oid sequenceId = InvalidOid;
1309 /* Get the OID of the table */
1310 tablerv = makeRangeVarFromNameList(textToQualifiedNameList(tablename));
1311 tableOid = RangeVarGetRelid(tablerv, false);
1313 /* Get the number of the column */
1314 column = text_to_cstring(columnname);
1316 attnum = get_attnum(tableOid, column);
1317 if (attnum == InvalidAttrNumber)
1319 (errcode(ERRCODE_UNDEFINED_COLUMN),
1320 errmsg("column \"%s\" of relation \"%s\" does not exist",
1321 column, tablerv->relname)));
1323 /* Search the dependency table for the dependent sequence */
1324 depRel = heap_open(DependRelationId, AccessShareLock);
1326 ScanKeyInit(&key[0],
1327 Anum_pg_depend_refclassid,
1328 BTEqualStrategyNumber, F_OIDEQ,
1329 ObjectIdGetDatum(RelationRelationId));
1330 ScanKeyInit(&key[1],
1331 Anum_pg_depend_refobjid,
1332 BTEqualStrategyNumber, F_OIDEQ,
1333 ObjectIdGetDatum(tableOid));
1334 ScanKeyInit(&key[2],
1335 Anum_pg_depend_refobjsubid,
1336 BTEqualStrategyNumber, F_INT4EQ,
1337 Int32GetDatum(attnum));
1339 scan = systable_beginscan(depRel, DependReferenceIndexId, true,
1340 SnapshotNow, 3, key);
1342 while (HeapTupleIsValid(tup = systable_getnext(scan)))
1344 Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
1347 * We assume any auto dependency of a sequence on a column must be
1348 * what we are looking for. (We need the relkind test because indexes
1349 * can also have auto dependencies on columns.)
1351 if (deprec->classid == RelationRelationId &&
1352 deprec->objsubid == 0 &&
1353 deprec->deptype == DEPENDENCY_AUTO &&
1354 get_rel_relkind(deprec->objid) == RELKIND_SEQUENCE)
1356 sequenceId = deprec->objid;
1361 systable_endscan(scan);
1362 heap_close(depRel, AccessShareLock);
1364 if (OidIsValid(sequenceId))
1367 Form_pg_class classtuple;
1371 /* Get the sequence's pg_class entry */
1372 classtup = SearchSysCache(RELOID,
1373 ObjectIdGetDatum(sequenceId),
1375 if (!HeapTupleIsValid(classtup))
1376 elog(ERROR, "cache lookup failed for relation %u", sequenceId);
1377 classtuple = (Form_pg_class) GETSTRUCT(classtup);
1379 /* Get the namespace */
1380 nspname = get_namespace_name(classtuple->relnamespace);
1382 elog(ERROR, "cache lookup failed for namespace %u",
1383 classtuple->relnamespace);
1385 /* And construct the result string */
1386 result = quote_qualified_identifier(nspname,
1387 NameStr(classtuple->relname));
1389 ReleaseSysCache(classtup);
1391 PG_RETURN_TEXT_P(string_to_text(result));
1399 * pg_get_functiondef
1400 * Returns the complete "CREATE OR REPLACE FUNCTION ..." statement for
1401 * the specified function.
1404 pg_get_functiondef(PG_FUNCTION_ARGS)
1406 Oid funcid = PG_GETARG_OID(0);
1412 Form_pg_language lang;
1421 initStringInfo(&buf);
1423 /* Look up the function */
1424 proctup = SearchSysCache(PROCOID,
1425 ObjectIdGetDatum(funcid),
1427 if (!HeapTupleIsValid(proctup))
1428 elog(ERROR, "cache lookup failed for function %u", funcid);
1429 proc = (Form_pg_proc) GETSTRUCT(proctup);
1430 name = NameStr(proc->proname);
1434 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1435 errmsg("\"%s\" is an aggregate function", name)));
1437 /* Need its pg_language tuple for the language name */
1438 langtup = SearchSysCache(LANGOID,
1439 ObjectIdGetDatum(proc->prolang),
1441 if (!HeapTupleIsValid(langtup))
1442 elog(ERROR, "cache lookup failed for language %u", proc->prolang);
1443 lang = (Form_pg_language) GETSTRUCT(langtup);
1446 * We always qualify the function name, to ensure the right function
1449 nsp = get_namespace_name(proc->pronamespace);
1450 appendStringInfo(&buf, "CREATE OR REPLACE FUNCTION %s(",
1451 quote_qualified_identifier(nsp, name));
1452 (void) print_function_arguments(&buf, proctup, false, true);
1453 appendStringInfoString(&buf, ")\n RETURNS ");
1454 print_function_rettype(&buf, proctup);
1455 appendStringInfo(&buf, "\n LANGUAGE %s\n",
1456 quote_identifier(NameStr(lang->lanname)));
1458 /* Emit some miscellaneous options on one line */
1461 switch (proc->provolatile)
1463 case PROVOLATILE_IMMUTABLE:
1464 appendStringInfoString(&buf, " IMMUTABLE");
1466 case PROVOLATILE_STABLE:
1467 appendStringInfoString(&buf, " STABLE");
1469 case PROVOLATILE_VOLATILE:
1472 if (proc->proisstrict)
1473 appendStringInfoString(&buf, " STRICT");
1474 if (proc->prosecdef)
1475 appendStringInfoString(&buf, " SECURITY DEFINER");
1477 /* This code for the default cost and rows should match functioncmds.c */
1478 if (proc->prolang == INTERNALlanguageId ||
1479 proc->prolang == ClanguageId)
1483 if (proc->procost != procost)
1484 appendStringInfo(&buf, " COST %g", proc->procost);
1486 if (proc->prorows > 0 && proc->prorows != 1000)
1487 appendStringInfo(&buf, " ROWS %g", proc->prorows);
1489 if (oldlen != buf.len)
1490 appendStringInfoChar(&buf, '\n');
1492 /* Emit any proconfig options, one per line */
1493 tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_proconfig, &isnull);
1496 ArrayType *a = DatumGetArrayTypeP(tmp);
1499 Assert(ARR_ELEMTYPE(a) == TEXTOID);
1500 Assert(ARR_NDIM(a) == 1);
1501 Assert(ARR_LBOUND(a)[0] == 1);
1503 for (i = 1; i <= ARR_DIMS(a)[0]; i++)
1507 d = array_ref(a, 1, &i,
1508 -1 /* varlenarray */ ,
1509 -1 /* TEXT's typlen */ ,
1510 false /* TEXT's typbyval */ ,
1511 'i' /* TEXT's typalign */ ,
1515 char *configitem = TextDatumGetCString(d);
1518 pos = strchr(configitem, '=');
1523 appendStringInfo(&buf, " SET %s TO ",
1524 quote_identifier(configitem));
1527 * Some GUC variable names are 'LIST' type and hence must not
1530 if (pg_strcasecmp(configitem, "DateStyle") == 0
1531 || pg_strcasecmp(configitem, "search_path") == 0)
1532 appendStringInfoString(&buf, pos);
1534 simple_quote_literal(&buf, pos);
1535 appendStringInfoChar(&buf, '\n');
1540 /* And finally the function definition ... */
1541 appendStringInfoString(&buf, "AS ");
1543 tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_probin, &isnull);
1546 simple_quote_literal(&buf, TextDatumGetCString(tmp));
1547 appendStringInfoString(&buf, ", "); /* assume prosrc isn't null */
1550 tmp = SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_prosrc, &isnull);
1552 elog(ERROR, "null prosrc");
1553 prosrc = TextDatumGetCString(tmp);
1556 * We always use dollar quoting. Figure out a suitable delimiter.
1558 * Since the user is likely to be editing the function body string,
1559 * we shouldn't use a short delimiter that he might easily create a
1560 * conflict with. Hence prefer "$function$", but extend if needed.
1562 initStringInfo(&dq);
1563 appendStringInfoString(&dq, "$function");
1564 while (strstr(prosrc, dq.data) != NULL)
1565 appendStringInfoChar(&dq, 'x');
1566 appendStringInfoChar(&dq, '$');
1568 appendStringInfoString(&buf, dq.data);
1569 appendStringInfoString(&buf, prosrc);
1570 appendStringInfoString(&buf, dq.data);
1572 appendStringInfoString(&buf, "\n");
1574 ReleaseSysCache(langtup);
1575 ReleaseSysCache(proctup);
1577 PG_RETURN_TEXT_P(string_to_text(buf.data));
1581 * pg_get_function_arguments
1582 * Get a nicely-formatted list of arguments for a function.
1583 * This is everything that would go between the parentheses in
1587 pg_get_function_arguments(PG_FUNCTION_ARGS)
1589 Oid funcid = PG_GETARG_OID(0);
1593 initStringInfo(&buf);
1595 proctup = SearchSysCache(PROCOID,
1596 ObjectIdGetDatum(funcid),
1598 if (!HeapTupleIsValid(proctup))
1599 elog(ERROR, "cache lookup failed for function %u", funcid);
1601 (void) print_function_arguments(&buf, proctup, false, true);
1603 ReleaseSysCache(proctup);
1605 PG_RETURN_TEXT_P(string_to_text(buf.data));
1609 * pg_get_function_identity_arguments
1610 * Get a formatted list of arguments for a function.
1611 * This is everything that would go between the parentheses in
1612 * ALTER FUNCTION, etc. In particular, don't print defaults.
1615 pg_get_function_identity_arguments(PG_FUNCTION_ARGS)
1617 Oid funcid = PG_GETARG_OID(0);
1621 initStringInfo(&buf);
1623 proctup = SearchSysCache(PROCOID,
1624 ObjectIdGetDatum(funcid),
1626 if (!HeapTupleIsValid(proctup))
1627 elog(ERROR, "cache lookup failed for function %u", funcid);
1629 (void) print_function_arguments(&buf, proctup, false, false);
1631 ReleaseSysCache(proctup);
1633 PG_RETURN_TEXT_P(string_to_text(buf.data));
1637 * pg_get_function_result
1638 * Get a nicely-formatted version of the result type of a function.
1639 * This is what would appear after RETURNS in CREATE FUNCTION.
1642 pg_get_function_result(PG_FUNCTION_ARGS)
1644 Oid funcid = PG_GETARG_OID(0);
1648 initStringInfo(&buf);
1650 proctup = SearchSysCache(PROCOID,
1651 ObjectIdGetDatum(funcid),
1653 if (!HeapTupleIsValid(proctup))
1654 elog(ERROR, "cache lookup failed for function %u", funcid);
1656 print_function_rettype(&buf, proctup);
1658 ReleaseSysCache(proctup);
1660 PG_RETURN_TEXT_P(string_to_text(buf.data));
1664 * Guts of pg_get_function_result: append the function's return type
1665 * to the specified buffer.
1668 print_function_rettype(StringInfo buf, HeapTuple proctup)
1670 Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(proctup);
1672 StringInfoData rbuf;
1674 initStringInfo(&rbuf);
1676 if (proc->proretset)
1678 /* It might be a table function; try to print the arguments */
1679 appendStringInfoString(&rbuf, "TABLE(");
1680 ntabargs = print_function_arguments(&rbuf, proctup, true, false);
1682 appendStringInfoString(&rbuf, ")");
1684 resetStringInfo(&rbuf);
1689 /* Not a table function, so do the normal thing */
1690 if (proc->proretset)
1691 appendStringInfoString(&rbuf, "SETOF ");
1692 appendStringInfoString(&rbuf, format_type_be(proc->prorettype));
1695 appendStringInfoString(buf, rbuf.data);
1699 * Common code for pg_get_function_arguments and pg_get_function_result:
1700 * append the desired subset of arguments to buf. We print only TABLE
1701 * arguments when print_table_args is true, and all the others when it's false.
1702 * We print argument defaults only if print_defaults is true.
1703 * Function return value is the number of arguments printed.
1706 print_function_arguments(StringInfo buf, HeapTuple proctup,
1707 bool print_table_args, bool print_defaults)
1709 Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(proctup);
1717 ListCell *nextargdefault = NULL;
1720 numargs = get_func_arg_info(proctup,
1721 &argtypes, &argnames, &argmodes);
1723 nlackdefaults = numargs;
1724 if (print_defaults && proc->pronargdefaults > 0)
1726 Datum proargdefaults;
1729 proargdefaults = SysCacheGetAttr(PROCOID, proctup,
1730 Anum_pg_proc_proargdefaults,
1737 str = TextDatumGetCString(proargdefaults);
1738 argdefaults = (List *) stringToNode(str);
1739 Assert(IsA(argdefaults, List));
1741 nextargdefault = list_head(argdefaults);
1742 /* nlackdefaults counts only *input* arguments lacking defaults */
1743 nlackdefaults = proc->pronargs - list_length(argdefaults);
1749 for (i = 0; i < numargs; i++)
1751 Oid argtype = argtypes[i];
1752 char *argname = argnames ? argnames[i] : NULL;
1753 char argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
1754 const char *modename;
1763 case PROARGMODE_INOUT:
1764 modename = "INOUT ";
1767 case PROARGMODE_OUT:
1771 case PROARGMODE_VARIADIC:
1772 modename = "VARIADIC ";
1775 case PROARGMODE_TABLE:
1780 elog(ERROR, "invalid parameter mode '%c'", argmode);
1781 modename = NULL; /* keep compiler quiet */
1786 inputargno++; /* this is a 1-based counter */
1788 if (print_table_args != (argmode == PROARGMODE_TABLE))
1792 appendStringInfoString(buf, ", ");
1793 appendStringInfoString(buf, modename);
1794 if (argname && argname[0])
1795 appendStringInfo(buf, "%s ", argname);
1796 appendStringInfoString(buf, format_type_be(argtype));
1797 if (print_defaults && isinput && inputargno > nlackdefaults)
1801 Assert(nextargdefault != NULL);
1802 expr = (Node *) lfirst(nextargdefault);
1803 nextargdefault = lnext(nextargdefault);
1805 appendStringInfo(buf, " DEFAULT %s",
1806 deparse_expression(expr, NIL, false, false));
1816 * deparse_expression - General utility for deparsing expressions
1818 * calls deparse_expression_pretty with all prettyPrinting disabled
1821 deparse_expression(Node *expr, List *dpcontext,
1822 bool forceprefix, bool showimplicit)
1824 return deparse_expression_pretty(expr, dpcontext, forceprefix,
1825 showimplicit, 0, 0);
1829 * deparse_expression_pretty - General utility for deparsing expressions
1831 * expr is the node tree to be deparsed. It must be a transformed expression
1832 * tree (ie, not the raw output of gram.y).
1834 * dpcontext is a list of deparse_namespace nodes representing the context
1835 * for interpreting Vars in the node tree.
1837 * forceprefix is TRUE to force all Vars to be prefixed with their table names.
1839 * showimplicit is TRUE to force all implicit casts to be shown explicitly.
1841 * tries to pretty up the output according to prettyFlags and startIndent.
1843 * The result is a palloc'd string.
1847 deparse_expression_pretty(Node *expr, List *dpcontext,
1848 bool forceprefix, bool showimplicit,
1849 int prettyFlags, int startIndent)
1852 deparse_context context;
1854 initStringInfo(&buf);
1856 context.namespaces = dpcontext;
1857 context.varprefix = forceprefix;
1858 context.prettyFlags = prettyFlags;
1859 context.indentLevel = startIndent;
1861 get_rule_expr(expr, &context, showimplicit);
1867 * deparse_context_for - Build deparse context for a single relation
1869 * Given the reference name (alias) and OID of a relation, build deparsing
1870 * context for an expression referencing only that relation (as varno 1,
1871 * varlevelsup 0). This is sufficient for many uses of deparse_expression.
1875 deparse_context_for(const char *aliasname, Oid relid)
1877 deparse_namespace *dpns;
1880 dpns = (deparse_namespace *) palloc(sizeof(deparse_namespace));
1882 /* Build a minimal RTE for the rel */
1883 rte = makeNode(RangeTblEntry);
1884 rte->rtekind = RTE_RELATION;
1886 rte->eref = makeAlias(aliasname, NIL);
1888 rte->inFromCl = true;
1890 /* Build one-element rtable */
1891 dpns->rtable = list_make1(rte);
1893 dpns->subplans = NIL;
1894 dpns->outer_plan = dpns->inner_plan = NULL;
1896 /* Return a one-deep namespace stack */
1897 return list_make1(dpns);
1901 * deparse_context_for_plan - Build deparse context for a plan node
1903 * When deparsing an expression in a Plan tree, we might have to resolve
1904 * OUTER or INNER references. To do this, the caller must provide the
1905 * parent Plan node. In the normal case of a join plan node, OUTER and
1906 * INNER references can be resolved by drilling down into the left and
1907 * right child plans. A special case is that a nestloop inner indexscan
1908 * might have OUTER Vars, but the outer side of the join is not a child
1909 * plan node. To handle such cases the outer plan node must be passed
1910 * separately. (Pass NULL for outer_plan otherwise.)
1912 * Note: plan and outer_plan really ought to be declared as "Plan *", but
1913 * we use "Node *" to avoid having to include plannodes.h in builtins.h.
1915 * The plan's rangetable list must also be passed. We actually prefer to use
1916 * the rangetable to resolve simple Vars, but the plan inputs are necessary
1917 * for Vars that reference expressions computed in subplan target lists.
1919 * We also need the list of subplans associated with the Plan tree; this
1920 * is for resolving references to CTE subplans.
1923 deparse_context_for_plan(Node *plan, Node *outer_plan,
1924 List *rtable, List *subplans)
1926 deparse_namespace *dpns;
1928 dpns = (deparse_namespace *) palloc(sizeof(deparse_namespace));
1930 dpns->rtable = rtable;
1932 dpns->subplans = subplans;
1935 * Set up outer_plan and inner_plan from the Plan node (this includes
1936 * various special cases for particular Plan types).
1938 push_plan(dpns, (Plan *) plan);
1941 * If outer_plan is given, that overrides whatever we got from the plan.
1944 dpns->outer_plan = (Plan *) outer_plan;
1946 /* Return a one-deep namespace stack */
1947 return list_make1(dpns);
1951 * make_ruledef - reconstruct the CREATE RULE command
1952 * for a given pg_rewrite tuple
1956 make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
1966 List *actions = NIL;
1972 * Get the attribute values from the rules tuple
1974 fno = SPI_fnumber(rulettc, "rulename");
1975 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
1977 rulename = NameStr(*(DatumGetName(dat)));
1979 fno = SPI_fnumber(rulettc, "ev_type");
1980 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
1982 ev_type = DatumGetChar(dat);
1984 fno = SPI_fnumber(rulettc, "ev_class");
1985 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
1987 ev_class = DatumGetObjectId(dat);
1989 fno = SPI_fnumber(rulettc, "ev_attr");
1990 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
1992 ev_attr = DatumGetInt16(dat);
1994 fno = SPI_fnumber(rulettc, "is_instead");
1995 dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
1997 is_instead = DatumGetBool(dat);
1999 /* these could be nulls */
2000 fno = SPI_fnumber(rulettc, "ev_qual");
2001 ev_qual = SPI_getvalue(ruletup, rulettc, fno);
2003 fno = SPI_fnumber(rulettc, "ev_action");
2004 ev_action = SPI_getvalue(ruletup, rulettc, fno);
2005 if (ev_action != NULL)
2006 actions = (List *) stringToNode(ev_action);
2009 * Build the rules definition text
2011 appendStringInfo(buf, "CREATE RULE %s AS",
2012 quote_identifier(rulename));
2014 if (prettyFlags & PRETTYFLAG_INDENT)
2015 appendStringInfoString(buf, "\n ON ");
2017 appendStringInfoString(buf, " ON ");
2019 /* The event the rule is fired for */
2023 appendStringInfo(buf, "SELECT");
2027 appendStringInfo(buf, "UPDATE");
2031 appendStringInfo(buf, "INSERT");
2035 appendStringInfo(buf, "DELETE");
2040 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2041 errmsg("rule \"%s\" has unsupported event type %d",
2042 rulename, ev_type)));
2046 /* The relation the rule is fired on */
2047 appendStringInfo(buf, " TO %s", generate_relation_name(ev_class, NIL));
2049 appendStringInfo(buf, ".%s",
2050 quote_identifier(get_relid_attribute_name(ev_class,
2053 /* If the rule has an event qualification, add it */
2054 if (ev_qual == NULL)
2056 if (strlen(ev_qual) > 0 && strcmp(ev_qual, "<>") != 0)
2060 deparse_context context;
2061 deparse_namespace dpns;
2063 if (prettyFlags & PRETTYFLAG_INDENT)
2064 appendStringInfoString(buf, "\n ");
2065 appendStringInfo(buf, " WHERE ");
2067 qual = stringToNode(ev_qual);
2070 * We need to make a context for recognizing any Vars in the qual
2071 * (which can only be references to OLD and NEW). Use the rtable of
2072 * the first query in the action list for this purpose.
2074 query = (Query *) linitial(actions);
2077 * If the action is INSERT...SELECT, OLD/NEW have been pushed down
2078 * into the SELECT, and that's what we need to look at. (Ugly kluge
2079 * ... try to fix this when we redesign querytrees.)
2081 query = getInsertSelectQuery(query, NULL);
2083 /* Must acquire locks right away; see notes in get_query_def() */
2084 AcquireRewriteLocks(query);
2087 context.namespaces = list_make1(&dpns);
2088 context.varprefix = (list_length(query->rtable) != 1);
2089 context.prettyFlags = prettyFlags;
2090 context.indentLevel = PRETTYINDENT_STD;
2091 dpns.rtable = query->rtable;
2092 dpns.ctes = query->cteList;
2093 dpns.subplans = NIL;
2094 dpns.outer_plan = dpns.inner_plan = NULL;
2096 get_rule_expr(qual, &context, false);
2099 appendStringInfo(buf, " DO ");
2101 /* The INSTEAD keyword (if so) */
2103 appendStringInfo(buf, "INSTEAD ");
2105 /* Finally the rules actions */
2106 if (list_length(actions) > 1)
2111 appendStringInfo(buf, "(");
2112 foreach(action, actions)
2114 query = (Query *) lfirst(action);
2115 get_query_def(query, buf, NIL, NULL, prettyFlags, 0);
2117 appendStringInfo(buf, ";\n");
2119 appendStringInfo(buf, "; ");
2121 appendStringInfo(buf, ");");
2123 else if (list_length(actions) == 0)
2125 appendStringInfo(buf, "NOTHING;");
2131 query = (Query *) linitial(actions);
2132 get_query_def(query, buf, NIL, NULL, prettyFlags, 0);
2133 appendStringInfo(buf, ";");
2139 * make_viewdef - reconstruct the SELECT part of a
2144 make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
2154 List *actions = NIL;
2155 Relation ev_relation;
2160 * Get the attribute values from the rules tuple
2162 fno = SPI_fnumber(rulettc, "ev_type");
2163 ev_type = (char) SPI_getbinval(ruletup, rulettc, fno, &isnull);
2165 fno = SPI_fnumber(rulettc, "ev_class");
2166 ev_class = (Oid) SPI_getbinval(ruletup, rulettc, fno, &isnull);
2168 fno = SPI_fnumber(rulettc, "ev_attr");
2169 ev_attr = (int2) SPI_getbinval(ruletup, rulettc, fno, &isnull);
2171 fno = SPI_fnumber(rulettc, "is_instead");
2172 is_instead = (bool) SPI_getbinval(ruletup, rulettc, fno, &isnull);
2174 fno = SPI_fnumber(rulettc, "ev_qual");
2175 ev_qual = SPI_getvalue(ruletup, rulettc, fno);
2177 fno = SPI_fnumber(rulettc, "ev_action");
2178 ev_action = SPI_getvalue(ruletup, rulettc, fno);
2179 if (ev_action != NULL)
2180 actions = (List *) stringToNode(ev_action);
2182 if (list_length(actions) != 1)
2184 appendStringInfo(buf, "Not a view");
2188 query = (Query *) linitial(actions);
2190 if (ev_type != '1' || ev_attr >= 0 || !is_instead ||
2191 strcmp(ev_qual, "<>") != 0 || query->commandType != CMD_SELECT)
2193 appendStringInfo(buf, "Not a view");
2197 ev_relation = heap_open(ev_class, AccessShareLock);
2199 get_query_def(query, buf, NIL, RelationGetDescr(ev_relation),
2201 appendStringInfo(buf, ";");
2203 heap_close(ev_relation, AccessShareLock);
2208 * get_query_def - Parse back one query parsetree
2210 * If resultDesc is not NULL, then it is the output tuple descriptor for
2211 * the view represented by a SELECT query.
2215 get_query_def(Query *query, StringInfo buf, List *parentnamespace,
2216 TupleDesc resultDesc, int prettyFlags, int startIndent)
2218 deparse_context context;
2219 deparse_namespace dpns;
2222 * Before we begin to examine the query, acquire locks on referenced
2223 * relations, and fix up deleted columns in JOIN RTEs. This ensures
2224 * consistent results. Note we assume it's OK to scribble on the passed
2227 AcquireRewriteLocks(query);
2230 context.namespaces = lcons(&dpns, list_copy(parentnamespace));
2231 context.varprefix = (parentnamespace != NIL ||
2232 list_length(query->rtable) != 1);
2233 context.prettyFlags = prettyFlags;
2234 context.indentLevel = startIndent;
2236 dpns.rtable = query->rtable;
2237 dpns.ctes = query->cteList;
2238 dpns.subplans = NIL;
2239 dpns.outer_plan = dpns.inner_plan = NULL;
2241 switch (query->commandType)
2244 get_select_query_def(query, &context, resultDesc);
2248 get_update_query_def(query, &context);
2252 get_insert_query_def(query, &context);
2256 get_delete_query_def(query, &context);
2260 appendStringInfo(buf, "NOTHING");
2264 get_utility_query_def(query, &context);
2268 elog(ERROR, "unrecognized query command type: %d",
2269 query->commandType);
2275 * get_values_def - Parse back a VALUES list
2279 get_values_def(List *values_lists, deparse_context *context)
2281 StringInfo buf = context->buf;
2282 bool first_list = true;
2285 appendStringInfoString(buf, "VALUES ");
2287 foreach(vtl, values_lists)
2289 List *sublist = (List *) lfirst(vtl);
2290 bool first_col = true;
2296 appendStringInfoString(buf, ", ");
2298 appendStringInfoChar(buf, '(');
2299 foreach(lc, sublist)
2301 Node *col = (Node *) lfirst(lc);
2306 appendStringInfoChar(buf, ',');
2309 * Strip any top-level nodes representing indirection assignments,
2310 * then print the result.
2312 get_rule_expr(processIndirection(col, context, false),
2315 appendStringInfoChar(buf, ')');
2320 * get_with_clause - Parse back a WITH clause
2324 get_with_clause(Query *query, deparse_context *context)
2326 StringInfo buf = context->buf;
2330 if (query->cteList == NIL)
2333 if (PRETTY_INDENT(context))
2335 context->indentLevel += PRETTYINDENT_STD;
2336 appendStringInfoChar(buf, ' ');
2339 if (query->hasRecursive)
2340 sep = "WITH RECURSIVE ";
2343 foreach(l, query->cteList)
2345 CommonTableExpr *cte = (CommonTableExpr *) lfirst(l);
2347 appendStringInfoString(buf, sep);
2348 appendStringInfoString(buf, quote_identifier(cte->ctename));
2349 if (cte->aliascolnames)
2354 appendStringInfoChar(buf, '(');
2355 foreach(col, cte->aliascolnames)
2360 appendStringInfoString(buf, ", ");
2361 appendStringInfoString(buf,
2362 quote_identifier(strVal(lfirst(col))));
2364 appendStringInfoChar(buf, ')');
2366 appendStringInfoString(buf, " AS (");
2367 if (PRETTY_INDENT(context))
2368 appendContextKeyword(context, "", 0, 0, 0);
2369 get_query_def((Query *) cte->ctequery, buf, context->namespaces, NULL,
2370 context->prettyFlags, context->indentLevel);
2371 if (PRETTY_INDENT(context))
2372 appendContextKeyword(context, "", 0, 0, 0);
2373 appendStringInfoChar(buf, ')');
2377 if (PRETTY_INDENT(context))
2379 context->indentLevel -= PRETTYINDENT_STD;
2380 appendContextKeyword(context, "", 0, 0, 0);
2383 appendStringInfoChar(buf, ' ');
2387 * get_select_query_def - Parse back a SELECT parsetree
2391 get_select_query_def(Query *query, deparse_context *context,
2392 TupleDesc resultDesc)
2394 StringInfo buf = context->buf;
2399 /* Insert the WITH clause if given */
2400 get_with_clause(query, context);
2403 * If the Query node has a setOperations tree, then it's the top level of
2404 * a UNION/INTERSECT/EXCEPT query; only the WITH, ORDER BY and LIMIT
2405 * fields are interesting in the top query itself.
2407 if (query->setOperations)
2409 get_setop_query(query->setOperations, query, context, resultDesc);
2410 /* ORDER BY clauses must be simple in this case */
2415 get_basic_select_query(query, context, resultDesc);
2416 force_colno = false;
2419 /* Add the ORDER BY clause if given */
2420 if (query->sortClause != NIL)
2422 appendContextKeyword(context, " ORDER BY ",
2423 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2425 foreach(l, query->sortClause)
2427 SortGroupClause *srt = (SortGroupClause *) lfirst(l);
2430 TypeCacheEntry *typentry;
2432 appendStringInfoString(buf, sep);
2433 sortexpr = get_rule_sortgroupclause(srt, query->targetList,
2434 force_colno, context);
2435 sortcoltype = exprType(sortexpr);
2436 /* See whether operator is default < or > for datatype */
2437 typentry = lookup_type_cache(sortcoltype,
2438 TYPECACHE_LT_OPR | TYPECACHE_GT_OPR);
2439 if (srt->sortop == typentry->lt_opr)
2441 /* ASC is default, so emit nothing for it */
2442 if (srt->nulls_first)
2443 appendStringInfo(buf, " NULLS FIRST");
2445 else if (srt->sortop == typentry->gt_opr)
2447 appendStringInfo(buf, " DESC");
2448 /* DESC defaults to NULLS FIRST */
2449 if (!srt->nulls_first)
2450 appendStringInfo(buf, " NULLS LAST");
2454 appendStringInfo(buf, " USING %s",
2455 generate_operator_name(srt->sortop,
2458 /* be specific to eliminate ambiguity */
2459 if (srt->nulls_first)
2460 appendStringInfo(buf, " NULLS FIRST");
2462 appendStringInfo(buf, " NULLS LAST");
2468 /* Add the LIMIT clause if given */
2469 if (query->limitOffset != NULL)
2471 appendContextKeyword(context, " OFFSET ",
2472 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2473 get_rule_expr(query->limitOffset, context, false);
2475 if (query->limitCount != NULL)
2477 appendContextKeyword(context, " LIMIT ",
2478 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2479 if (IsA(query->limitCount, Const) &&
2480 ((Const *) query->limitCount)->constisnull)
2481 appendStringInfo(buf, "ALL");
2483 get_rule_expr(query->limitCount, context, false);
2486 /* Add FOR UPDATE/SHARE clauses if present */
2487 foreach(l, query->rowMarks)
2489 RowMarkClause *rc = (RowMarkClause *) lfirst(l);
2490 RangeTblEntry *rte = rt_fetch(rc->rti, query->rtable);
2493 appendContextKeyword(context, " FOR UPDATE",
2494 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2496 appendContextKeyword(context, " FOR SHARE",
2497 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2498 appendStringInfo(buf, " OF %s",
2499 quote_identifier(rte->eref->aliasname));
2501 appendStringInfo(buf, " NOWAIT");
2506 get_basic_select_query(Query *query, deparse_context *context,
2507 TupleDesc resultDesc)
2509 StringInfo buf = context->buf;
2513 if (PRETTY_INDENT(context))
2515 context->indentLevel += PRETTYINDENT_STD;
2516 appendStringInfoChar(buf, ' ');
2520 * If the query looks like SELECT * FROM (VALUES ...), then print just the
2521 * VALUES part. This reverses what transformValuesClause() did at parse
2522 * time. If the jointree contains just a single VALUES RTE, we assume
2523 * this case applies (without looking at the targetlist...)
2525 if (list_length(query->jointree->fromlist) == 1)
2527 RangeTblRef *rtr = (RangeTblRef *) linitial(query->jointree->fromlist);
2529 if (IsA(rtr, RangeTblRef))
2531 RangeTblEntry *rte = rt_fetch(rtr->rtindex, query->rtable);
2533 if (rte->rtekind == RTE_VALUES)
2535 get_values_def(rte->values_lists, context);
2542 * Build up the query string - first we say SELECT
2544 appendStringInfo(buf, "SELECT");
2546 /* Add the DISTINCT clause if given */
2547 if (query->distinctClause != NIL)
2549 if (query->hasDistinctOn)
2551 appendStringInfo(buf, " DISTINCT ON (");
2553 foreach(l, query->distinctClause)
2555 SortGroupClause *srt = (SortGroupClause *) lfirst(l);
2557 appendStringInfoString(buf, sep);
2558 get_rule_sortgroupclause(srt, query->targetList,
2562 appendStringInfo(buf, ")");
2565 appendStringInfo(buf, " DISTINCT");
2568 /* Then we tell what to select (the targetlist) */
2569 get_target_list(query->targetList, context, resultDesc);
2571 /* Add the FROM clause if needed */
2572 get_from_clause(query, " FROM ", context);
2574 /* Add the WHERE clause if given */
2575 if (query->jointree->quals != NULL)
2577 appendContextKeyword(context, " WHERE ",
2578 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2579 get_rule_expr(query->jointree->quals, context, false);
2582 /* Add the GROUP BY clause if given */
2583 if (query->groupClause != NULL)
2585 appendContextKeyword(context, " GROUP BY ",
2586 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2588 foreach(l, query->groupClause)
2590 SortGroupClause *grp = (SortGroupClause *) lfirst(l);
2592 appendStringInfoString(buf, sep);
2593 get_rule_sortgroupclause(grp, query->targetList,
2599 /* Add the HAVING clause if given */
2600 if (query->havingQual != NULL)
2602 appendContextKeyword(context, " HAVING ",
2603 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2604 get_rule_expr(query->havingQual, context, false);
2609 * get_target_list - Parse back a SELECT target list
2611 * This is also used for RETURNING lists in INSERT/UPDATE/DELETE.
2615 get_target_list(List *targetList, deparse_context *context,
2616 TupleDesc resultDesc)
2618 StringInfo buf = context->buf;
2625 foreach(l, targetList)
2627 TargetEntry *tle = (TargetEntry *) lfirst(l);
2632 continue; /* ignore junk entries */
2634 appendStringInfoString(buf, sep);
2639 * We special-case Var nodes rather than using get_rule_expr. This is
2640 * needed because get_rule_expr will display a whole-row Var as
2641 * "foo.*", which is the preferred notation in most contexts, but at
2642 * the top level of a SELECT list it's not right (the parser will
2643 * expand that notation into multiple columns, yielding behavior
2644 * different from a whole-row Var). We want just "foo", instead.
2646 if (tle->expr && IsA(tle->expr, Var))
2648 attname = get_variable((Var *) tle->expr, 0, false, context);
2652 get_rule_expr((Node *) tle->expr, context, true);
2653 /* We'll show the AS name unless it's this: */
2654 attname = "?column?";
2658 * Figure out what the result column should be called. In the context
2659 * of a view, use the view's tuple descriptor (so as to pick up the
2660 * effects of any column RENAME that's been done on the view).
2661 * Otherwise, just use what we can find in the TLE.
2663 if (resultDesc && colno <= resultDesc->natts)
2664 colname = NameStr(resultDesc->attrs[colno - 1]->attname);
2666 colname = tle->resname;
2668 /* Show AS unless the column's name is correct as-is */
2669 if (colname) /* resname could be NULL */
2671 if (attname == NULL || strcmp(attname, colname) != 0)
2672 appendStringInfo(buf, " AS %s", quote_identifier(colname));
2678 get_setop_query(Node *setOp, Query *query, deparse_context *context,
2679 TupleDesc resultDesc)
2681 StringInfo buf = context->buf;
2684 if (IsA(setOp, RangeTblRef))
2686 RangeTblRef *rtr = (RangeTblRef *) setOp;
2687 RangeTblEntry *rte = rt_fetch(rtr->rtindex, query->rtable);
2688 Query *subquery = rte->subquery;
2690 Assert(subquery != NULL);
2691 Assert(subquery->setOperations == NULL);
2692 /* Need parens if WITH, ORDER BY, FOR UPDATE, or LIMIT; see gram.y */
2693 need_paren = (subquery->cteList ||
2694 subquery->sortClause ||
2695 subquery->rowMarks ||
2696 subquery->limitOffset ||
2697 subquery->limitCount);
2699 appendStringInfoChar(buf, '(');
2700 get_query_def(subquery, buf, context->namespaces, resultDesc,
2701 context->prettyFlags, context->indentLevel);
2703 appendStringInfoChar(buf, ')');
2705 else if (IsA(setOp, SetOperationStmt))
2707 SetOperationStmt *op = (SetOperationStmt *) setOp;
2709 if (PRETTY_INDENT(context))
2711 context->indentLevel += PRETTYINDENT_STD;
2712 appendStringInfoSpaces(buf, PRETTYINDENT_STD);
2716 * We force parens whenever nesting two SetOperationStmts. There are
2717 * some cases in which parens are needed around a leaf query too, but
2718 * those are more easily handled at the next level down (see code
2721 need_paren = !IsA(op->larg, RangeTblRef);
2724 appendStringInfoChar(buf, '(');
2725 get_setop_query(op->larg, query, context, resultDesc);
2727 appendStringInfoChar(buf, ')');
2729 if (!PRETTY_INDENT(context))
2730 appendStringInfoChar(buf, ' ');
2734 appendContextKeyword(context, "UNION ",
2735 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2737 case SETOP_INTERSECT:
2738 appendContextKeyword(context, "INTERSECT ",
2739 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2742 appendContextKeyword(context, "EXCEPT ",
2743 -PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
2746 elog(ERROR, "unrecognized set op: %d",
2750 appendStringInfo(buf, "ALL ");
2752 if (PRETTY_INDENT(context))
2753 appendContextKeyword(context, "", 0, 0, 0);
2755 need_paren = !IsA(op->rarg, RangeTblRef);
2758 appendStringInfoChar(buf, '(');
2759 get_setop_query(op->rarg, query, context, resultDesc);
2761 appendStringInfoChar(buf, ')');
2763 if (PRETTY_INDENT(context))
2764 context->indentLevel -= PRETTYINDENT_STD;
2768 elog(ERROR, "unrecognized node type: %d",
2769 (int) nodeTag(setOp));
2774 * Display a sort/group clause.
2776 * Also returns the expression tree, so caller need not find it again.
2779 get_rule_sortgroupclause(SortGroupClause *srt, List *tlist, bool force_colno,
2780 deparse_context *context)
2782 StringInfo buf = context->buf;
2786 tle = get_sortgroupclause_tle(srt, tlist);
2787 expr = (Node *) tle->expr;
2790 * Use column-number form if requested by caller. Otherwise, if
2791 * expression is a constant, force it to be dumped with an explicit
2792 * cast as decoration --- this is because a simple integer constant
2793 * is ambiguous (and will be misinterpreted by findTargetlistEntry())
2794 * if we dump it without any decoration. Otherwise, just dump the
2795 * expression normally.
2799 Assert(!tle->resjunk);
2800 appendStringInfo(buf, "%d", tle->resno);
2802 else if (expr && IsA(expr, Const))
2803 get_const_expr((Const *) expr, context, 1);
2805 get_rule_expr(expr, context, true);
2811 * get_insert_query_def - Parse back an INSERT parsetree
2815 get_insert_query_def(Query *query, deparse_context *context)
2817 StringInfo buf = context->buf;
2818 RangeTblEntry *select_rte = NULL;
2819 RangeTblEntry *values_rte = NULL;
2822 ListCell *values_cell;
2824 List *strippedexprs;
2827 * If it's an INSERT ... SELECT or VALUES (...), (...), ... there will be
2828 * a single RTE for the SELECT or VALUES.
2830 foreach(l, query->rtable)
2832 rte = (RangeTblEntry *) lfirst(l);
2834 if (rte->rtekind == RTE_SUBQUERY)
2837 elog(ERROR, "too many subquery RTEs in INSERT");
2841 if (rte->rtekind == RTE_VALUES)
2844 elog(ERROR, "too many values RTEs in INSERT");
2848 if (select_rte && values_rte)
2849 elog(ERROR, "both subquery and values RTEs in INSERT");
2852 * Start the query with INSERT INTO relname
2854 rte = rt_fetch(query->resultRelation, query->rtable);
2855 Assert(rte->rtekind == RTE_RELATION);
2857 if (PRETTY_INDENT(context))
2859 context->indentLevel += PRETTYINDENT_STD;
2860 appendStringInfoChar(buf, ' ');
2862 appendStringInfo(buf, "INSERT INTO %s (",
2863 generate_relation_name(rte->relid, NIL));
2866 * Add the insert-column-names list. To handle indirection properly, we
2867 * need to look for indirection nodes in the top targetlist (if it's
2868 * INSERT ... SELECT or INSERT ... single VALUES), or in the first
2869 * expression list of the VALUES RTE (if it's INSERT ... multi VALUES). We
2870 * assume that all the expression lists will have similar indirection in
2874 values_cell = list_head((List *) linitial(values_rte->values_lists));
2877 strippedexprs = NIL;
2879 foreach(l, query->targetList)
2881 TargetEntry *tle = (TargetEntry *) lfirst(l);
2884 continue; /* ignore junk entries */
2886 appendStringInfoString(buf, sep);
2890 * Put out name of target column; look in the catalogs, not at
2891 * tle->resname, since resname will fail to track RENAME.
2893 appendStringInfoString(buf,
2894 quote_identifier(get_relid_attribute_name(rte->relid,
2898 * Print any indirection needed (subfields or subscripts), and strip
2899 * off the top-level nodes representing the indirection assignments.
2903 /* we discard the stripped expression in this case */
2904 processIndirection((Node *) lfirst(values_cell), context, true);
2905 values_cell = lnext(values_cell);
2909 /* we keep a list of the stripped expressions in this case */
2910 strippedexprs = lappend(strippedexprs,
2911 processIndirection((Node *) tle->expr,
2915 appendStringInfo(buf, ") ");
2919 /* Add the SELECT */
2920 get_query_def(select_rte->subquery, buf, NIL, NULL,
2921 context->prettyFlags, context->indentLevel);
2923 else if (values_rte)
2925 /* A WITH clause is possible here */
2926 get_with_clause(query, context);
2927 /* Add the multi-VALUES expression lists */
2928 get_values_def(values_rte->values_lists, context);
2932 /* A WITH clause is possible here */
2933 get_with_clause(query, context);
2934 /* Add the single-VALUES expression list */
2935 appendContextKeyword(context, "VALUES (",
2936 -PRETTYINDENT_STD, PRETTYINDENT_STD, 2);
2937 get_rule_expr((Node *) strippedexprs, context, false);
2938 appendStringInfoChar(buf, ')');
2941 /* Add RETURNING if present */
2942 if (query->returningList)
2944 appendContextKeyword(context, " RETURNING",
2945 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
2946 get_target_list(query->returningList, context, NULL);
2952 * get_update_query_def - Parse back an UPDATE parsetree
2956 get_update_query_def(Query *query, deparse_context *context)
2958 StringInfo buf = context->buf;
2964 * Start the query with UPDATE relname SET
2966 rte = rt_fetch(query->resultRelation, query->rtable);
2967 Assert(rte->rtekind == RTE_RELATION);
2968 if (PRETTY_INDENT(context))
2970 appendStringInfoChar(buf, ' ');
2971 context->indentLevel += PRETTYINDENT_STD;
2973 appendStringInfo(buf, "UPDATE %s%s",
2975 generate_relation_name(rte->relid, NIL));
2976 if (rte->alias != NULL)
2977 appendStringInfo(buf, " %s",
2978 quote_identifier(rte->alias->aliasname));
2979 appendStringInfoString(buf, " SET ");
2981 /* Add the comma separated list of 'attname = value' */
2983 foreach(l, query->targetList)
2985 TargetEntry *tle = (TargetEntry *) lfirst(l);
2989 continue; /* ignore junk entries */
2991 appendStringInfoString(buf, sep);
2995 * Put out name of target column; look in the catalogs, not at
2996 * tle->resname, since resname will fail to track RENAME.
2998 appendStringInfoString(buf,
2999 quote_identifier(get_relid_attribute_name(rte->relid,
3003 * Print any indirection needed (subfields or subscripts), and strip
3004 * off the top-level nodes representing the indirection assignments.
3006 expr = processIndirection((Node *) tle->expr, context, true);
3008 appendStringInfo(buf, " = ");
3010 get_rule_expr(expr, context, false);
3013 /* Add the FROM clause if needed */
3014 get_from_clause(query, " FROM ", context);
3016 /* Add a WHERE clause if given */
3017 if (query->jointree->quals != NULL)
3019 appendContextKeyword(context, " WHERE ",
3020 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
3021 get_rule_expr(query->jointree->quals, context, false);
3024 /* Add RETURNING if present */
3025 if (query->returningList)
3027 appendContextKeyword(context, " RETURNING",
3028 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
3029 get_target_list(query->returningList, context, NULL);
3035 * get_delete_query_def - Parse back a DELETE parsetree
3039 get_delete_query_def(Query *query, deparse_context *context)
3041 StringInfo buf = context->buf;
3045 * Start the query with DELETE FROM relname
3047 rte = rt_fetch(query->resultRelation, query->rtable);
3048 Assert(rte->rtekind == RTE_RELATION);
3049 if (PRETTY_INDENT(context))
3051 appendStringInfoChar(buf, ' ');
3052 context->indentLevel += PRETTYINDENT_STD;
3054 appendStringInfo(buf, "DELETE FROM %s%s",
3056 generate_relation_name(rte->relid, NIL));
3057 if (rte->alias != NULL)
3058 appendStringInfo(buf, " %s",
3059 quote_identifier(rte->alias->aliasname));
3061 /* Add the USING clause if given */
3062 get_from_clause(query, " USING ", context);
3064 /* Add a WHERE clause if given */
3065 if (query->jointree->quals != NULL)
3067 appendContextKeyword(context, " WHERE ",
3068 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
3069 get_rule_expr(query->jointree->quals, context, false);
3072 /* Add RETURNING if present */
3073 if (query->returningList)
3075 appendContextKeyword(context, " RETURNING",
3076 -PRETTYINDENT_STD, PRETTYINDENT_STD, 1);
3077 get_target_list(query->returningList, context, NULL);
3083 * get_utility_query_def - Parse back a UTILITY parsetree
3087 get_utility_query_def(Query *query, deparse_context *context)
3089 StringInfo buf = context->buf;
3091 if (query->utilityStmt && IsA(query->utilityStmt, NotifyStmt))
3093 NotifyStmt *stmt = (NotifyStmt *) query->utilityStmt;
3095 appendContextKeyword(context, "",
3096 0, PRETTYINDENT_STD, 1);
3097 appendStringInfo(buf, "NOTIFY %s",
3098 quote_identifier(stmt->conditionname));
3102 /* Currently only NOTIFY utility commands can appear in rules */
3103 elog(ERROR, "unexpected utility statement type");
3109 * push_plan: set up deparse_namespace to recurse into the tlist of a subplan
3111 * When expanding an OUTER or INNER reference, we must push new outer/inner
3112 * subplans in case the referenced expression itself uses OUTER/INNER. We
3113 * modify the top stack entry in-place to avoid affecting levelsup issues
3114 * (although in a Plan tree there really shouldn't be any).
3116 * Caller must save and restore outer_plan and inner_plan around this.
3118 * We also use this to initialize the fields during deparse_context_for_plan.
3121 push_plan(deparse_namespace *dpns, Plan *subplan)
3124 * We special-case Append to pretend that the first child plan is the
3125 * OUTER referent; otherwise normal.
3127 if (IsA(subplan, Append))
3128 dpns->outer_plan = (Plan *) linitial(((Append *) subplan)->appendplans);
3130 dpns->outer_plan = outerPlan(subplan);
3133 * For a SubqueryScan, pretend the subplan is INNER referent. (We don't
3134 * use OUTER because that could someday conflict with the normal meaning.)
3135 * Likewise, for a CteScan, pretend the subquery's plan is INNER referent.
3137 if (IsA(subplan, SubqueryScan))
3138 dpns->inner_plan = ((SubqueryScan *) subplan)->subplan;
3139 else if (IsA(subplan, CteScan))
3141 int ctePlanId = ((CteScan *) subplan)->ctePlanId;
3143 if (ctePlanId > 0 && ctePlanId <= list_length(dpns->subplans))
3144 dpns->inner_plan = list_nth(dpns->subplans, ctePlanId - 1);
3146 dpns->inner_plan = NULL;
3149 dpns->inner_plan = innerPlan(subplan);
3154 * Display a Var appropriately.
3156 * In some cases (currently only when recursing into an unnamed join)
3157 * the Var's varlevelsup has to be interpreted with respect to a context
3158 * above the current one; levelsup indicates the offset.
3160 * If showstar is TRUE, whole-row Vars are displayed as "foo.*";
3161 * if FALSE, merely as "foo".
3163 * Returns the attname of the Var, or NULL if not determinable.
3166 get_variable(Var *var, int levelsup, bool showstar, deparse_context *context)
3168 StringInfo buf = context->buf;
3172 deparse_namespace *dpns;
3177 /* Find appropriate nesting depth */
3178 netlevelsup = var->varlevelsup + levelsup;
3179 if (netlevelsup >= list_length(context->namespaces))
3180 elog(ERROR, "bogus varlevelsup: %d offset %d",
3181 var->varlevelsup, levelsup);
3182 dpns = (deparse_namespace *) list_nth(context->namespaces,
3186 * Try to find the relevant RTE in this rtable. In a plan tree, it's
3187 * likely that varno is OUTER or INNER, in which case we must dig down
3188 * into the subplans.
3190 if (var->varno >= 1 && var->varno <= list_length(dpns->rtable))
3192 rte = rt_fetch(var->varno, dpns->rtable);
3193 attnum = var->varattno;
3195 else if (var->varno == OUTER && dpns->outer_plan)
3201 tle = get_tle_by_resno(dpns->outer_plan->targetlist, var->varattno);
3203 elog(ERROR, "bogus varattno for OUTER var: %d", var->varattno);
3205 Assert(netlevelsup == 0);
3206 save_outer = dpns->outer_plan;
3207 save_inner = dpns->inner_plan;
3208 push_plan(dpns, dpns->outer_plan);
3211 * Force parentheses because our caller probably assumed a Var is a
3212 * simple expression.
3214 if (!IsA(tle->expr, Var))
3215 appendStringInfoChar(buf, '(');
3216 get_rule_expr((Node *) tle->expr, context, true);
3217 if (!IsA(tle->expr, Var))
3218 appendStringInfoChar(buf, ')');
3220 dpns->outer_plan = save_outer;
3221 dpns->inner_plan = save_inner;
3224 else if (var->varno == INNER && dpns->inner_plan)
3230 tle = get_tle_by_resno(dpns->inner_plan->targetlist, var->varattno);
3232 elog(ERROR, "bogus varattno for INNER var: %d", var->varattno);
3234 Assert(netlevelsup == 0);
3235 save_outer = dpns->outer_plan;
3236 save_inner = dpns->inner_plan;
3237 push_plan(dpns, dpns->inner_plan);
3240 * Force parentheses because our caller probably assumed a Var is a
3241 * simple expression.
3243 if (!IsA(tle->expr, Var))
3244 appendStringInfoChar(buf, '(');
3245 get_rule_expr((Node *) tle->expr, context, true);
3246 if (!IsA(tle->expr, Var))
3247 appendStringInfoChar(buf, ')');
3249 dpns->outer_plan = save_outer;
3250 dpns->inner_plan = save_inner;
3255 elog(ERROR, "bogus varno: %d", var->varno);
3256 return NULL; /* keep compiler quiet */
3259 /* Identify names to use */
3260 schemaname = NULL; /* default assumptions */
3261 refname = rte->eref->aliasname;
3263 /* Exceptions occur only if the RTE is alias-less */
3264 if (rte->alias == NULL)
3266 if (rte->rtekind == RTE_RELATION)
3269 * It's possible that use of the bare refname would find another
3270 * more-closely-nested RTE, or be ambiguous, in which case we need
3271 * to specify the schemaname to avoid these errors.
3273 if (find_rte_by_refname(rte->eref->aliasname, context) != rte)
3274 schemaname = get_namespace_name(get_rel_namespace(rte->relid));
3276 else if (rte->rtekind == RTE_JOIN)
3279 * If it's an unnamed join, look at the expansion of the alias
3280 * variable. If it's a simple reference to one of the input vars
3281 * then recursively print the name of that var, instead. (This
3282 * allows correct decompiling of cases where there are identically
3283 * named columns on both sides of the join.) When it's not a
3284 * simple reference, we have to just print the unqualified
3285 * variable name (this can only happen with columns that were
3286 * merged by USING or NATURAL clauses).
3288 * This wouldn't work in decompiling plan trees, because we don't
3289 * store joinaliasvars lists after planning; but a plan tree
3290 * should never contain a join alias variable.
3292 if (rte->joinaliasvars == NIL)
3293 elog(ERROR, "cannot decompile join alias var in plan tree");
3298 aliasvar = (Var *) list_nth(rte->joinaliasvars, attnum - 1);
3299 if (IsA(aliasvar, Var))
3301 return get_variable(aliasvar, var->varlevelsup + levelsup,
3305 /* Unnamed join has neither schemaname nor refname */
3310 if (attnum == InvalidAttrNumber)
3313 attname = get_rte_attribute_name(rte, attnum);
3315 if (refname && (context->varprefix || attname == NULL))
3318 appendStringInfo(buf, "%s.",
3319 quote_identifier(schemaname));
3321 if (strcmp(refname, "*NEW*") == 0)
3322 appendStringInfoString(buf, "new");
3323 else if (strcmp(refname, "*OLD*") == 0)
3324 appendStringInfoString(buf, "old");
3326 appendStringInfoString(buf, quote_identifier(refname));
3328 if (attname || showstar)
3329 appendStringInfoChar(buf, '.');
3332 appendStringInfoString(buf, quote_identifier(attname));
3334 appendStringInfoChar(buf, '*');
3341 * Get the name of a field of an expression of composite type.
3343 * This is fairly straightforward except for the case of a Var of type RECORD.
3344 * Since no actual table or view column is allowed to have type RECORD, such
3345 * a Var must refer to a JOIN or FUNCTION RTE or to a subquery output. We
3346 * drill down to find the ultimate defining expression and attempt to infer
3347 * the field name from it. We ereport if we can't determine the name.
3349 * levelsup is an extra offset to interpret the Var's varlevelsup correctly.
3352 get_name_for_var_field(Var *var, int fieldno,
3353 int levelsup, deparse_context *context)
3358 deparse_namespace *dpns;
3359 TupleDesc tupleDesc;
3363 * If it's a RowExpr that was expanded from a whole-row Var, use the
3364 * column names attached to it.
3366 if (IsA(var, RowExpr))
3368 RowExpr *r = (RowExpr *) var;
3370 if (fieldno > 0 && fieldno <= list_length(r->colnames))
3371 return strVal(list_nth(r->colnames, fieldno - 1));
3375 * If it's a Var of type RECORD, we have to find what the Var refers to;
3376 * if not, we can use get_expr_result_type. If that fails, we try
3377 * lookup_rowtype_tupdesc, which will probably fail too, but will ereport
3378 * an acceptable message.
3380 if (!IsA(var, Var) ||
3381 var->vartype != RECORDOID)
3383 if (get_expr_result_type((Node *) var, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
3384 tupleDesc = lookup_rowtype_tupdesc_copy(exprType((Node *) var),
3385 exprTypmod((Node *) var));
3387 /* Got the tupdesc, so we can extract the field name */
3388 Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
3389 return NameStr(tupleDesc->attrs[fieldno - 1]->attname);
3392 /* Find appropriate nesting depth */
3393 netlevelsup = var->varlevelsup + levelsup;
3394 if (netlevelsup >= list_length(context->namespaces))
3395 elog(ERROR, "bogus varlevelsup: %d offset %d",
3396 var->varlevelsup, levelsup);
3397 dpns = (deparse_namespace *) list_nth(context->namespaces,
3401 * Try to find the relevant RTE in this rtable. In a plan tree, it's
3402 * likely that varno is OUTER or INNER, in which case we must dig down
3403 * into the subplans.
3405 if (var->varno >= 1 && var->varno <= list_length(dpns->rtable))
3407 rte = rt_fetch(var->varno, dpns->rtable);
3408 attnum = var->varattno;
3410 else if (var->varno == OUTER && dpns->outer_plan)
3417 tle = get_tle_by_resno(dpns->outer_plan->targetlist, var->varattno);
3419 elog(ERROR, "bogus varattno for OUTER var: %d", var->varattno);
3421 Assert(netlevelsup == 0);
3422 save_outer = dpns->outer_plan;
3423 save_inner = dpns->inner_plan;
3424 push_plan(dpns, dpns->outer_plan);
3426 result = get_name_for_var_field((Var *) tle->expr, fieldno,
3429 dpns->outer_plan = save_outer;
3430 dpns->inner_plan = save_inner;
3433 else if (var->varno == INNER && dpns->inner_plan)
3440 tle = get_tle_by_resno(dpns->inner_plan->targetlist, var->varattno);
3442 elog(ERROR, "bogus varattno for INNER var: %d", var->varattno);
3444 Assert(netlevelsup == 0);
3445 save_outer = dpns->outer_plan;
3446 save_inner = dpns->inner_plan;
3447 push_plan(dpns, dpns->inner_plan);
3449 result = get_name_for_var_field((Var *) tle->expr, fieldno,
3452 dpns->outer_plan = save_outer;
3453 dpns->inner_plan = save_inner;
3458 elog(ERROR, "bogus varno: %d", var->varno);
3459 return NULL; /* keep compiler quiet */
3462 if (attnum == InvalidAttrNumber)
3464 /* Var is whole-row reference to RTE, so select the right field */
3465 return get_rte_attribute_name(rte, fieldno);
3469 * This part has essentially the same logic as the parser's
3470 * expandRecordVariable() function, but we are dealing with a different
3471 * representation of the input context, and we only need one field name
3472 * not a TupleDesc. Also, we need special cases for finding subquery
3473 * and CTE subplans when deparsing Plan trees.
3475 expr = (Node *) var; /* default if we can't drill down */
3477 switch (rte->rtekind)
3484 * This case should not occur: a column of a table or values list
3485 * shouldn't have type RECORD. Fall through and fail (most
3486 * likely) at the bottom.
3490 /* Subselect-in-FROM: examine sub-select's output expr */
3494 TargetEntry *ste = get_tle_by_resno(rte->subquery->targetList,
3497 if (ste == NULL || ste->resjunk)
3498 elog(ERROR, "subquery %s does not have attribute %d",
3499 rte->eref->aliasname, attnum);
3500 expr = (Node *) ste->expr;
3504 * Recurse into the sub-select to see what its Var
3505 * refers to. We have to build an additional level of
3506 * namespace to keep in step with varlevelsup in the
3509 deparse_namespace mydpns;
3512 mydpns.rtable = rte->subquery->rtable;
3513 mydpns.ctes = rte->subquery->cteList;
3514 mydpns.subplans = NIL;
3515 mydpns.outer_plan = mydpns.inner_plan = NULL;
3517 context->namespaces = lcons(&mydpns,
3518 context->namespaces);
3520 result = get_name_for_var_field((Var *) expr, fieldno,
3523 context->namespaces =
3524 list_delete_first(context->namespaces);
3528 /* else fall through to inspect the expression */
3533 * We're deparsing a Plan tree so we don't have complete
3534 * RTE entries (in particular, rte->subquery is NULL).
3535 * But the only place we'd see a Var directly referencing
3536 * a SUBQUERY RTE is in a SubqueryScan plan node, and we
3537 * can look into the child plan's tlist instead.
3544 if (!dpns->inner_plan)
3545 elog(ERROR, "failed to find plan for subquery %s",
3546 rte->eref->aliasname);
3547 tle = get_tle_by_resno(dpns->inner_plan->targetlist,
3550 elog(ERROR, "bogus varattno for subquery var: %d",
3552 Assert(netlevelsup == 0);
3553 save_outer = dpns->outer_plan;
3554 save_inner = dpns->inner_plan;
3555 push_plan(dpns, dpns->inner_plan);
3557 result = get_name_for_var_field((Var *) tle->expr, fieldno,
3560 dpns->outer_plan = save_outer;
3561 dpns->inner_plan = save_inner;
3567 /* Join RTE --- recursively inspect the alias variable */
3568 if (rte->joinaliasvars == NIL)
3569 elog(ERROR, "cannot decompile join alias var in plan tree");
3570 Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars));
3571 expr = (Node *) list_nth(rte->joinaliasvars, attnum - 1);
3573 return get_name_for_var_field((Var *) expr, fieldno,
3574 var->varlevelsup + levelsup,
3576 /* else fall through to inspect the expression */
3581 * We couldn't get here unless a function is declared with one of
3582 * its result columns as RECORD, which is not allowed.
3586 /* CTE reference: examine subquery's output expr */
3588 CommonTableExpr *cte = NULL;
3593 * Try to find the referenced CTE using the namespace stack.
3595 ctelevelsup = rte->ctelevelsup + netlevelsup;
3596 if (ctelevelsup >= list_length(context->namespaces))
3600 deparse_namespace *ctedpns;
3602 ctedpns = (deparse_namespace *)
3603 list_nth(context->namespaces, ctelevelsup);
3604 foreach(lc, ctedpns->ctes)
3606 cte = (CommonTableExpr *) lfirst(lc);
3607 if (strcmp(cte->ctename, rte->ctename) == 0)
3613 Query *ctequery = (Query *) cte->ctequery;
3614 TargetEntry *ste = get_tle_by_resno(ctequery->targetList,
3617 if (ste == NULL || ste->resjunk)
3618 elog(ERROR, "subquery %s does not have attribute %d",
3619 rte->eref->aliasname, attnum);
3620 expr = (Node *) ste->expr;
3624 * Recurse into the CTE to see what its Var refers
3625 * to. We have to build an additional level of
3626 * namespace to keep in step with varlevelsup in the
3627 * CTE. Furthermore it could be an outer CTE, so
3628 * we may have to delete some levels of namespace.
3630 List *save_nslist = context->namespaces;
3632 deparse_namespace mydpns;
3635 mydpns.rtable = ctequery->rtable;
3636 mydpns.ctes = ctequery->cteList;
3637 mydpns.subplans = NIL;
3638 mydpns.outer_plan = mydpns.inner_plan = NULL;
3640 new_nslist = list_copy_tail(context->namespaces,
3642 context->namespaces = lcons(&mydpns, new_nslist);
3644 result = get_name_for_var_field((Var *) expr, fieldno,
3647 context->namespaces = save_nslist;
3651 /* else fall through to inspect the expression */
3656 * We're deparsing a Plan tree so we don't have a CTE
3657 * list. But the only place we'd see a Var directly
3658 * referencing a CTE RTE is in a CteScan plan node, and
3659 * we can look into the subplan's tlist instead.
3666 if (!dpns->inner_plan)
3667 elog(ERROR, "failed to find plan for CTE %s",
3668 rte->eref->aliasname);
3669 tle = get_tle_by_resno(dpns->inner_plan->targetlist,
3672 elog(ERROR, "bogus varattno for subquery var: %d",
3674 Assert(netlevelsup == 0);
3675 save_outer = dpns->outer_plan;
3676 save_inner = dpns->inner_plan;
3677 push_plan(dpns, dpns->inner_plan);
3679 result = get_name_for_var_field((Var *) tle->expr, fieldno,
3682 dpns->outer_plan = save_outer;
3683 dpns->inner_plan = save_inner;
3691 * We now have an expression we can't expand any more, so see if
3692 * get_expr_result_type() can do anything with it. If not, pass to
3693 * lookup_rowtype_tupdesc() which will probably fail, but will give an
3694 * appropriate error message while failing.
3696 if (get_expr_result_type(expr, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
3697 tupleDesc = lookup_rowtype_tupdesc_copy(exprType(expr),
3700 /* Got the tupdesc, so we can extract the field name */
3701 Assert(fieldno >= 1 && fieldno <= tupleDesc->natts);
3702 return NameStr(tupleDesc->attrs[fieldno - 1]->attname);
3707 * find_rte_by_refname - look up an RTE by refname in a deparse context
3709 * Returns NULL if there is no matching RTE or the refname is ambiguous.
3711 * NOTE: this code is not really correct since it does not take account of
3712 * the fact that not all the RTEs in a rangetable may be visible from the
3713 * point where a Var reference appears. For the purposes we need, however,
3714 * the only consequence of a false match is that we might stick a schema
3715 * qualifier on a Var that doesn't really need it. So it seems close
3718 static RangeTblEntry *
3719 find_rte_by_refname(const char *refname, deparse_context *context)
3721 RangeTblEntry *result = NULL;
3724 foreach(nslist, context->namespaces)
3726 deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist);
3729 foreach(rtlist, dpns->rtable)
3731 RangeTblEntry *rte = (RangeTblEntry *) lfirst(rtlist);
3733 if (strcmp(rte->eref->aliasname, refname) == 0)
3736 return NULL; /* it's ambiguous */
3748 * get_simple_binary_op_name
3750 * helper function for isSimpleNode
3751 * will return single char binary operator name, or NULL if it's not
3754 get_simple_binary_op_name(OpExpr *expr)
3756 List *args = expr->args;
3758 if (list_length(args) == 2)
3760 /* binary operator */
3761 Node *arg1 = (Node *) linitial(args);
3762 Node *arg2 = (Node *) lsecond(args);
3765 op = generate_operator_name(expr->opno, exprType(arg1), exprType(arg2));
3766 if (strlen(op) == 1)
3774 * isSimpleNode - check if given node is simple (doesn't need parenthesizing)
3776 * true : simple in the context of parent node's type
3777 * false : not simple
3780 isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
3785 switch (nodeTag(node))
3790 case T_CoerceToDomainValue:
3791 case T_SetToDefault:
3792 case T_CurrentOfExpr:
3793 /* single words: always simple */
3799 case T_CoalesceExpr:
3805 /* function-like: name(..) or name[..] */
3808 /* CASE keywords act as parentheses */
3815 * appears simple since . has top precedence, unless parent is
3816 * T_FieldSelect itself!
3818 return (IsA(parentNode, FieldSelect) ? false : true);
3823 * treat like FieldSelect (probably doesn't matter)
3825 return (IsA(parentNode, FieldStore) ? false : true);
3827 case T_CoerceToDomain:
3828 /* maybe simple, check args */
3829 return isSimpleNode((Node *) ((CoerceToDomain *) node)->arg,
3832 return isSimpleNode((Node *) ((RelabelType *) node)->arg,
3835 return isSimpleNode((Node *) ((CoerceViaIO *) node)->arg,
3837 case T_ArrayCoerceExpr:
3838 return isSimpleNode((Node *) ((ArrayCoerceExpr *) node)->arg,
3840 case T_ConvertRowtypeExpr:
3841 return isSimpleNode((Node *) ((ConvertRowtypeExpr *) node)->arg,
3846 /* depends on parent node type; needs further checking */
3847 if (prettyFlags & PRETTYFLAG_PAREN && IsA(parentNode, OpExpr))
3850 const char *parentOp;
3853 bool is_lopriparent;
3854 bool is_hipriparent;
3856 op = get_simple_binary_op_name((OpExpr *) node);
3860 /* We know only the basic operators + - and * / % */
3861 is_lopriop = (strchr("+-", *op) != NULL);
3862 is_hipriop = (strchr("*/%", *op) != NULL);
3863 if (!(is_lopriop || is_hipriop))
3866 parentOp = get_simple_binary_op_name((OpExpr *) parentNode);
3870 is_lopriparent = (strchr("+-", *parentOp) != NULL);
3871 is_hipriparent = (strchr("*/%", *parentOp) != NULL);
3872 if (!(is_lopriparent || is_hipriparent))
3875 if (is_hipriop && is_lopriparent)
3876 return true; /* op binds tighter than parent */
3878 if (is_lopriop && is_hipriparent)
3882 * Operators are same priority --- can skip parens only if
3883 * we have (a - b) - c, not a - (b - c).
3885 if (node == (Node *) linitial(((OpExpr *) parentNode)->args))
3890 /* else do the same stuff as for T_SubLink et al. */
3897 case T_DistinctExpr:
3898 switch (nodeTag(parentNode))
3902 /* special handling for casts */
3903 CoercionForm type = ((FuncExpr *) parentNode)->funcformat;
3905 if (type == COERCE_EXPLICIT_CAST ||
3906 type == COERCE_IMPLICIT_CAST)
3908 return true; /* own parentheses */
3910 case T_BoolExpr: /* lower precedence */
3911 case T_ArrayRef: /* other separators */
3912 case T_ArrayExpr: /* other separators */
3913 case T_RowExpr: /* other separators */
3914 case T_CoalesceExpr: /* own parentheses */
3915 case T_MinMaxExpr: /* own parentheses */
3916 case T_XmlExpr: /* own parentheses */
3917 case T_NullIfExpr: /* other separators */
3918 case T_Aggref: /* own parentheses */
3919 case T_CaseExpr: /* other separators */
3926 switch (nodeTag(parentNode))
3929 if (prettyFlags & PRETTYFLAG_PAREN)
3932 BoolExprType parentType;
3934 type = ((BoolExpr *) node)->boolop;
3935 parentType = ((BoolExpr *) parentNode)->boolop;
3940 if (parentType == AND_EXPR || parentType == OR_EXPR)
3944 if (parentType == OR_EXPR)
3952 /* special handling for casts */
3953 CoercionForm type = ((FuncExpr *) parentNode)->funcformat;
3955 if (type == COERCE_EXPLICIT_CAST ||
3956 type == COERCE_IMPLICIT_CAST)
3958 return true; /* own parentheses */
3960 case T_ArrayRef: /* other separators */
3961 case T_ArrayExpr: /* other separators */
3962 case T_RowExpr: /* other separators */
3963 case T_CoalesceExpr: /* own parentheses */
3964 case T_MinMaxExpr: /* own parentheses */
3965 case T_XmlExpr: /* own parentheses */
3966 case T_NullIfExpr: /* other separators */
3967 case T_Aggref: /* own parentheses */
3968 case T_CaseExpr: /* other separators */
3977 /* those we don't know: in dubio complexo */
3983 * appendStringInfoSpaces - append spaces to buffer
3986 appendStringInfoSpaces(StringInfo buf, int count)
3989 appendStringInfoChar(buf, ' ');
3993 * appendContextKeyword - append a keyword to buffer
3995 * If prettyPrint is enabled, perform a line break, and adjust indentation.
3996 * Otherwise, just append the keyword.
3999 appendContextKeyword(deparse_context *context, const char *str,
4000 int indentBefore, int indentAfter, int indentPlus)
4002 if (PRETTY_INDENT(context))
4004 context->indentLevel += indentBefore;
4006 appendStringInfoChar(context->buf, '\n');
4007 appendStringInfoSpaces(context->buf,
4008 Max(context->indentLevel, 0) + indentPlus);
4009 appendStringInfoString(context->buf, str);
4011 context->indentLevel += indentAfter;
4012 if (context->indentLevel < 0)
4013 context->indentLevel = 0;
4016 appendStringInfoString(context->buf, str);
4020 * get_rule_expr_paren - deparse expr using get_rule_expr,
4021 * embracing the string with parentheses if necessary for prettyPrint.
4023 * Never embrace if prettyFlags=0, because it's done in the calling node.
4025 * Any node that does *not* embrace its argument node by sql syntax (with
4026 * parentheses, non-operator keywords like CASE/WHEN/ON, or comma etc) should
4027 * use get_rule_expr_paren instead of get_rule_expr so parentheses can be
4031 get_rule_expr_paren(Node *node, deparse_context *context,
4032 bool showimplicit, Node *parentNode)
4036 need_paren = PRETTY_PAREN(context) &&
4037 !isSimpleNode(node, parentNode, context->prettyFlags);
4040 appendStringInfoChar(context->buf, '(');
4042 get_rule_expr(node, context, showimplicit);
4045 appendStringInfoChar(context->buf, ')');
4050 * get_rule_expr - Parse back an expression
4052 * Note: showimplicit determines whether we display any implicit cast that
4053 * is present at the top of the expression tree. It is a passed argument,
4054 * not a field of the context struct, because we change the value as we
4055 * recurse down into the expression. In general we suppress implicit casts
4056 * when the result type is known with certainty (eg, the arguments of an
4057 * OR must be boolean). We display implicit casts for arguments of functions
4058 * and operators, since this is needed to be certain that the same function
4059 * or operator will be chosen when the expression is re-parsed.
4063 get_rule_expr(Node *node, deparse_context *context,
4066 StringInfo buf = context->buf;
4072 * Each level of get_rule_expr must emit an indivisible term
4073 * (parenthesized if necessary) to ensure result is reparsed into the same
4074 * expression tree. The only exception is that when the input is a List,
4075 * we emit the component items comma-separated with no surrounding
4076 * decoration; this is convenient for most callers.
4078 switch (nodeTag(node))
4081 (void) get_variable((Var *) node, 0, true, context);
4085 get_const_expr((Const *) node, context, 0);
4089 appendStringInfo(buf, "$%d", ((Param *) node)->paramid);
4093 get_agg_expr((Aggref *) node, context);
4098 ArrayRef *aref = (ArrayRef *) node;
4102 * Parenthesize the argument unless it's a simple Var or a
4103 * FieldSelect. (In particular, if it's another ArrayRef, we
4104 * *must* parenthesize to avoid confusion.)
4106 need_parens = !IsA(aref->refexpr, Var) &&
4107 !IsA(aref->refexpr, FieldSelect);
4109 appendStringInfoChar(buf, '(');
4110 get_rule_expr((Node *) aref->refexpr, context, showimplicit);
4112 appendStringInfoChar(buf, ')');
4113 printSubscripts(aref, context);
4116 * Array assignment nodes should have been handled in
4117 * processIndirection().
4119 if (aref->refassgnexpr)
4120 elog(ERROR, "unexpected refassgnexpr");
4125 get_func_expr((FuncExpr *) node, context, showimplicit);
4129 get_oper_expr((OpExpr *) node, context);
4132 case T_DistinctExpr:
4134 DistinctExpr *expr = (DistinctExpr *) node;
4135 List *args = expr->args;
4136 Node *arg1 = (Node *) linitial(args);
4137 Node *arg2 = (Node *) lsecond(args);
4139 if (!PRETTY_PAREN(context))
4140 appendStringInfoChar(buf, '(');
4141 get_rule_expr_paren(arg1, context, true, node);
4142 appendStringInfo(buf, " IS DISTINCT FROM ");
4143 get_rule_expr_paren(arg2, context, true, node);
4144 if (!PRETTY_PAREN(context))
4145 appendStringInfoChar(buf, ')');
4149 case T_ScalarArrayOpExpr:
4151 ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
4152 List *args = expr->args;
4153 Node *arg1 = (Node *) linitial(args);
4154 Node *arg2 = (Node *) lsecond(args);
4156 if (!PRETTY_PAREN(context))
4157 appendStringInfoChar(buf, '(');
4158 get_rule_expr_paren(arg1, context, true, node);
4159 appendStringInfo(buf, " %s %s (",
4160 generate_operator_name(expr->opno,
4162 get_element_type(exprType(arg2))),
4163 expr->useOr ? "ANY" : "ALL");
4164 get_rule_expr_paren(arg2, context, true, node);
4165 appendStringInfoChar(buf, ')');
4166 if (!PRETTY_PAREN(context))
4167 appendStringInfoChar(buf, ')');
4173 BoolExpr *expr = (BoolExpr *) node;
4174 Node *first_arg = linitial(expr->args);
4175 ListCell *arg = lnext(list_head(expr->args));
4177 switch (expr->boolop)
4180 if (!PRETTY_PAREN(context))
4181 appendStringInfoChar(buf, '(');
4182 get_rule_expr_paren(first_arg, context,
4186 appendStringInfo(buf, " AND ");
4187 get_rule_expr_paren((Node *) lfirst(arg), context,
4191 if (!PRETTY_PAREN(context))
4192 appendStringInfoChar(buf, ')');
4196 if (!PRETTY_PAREN(context))
4197 appendStringInfoChar(buf, '(');
4198 get_rule_expr_paren(first_arg, context,
4202 appendStringInfo(buf, " OR ");
4203 get_rule_expr_paren((Node *) lfirst(arg), context,
4207 if (!PRETTY_PAREN(context))
4208 appendStringInfoChar(buf, ')');
4212 if (!PRETTY_PAREN(context))
4213 appendStringInfoChar(buf, '(');
4214 appendStringInfo(buf, "NOT ");
4215 get_rule_expr_paren(first_arg, context,
4217 if (!PRETTY_PAREN(context))
4218 appendStringInfoChar(buf, ')');
4222 elog(ERROR, "unrecognized boolop: %d",
4223 (int) expr->boolop);
4229 get_sublink_expr((SubLink *) node, context);
4235 * We cannot see an already-planned subplan in rule deparsing,
4236 * only while EXPLAINing a query plan. For now, just punt.
4238 if (((SubPlan *) node)->useHashTable)
4239 appendStringInfo(buf, "(hashed subplan)");
4241 appendStringInfo(buf, "(subplan)");
4245 case T_AlternativeSubPlan:
4246 /* As above, just punt */
4247 appendStringInfo(buf, "(alternative subplans)");
4252 FieldSelect *fselect = (FieldSelect *) node;
4253 Node *arg = (Node *) fselect->arg;
4254 int fno = fselect->fieldnum;
4255 const char *fieldname;
4259 * Parenthesize the argument unless it's an ArrayRef or
4260 * another FieldSelect. Note in particular that it would be
4261 * WRONG to not parenthesize a Var argument; simplicity is not
4262 * the issue here, having the right number of names is.
4264 need_parens = !IsA(arg, ArrayRef) &&!IsA(arg, FieldSelect);
4266 appendStringInfoChar(buf, '(');
4267 get_rule_expr(arg, context, true);
4269 appendStringInfoChar(buf, ')');
4272 * Get and print the field name.
4274 fieldname = get_name_for_var_field((Var *) arg, fno,
4276 appendStringInfo(buf, ".%s", quote_identifier(fieldname));
4283 * We shouldn't see FieldStore here; it should have been stripped
4284 * off by processIndirection().
4286 elog(ERROR, "unexpected FieldStore");
4291 RelabelType *relabel = (RelabelType *) node;
4292 Node *arg = (Node *) relabel->arg;
4294 if (relabel->relabelformat == COERCE_IMPLICIT_CAST &&
4297 /* don't show the implicit cast */
4298 get_rule_expr_paren(arg, context, false, node);
4302 get_coercion_expr(arg, context,
4303 relabel->resulttype,
4304 relabel->resulttypmod,
4312 CoerceViaIO *iocoerce = (CoerceViaIO *) node;
4313 Node *arg = (Node *) iocoerce->arg;
4315 if (iocoerce->coerceformat == COERCE_IMPLICIT_CAST &&
4318 /* don't show the implicit cast */
4319 get_rule_expr_paren(arg, context, false, node);
4323 get_coercion_expr(arg, context,
4324 iocoerce->resulttype,
4331 case T_ArrayCoerceExpr:
4333 ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;
4334 Node *arg = (Node *) acoerce->arg;
4336 if (acoerce->coerceformat == COERCE_IMPLICIT_CAST &&
4339 /* don't show the implicit cast */
4340 get_rule_expr_paren(arg, context, false, node);
4344 get_coercion_expr(arg, context,
4345 acoerce->resulttype,
4346 acoerce->resulttypmod,
4352 case T_ConvertRowtypeExpr:
4354 ConvertRowtypeExpr *convert = (ConvertRowtypeExpr *) node;
4355 Node *arg = (Node *) convert->arg;
4357 if (convert->convertformat == COERCE_IMPLICIT_CAST &&
4360 /* don't show the implicit cast */
4361 get_rule_expr_paren(arg, context, false, node);
4365 get_coercion_expr(arg, context,
4366 convert->resulttype, -1,
4374 CaseExpr *caseexpr = (CaseExpr *) node;
4377 appendContextKeyword(context, "CASE",
4378 0, PRETTYINDENT_VAR, 0);
4381 appendStringInfoChar(buf, ' ');
4382 get_rule_expr((Node *) caseexpr->arg, context, true);
4384 foreach(temp, caseexpr->args)
4386 CaseWhen *when = (CaseWhen *) lfirst(temp);
4387 Node *w = (Node *) when->expr;
4389 if (!PRETTY_INDENT(context))
4390 appendStringInfoChar(buf, ' ');
4391 appendContextKeyword(context, "WHEN ",
4396 * The parser should have produced WHEN clauses of the
4397 * form "CaseTestExpr = RHS"; we want to show just the
4398 * RHS. If the user wrote something silly like "CASE
4399 * boolexpr WHEN TRUE THEN ...", then the optimizer's
4400 * simplify_boolean_equality() may have reduced this
4401 * to just "CaseTestExpr" or "NOT CaseTestExpr", for
4402 * which we have to show "TRUE" or "FALSE". Also,
4403 * depending on context the original CaseTestExpr
4404 * might have been reduced to a Const (but we won't
4405 * see "WHEN Const").
4411 Assert(IsA(linitial(((OpExpr *) w)->args),
4413 IsA(linitial(((OpExpr *) w)->args),
4415 rhs = (Node *) lsecond(((OpExpr *) w)->args);
4416 get_rule_expr(rhs, context, false);
4418 else if (IsA(w, CaseTestExpr))
4419 appendStringInfo(buf, "TRUE");
4420 else if (not_clause(w))
4422 Assert(IsA(get_notclausearg((Expr *) w),
4424 appendStringInfo(buf, "FALSE");
4427 elog(ERROR, "unexpected CASE WHEN clause: %d",
4431 get_rule_expr(w, context, false);
4432 appendStringInfo(buf, " THEN ");
4433 get_rule_expr((Node *) when->result, context, true);
4435 if (!PRETTY_INDENT(context))
4436 appendStringInfoChar(buf, ' ');
4437 appendContextKeyword(context, "ELSE ",
4439 get_rule_expr((Node *) caseexpr->defresult, context, true);
4440 if (!PRETTY_INDENT(context))
4441 appendStringInfoChar(buf, ' ');
4442 appendContextKeyword(context, "END",
4443 -PRETTYINDENT_VAR, 0, 0);
4449 ArrayExpr *arrayexpr = (ArrayExpr *) node;
4451 appendStringInfo(buf, "ARRAY[");
4452 get_rule_expr((Node *) arrayexpr->elements, context, true);
4453 appendStringInfoChar(buf, ']');
4455 * If the array isn't empty, we assume its elements are
4456 * coerced to the desired type. If it's empty, though, we
4457 * need an explicit coercion to the array type.
4459 if (arrayexpr->elements == NIL)
4460 appendStringInfo(buf, "::%s",
4461 format_type_with_typemod(arrayexpr->array_typeid, -1));
4467 RowExpr *rowexpr = (RowExpr *) node;
4468 TupleDesc tupdesc = NULL;
4474 * If it's a named type and not RECORD, we may have to skip
4475 * dropped columns and/or claim there are NULLs for added
4478 if (rowexpr->row_typeid != RECORDOID)
4480 tupdesc = lookup_rowtype_tupdesc(rowexpr->row_typeid, -1);
4481 Assert(list_length(rowexpr->args) <= tupdesc->natts);
4485 * SQL99 allows "ROW" to be omitted when there is more than
4486 * one column, but for simplicity we always print it.
4488 appendStringInfo(buf, "ROW(");
4491 foreach(arg, rowexpr->args)
4493 Node *e = (Node *) lfirst(arg);
4495 if (tupdesc == NULL ||
4496 !tupdesc->attrs[i]->attisdropped)
4498 appendStringInfoString(buf, sep);
4499 get_rule_expr(e, context, true);
4504 if (tupdesc != NULL)
4506 while (i < tupdesc->natts)
4508 if (!tupdesc->attrs[i]->attisdropped)
4510 appendStringInfoString(buf, sep);
4511 appendStringInfo(buf, "NULL");
4517 ReleaseTupleDesc(tupdesc);
4519 appendStringInfo(buf, ")");
4520 if (rowexpr->row_format == COERCE_EXPLICIT_CAST)
4521 appendStringInfo(buf, "::%s",
4522 format_type_with_typemod(rowexpr->row_typeid, -1));
4526 case T_RowCompareExpr:
4528 RowCompareExpr *rcexpr = (RowCompareExpr *) node;
4533 * SQL99 allows "ROW" to be omitted when there is more than
4534 * one column, but for simplicity we always print it.
4536 appendStringInfo(buf, "(ROW(");
4538 foreach(arg, rcexpr->largs)
4540 Node *e = (Node *) lfirst(arg);
4542 appendStringInfoString(buf, sep);
4543 get_rule_expr(e, context, true);
4548 * We assume that the name of the first-column operator will
4549 * do for all the rest too. This is definitely open to
4550 * failure, eg if some but not all operators were renamed
4551 * since the construct was parsed, but there seems no way to
4554 appendStringInfo(buf, ") %s ROW(",
4555 generate_operator_name(linitial_oid(rcexpr->opnos),
4556 exprType(linitial(rcexpr->largs)),
4557 exprType(linitial(rcexpr->rargs))));
4559 foreach(arg, rcexpr->rargs)
4561 Node *e = (Node *) lfirst(arg);
4563 appendStringInfoString(buf, sep);
4564 get_rule_expr(e, context, true);
4567 appendStringInfo(buf, "))");
4571 case T_CoalesceExpr:
4573 CoalesceExpr *coalesceexpr = (CoalesceExpr *) node;
4575 appendStringInfo(buf, "COALESCE(");
4576 get_rule_expr((Node *) coalesceexpr->args, context, true);
4577 appendStringInfoChar(buf, ')');
4583 MinMaxExpr *minmaxexpr = (MinMaxExpr *) node;
4585 switch (minmaxexpr->op)
4588 appendStringInfo(buf, "GREATEST(");
4591 appendStringInfo(buf, "LEAST(");
4594 get_rule_expr((Node *) minmaxexpr->args, context, true);
4595 appendStringInfoChar(buf, ')');
4601 XmlExpr *xexpr = (XmlExpr *) node;
4602 bool needcomma = false;
4610 appendStringInfoString(buf, "XMLCONCAT(");
4613 appendStringInfoString(buf, "XMLELEMENT(");
4616 appendStringInfoString(buf, "XMLFOREST(");
4619 appendStringInfoString(buf, "XMLPARSE(");
4622 appendStringInfoString(buf, "XMLPI(");
4625 appendStringInfoString(buf, "XMLROOT(");
4627 case IS_XMLSERIALIZE:
4628 appendStringInfoString(buf, "XMLSERIALIZE(");
4633 if (xexpr->op == IS_XMLPARSE || xexpr->op == IS_XMLSERIALIZE)
4635 if (xexpr->xmloption == XMLOPTION_DOCUMENT)
4636 appendStringInfoString(buf, "DOCUMENT ");
4638 appendStringInfoString(buf, "CONTENT ");
4642 appendStringInfo(buf, "NAME %s",
4643 quote_identifier(map_xml_name_to_sql_identifier(xexpr->name)));
4646 if (xexpr->named_args)
4648 if (xexpr->op != IS_XMLFOREST)
4651 appendStringInfoString(buf, ", ");
4652 appendStringInfoString(buf, "XMLATTRIBUTES(");
4655 forboth(arg, xexpr->named_args, narg, xexpr->arg_names)
4657 Node *e = (Node *) lfirst(arg);
4658 char *argname = strVal(lfirst(narg));
4661 appendStringInfoString(buf, ", ");
4662 get_rule_expr((Node *) e, context, true);
4663 appendStringInfo(buf, " AS %s",
4664 quote_identifier(map_xml_name_to_sql_identifier(argname)));
4667 if (xexpr->op != IS_XMLFOREST)
4668 appendStringInfoChar(buf, ')');
4673 appendStringInfoString(buf, ", ");
4680 case IS_XMLSERIALIZE:
4681 /* no extra decoration needed */
4682 get_rule_expr((Node *) xexpr->args, context, true);
4685 Assert(list_length(xexpr->args) == 2);
4687 get_rule_expr((Node *) linitial(xexpr->args),
4690 con = (Const *) lsecond(xexpr->args);
4691 Assert(IsA(con, Const));
4692 Assert(!con->constisnull);
4693 if (DatumGetBool(con->constvalue))
4694 appendStringInfoString(buf,
4695 " PRESERVE WHITESPACE");
4697 appendStringInfoString(buf,
4698 " STRIP WHITESPACE");
4701 Assert(list_length(xexpr->args) == 3);
4703 get_rule_expr((Node *) linitial(xexpr->args),
4706 appendStringInfoString(buf, ", VERSION ");
4707 con = (Const *) lsecond(xexpr->args);
4708 if (IsA(con, Const) &&
4710 appendStringInfoString(buf, "NO VALUE");
4712 get_rule_expr((Node *) con, context, false);
4714 con = (Const *) lthird(xexpr->args);
4715 Assert(IsA(con, Const));
4716 if (con->constisnull)
4717 /* suppress STANDALONE NO VALUE */ ;
4720 switch (DatumGetInt32(con->constvalue))
4722 case XML_STANDALONE_YES:
4723 appendStringInfoString(buf,
4724 ", STANDALONE YES");
4726 case XML_STANDALONE_NO:
4727 appendStringInfoString(buf,
4730 case XML_STANDALONE_NO_VALUE:
4731 appendStringInfoString(buf,
4732 ", STANDALONE NO VALUE");
4740 get_rule_expr_paren((Node *) xexpr->args, context, false, node);
4745 if (xexpr->op == IS_XMLSERIALIZE)
4746 appendStringInfo(buf, " AS %s", format_type_with_typemod(xexpr->type,
4748 if (xexpr->op == IS_DOCUMENT)
4749 appendStringInfoString(buf, " IS DOCUMENT");
4751 appendStringInfoChar(buf, ')');
4757 NullIfExpr *nullifexpr = (NullIfExpr *) node;
4759 appendStringInfo(buf, "NULLIF(");
4760 get_rule_expr((Node *) nullifexpr->args, context, true);
4761 appendStringInfoChar(buf, ')');
4767 NullTest *ntest = (NullTest *) node;
4769 if (!PRETTY_PAREN(context))
4770 appendStringInfoChar(buf, '(');
4771 get_rule_expr_paren((Node *) ntest->arg, context, true, node);
4772 switch (ntest->nulltesttype)
4775 appendStringInfo(buf, " IS NULL");
4778 appendStringInfo(buf, " IS NOT NULL");
4781 elog(ERROR, "unrecognized nulltesttype: %d",
4782 (int) ntest->nulltesttype);
4784 if (!PRETTY_PAREN(context))
4785 appendStringInfoChar(buf, ')');
4791 BooleanTest *btest = (BooleanTest *) node;
4793 if (!PRETTY_PAREN(context))
4794 appendStringInfoChar(buf, '(');
4795 get_rule_expr_paren((Node *) btest->arg, context, false, node);
4796 switch (btest->booltesttype)
4799 appendStringInfo(buf, " IS TRUE");
4802 appendStringInfo(buf, " IS NOT TRUE");
4805 appendStringInfo(buf, " IS FALSE");
4808 appendStringInfo(buf, " IS NOT FALSE");
4811 appendStringInfo(buf, " IS UNKNOWN");
4813 case IS_NOT_UNKNOWN:
4814 appendStringInfo(buf, " IS NOT UNKNOWN");
4817 elog(ERROR, "unrecognized booltesttype: %d",
4818 (int) btest->booltesttype);
4820 if (!PRETTY_PAREN(context))
4821 appendStringInfoChar(buf, ')');
4825 case T_CoerceToDomain:
4827 CoerceToDomain *ctest = (CoerceToDomain *) node;
4828 Node *arg = (Node *) ctest->arg;
4830 if (ctest->coercionformat == COERCE_IMPLICIT_CAST &&
4833 /* don't show the implicit cast */
4834 get_rule_expr(arg, context, false);
4838 get_coercion_expr(arg, context,
4840 ctest->resulttypmod,
4846 case T_CoerceToDomainValue:
4847 appendStringInfo(buf, "VALUE");
4850 case T_SetToDefault:
4851 appendStringInfo(buf, "DEFAULT");
4854 case T_CurrentOfExpr:
4856 CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
4858 if (cexpr->cursor_name)
4859 appendStringInfo(buf, "CURRENT OF %s",
4860 quote_identifier(cexpr->cursor_name));
4862 appendStringInfo(buf, "CURRENT OF $%d",
4863 cexpr->cursor_param);
4873 foreach(l, (List *) node)
4875 appendStringInfoString(buf, sep);
4876 get_rule_expr((Node *) lfirst(l), context, showimplicit);
4883 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
4890 * get_oper_expr - Parse back an OpExpr node
4893 get_oper_expr(OpExpr *expr, deparse_context *context)
4895 StringInfo buf = context->buf;
4896 Oid opno = expr->opno;
4897 List *args = expr->args;
4899 if (!PRETTY_PAREN(context))
4900 appendStringInfoChar(buf, '(');
4901 if (list_length(args) == 2)
4903 /* binary operator */
4904 Node *arg1 = (Node *) linitial(args);
4905 Node *arg2 = (Node *) lsecond(args);
4907 get_rule_expr_paren(arg1, context, true, (Node *) expr);
4908 appendStringInfo(buf, " %s ",
4909 generate_operator_name(opno,
4912 get_rule_expr_paren(arg2, context, true, (Node *) expr);
4916 /* unary operator --- but which side? */
4917 Node *arg = (Node *) linitial(args);
4919 Form_pg_operator optup;
4921 tp = SearchSysCache(OPEROID,
4922 ObjectIdGetDatum(opno),
4924 if (!HeapTupleIsValid(tp))
4925 elog(ERROR, "cache lookup failed for operator %u", opno);
4926 optup = (Form_pg_operator) GETSTRUCT(tp);
4927 switch (optup->oprkind)
4930 appendStringInfo(buf, "%s ",
4931 generate_operator_name(opno,
4934 get_rule_expr_paren(arg, context, true, (Node *) expr);
4937 get_rule_expr_paren(arg, context, true, (Node *) expr);
4938 appendStringInfo(buf, " %s",
4939 generate_operator_name(opno,
4944 elog(ERROR, "bogus oprkind: %d", optup->oprkind);
4946 ReleaseSysCache(tp);
4948 if (!PRETTY_PAREN(context))
4949 appendStringInfoChar(buf, ')');
4953 * get_func_expr - Parse back a FuncExpr node
4956 get_func_expr(FuncExpr *expr, deparse_context *context,
4959 StringInfo buf = context->buf;
4960 Oid funcoid = expr->funcid;
4961 Oid argtypes[FUNC_MAX_ARGS];
4967 * If the function call came from an implicit coercion, then just show the
4968 * first argument --- unless caller wants to see implicit coercions.
4970 if (expr->funcformat == COERCE_IMPLICIT_CAST && !showimplicit)
4972 get_rule_expr_paren((Node *) linitial(expr->args), context,
4973 false, (Node *) expr);
4978 * If the function call came from a cast, then show the first argument
4979 * plus an explicit cast operation.
4981 if (expr->funcformat == COERCE_EXPLICIT_CAST ||
4982 expr->funcformat == COERCE_IMPLICIT_CAST)
4984 Node *arg = linitial(expr->args);
4985 Oid rettype = expr->funcresulttype;
4986 int32 coercedTypmod;
4988 /* Get the typmod if this is a length-coercion function */
4989 (void) exprIsLengthCoercion((Node *) expr, &coercedTypmod);
4991 get_coercion_expr(arg, context,
4992 rettype, coercedTypmod,
4999 * Normal function: display as proname(args). First we need to extract
5000 * the argument datatypes.
5003 foreach(l, expr->args)
5005 if (nargs >= FUNC_MAX_ARGS)
5007 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
5008 errmsg("too many arguments")));
5009 argtypes[nargs] = exprType((Node *) lfirst(l));
5013 appendStringInfo(buf, "%s(",
5014 generate_function_name(funcoid, nargs, argtypes,
5017 foreach(l, expr->args)
5020 appendStringInfoString(buf, ", ");
5021 if (is_variadic && lnext(l) == NULL)
5022 appendStringInfoString(buf, "VARIADIC ");
5023 get_rule_expr((Node *) lfirst(l), context, true);
5025 appendStringInfoChar(buf, ')');
5029 * get_agg_expr - Parse back an Aggref node
5032 get_agg_expr(Aggref *aggref, deparse_context *context)
5034 StringInfo buf = context->buf;
5035 Oid argtypes[FUNC_MAX_ARGS];
5040 foreach(l, aggref->args)
5042 if (nargs >= FUNC_MAX_ARGS)
5044 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
5045 errmsg("too many arguments")));
5046 argtypes[nargs] = exprType((Node *) lfirst(l));
5050 appendStringInfo(buf, "%s(%s",
5051 generate_function_name(aggref->aggfnoid,
5052 nargs, argtypes, NULL),
5053 aggref->aggdistinct ? "DISTINCT " : "");
5054 /* aggstar can be set only in zero-argument aggregates */
5055 if (aggref->aggstar)
5056 appendStringInfoChar(buf, '*');
5058 get_rule_expr((Node *) aggref->args, context, true);
5059 appendStringInfoChar(buf, ')');
5065 * Make a string representation of a value coerced to a specific type
5069 get_coercion_expr(Node *arg, deparse_context *context,
5070 Oid resulttype, int32 resulttypmod,
5073 StringInfo buf = context->buf;
5076 * Since parse_coerce.c doesn't immediately collapse application of
5077 * length-coercion functions to constants, what we'll typically see in
5078 * such cases is a Const with typmod -1 and a length-coercion function
5079 * right above it. Avoid generating redundant output. However, beware of
5080 * suppressing casts when the user actually wrote something like
5081 * 'foo'::text::char(3).
5083 if (arg && IsA(arg, Const) &&
5084 ((Const *) arg)->consttype == resulttype &&
5085 ((Const *) arg)->consttypmod == -1)
5087 /* Show the constant without normal ::typename decoration */
5088 get_const_expr((Const *) arg, context, -1);
5092 if (!PRETTY_PAREN(context))
5093 appendStringInfoChar(buf, '(');
5094 get_rule_expr_paren(arg, context, false, parentNode);
5095 if (!PRETTY_PAREN(context))
5096 appendStringInfoChar(buf, ')');
5098 appendStringInfo(buf, "::%s",
5099 format_type_with_typemod(resulttype, resulttypmod));
5105 * Make a string representation of a Const
5107 * showtype can be -1 to never show "::typename" decoration, or +1 to always
5108 * show it, or 0 to show it only if the constant wouldn't be assumed to be
5109 * the right type by default.
5113 get_const_expr(Const *constval, deparse_context *context, int showtype)
5115 StringInfo buf = context->buf;
5119 bool isfloat = false;
5122 if (constval->constisnull)
5125 * Always label the type of a NULL constant to prevent misdecisions
5126 * about type when reparsing.
5128 appendStringInfo(buf, "NULL");
5130 appendStringInfo(buf, "::%s",
5131 format_type_with_typemod(constval->consttype,
5132 constval->consttypmod));
5136 getTypeOutputInfo(constval->consttype,
5137 &typoutput, &typIsVarlena);
5139 extval = OidOutputFunctionCall(typoutput, constval->constvalue);
5141 switch (constval->consttype)
5152 * These types are printed without quotes unless they contain
5153 * values that aren't accepted by the scanner unquoted (e.g.,
5154 * 'NaN'). Note that strtod() and friends might accept NaN,
5155 * so we can't use that to test.
5157 * In reality we only need to defend against infinity and NaN,
5158 * so we need not get too crazy about pattern matching here.
5160 * There is a special-case gotcha: if the constant is signed,
5161 * we need to parenthesize it, else the parser might see a
5162 * leading plus/minus as binding less tightly than adjacent
5163 * operators --- particularly, the cast that we might attach
5166 if (strspn(extval, "0123456789+-eE.") == strlen(extval))
5168 if (extval[0] == '+' || extval[0] == '-')
5169 appendStringInfo(buf, "(%s)", extval);
5171 appendStringInfoString(buf, extval);
5172 if (strcspn(extval, "eE.") != strlen(extval))
5173 isfloat = true; /* it looks like a float */
5176 appendStringInfo(buf, "'%s'", extval);
5182 appendStringInfo(buf, "B'%s'", extval);
5186 if (strcmp(extval, "t") == 0)
5187 appendStringInfo(buf, "true");
5189 appendStringInfo(buf, "false");
5193 simple_quote_literal(buf, extval);
5203 * For showtype == 0, append ::typename unless the constant will be
5204 * implicitly typed as the right type when it is read in.
5206 * XXX this code has to be kept in sync with the behavior of the parser,
5207 * especially make_const.
5209 switch (constval->consttype)
5214 /* These types can be left unlabeled */
5220 * Float-looking constants will be typed as numeric, but if
5221 * there's a specific typmod we need to show it.
5223 needlabel = !isfloat || (constval->consttypmod >= 0);
5229 if (needlabel || showtype > 0)
5230 appendStringInfo(buf, "::%s",
5231 format_type_with_typemod(constval->consttype,
5232 constval->consttypmod));
5236 * simple_quote_literal - Format a string as a SQL literal, append to buf
5239 simple_quote_literal(StringInfo buf, const char *val)
5244 * We form the string literal according to the prevailing setting
5245 * of standard_conforming_strings; we never use E''. User is
5246 * responsible for making sure result is used correctly.
5248 appendStringInfoChar(buf, '\'');
5249 for (valptr = val; *valptr; valptr++)
5253 if (SQL_STR_DOUBLE(ch, !standard_conforming_strings))
5254 appendStringInfoChar(buf, ch);
5255 appendStringInfoChar(buf, ch);
5257 appendStringInfoChar(buf, '\'');
5262 * get_sublink_expr - Parse back a sublink
5266 get_sublink_expr(SubLink *sublink, deparse_context *context)
5268 StringInfo buf = context->buf;
5269 Query *query = (Query *) (sublink->subselect);
5270 char *opname = NULL;
5273 if (sublink->subLinkType == ARRAY_SUBLINK)
5274 appendStringInfo(buf, "ARRAY(");
5276 appendStringInfoChar(buf, '(');
5279 * Note that we print the name of only the first operator, when there are
5280 * multiple combining operators. This is an approximation that could go
5281 * wrong in various scenarios (operators in different schemas, renamed
5282 * operators, etc) but there is not a whole lot we can do about it, since
5283 * the syntax allows only one operator to be shown.
5285 if (sublink->testexpr)
5287 if (IsA(sublink->testexpr, OpExpr))
5289 /* single combining operator */
5290 OpExpr *opexpr = (OpExpr *) sublink->testexpr;
5292 get_rule_expr(linitial(opexpr->args), context, true);
5293 opname = generate_operator_name(opexpr->opno,
5294 exprType(linitial(opexpr->args)),
5295 exprType(lsecond(opexpr->args)));
5297 else if (IsA(sublink->testexpr, BoolExpr))
5299 /* multiple combining operators, = or <> cases */
5303 appendStringInfoChar(buf, '(');
5305 foreach(l, ((BoolExpr *) sublink->testexpr)->args)
5307 OpExpr *opexpr = (OpExpr *) lfirst(l);
5309 Assert(IsA(opexpr, OpExpr));
5310 appendStringInfoString(buf, sep);
5311 get_rule_expr(linitial(opexpr->args), context, true);
5313 opname = generate_operator_name(opexpr->opno,
5314 exprType(linitial(opexpr->args)),
5315 exprType(lsecond(opexpr->args)));
5318 appendStringInfoChar(buf, ')');
5320 else if (IsA(sublink->testexpr, RowCompareExpr))
5322 /* multiple combining operators, < <= > >= cases */
5323 RowCompareExpr *rcexpr = (RowCompareExpr *) sublink->testexpr;
5325 appendStringInfoChar(buf, '(');
5326 get_rule_expr((Node *) rcexpr->largs, context, true);
5327 opname = generate_operator_name(linitial_oid(rcexpr->opnos),
5328 exprType(linitial(rcexpr->largs)),
5329 exprType(linitial(rcexpr->rargs)));
5330 appendStringInfoChar(buf, ')');
5333 elog(ERROR, "unrecognized testexpr type: %d",
5334 (int) nodeTag(sublink->testexpr));
5339 switch (sublink->subLinkType)
5341 case EXISTS_SUBLINK:
5342 appendStringInfo(buf, "EXISTS ");
5346 if (strcmp(opname, "=") == 0) /* Represent = ANY as IN */
5347 appendStringInfo(buf, " IN ");
5349 appendStringInfo(buf, " %s ANY ", opname);
5353 appendStringInfo(buf, " %s ALL ", opname);
5356 case ROWCOMPARE_SUBLINK:
5357 appendStringInfo(buf, " %s ", opname);
5365 case CTE_SUBLINK: /* shouldn't occur in a SubLink */
5367 elog(ERROR, "unrecognized sublink type: %d",
5368 (int) sublink->subLinkType);
5373 appendStringInfoChar(buf, '(');
5375 get_query_def(query, buf, context->namespaces, NULL,
5376 context->prettyFlags, context->indentLevel);
5379 appendStringInfo(buf, "))");
5381 appendStringInfoChar(buf, ')');
5386 * get_from_clause - Parse back a FROM clause
5388 * "prefix" is the keyword that denotes the start of the list of FROM
5389 * elements. It is FROM when used to parse back SELECT and UPDATE, but
5390 * is USING when parsing back DELETE.
5394 get_from_clause(Query *query, const char *prefix, deparse_context *context)
5396 StringInfo buf = context->buf;
5401 * We use the query's jointree as a guide to what to print. However, we
5402 * must ignore auto-added RTEs that are marked not inFromCl. (These can
5403 * only appear at the top level of the jointree, so it's sufficient to
5404 * check here.) This check also ensures we ignore the rule pseudo-RTEs
5407 foreach(l, query->jointree->fromlist)
5409 Node *jtnode = (Node *) lfirst(l);
5411 if (IsA(jtnode, RangeTblRef))
5413 int varno = ((RangeTblRef *) jtnode)->rtindex;
5414 RangeTblEntry *rte = rt_fetch(varno, query->rtable);
5422 appendContextKeyword(context, prefix,
5423 -PRETTYINDENT_STD, PRETTYINDENT_STD, 2);
5427 appendStringInfoString(buf, ", ");
5429 get_from_clause_item(jtnode, query, context);
5434 get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
5436 StringInfo buf = context->buf;
5438 if (IsA(jtnode, RangeTblRef))
5440 int varno = ((RangeTblRef *) jtnode)->rtindex;
5441 RangeTblEntry *rte = rt_fetch(varno, query->rtable);
5442 bool gavealias = false;
5444 switch (rte->rtekind)
5447 /* Normal relation RTE */
5448 appendStringInfo(buf, "%s%s",
5450 generate_relation_name(rte->relid,
5451 context->namespaces));
5455 appendStringInfoChar(buf, '(');
5456 get_query_def(rte->subquery, buf, context->namespaces, NULL,
5457 context->prettyFlags, context->indentLevel);
5458 appendStringInfoChar(buf, ')');
5462 get_rule_expr(rte->funcexpr, context, true);
5465 /* Values list RTE */
5466 get_values_def(rte->values_lists, context);
5469 appendStringInfoString(buf, quote_identifier(rte->ctename));
5472 elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
5476 if (rte->alias != NULL)
5478 appendStringInfo(buf, " %s",
5479 quote_identifier(rte->alias->aliasname));
5482 else if (rte->rtekind == RTE_RELATION &&
5483 strcmp(rte->eref->aliasname, get_rel_name(rte->relid)) != 0)
5486 * Apparently the rel has been renamed since the rule was made.
5487 * Emit a fake alias clause so that variable references will still
5488 * work. This is not a 100% solution but should work in most
5489 * reasonable situations.
5491 appendStringInfo(buf, " %s",
5492 quote_identifier(rte->eref->aliasname));
5495 else if (rte->rtekind == RTE_FUNCTION)
5498 * For a function RTE, always give an alias. This covers possible
5499 * renaming of the function and/or instability of the
5500 * FigureColname rules for things that aren't simple functions.
5502 appendStringInfo(buf, " %s",
5503 quote_identifier(rte->eref->aliasname));
5507 if (rte->rtekind == RTE_FUNCTION)
5509 if (rte->funccoltypes != NIL)
5511 /* Function returning RECORD, reconstruct the columndefs */
5513 appendStringInfo(buf, " AS ");
5514 get_from_clause_coldeflist(rte->eref->colnames,
5516 rte->funccoltypmods,
5522 * For a function RTE, always emit a complete column alias
5523 * list; this is to protect against possible instability of
5524 * the default column names (eg, from altering parameter
5527 get_from_clause_alias(rte->eref, rte, context);
5533 * For non-function RTEs, just report whatever the user originally
5534 * gave as column aliases.
5536 get_from_clause_alias(rte->alias, rte, context);
5539 else if (IsA(jtnode, JoinExpr))
5541 JoinExpr *j = (JoinExpr *) jtnode;
5542 bool need_paren_on_right;
5544 need_paren_on_right = PRETTY_PAREN(context) &&
5545 !IsA(j->rarg, RangeTblRef) &&
5546 !(IsA(j->rarg, JoinExpr) &&((JoinExpr *) j->rarg)->alias != NULL);
5548 if (!PRETTY_PAREN(context) || j->alias != NULL)
5549 appendStringInfoChar(buf, '(');
5551 get_from_clause_item(j->larg, query, context);
5555 if (!PRETTY_INDENT(context))
5556 appendStringInfoChar(buf, ' ');
5557 switch (j->jointype)
5560 appendContextKeyword(context, "NATURAL JOIN ",
5562 PRETTYINDENT_JOIN, 0);
5565 appendContextKeyword(context, "NATURAL LEFT JOIN ",
5567 PRETTYINDENT_JOIN, 0);
5570 appendContextKeyword(context, "NATURAL FULL JOIN ",
5572 PRETTYINDENT_JOIN, 0);
5575 appendContextKeyword(context, "NATURAL RIGHT JOIN ",
5577 PRETTYINDENT_JOIN, 0);
5580 elog(ERROR, "unrecognized join type: %d",
5586 switch (j->jointype)
5590 appendContextKeyword(context, " JOIN ",
5592 PRETTYINDENT_JOIN, 2);
5594 appendContextKeyword(context, " CROSS JOIN ",
5596 PRETTYINDENT_JOIN, 1);
5599 appendContextKeyword(context, " LEFT JOIN ",
5601 PRETTYINDENT_JOIN, 2);
5604 appendContextKeyword(context, " FULL JOIN ",
5606 PRETTYINDENT_JOIN, 2);
5609 appendContextKeyword(context, " RIGHT JOIN ",
5611 PRETTYINDENT_JOIN, 2);
5614 elog(ERROR, "unrecognized join type: %d",
5619 if (need_paren_on_right)
5620 appendStringInfoChar(buf, '(');
5621 get_from_clause_item(j->rarg, query, context);
5622 if (need_paren_on_right)
5623 appendStringInfoChar(buf, ')');
5625 context->indentLevel -= PRETTYINDENT_JOIN_ON;
5633 appendStringInfo(buf, " USING (");
5634 foreach(col, j->using)
5636 if (col != list_head(j->using))
5637 appendStringInfo(buf, ", ");
5638 appendStringInfoString(buf,
5639 quote_identifier(strVal(lfirst(col))));
5641 appendStringInfoChar(buf, ')');
5645 appendStringInfo(buf, " ON ");
5646 if (!PRETTY_PAREN(context))
5647 appendStringInfoChar(buf, '(');
5648 get_rule_expr(j->quals, context, false);
5649 if (!PRETTY_PAREN(context))
5650 appendStringInfoChar(buf, ')');
5653 if (!PRETTY_PAREN(context) || j->alias != NULL)
5654 appendStringInfoChar(buf, ')');
5656 /* Yes, it's correct to put alias after the right paren ... */
5657 if (j->alias != NULL)
5659 appendStringInfo(buf, " %s",
5660 quote_identifier(j->alias->aliasname));
5661 get_from_clause_alias(j->alias,
5662 rt_fetch(j->rtindex, query->rtable),
5667 elog(ERROR, "unrecognized node type: %d",
5668 (int) nodeTag(jtnode));
5672 * get_from_clause_alias - reproduce column alias list
5674 * This is tricky because we must ignore dropped columns.
5677 get_from_clause_alias(Alias *alias, RangeTblEntry *rte,
5678 deparse_context *context)
5680 StringInfo buf = context->buf;
5685 if (alias == NULL || alias->colnames == NIL)
5686 return; /* definitely nothing to do */
5689 foreach(col, alias->colnames)
5692 if (get_rte_attribute_is_dropped(rte, attnum))
5696 appendStringInfoChar(buf, '(');
5700 appendStringInfo(buf, ", ");
5701 appendStringInfoString(buf,
5702 quote_identifier(strVal(lfirst(col))));
5705 appendStringInfoChar(buf, ')');
5709 * get_from_clause_coldeflist - reproduce FROM clause coldeflist
5711 * The coldeflist is appended immediately (no space) to buf. Caller is
5712 * responsible for ensuring that an alias or AS is present before it.
5715 get_from_clause_coldeflist(List *names, List *types, List *typmods,
5716 deparse_context *context)
5718 StringInfo buf = context->buf;
5724 appendStringInfoChar(buf, '(');
5726 l2 = list_head(types);
5727 l3 = list_head(typmods);
5730 char *attname = strVal(lfirst(l1));
5734 atttypid = lfirst_oid(l2);
5736 atttypmod = lfirst_int(l3);
5740 appendStringInfo(buf, ", ");
5741 appendStringInfo(buf, "%s %s",
5742 quote_identifier(attname),
5743 format_type_with_typemod(atttypid, atttypmod));
5747 appendStringInfoChar(buf, ')');
5751 * get_opclass_name - fetch name of an index operator class
5753 * The opclass name is appended (after a space) to buf.
5755 * Output is suppressed if the opclass is the default for the given
5756 * actual_datatype. (If you don't want this behavior, just pass
5757 * InvalidOid for actual_datatype.)
5760 get_opclass_name(Oid opclass, Oid actual_datatype,
5764 Form_pg_opclass opcrec;
5768 ht_opc = SearchSysCache(CLAOID,
5769 ObjectIdGetDatum(opclass),
5771 if (!HeapTupleIsValid(ht_opc))
5772 elog(ERROR, "cache lookup failed for opclass %u", opclass);
5773 opcrec = (Form_pg_opclass) GETSTRUCT(ht_opc);
5775 if (!OidIsValid(actual_datatype) ||
5776 GetDefaultOpClass(actual_datatype, opcrec->opcmethod) != opclass)
5778 /* Okay, we need the opclass name. Do we need to qualify it? */
5779 opcname = NameStr(opcrec->opcname);
5780 if (OpclassIsVisible(opclass))
5781 appendStringInfo(buf, " %s", quote_identifier(opcname));
5784 nspname = get_namespace_name(opcrec->opcnamespace);
5785 appendStringInfo(buf, " %s.%s",
5786 quote_identifier(nspname),
5787 quote_identifier(opcname));
5790 ReleaseSysCache(ht_opc);
5794 * processIndirection - take care of array and subfield assignment
5796 * We strip any top-level FieldStore or assignment ArrayRef nodes that
5797 * appear in the input, and return the subexpression that's to be assigned.
5798 * If printit is true, we also print out the appropriate decoration for the
5799 * base column name (that the caller just printed).
5802 processIndirection(Node *node, deparse_context *context, bool printit)
5804 StringInfo buf = context->buf;
5810 if (IsA(node, FieldStore))
5812 FieldStore *fstore = (FieldStore *) node;
5816 /* lookup tuple type */
5817 typrelid = get_typ_typrelid(fstore->resulttype);
5818 if (!OidIsValid(typrelid))
5819 elog(ERROR, "argument type %s of FieldStore is not a tuple type",
5820 format_type_be(fstore->resulttype));
5823 * Print the field name. Note we assume here that there's only
5824 * one field being assigned to. This is okay in stored rules but
5825 * could be wrong in executable target lists. Presently no
5826 * problem since explain.c doesn't print plan targetlists, but
5827 * someday may have to think of something ...
5829 fieldname = get_relid_attribute_name(typrelid,
5830 linitial_int(fstore->fieldnums));
5832 appendStringInfo(buf, ".%s", quote_identifier(fieldname));
5835 * We ignore arg since it should be an uninteresting reference to
5836 * the target column or subcolumn.
5838 node = (Node *) linitial(fstore->newvals);
5840 else if (IsA(node, ArrayRef))
5842 ArrayRef *aref = (ArrayRef *) node;
5844 if (aref->refassgnexpr == NULL)
5847 printSubscripts(aref, context);
5850 * We ignore refexpr since it should be an uninteresting reference
5851 * to the target column or subcolumn.
5853 node = (Node *) aref->refassgnexpr;
5863 printSubscripts(ArrayRef *aref, deparse_context *context)
5865 StringInfo buf = context->buf;
5866 ListCell *lowlist_item;
5867 ListCell *uplist_item;
5869 lowlist_item = list_head(aref->reflowerindexpr); /* could be NULL */
5870 foreach(uplist_item, aref->refupperindexpr)
5872 appendStringInfoChar(buf, '[');
5875 get_rule_expr((Node *) lfirst(lowlist_item), context, false);
5876 appendStringInfoChar(buf, ':');
5877 lowlist_item = lnext(lowlist_item);
5879 get_rule_expr((Node *) lfirst(uplist_item), context, false);
5880 appendStringInfoChar(buf, ']');
5885 * quote_identifier - Quote an identifier only if needed
5887 * When quotes are needed, we palloc the required space; slightly
5888 * space-wasteful but well worth it for notational simplicity.
5891 quote_identifier(const char *ident)
5894 * Can avoid quoting if ident starts with a lowercase letter or underscore
5895 * and contains only lowercase letters, digits, and underscores, *and* is
5896 * not any SQL keyword. Otherwise, supply quotes.
5905 * would like to use <ctype.h> macros here, but they might yield unwanted
5906 * locale-specific results...
5908 safe = ((ident[0] >= 'a' && ident[0] <= 'z') || ident[0] == '_');
5910 for (ptr = ident; *ptr; ptr++)
5914 if ((ch >= 'a' && ch <= 'z') ||
5915 (ch >= '0' && ch <= '9') ||
5931 * Check for keyword. We quote keywords except for unreserved ones.
5932 * (In some cases we could avoid quoting a col_name or type_func_name
5933 * keyword, but it seems much harder than it's worth to tell that.)
5935 * Note: ScanKeywordLookup() does case-insensitive comparison, but
5936 * that's fine, since we already know we have all-lower-case.
5938 const ScanKeyword *keyword = ScanKeywordLookup(ident);
5940 if (keyword != NULL && keyword->category != UNRESERVED_KEYWORD)
5945 return ident; /* no change needed */
5947 result = (char *) palloc(strlen(ident) + nquotes + 2 + 1);
5951 for (ptr = ident; *ptr; ptr++)
5966 * quote_qualified_identifier - Quote a possibly-qualified identifier
5968 * Return a name of the form namespace.ident, or just ident if namespace
5969 * is NULL, quoting each component if necessary. The result is palloc'd.
5972 quote_qualified_identifier(const char *namespace,
5977 initStringInfo(&buf);
5979 appendStringInfo(&buf, "%s.", quote_identifier(namespace));
5980 appendStringInfoString(&buf, quote_identifier(ident));
5985 * generate_relation_name
5986 * Compute the name to display for a relation specified by OID
5988 * The result includes all necessary quoting and schema-prefixing.
5990 * If namespaces isn't NIL, it must be a list of deparse_namespace nodes.
5991 * We will forcibly qualify the relation name if it equals any CTE name
5992 * visible in the namespace list.
5995 generate_relation_name(Oid relid, List *namespaces)
5998 Form_pg_class reltup;
6005 tp = SearchSysCache(RELOID,
6006 ObjectIdGetDatum(relid),
6008 if (!HeapTupleIsValid(tp))
6009 elog(ERROR, "cache lookup failed for relation %u", relid);
6010 reltup = (Form_pg_class) GETSTRUCT(tp);
6011 relname = NameStr(reltup->relname);
6013 /* Check for conflicting CTE name */
6015 foreach(nslist, namespaces)
6017 deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist);
6020 foreach(ctlist, dpns->ctes)
6022 CommonTableExpr *cte = (CommonTableExpr *) lfirst(ctlist);
6024 if (strcmp(cte->ctename, relname) == 0)
6034 /* Otherwise, qualify the name if not visible in search path */
6036 need_qual = !RelationIsVisible(relid);
6039 nspname = get_namespace_name(reltup->relnamespace);
6043 result = quote_qualified_identifier(nspname, relname);
6045 ReleaseSysCache(tp);
6051 * generate_function_name
6052 * Compute the name to display for a function specified by OID,
6053 * given that it is being called with the specified actual arg types.
6054 * (Arg types matter because of ambiguous-function resolution rules.)
6056 * The result includes all necessary quoting and schema-prefixing. We can
6057 * also pass back an indication of whether the function is variadic.
6060 generate_function_name(Oid funcid, int nargs, Oid *argtypes,
6064 Form_pg_proc procform;
6068 FuncDetailCode p_result;
6073 Oid *p_true_typeids;
6075 proctup = SearchSysCache(PROCOID,
6076 ObjectIdGetDatum(funcid),
6078 if (!HeapTupleIsValid(proctup))
6079 elog(ERROR, "cache lookup failed for function %u", funcid);
6080 procform = (Form_pg_proc) GETSTRUCT(proctup);
6081 proname = NameStr(procform->proname);
6084 * The idea here is to schema-qualify only if the parser would fail to
6085 * resolve the correct function given the unqualified func name with the
6086 * specified argtypes.
6088 p_result = func_get_detail(list_make1(makeString(proname)),
6089 NIL, nargs, argtypes, false, true,
6090 &p_funcid, &p_rettype,
6091 &p_retset, &p_nvargs, &p_true_typeids, NULL);
6092 if ((p_result == FUNCDETAIL_NORMAL || p_result == FUNCDETAIL_AGGREGATE) &&
6096 nspname = get_namespace_name(procform->pronamespace);
6098 result = quote_qualified_identifier(nspname, proname);
6100 /* Check variadic-ness if caller cares */
6103 /* "any" variadics are not treated as variadics for listing */
6104 if (OidIsValid(procform->provariadic) &&
6105 procform->provariadic != ANYOID)
6106 *is_variadic = true;
6108 *is_variadic = false;
6111 ReleaseSysCache(proctup);
6117 * generate_operator_name
6118 * Compute the name to display for an operator specified by OID,
6119 * given that it is being called with the specified actual arg types.
6120 * (Arg types matter because of ambiguous-operator resolution rules.
6121 * Pass InvalidOid for unused arg of a unary operator.)
6123 * The result includes all necessary quoting and schema-prefixing,
6124 * plus the OPERATOR() decoration needed to use a qualified operator name
6128 generate_operator_name(Oid operid, Oid arg1, Oid arg2)
6132 Form_pg_operator operform;
6137 initStringInfo(&buf);
6139 opertup = SearchSysCache(OPEROID,
6140 ObjectIdGetDatum(operid),
6142 if (!HeapTupleIsValid(opertup))
6143 elog(ERROR, "cache lookup failed for operator %u", operid);
6144 operform = (Form_pg_operator) GETSTRUCT(opertup);
6145 oprname = NameStr(operform->oprname);
6148 * The idea here is to schema-qualify only if the parser would fail to
6149 * resolve the correct operator given the unqualified op name with the
6150 * specified argtypes.
6152 switch (operform->oprkind)
6155 p_result = oper(NULL, list_make1(makeString(oprname)), arg1, arg2,
6159 p_result = left_oper(NULL, list_make1(makeString(oprname)), arg2,
6163 p_result = right_oper(NULL, list_make1(makeString(oprname)), arg1,
6167 elog(ERROR, "unrecognized oprkind: %d", operform->oprkind);
6168 p_result = NULL; /* keep compiler quiet */
6172 if (p_result != NULL && oprid(p_result) == operid)
6176 nspname = get_namespace_name(operform->oprnamespace);
6177 appendStringInfo(&buf, "OPERATOR(%s.", quote_identifier(nspname));
6180 appendStringInfoString(&buf, oprname);
6183 appendStringInfoChar(&buf, ')');
6185 if (p_result != NULL)
6186 ReleaseSysCache(p_result);
6188 ReleaseSysCache(opertup);
6194 * Given a C string, produce a TEXT datum.
6196 * We assume that the input was palloc'd and may be freed.
6199 string_to_text(char *str)
6203 result = cstring_to_text(str);
6209 * Generate a C string representing a relation's reloptions, or NULL if none.
6212 flatten_reloptions(Oid relid)
6214 char *result = NULL;
6219 tuple = SearchSysCache(RELOID,
6220 ObjectIdGetDatum(relid),
6222 if (!HeapTupleIsValid(tuple))
6223 elog(ERROR, "cache lookup failed for relation %u", relid);
6225 reloptions = SysCacheGetAttr(RELOID, tuple,
6226 Anum_pg_class_reloptions, &isnull);
6233 * We want to use array_to_text(reloptions, ', ') --- but
6234 * DirectFunctionCall2(array_to_text) does not work, because
6235 * array_to_text() relies on flinfo to be valid. So use
6238 sep = CStringGetTextDatum(", ");
6239 txt = OidFunctionCall2(F_ARRAY_TO_TEXT, reloptions, sep);
6240 result = TextDatumGetCString(txt);
6243 ReleaseSysCache(tuple);